", masterID))
+ if secret.Name != name {
+ secret.Name = name
+ if len(secret.Annotations) == 0 {
+ secret.Annotations = map[string]string{}
+ }
+ secret.Annotations[rewritePrefix+"RewriteNodeIPs"] = nodeName
+ }
+ }
+ },
+ }
+}
diff --git a/vendor/github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphapi/type_registry.go b/vendor/github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphapi/type_registry.go
new file mode 100644
index 0000000000..fe797d6623
--- /dev/null
+++ b/vendor/github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphapi/type_registry.go
@@ -0,0 +1,62 @@
+package certgraphapi
+
+// PKIRegistryInfo holds information about TLS artifacts stored in etcd. This includes object location and metadata based on object annotations
+type PKIRegistryInfo struct {
+ // +mapType:=atomic
+ CertificateAuthorityBundles []PKIRegistryInClusterCABundle `json:"certificateAuthorityBundles"`
+ // +mapType:=atomic
+ CertKeyPairs []PKIRegistryInClusterCertKeyPair `json:"certKeyPairs"`
+}
+
+// PKIRegistryInClusterCertKeyPair identifies certificate key pair and stores its metadata
+type PKIRegistryInClusterCertKeyPair struct {
+ // SecretLocation points to the secret location
+ SecretLocation InClusterSecretLocation `json:"secretLocation"`
+ // CertKeyInfo stores metadata for certificate key pair
+ CertKeyInfo PKIRegistryCertKeyPairInfo `json:"certKeyInfo"`
+}
+
+// PKIRegistryCertKeyPairInfo holds information about certificate key pair
+type PKIRegistryCertKeyPairInfo struct {
+ // SelectedCertMetadataAnnotations is a specified subset of annotations. NOT all annotations.
+ // The caller will specify which annotations he wants.
+ SelectedCertMetadataAnnotations []AnnotationValue `json:"selectedCertMetadataAnnotations,omitempty"`
+
+ // OwningJiraComponent is a component name when a new OCP issue is filed in Jira
+ // Deprecated
+ OwningJiraComponent string `json:"owningJiraComponent"`
+ // Description is a one sentence description of the certificate pair purpose
+ // Deprecated
+ Description string `json:"description"`
+
+ //CertificateData PKIRegistryCertKeyMetadata
+}
+
+// PKIRegistryInClusterCABundle holds information about certificate authority bundle
+type PKIRegistryInClusterCABundle struct {
+ // ConfigMapLocation points to the configmap location
+ ConfigMapLocation InClusterConfigMapLocation `json:"configMapLocation"`
+ // CABundleInfo stores metadata for the certificate authority bundle
+ CABundleInfo PKIRegistryCertificateAuthorityInfo `json:"certificateAuthorityBundleInfo"`
+}
+
+// PKIRegistryCertificateAuthorityInfo holds information about certificate authority bundle
+type PKIRegistryCertificateAuthorityInfo struct {
+ // SelectedCertMetadataAnnotations is a specified subset of annotations. NOT all annotations.
+ // The caller will specify which annotations he wants.
+ SelectedCertMetadataAnnotations []AnnotationValue `json:"selectedCertMetadataAnnotations,omitempty"`
+
+ // OwningJiraComponent is a component name when a new OCP issue is filed in Jira
+ // Deprecated
+ OwningJiraComponent string `json:"owningJiraComponent"`
+ // Description is a one sentence description of the certificate pair purpose
+ // Deprecated
+ Description string `json:"description"`
+}
+
+type AnnotationValue struct {
+ // Key is the annotation key from the resource
+ Key string `json:"key"`
+ // Value is the annotation value from the resource
+ Value string `json:"value"`
+}
diff --git a/vendor/github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphapi/types.go b/vendor/github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphapi/types.go
new file mode 100644
index 0000000000..d1be9e21f4
--- /dev/null
+++ b/vendor/github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphapi/types.go
@@ -0,0 +1,219 @@
+package certgraphapi
+
+import (
+ "encoding/json"
+ "strings"
+)
+
+type PKIList struct {
+ // LogicalName is an inexact representation of what this is for. It may be empty. It will usually be some hardcoded
+ // heuristic trying to find it.
+ LogicalName string
+
+ Description string
+
+ InClusterResourceData PerInClusterResourceData
+
+ CertificateAuthorityBundles CertificateAuthorityBundleList
+ CertKeyPairs CertKeyPairList
+}
+
+// PerInClusterResourceData tracks metadata that corresponds to specific secrets and configmaps.
+// This data should not duplicate the analysis of the certkeypair lists, but is pulled from annotations on the resources.
+// It will be stitched together by a generator after the fact.
+type PerInClusterResourceData struct {
+ // +mapType:=atomic
+ CertificateAuthorityBundles []PKIRegistryInClusterCABundle `json:"certificateAuthorityBundles"`
+ // +mapType:=atomic
+ CertKeyPairs []PKIRegistryInClusterCertKeyPair `json:"certKeyPairs"`
+}
+
+type CertificateAuthorityBundleList struct {
+ Items []CertificateAuthorityBundle
+}
+
+type CertificateAuthorityBundle struct {
+ // LogicalName is an inexact representation of what this is for. It may be empty. It will usually be some hardcoded
+ // heuristic trying to determine it.
+ LogicalName string
+
+ Description string
+
+ // Name is CommonName::SerialNumber
+ Name string
+
+ Spec CertificateAuthorityBundleSpec
+ Status CertificateAuthorityBundleStatus
+}
+
+type CertificateAuthorityBundleStatus struct {
+ Errors []string
+}
+
+type CertificateAuthorityBundleSpec struct {
+ ConfigMapLocations []InClusterConfigMapLocation
+ OnDiskLocations []OnDiskLocation
+
+ CertificateMetadata []CertKeyMetadata
+}
+
+type CertKeyPairList struct {
+ Items []CertKeyPair
+}
+
+type CertKeyPair struct {
+ // LogicalName is an inexact representation of what this is for. It may be empty. It will usually be some hardcoded
+ // heuristic trying to determine it.
+ LogicalName string
+
+ Description string
+
+ // Name is CommonName::SerialNumber
+ Name string
+
+ Spec CertKeyPairSpec
+ Status CertKeyPairStatus
+}
+
+type CertKeyPairStatus struct {
+ Errors []string
+}
+
+type CertKeyPairSpec struct {
+ SecretLocations []InClusterSecretLocation
+ OnDiskLocations []OnDiskCertKeyPairLocation
+
+ CertMetadata CertKeyMetadata
+ Details CertKeyPairDetails
+}
+
+type InClusterSecretLocation struct {
+ Namespace string
+ Name string
+}
+
+type InClusterConfigMapLocation struct {
+ Namespace string
+ Name string
+}
+
+type OnDiskCertKeyPairLocation struct {
+ Cert OnDiskLocation
+ Key OnDiskLocation
+}
+
+type OnDiskLocation struct {
+ Path string
+ User string
+ Group string
+ Permissions string
+ SELinuxOptions string
+}
+
+type CertKeyPairDetails struct {
+ CertType string
+
+ SignerDetails *SignerCertDetails
+ ServingCertDetails *ServingCertDetails
+ ClientCertDetails *ClientCertDetails
+}
+
+type SignerCertDetails struct {
+}
+
+type ServingCertDetails struct {
+ DNSNames []string
+ IPAddresses []string
+}
+
+type ClientCertDetails struct {
+ Organizations []string
+}
+
+type CertIdentifier struct {
+ CommonName string
+ SerialNumber string
+
+ Issuer *CertIdentifier
+}
+
+type CertKeyMetadata struct {
+ CertIdentifier CertIdentifier
+ SignatureAlgorithm string
+ PublicKeyAlgorithm string
+ PublicKeyBitSize string
+ ValidityDuration string
+ Usages []string
+ ExtendedUsages []string
+}
+
+// do better
+func (t *CertKeyPair) DeepCopy() *CertKeyPair {
+ jsonBytes, err := json.Marshal(t)
+ if err != nil {
+ panic(err)
+ }
+
+ ret := &CertKeyPair{}
+ if err := json.Unmarshal(jsonBytes, ret); err != nil {
+ panic(err)
+ }
+
+ return ret
+}
+
+// do better
+func (t *CertificateAuthorityBundle) DeepCopy() *CertificateAuthorityBundle {
+ jsonBytes, err := json.Marshal(t)
+ if err != nil {
+ panic(err)
+ }
+
+ ret := &CertificateAuthorityBundle{}
+ if err := json.Unmarshal(jsonBytes, ret); err != nil {
+ panic(err)
+ }
+
+ return ret
+}
+
+type ConfigMapRefByNamespaceName []InClusterConfigMapLocation
+type SecretRefByNamespaceName []InClusterSecretLocation
+type SecretInfoByNamespaceName map[InClusterSecretLocation]PKIRegistryCertKeyPairInfo
+type ConfigMapInfoByNamespaceName map[InClusterConfigMapLocation]PKIRegistryCertificateAuthorityInfo
+
+func (n SecretRefByNamespaceName) Len() int {
+ return len(n)
+}
+func (n SecretRefByNamespaceName) Swap(i, j int) {
+ n[i], n[j] = n[j], n[i]
+}
+func (n SecretRefByNamespaceName) Less(i, j int) bool {
+ diff := strings.Compare(n[i].Namespace, n[j].Namespace)
+ switch {
+ case diff < 0:
+ return true
+ case diff > 0:
+ return false
+ }
+
+ return strings.Compare(n[i].Name, n[j].Name) < 0
+}
+
+func (n ConfigMapRefByNamespaceName) Len() int {
+ return len(n)
+}
+func (n ConfigMapRefByNamespaceName) Swap(i, j int) {
+ n[i], n[j] = n[j], n[i]
+}
+func (n ConfigMapRefByNamespaceName) Less(i, j int) bool {
+ diff := strings.Compare(n[i].Namespace, n[j].Namespace)
+ switch {
+ case diff < 0:
+ return true
+ case diff > 0:
+ return false
+ }
+
+ return strings.Compare(n[i].Name, n[j].Name) < 0
+}
diff --git a/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
index c585a65b3f..62d98829b4 100644
--- a/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
+++ b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go
@@ -371,7 +371,7 @@ func (c *TLSCertificateConfig) GetPEMBytes() ([]byte, []byte, error) {
if err != nil {
return nil, nil, err
}
- keyBytes, err := encodeKey(c.Key)
+ keyBytes, err := EncodeKey(c.Key)
if err != nil {
return nil, nil, err
}
@@ -644,15 +644,20 @@ func MakeSelfSignedCAConfigForSubject(subject pkix.Name, expireDays int) (*TLSCe
}
caLifetime := time.Duration(caLifetimeInDays) * 24 * time.Hour
- return makeSelfSignedCAConfigForSubjectAndDuration(subject, caLifetime)
+ return makeSelfSignedCAConfigForSubjectAndDuration(subject, time.Now, caLifetime)
}
func MakeSelfSignedCAConfigForDuration(name string, caLifetime time.Duration) (*TLSCertificateConfig, error) {
subject := pkix.Name{CommonName: name}
- return makeSelfSignedCAConfigForSubjectAndDuration(subject, caLifetime)
+ return makeSelfSignedCAConfigForSubjectAndDuration(subject, time.Now, caLifetime)
}
-func makeSelfSignedCAConfigForSubjectAndDuration(subject pkix.Name, caLifetime time.Duration) (*TLSCertificateConfig, error) {
+func UnsafeMakeSelfSignedCAConfigForDurationAtTime(name string, currentTime func() time.Time, caLifetime time.Duration) (*TLSCertificateConfig, error) {
+ subject := pkix.Name{CommonName: name}
+ return makeSelfSignedCAConfigForSubjectAndDuration(subject, currentTime, caLifetime)
+}
+
+func makeSelfSignedCAConfigForSubjectAndDuration(subject pkix.Name, currentTime func() time.Time, caLifetime time.Duration) (*TLSCertificateConfig, error) {
// Create CA cert
rootcaPublicKey, rootcaPrivateKey, publicKeyHash, err := newKeyPairWithHash()
if err != nil {
@@ -661,7 +666,7 @@ func makeSelfSignedCAConfigForSubjectAndDuration(subject pkix.Name, caLifetime t
// AuthorityKeyId and SubjectKeyId should match for a self-signed CA
authorityKeyId := publicKeyHash
subjectKeyId := publicKeyHash
- rootcaTemplate := newSigningCertificateTemplateForDuration(subject, caLifetime, time.Now, authorityKeyId, subjectKeyId)
+ rootcaTemplate := newSigningCertificateTemplateForDuration(subject, caLifetime, currentTime, authorityKeyId, subjectKeyId)
rootcaCert, err := signCertificate(rootcaTemplate, rootcaPublicKey, rootcaTemplate, rootcaPrivateKey)
if err != nil {
return nil, err
@@ -682,7 +687,7 @@ func MakeCAConfigForDuration(name string, caLifetime time.Duration, issuer *CA)
authorityKeyId := issuer.Config.Certs[0].SubjectKeyId
subjectKeyId := publicKeyHash
signerTemplate := newSigningCertificateTemplateForDuration(pkix.Name{CommonName: name}, caLifetime, time.Now, authorityKeyId, subjectKeyId)
- signerCert, err := issuer.signCertificate(signerTemplate, signerPublicKey)
+ signerCert, err := issuer.SignCertificate(signerTemplate, signerPublicKey)
if err != nil {
return nil, err
}
@@ -798,7 +803,7 @@ func (ca *CA) MakeServerCert(hostnames sets.String, expireDays int, fns ...Certi
return nil, err
}
}
- serverCrt, err := ca.signCertificate(serverTemplate, serverPublicKey)
+ serverCrt, err := ca.SignCertificate(serverTemplate, serverPublicKey)
if err != nil {
return nil, err
}
@@ -819,7 +824,7 @@ func (ca *CA) MakeServerCertForDuration(hostnames sets.String, lifetime time.Dur
return nil, err
}
}
- serverCrt, err := ca.signCertificate(serverTemplate, serverPublicKey)
+ serverCrt, err := ca.SignCertificate(serverTemplate, serverPublicKey)
if err != nil {
return nil, err
}
@@ -845,7 +850,7 @@ func GetClientCertificate(certFile, keyFile string, u user.Info) (*TLSCertificat
return nil, err
}
- if subject := certConfig.Certs[0].Subject; subjectChanged(subject, userToSubject(u)) {
+ if subject := certConfig.Certs[0].Subject; subjectChanged(subject, UserToSubject(u)) {
return nil, fmt.Errorf("existing client certificate in %s was issued for a different Subject (%s)",
certFile, subject)
}
@@ -873,8 +878,8 @@ func (ca *CA) MakeClientCertificate(certFile, keyFile string, u user.Info, expir
}
clientPublicKey, clientPrivateKey, _ := NewKeyPair()
- clientTemplate := newClientCertificateTemplate(userToSubject(u), expireDays, time.Now)
- clientCrt, err := ca.signCertificate(clientTemplate, clientPublicKey)
+ clientTemplate := NewClientCertificateTemplate(UserToSubject(u), expireDays, time.Now)
+ clientCrt, err := ca.SignCertificate(clientTemplate, clientPublicKey)
if err != nil {
return nil, err
}
@@ -883,7 +888,7 @@ func (ca *CA) MakeClientCertificate(certFile, keyFile string, u user.Info, expir
if err != nil {
return nil, err
}
- keyData, err := encodeKey(clientPrivateKey)
+ keyData, err := EncodeKey(clientPrivateKey)
if err != nil {
return nil, err
}
@@ -900,8 +905,8 @@ func (ca *CA) MakeClientCertificate(certFile, keyFile string, u user.Info, expir
func (ca *CA) MakeClientCertificateForDuration(u user.Info, lifetime time.Duration) (*TLSCertificateConfig, error) {
clientPublicKey, clientPrivateKey, _ := NewKeyPair()
- clientTemplate := newClientCertificateTemplateForDuration(userToSubject(u), lifetime, time.Now)
- clientCrt, err := ca.signCertificate(clientTemplate, clientPublicKey)
+ clientTemplate := NewClientCertificateTemplateForDuration(UserToSubject(u), lifetime, time.Now)
+ clientCrt, err := ca.SignCertificate(clientTemplate, clientPublicKey)
if err != nil {
return nil, err
}
@@ -910,7 +915,7 @@ func (ca *CA) MakeClientCertificateForDuration(u user.Info, lifetime time.Durati
if err != nil {
return nil, err
}
- keyData, err := encodeKey(clientPrivateKey)
+ keyData, err := EncodeKey(clientPrivateKey)
if err != nil {
return nil, err
}
@@ -935,7 +940,7 @@ func (s sortedForDER) Less(i, j int) bool {
return l1 < l2
}
-func userToSubject(u user.Info) pkix.Name {
+func UserToSubject(u user.Info) pkix.Name {
// Ok we are going to order groups in a peculiar way here to workaround a
// 2 bugs, 1 in golang (https://github.com/golang/go/issues/24254) which
// incorrectly encodes Multivalued RDNs and another in GNUTLS clients
@@ -961,7 +966,7 @@ func userToSubject(u user.Info) pkix.Name {
}
}
-func (ca *CA) signCertificate(template *x509.Certificate, requestKey crypto.PublicKey) (*x509.Certificate, error) {
+func (ca *CA) SignCertificate(template *x509.Certificate, requestKey crypto.PublicKey) (*x509.Certificate, error) {
// Increment and persist serial
serial, err := ca.SerialGenerator.Next(template)
if err != nil {
@@ -1108,7 +1113,7 @@ func CertsFromPEM(pemCerts []byte) ([]*x509.Certificate, error) {
}
// Can be used as a certificate in http.Transport TLSClientConfig
-func newClientCertificateTemplate(subject pkix.Name, expireDays int, currentTime func() time.Time) *x509.Certificate {
+func NewClientCertificateTemplate(subject pkix.Name, expireDays int, currentTime func() time.Time) *x509.Certificate {
var lifetimeInDays = DefaultCertificateLifetimeInDays
if expireDays > 0 {
lifetimeInDays = expireDays
@@ -1120,11 +1125,11 @@ func newClientCertificateTemplate(subject pkix.Name, expireDays int, currentTime
lifetime := time.Duration(lifetimeInDays) * 24 * time.Hour
- return newClientCertificateTemplateForDuration(subject, lifetime, currentTime)
+ return NewClientCertificateTemplateForDuration(subject, lifetime, currentTime)
}
// Can be used as a certificate in http.Transport TLSClientConfig
-func newClientCertificateTemplateForDuration(subject pkix.Name, lifetime time.Duration, currentTime func() time.Time) *x509.Certificate {
+func NewClientCertificateTemplateForDuration(subject pkix.Name, lifetime time.Duration, currentTime func() time.Time) *x509.Certificate {
return &x509.Certificate{
Subject: subject,
@@ -1170,7 +1175,7 @@ func EncodeCertificates(certs ...*x509.Certificate) ([]byte, error) {
}
return b.Bytes(), nil
}
-func encodeKey(key crypto.PrivateKey) ([]byte, error) {
+func EncodeKey(key crypto.PrivateKey) ([]byte, error) {
b := bytes.Buffer{}
switch key := key.(type) {
case *ecdsa.PrivateKey:
@@ -1204,7 +1209,7 @@ func writeCertificates(f io.Writer, certs ...*x509.Certificate) error {
return nil
}
func writeKeyFile(f io.Writer, key crypto.PrivateKey) error {
- bytes, err := encodeKey(key)
+ bytes, err := EncodeKey(key)
if err != nil {
return err
}
diff --git a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go
index d3cd885801..22aedb18f5 100644
--- a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go
+++ b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go
@@ -16,7 +16,6 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/client-go/util/retry"
- "k8s.io/klog/v2"
"github.com/ghodss/yaml"
@@ -145,7 +144,7 @@ func UpdateSpec(ctx context.Context, client OperatorClient, updateFuncs ...Updat
return operatorSpec, updated, err
}
-// UpdateSpecConfigFn returns a func to update the config.
+// UpdateObservedConfigFn returns a func to update the config.
func UpdateObservedConfigFn(config map[string]interface{}) UpdateOperatorSpecFunc {
return func(oldSpec *operatorv1.OperatorSpec) error {
oldSpec.ObservedConfig = runtime.RawExtension{Object: &unstructured.Unstructured{Object: config}}
@@ -187,7 +186,7 @@ func UpdateStatus(ctx context.Context, client OperatorClient, updateFuncs ...Upd
return updatedOperatorStatus, updated, err
}
-// UpdateConditionFunc returns a func to update a condition.
+// UpdateConditionFn returns a func to update a condition.
func UpdateConditionFn(cond operatorv1.OperatorCondition) UpdateStatusFunc {
return func(oldStatus *operatorv1.OperatorStatus) error {
SetOperatorCondition(&oldStatus.Conditions, cond)
@@ -195,7 +194,7 @@ func UpdateConditionFn(cond operatorv1.OperatorCondition) UpdateStatusFunc {
}
}
-// UpdateStatusFunc is a func that mutates an operator status.
+// UpdateStaticPodStatusFunc is a func that mutates an operator status.
type UpdateStaticPodStatusFunc func(status *operatorv1.StaticPodOperatorStatus) error
// UpdateStaticPodStatus applies the update funcs to the oldStatus abd tries to update via the client.
@@ -207,7 +206,7 @@ func UpdateStaticPodStatus(ctx context.Context, client StaticPodOperatorClient,
if err != nil {
return err
}
- klog.V(2).Infof("status.LatestAvailableRevision: %v, resourceVersion: %v", oldStatus.LatestAvailableRevision, resourceVersion)
+
newStatus := oldStatus.DeepCopy()
for _, update := range updateFuncs {
if err := update(newStatus); err != nil {
diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE
new file mode 100644
index 0000000000..c67dad612a
--- /dev/null
+++ b/vendor/github.com/pmezard/go-difflib/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013, Patrick Mezard
+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.
+ The names of its contributors may not 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.
diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go
new file mode 100644
index 0000000000..003e99fadb
--- /dev/null
+++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go
@@ -0,0 +1,772 @@
+// Package difflib is a partial port of Python difflib module.
+//
+// It provides tools to compare sequences of strings and generate textual diffs.
+//
+// The following class and functions have been ported:
+//
+// - SequenceMatcher
+//
+// - unified_diff
+//
+// - context_diff
+//
+// Getting unified diffs was the main goal of the port. Keep in mind this code
+// is mostly suitable to output text differences in a human friendly way, there
+// are no guarantees generated diffs are consumable by patch(1).
+package difflib
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "strings"
+)
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+func calculateRatio(matches, length int) float64 {
+ if length > 0 {
+ return 2.0 * float64(matches) / float64(length)
+ }
+ return 1.0
+}
+
+type Match struct {
+ A int
+ B int
+ Size int
+}
+
+type OpCode struct {
+ Tag byte
+ I1 int
+ I2 int
+ J1 int
+ J2 int
+}
+
+// SequenceMatcher compares sequence of strings. The basic
+// algorithm predates, and is a little fancier than, an algorithm
+// published in the late 1980's by Ratcliff and Obershelp under the
+// hyperbolic name "gestalt pattern matching". The basic idea is to find
+// the longest contiguous matching subsequence that contains no "junk"
+// elements (R-O doesn't address junk). The same idea is then applied
+// recursively to the pieces of the sequences to the left and to the right
+// of the matching subsequence. This does not yield minimal edit
+// sequences, but does tend to yield matches that "look right" to people.
+//
+// SequenceMatcher tries to compute a "human-friendly diff" between two
+// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the
+// longest *contiguous* & junk-free matching subsequence. That's what
+// catches peoples' eyes. The Windows(tm) windiff has another interesting
+// notion, pairing up elements that appear uniquely in each sequence.
+// That, and the method here, appear to yield more intuitive difference
+// reports than does diff. This method appears to be the least vulnerable
+// to synching up on blocks of "junk lines", though (like blank lines in
+// ordinary text files, or maybe "" lines in HTML files). That may be
+// because this is the only method of the 3 that has a *concept* of
+// "junk" .
+//
+// Timing: Basic R-O is cubic time worst case and quadratic time expected
+// case. SequenceMatcher is quadratic time for the worst case and has
+// expected-case behavior dependent in a complicated way on how many
+// elements the sequences have in common; best case time is linear.
+type SequenceMatcher struct {
+ a []string
+ b []string
+ b2j map[string][]int
+ IsJunk func(string) bool
+ autoJunk bool
+ bJunk map[string]struct{}
+ matchingBlocks []Match
+ fullBCount map[string]int
+ bPopular map[string]struct{}
+ opCodes []OpCode
+}
+
+func NewMatcher(a, b []string) *SequenceMatcher {
+ m := SequenceMatcher{autoJunk: true}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+func NewMatcherWithJunk(a, b []string, autoJunk bool,
+ isJunk func(string) bool) *SequenceMatcher {
+
+ m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
+ m.SetSeqs(a, b)
+ return &m
+}
+
+// Set two sequences to be compared.
+func (m *SequenceMatcher) SetSeqs(a, b []string) {
+ m.SetSeq1(a)
+ m.SetSeq2(b)
+}
+
+// Set the first sequence to be compared. The second sequence to be compared is
+// not changed.
+//
+// SequenceMatcher computes and caches detailed information about the second
+// sequence, so if you want to compare one sequence S against many sequences,
+// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other
+// sequences.
+//
+// See also SetSeqs() and SetSeq2().
+func (m *SequenceMatcher) SetSeq1(a []string) {
+ if &a == &m.a {
+ return
+ }
+ m.a = a
+ m.matchingBlocks = nil
+ m.opCodes = nil
+}
+
+// Set the second sequence to be compared. The first sequence to be compared is
+// not changed.
+func (m *SequenceMatcher) SetSeq2(b []string) {
+ if &b == &m.b {
+ return
+ }
+ m.b = b
+ m.matchingBlocks = nil
+ m.opCodes = nil
+ m.fullBCount = nil
+ m.chainB()
+}
+
+func (m *SequenceMatcher) chainB() {
+ // Populate line -> index mapping
+ b2j := map[string][]int{}
+ for i, s := range m.b {
+ indices := b2j[s]
+ indices = append(indices, i)
+ b2j[s] = indices
+ }
+
+ // Purge junk elements
+ m.bJunk = map[string]struct{}{}
+ if m.IsJunk != nil {
+ junk := m.bJunk
+ for s, _ := range b2j {
+ if m.IsJunk(s) {
+ junk[s] = struct{}{}
+ }
+ }
+ for s, _ := range junk {
+ delete(b2j, s)
+ }
+ }
+
+ // Purge remaining popular elements
+ popular := map[string]struct{}{}
+ n := len(m.b)
+ if m.autoJunk && n >= 200 {
+ ntest := n/100 + 1
+ for s, indices := range b2j {
+ if len(indices) > ntest {
+ popular[s] = struct{}{}
+ }
+ }
+ for s, _ := range popular {
+ delete(b2j, s)
+ }
+ }
+ m.bPopular = popular
+ m.b2j = b2j
+}
+
+func (m *SequenceMatcher) isBJunk(s string) bool {
+ _, ok := m.bJunk[s]
+ return ok
+}
+
+// Find longest matching block in a[alo:ahi] and b[blo:bhi].
+//
+// If IsJunk is not defined:
+//
+// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
+// alo <= i <= i+k <= ahi
+// blo <= j <= j+k <= bhi
+// and for all (i',j',k') meeting those conditions,
+// k >= k'
+// i <= i'
+// and if i == i', j <= j'
+//
+// In other words, of all maximal matching blocks, return one that
+// starts earliest in a, and of all those maximal matching blocks that
+// start earliest in a, return the one that starts earliest in b.
+//
+// If IsJunk is defined, first the longest matching block is
+// determined as above, but with the additional restriction that no
+// junk element appears in the block. Then that block is extended as
+// far as possible by matching (only) junk elements on both sides. So
+// the resulting block never matches on junk except as identical junk
+// happens to be adjacent to an "interesting" match.
+//
+// If no blocks match, return (alo, blo, 0).
+func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match {
+ // CAUTION: stripping common prefix or suffix would be incorrect.
+ // E.g.,
+ // ab
+ // acab
+ // Longest matching block is "ab", but if common prefix is
+ // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so
+ // strip, so ends up claiming that ab is changed to acab by
+ // inserting "ca" in the middle. That's minimal but unintuitive:
+ // "it's obvious" that someone inserted "ac" at the front.
+ // Windiff ends up at the same place as diff, but by pairing up
+ // the unique 'b's and then matching the first two 'a's.
+ besti, bestj, bestsize := alo, blo, 0
+
+ // find longest junk-free match
+ // during an iteration of the loop, j2len[j] = length of longest
+ // junk-free match ending with a[i-1] and b[j]
+ j2len := map[int]int{}
+ for i := alo; i != ahi; i++ {
+ // look at all instances of a[i] in b; note that because
+ // b2j has no junk keys, the loop is skipped if a[i] is junk
+ newj2len := map[int]int{}
+ for _, j := range m.b2j[m.a[i]] {
+ // a[i] matches b[j]
+ if j < blo {
+ continue
+ }
+ if j >= bhi {
+ break
+ }
+ k := j2len[j-1] + 1
+ newj2len[j] = k
+ if k > bestsize {
+ besti, bestj, bestsize = i-k+1, j-k+1, k
+ }
+ }
+ j2len = newj2len
+ }
+
+ // Extend the best by non-junk elements on each end. In particular,
+ // "popular" non-junk elements aren't in b2j, which greatly speeds
+ // the inner loop above, but also means "the best" match so far
+ // doesn't contain any junk *or* popular non-junk elements.
+ for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ !m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ // Now that we have a wholly interesting match (albeit possibly
+ // empty!), we may as well suck up the matching junk on each
+ // side of it too. Can't think of a good reason not to, and it
+ // saves post-processing the (possibly considerable) expense of
+ // figuring out what to do with it. In the case of an empty
+ // interesting match, this is clearly the right thing to do,
+ // because no other kind of match is possible in the regions.
+ for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) &&
+ m.a[besti-1] == m.b[bestj-1] {
+ besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
+ }
+ for besti+bestsize < ahi && bestj+bestsize < bhi &&
+ m.isBJunk(m.b[bestj+bestsize]) &&
+ m.a[besti+bestsize] == m.b[bestj+bestsize] {
+ bestsize += 1
+ }
+
+ return Match{A: besti, B: bestj, Size: bestsize}
+}
+
+// Return list of triples describing matching subsequences.
+//
+// Each triple is of the form (i, j, n), and means that
+// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in
+// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are
+// adjacent triples in the list, and the second is not the last triple in the
+// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe
+// adjacent equal blocks.
+//
+// The last triple is a dummy, (len(a), len(b), 0), and is the only
+// triple with n==0.
+func (m *SequenceMatcher) GetMatchingBlocks() []Match {
+ if m.matchingBlocks != nil {
+ return m.matchingBlocks
+ }
+
+ var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match
+ matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match {
+ match := m.findLongestMatch(alo, ahi, blo, bhi)
+ i, j, k := match.A, match.B, match.Size
+ if match.Size > 0 {
+ if alo < i && blo < j {
+ matched = matchBlocks(alo, i, blo, j, matched)
+ }
+ matched = append(matched, match)
+ if i+k < ahi && j+k < bhi {
+ matched = matchBlocks(i+k, ahi, j+k, bhi, matched)
+ }
+ }
+ return matched
+ }
+ matched := matchBlocks(0, len(m.a), 0, len(m.b), nil)
+
+ // It's possible that we have adjacent equal blocks in the
+ // matching_blocks list now.
+ nonAdjacent := []Match{}
+ i1, j1, k1 := 0, 0, 0
+ for _, b := range matched {
+ // Is this block adjacent to i1, j1, k1?
+ i2, j2, k2 := b.A, b.B, b.Size
+ if i1+k1 == i2 && j1+k1 == j2 {
+ // Yes, so collapse them -- this just increases the length of
+ // the first block by the length of the second, and the first
+ // block so lengthened remains the block to compare against.
+ k1 += k2
+ } else {
+ // Not adjacent. Remember the first block (k1==0 means it's
+ // the dummy we started with), and make the second block the
+ // new block to compare against.
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+ i1, j1, k1 = i2, j2, k2
+ }
+ }
+ if k1 > 0 {
+ nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
+ }
+
+ nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0})
+ m.matchingBlocks = nonAdjacent
+ return m.matchingBlocks
+}
+
+// Return list of 5-tuples describing how to turn a into b.
+//
+// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple
+// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
+// tuple preceding it, and likewise for j1 == the previous j2.
+//
+// The tags are characters, with these meanings:
+//
+// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2]
+//
+// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case.
+//
+// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case.
+//
+// 'e' (equal): a[i1:i2] == b[j1:j2]
+func (m *SequenceMatcher) GetOpCodes() []OpCode {
+ if m.opCodes != nil {
+ return m.opCodes
+ }
+ i, j := 0, 0
+ matching := m.GetMatchingBlocks()
+ opCodes := make([]OpCode, 0, len(matching))
+ for _, m := range matching {
+ // invariant: we've pumped out correct diffs to change
+ // a[:i] into b[:j], and the next matching block is
+ // a[ai:ai+size] == b[bj:bj+size]. So we need to pump
+ // out a diff to change a[i:ai] into b[j:bj], pump out
+ // the matching block, and move (i,j) beyond the match
+ ai, bj, size := m.A, m.B, m.Size
+ tag := byte(0)
+ if i < ai && j < bj {
+ tag = 'r'
+ } else if i < ai {
+ tag = 'd'
+ } else if j < bj {
+ tag = 'i'
+ }
+ if tag > 0 {
+ opCodes = append(opCodes, OpCode{tag, i, ai, j, bj})
+ }
+ i, j = ai+size, bj+size
+ // the list of matching blocks is terminated by a
+ // sentinel with size 0
+ if size > 0 {
+ opCodes = append(opCodes, OpCode{'e', ai, i, bj, j})
+ }
+ }
+ m.opCodes = opCodes
+ return m.opCodes
+}
+
+// Isolate change clusters by eliminating ranges with no changes.
+//
+// Return a generator of groups with up to n lines of context.
+// Each group is in the same format as returned by GetOpCodes().
+func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
+ if n < 0 {
+ n = 3
+ }
+ codes := m.GetOpCodes()
+ if len(codes) == 0 {
+ codes = []OpCode{OpCode{'e', 0, 1, 0, 1}}
+ }
+ // Fixup leading and trailing groups if they show no changes.
+ if codes[0].Tag == 'e' {
+ c := codes[0]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
+ }
+ if codes[len(codes)-1].Tag == 'e' {
+ c := codes[len(codes)-1]
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
+ }
+ nn := n + n
+ groups := [][]OpCode{}
+ group := []OpCode{}
+ for _, c := range codes {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ // End the current group and start a new one whenever
+ // there is a large range with no changes.
+ if c.Tag == 'e' && i2-i1 > nn {
+ group = append(group, OpCode{c.Tag, i1, min(i2, i1+n),
+ j1, min(j2, j1+n)})
+ groups = append(groups, group)
+ group = []OpCode{}
+ i1, j1 = max(i1, i2-n), max(j1, j2-n)
+ }
+ group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
+ }
+ if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') {
+ groups = append(groups, group)
+ }
+ return groups
+}
+
+// Return a measure of the sequences' similarity (float in [0,1]).
+//
+// Where T is the total number of elements in both sequences, and
+// M is the number of matches, this is 2.0*M / T.
+// Note that this is 1 if the sequences are identical, and 0 if
+// they have nothing in common.
+//
+// .Ratio() is expensive to compute if you haven't already computed
+// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
+// want to try .QuickRatio() or .RealQuickRation() first to get an
+// upper bound.
+func (m *SequenceMatcher) Ratio() float64 {
+ matches := 0
+ for _, m := range m.GetMatchingBlocks() {
+ matches += m.Size
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() relatively quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute.
+func (m *SequenceMatcher) QuickRatio() float64 {
+ // viewing a and b as multisets, set matches to the cardinality
+ // of their intersection; this counts the number of matches
+ // without regard to order, so is clearly an upper bound
+ if m.fullBCount == nil {
+ m.fullBCount = map[string]int{}
+ for _, s := range m.b {
+ m.fullBCount[s] = m.fullBCount[s] + 1
+ }
+ }
+
+ // avail[x] is the number of times x appears in 'b' less the
+ // number of times we've seen it in 'a' so far ... kinda
+ avail := map[string]int{}
+ matches := 0
+ for _, s := range m.a {
+ n, ok := avail[s]
+ if !ok {
+ n = m.fullBCount[s]
+ }
+ avail[s] = n - 1
+ if n > 0 {
+ matches += 1
+ }
+ }
+ return calculateRatio(matches, len(m.a)+len(m.b))
+}
+
+// Return an upper bound on ratio() very quickly.
+//
+// This isn't defined beyond that it is an upper bound on .Ratio(), and
+// is faster to compute than either .Ratio() or .QuickRatio().
+func (m *SequenceMatcher) RealQuickRatio() float64 {
+ la, lb := len(m.a), len(m.b)
+ return calculateRatio(min(la, lb), la+lb)
+}
+
+// Convert range to the "ed" format
+func formatRangeUnified(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ return fmt.Sprintf("%d,%d", beginning, length)
+}
+
+// Unified diff parameters
+type UnifiedDiff struct {
+ A []string // First sequence lines
+ FromFile string // First file name
+ FromDate string // First file time
+ B []string // Second sequence lines
+ ToFile string // Second file name
+ ToDate string // Second file time
+ Eol string // Headers end of line, defaults to LF
+ Context int // Number of context lines
+}
+
+// Compare two sequences of lines; generate the delta as a unified diff.
+//
+// Unified diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by 'n' which
+// defaults to three.
+//
+// By default, the diff control lines (those with ---, +++, or @@) are
+// created with a trailing newline. This is helpful so that inputs
+// created from file.readlines() result in diffs that are suitable for
+// file.writelines() since both the inputs and outputs have trailing
+// newlines.
+//
+// For inputs that do not have trailing newlines, set the lineterm
+// argument to "" so that the output will be uniformly newline free.
+//
+// The unidiff format normally has a header for filenames and modification
+// times. Any or all of these may be specified using strings for
+// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
+// The modification times are normally expressed in the ISO 8601 format.
+func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ wf := func(format string, args ...interface{}) error {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ return err
+ }
+ ws := func(s string) error {
+ _, err := buf.WriteString(s)
+ return err
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ first, last := g[0], g[len(g)-1]
+ range1 := formatRangeUnified(first.I1, last.I2)
+ range2 := formatRangeUnified(first.J1, last.J2)
+ if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil {
+ return err
+ }
+ for _, c := range g {
+ i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
+ if c.Tag == 'e' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws(" " + line); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, line := range diff.A[i1:i2] {
+ if err := ws("-" + line); err != nil {
+ return err
+ }
+ }
+ }
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, line := range diff.B[j1:j2] {
+ if err := ws("+" + line); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Like WriteUnifiedDiff but returns the diff a string.
+func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteUnifiedDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Convert range to the "ed" format.
+func formatRangeContext(start, stop int) string {
+ // Per the diff spec at http://www.unix.org/single_unix_specification/
+ beginning := start + 1 // lines start numbering with one
+ length := stop - start
+ if length == 0 {
+ beginning -= 1 // empty ranges begin at line just before the range
+ }
+ if length <= 1 {
+ return fmt.Sprintf("%d", beginning)
+ }
+ return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
+}
+
+type ContextDiff UnifiedDiff
+
+// Compare two sequences of lines; generate the delta as a context diff.
+//
+// Context diffs are a compact way of showing line changes and a few
+// lines of context. The number of context lines is set by diff.Context
+// which defaults to three.
+//
+// By default, the diff control lines (those with *** or ---) are
+// created with a trailing newline.
+//
+// For inputs that do not have trailing newlines, set the diff.Eol
+// argument to "" so that the output will be uniformly newline free.
+//
+// The context diff format normally has a header for filenames and
+// modification times. Any or all of these may be specified using
+// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
+// The modification times are normally expressed in the ISO 8601 format.
+// If not specified, the strings default to blanks.
+func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ var diffErr error
+ wf := func(format string, args ...interface{}) {
+ _, err := buf.WriteString(fmt.Sprintf(format, args...))
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+ ws := func(s string) {
+ _, err := buf.WriteString(s)
+ if diffErr == nil && err != nil {
+ diffErr = err
+ }
+ }
+
+ if len(diff.Eol) == 0 {
+ diff.Eol = "\n"
+ }
+
+ prefix := map[byte]string{
+ 'i': "+ ",
+ 'd': "- ",
+ 'r': "! ",
+ 'e': " ",
+ }
+
+ started := false
+ m := NewMatcher(diff.A, diff.B)
+ for _, g := range m.GetGroupedOpCodes(diff.Context) {
+ if !started {
+ started = true
+ fromDate := ""
+ if len(diff.FromDate) > 0 {
+ fromDate = "\t" + diff.FromDate
+ }
+ toDate := ""
+ if len(diff.ToDate) > 0 {
+ toDate = "\t" + diff.ToDate
+ }
+ if diff.FromFile != "" || diff.ToFile != "" {
+ wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
+ wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
+ }
+ }
+
+ first, last := g[0], g[len(g)-1]
+ ws("***************" + diff.Eol)
+
+ range1 := formatRangeContext(first.I1, last.I2)
+ wf("*** %s ****%s", range1, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'd' {
+ for _, cc := range g {
+ if cc.Tag == 'i' {
+ continue
+ }
+ for _, line := range diff.A[cc.I1:cc.I2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+
+ range2 := formatRangeContext(first.J1, last.J2)
+ wf("--- %s ----%s", range2, diff.Eol)
+ for _, c := range g {
+ if c.Tag == 'r' || c.Tag == 'i' {
+ for _, cc := range g {
+ if cc.Tag == 'd' {
+ continue
+ }
+ for _, line := range diff.B[cc.J1:cc.J2] {
+ ws(prefix[cc.Tag] + line)
+ }
+ }
+ break
+ }
+ }
+ }
+ return diffErr
+}
+
+// Like WriteContextDiff but returns the diff a string.
+func GetContextDiffString(diff ContextDiff) (string, error) {
+ w := &bytes.Buffer{}
+ err := WriteContextDiff(w, diff)
+ return string(w.Bytes()), err
+}
+
+// Split a string on "\n" while preserving them. The output can be used
+// as input for UnifiedDiff and ContextDiff structures.
+func SplitLines(s string) []string {
+ lines := strings.SplitAfter(s, "\n")
+ lines[len(lines)-1] += "\n"
+ return lines
+}
diff --git a/vendor/github.com/prometheus/common/config/config.go b/vendor/github.com/prometheus/common/config/config.go
deleted file mode 100644
index 0b91f20d55..0000000000
--- a/vendor/github.com/prometheus/common/config/config.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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.
-
-// This package no longer handles safe yaml parsing. In order to
-// ensure correct yaml unmarshalling, use "yaml.UnmarshalStrict()".
-
-package config
-
-import (
- "encoding/json"
- "net/http"
- "path/filepath"
-)
-
-const secretToken = ""
-
-// Secret special type for storing secrets.
-type Secret string
-
-// MarshalYAML implements the yaml.Marshaler interface for Secrets.
-func (s Secret) MarshalYAML() (interface{}, error) {
- if s != "" {
- return secretToken, nil
- }
- return nil, nil
-}
-
-// UnmarshalYAML implements the yaml.Unmarshaler interface for Secrets.
-func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
- type plain Secret
- return unmarshal((*plain)(s))
-}
-
-// MarshalJSON implements the json.Marshaler interface for Secret.
-func (s Secret) MarshalJSON() ([]byte, error) {
- if len(s) == 0 {
- return json.Marshal("")
- }
- return json.Marshal(secretToken)
-}
-
-type Header map[string][]Secret
-
-func (h *Header) HTTPHeader() http.Header {
- if h == nil || *h == nil {
- return nil
- }
-
- header := make(http.Header)
-
- for name, values := range *h {
- var s []string
- if values != nil {
- s = make([]string, 0, len(values))
- for _, value := range values {
- s = append(s, string(value))
- }
- }
- header[name] = s
- }
-
- return header
-}
-
-// DirectorySetter is a config type that contains file paths that may
-// be relative to the file containing the config.
-type DirectorySetter interface {
- // SetDirectory joins any relative file paths with dir.
- // Any paths that are empty or absolute remain unchanged.
- SetDirectory(dir string)
-}
-
-// JoinDir joins dir and path if path is relative.
-// If path is empty or absolute, it is returned unchanged.
-func JoinDir(dir, path string) string {
- if path == "" || filepath.IsAbs(path) {
- return path
- }
- return filepath.Join(dir, path)
-}
diff --git a/vendor/github.com/prometheus/common/config/http_config.go b/vendor/github.com/prometheus/common/config/http_config.go
deleted file mode 100644
index 4763549b8f..0000000000
--- a/vendor/github.com/prometheus/common/config/http_config.go
+++ /dev/null
@@ -1,1269 +0,0 @@
-// 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 config
-
-import (
- "bytes"
- "context"
- "crypto/sha256"
- "crypto/tls"
- "crypto/x509"
- "encoding/json"
- "fmt"
- "net"
- "net/http"
- "net/url"
- "os"
- "path/filepath"
- "strings"
- "sync"
- "time"
-
- "github.com/mwitkow/go-conntrack"
- "golang.org/x/net/http/httpproxy"
- "golang.org/x/net/http2"
- "golang.org/x/oauth2"
- "golang.org/x/oauth2/clientcredentials"
- "gopkg.in/yaml.v2"
-)
-
-var (
- // DefaultHTTPClientConfig is the default HTTP client configuration.
- DefaultHTTPClientConfig = HTTPClientConfig{
- FollowRedirects: true,
- EnableHTTP2: true,
- }
-
- // defaultHTTPClientOptions holds the default HTTP client options.
- defaultHTTPClientOptions = httpClientOptions{
- keepAlivesEnabled: true,
- http2Enabled: true,
- // 5 minutes is typically above the maximum sane scrape interval. So we can
- // use keepalive for all configurations.
- idleConnTimeout: 5 * time.Minute,
- }
-)
-
-type closeIdler interface {
- CloseIdleConnections()
-}
-
-type TLSVersion uint16
-
-var TLSVersions = map[string]TLSVersion{
- "TLS13": (TLSVersion)(tls.VersionTLS13),
- "TLS12": (TLSVersion)(tls.VersionTLS12),
- "TLS11": (TLSVersion)(tls.VersionTLS11),
- "TLS10": (TLSVersion)(tls.VersionTLS10),
-}
-
-func (tv *TLSVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
- var s string
- err := unmarshal((*string)(&s))
- if err != nil {
- return err
- }
- if v, ok := TLSVersions[s]; ok {
- *tv = v
- return nil
- }
- return fmt.Errorf("unknown TLS version: %s", s)
-}
-
-func (tv TLSVersion) MarshalYAML() (interface{}, error) {
- for s, v := range TLSVersions {
- if tv == v {
- return s, nil
- }
- }
- return nil, fmt.Errorf("unknown TLS version: %d", tv)
-}
-
-// MarshalJSON implements the json.Unmarshaler interface for TLSVersion.
-func (tv *TLSVersion) UnmarshalJSON(data []byte) error {
- var s string
- if err := json.Unmarshal(data, &s); err != nil {
- return err
- }
- if v, ok := TLSVersions[s]; ok {
- *tv = v
- return nil
- }
- return fmt.Errorf("unknown TLS version: %s", s)
-}
-
-// MarshalJSON implements the json.Marshaler interface for TLSVersion.
-func (tv TLSVersion) MarshalJSON() ([]byte, error) {
- for s, v := range TLSVersions {
- if tv == v {
- return json.Marshal(s)
- }
- }
- return nil, fmt.Errorf("unknown TLS version: %d", tv)
-}
-
-// String implements the fmt.Stringer interface for TLSVersion.
-func (tv *TLSVersion) String() string {
- if tv == nil || *tv == 0 {
- return ""
- }
- for s, v := range TLSVersions {
- if *tv == v {
- return s
- }
- }
- return fmt.Sprintf("%d", tv)
-}
-
-// BasicAuth contains basic HTTP authentication credentials.
-type BasicAuth struct {
- Username string `yaml:"username" json:"username"`
- UsernameFile string `yaml:"username_file,omitempty" json:"username_file,omitempty"`
- Password Secret `yaml:"password,omitempty" json:"password,omitempty"`
- PasswordFile string `yaml:"password_file,omitempty" json:"password_file,omitempty"`
-}
-
-// SetDirectory joins any relative file paths with dir.
-func (a *BasicAuth) SetDirectory(dir string) {
- if a == nil {
- return
- }
- a.PasswordFile = JoinDir(dir, a.PasswordFile)
- a.UsernameFile = JoinDir(dir, a.UsernameFile)
-}
-
-// Authorization contains HTTP authorization credentials.
-type Authorization struct {
- Type string `yaml:"type,omitempty" json:"type,omitempty"`
- Credentials Secret `yaml:"credentials,omitempty" json:"credentials,omitempty"`
- CredentialsFile string `yaml:"credentials_file,omitempty" json:"credentials_file,omitempty"`
-}
-
-// SetDirectory joins any relative file paths with dir.
-func (a *Authorization) SetDirectory(dir string) {
- if a == nil {
- return
- }
- a.CredentialsFile = JoinDir(dir, a.CredentialsFile)
-}
-
-// URL is a custom URL type that allows validation at configuration load time.
-type URL struct {
- *url.URL
-}
-
-// UnmarshalYAML implements the yaml.Unmarshaler interface for URLs.
-func (u *URL) UnmarshalYAML(unmarshal func(interface{}) error) error {
- var s string
- if err := unmarshal(&s); err != nil {
- return err
- }
-
- urlp, err := url.Parse(s)
- if err != nil {
- return err
- }
- u.URL = urlp
- return nil
-}
-
-// MarshalYAML implements the yaml.Marshaler interface for URLs.
-func (u URL) MarshalYAML() (interface{}, error) {
- if u.URL != nil {
- return u.Redacted(), nil
- }
- return nil, nil
-}
-
-// Redacted returns the URL but replaces any password with "xxxxx".
-func (u URL) Redacted() string {
- if u.URL == nil {
- return ""
- }
-
- ru := *u.URL
- if _, ok := ru.User.Password(); ok {
- // We can not use secretToken because it would be escaped.
- ru.User = url.UserPassword(ru.User.Username(), "xxxxx")
- }
- return ru.String()
-}
-
-// UnmarshalJSON implements the json.Marshaler interface for URL.
-func (u *URL) UnmarshalJSON(data []byte) error {
- var s string
- if err := json.Unmarshal(data, &s); err != nil {
- return err
- }
- urlp, err := url.Parse(s)
- if err != nil {
- return err
- }
- u.URL = urlp
- return nil
-}
-
-// MarshalJSON implements the json.Marshaler interface for URL.
-func (u URL) MarshalJSON() ([]byte, error) {
- if u.URL != nil {
- return json.Marshal(u.URL.String())
- }
- return []byte("null"), nil
-}
-
-// OAuth2 is the oauth2 client configuration.
-type OAuth2 struct {
- ClientID string `yaml:"client_id" json:"client_id"`
- ClientSecret Secret `yaml:"client_secret" json:"client_secret"`
- ClientSecretFile string `yaml:"client_secret_file" json:"client_secret_file"`
- Scopes []string `yaml:"scopes,omitempty" json:"scopes,omitempty"`
- TokenURL string `yaml:"token_url" json:"token_url"`
- EndpointParams map[string]string `yaml:"endpoint_params,omitempty" json:"endpoint_params,omitempty"`
- TLSConfig TLSConfig `yaml:"tls_config,omitempty"`
- ProxyConfig `yaml:",inline"`
-}
-
-// UnmarshalYAML implements the yaml.Unmarshaler interface
-func (o *OAuth2) UnmarshalYAML(unmarshal func(interface{}) error) error {
- type plain OAuth2
- if err := unmarshal((*plain)(o)); err != nil {
- return err
- }
- return o.ProxyConfig.Validate()
-}
-
-// UnmarshalJSON implements the json.Marshaler interface for URL.
-func (o *OAuth2) UnmarshalJSON(data []byte) error {
- type plain OAuth2
- if err := json.Unmarshal(data, (*plain)(o)); err != nil {
- return err
- }
- return o.ProxyConfig.Validate()
-}
-
-// SetDirectory joins any relative file paths with dir.
-func (a *OAuth2) SetDirectory(dir string) {
- if a == nil {
- return
- }
- a.ClientSecretFile = JoinDir(dir, a.ClientSecretFile)
- a.TLSConfig.SetDirectory(dir)
-}
-
-// LoadHTTPConfig parses the YAML input s into a HTTPClientConfig.
-func LoadHTTPConfig(s string) (*HTTPClientConfig, error) {
- cfg := &HTTPClientConfig{}
- err := yaml.UnmarshalStrict([]byte(s), cfg)
- if err != nil {
- return nil, err
- }
- return cfg, nil
-}
-
-// LoadHTTPConfigFile parses the given YAML file into a HTTPClientConfig.
-func LoadHTTPConfigFile(filename string) (*HTTPClientConfig, []byte, error) {
- content, err := os.ReadFile(filename)
- if err != nil {
- return nil, nil, err
- }
- cfg, err := LoadHTTPConfig(string(content))
- if err != nil {
- return nil, nil, err
- }
- cfg.SetDirectory(filepath.Dir(filepath.Dir(filename)))
- return cfg, content, nil
-}
-
-// HTTPClientConfig configures an HTTP client.
-type HTTPClientConfig struct {
- // The HTTP basic authentication credentials for the targets.
- BasicAuth *BasicAuth `yaml:"basic_auth,omitempty" json:"basic_auth,omitempty"`
- // The HTTP authorization credentials for the targets.
- Authorization *Authorization `yaml:"authorization,omitempty" json:"authorization,omitempty"`
- // The OAuth2 client credentials used to fetch a token for the targets.
- OAuth2 *OAuth2 `yaml:"oauth2,omitempty" json:"oauth2,omitempty"`
- // The bearer token for the targets. Deprecated in favour of
- // Authorization.Credentials.
- BearerToken Secret `yaml:"bearer_token,omitempty" json:"bearer_token,omitempty"`
- // The bearer token file for the targets. Deprecated in favour of
- // Authorization.CredentialsFile.
- BearerTokenFile string `yaml:"bearer_token_file,omitempty" json:"bearer_token_file,omitempty"`
- // TLSConfig to use to connect to the targets.
- TLSConfig TLSConfig `yaml:"tls_config,omitempty" json:"tls_config,omitempty"`
- // FollowRedirects specifies whether the client should follow HTTP 3xx redirects.
- // The omitempty flag is not set, because it would be hidden from the
- // marshalled configuration when set to false.
- FollowRedirects bool `yaml:"follow_redirects" json:"follow_redirects"`
- // EnableHTTP2 specifies whether the client should configure HTTP2.
- // The omitempty flag is not set, because it would be hidden from the
- // marshalled configuration when set to false.
- EnableHTTP2 bool `yaml:"enable_http2" json:"enable_http2"`
- // Proxy configuration.
- ProxyConfig `yaml:",inline"`
-}
-
-// SetDirectory joins any relative file paths with dir.
-func (c *HTTPClientConfig) SetDirectory(dir string) {
- if c == nil {
- return
- }
- c.TLSConfig.SetDirectory(dir)
- c.BasicAuth.SetDirectory(dir)
- c.Authorization.SetDirectory(dir)
- c.OAuth2.SetDirectory(dir)
- c.BearerTokenFile = JoinDir(dir, c.BearerTokenFile)
-}
-
-// Validate validates the HTTPClientConfig to check only one of BearerToken,
-// BasicAuth and BearerTokenFile is configured. It also validates that ProxyURL
-// is set if ProxyConnectHeader is set.
-func (c *HTTPClientConfig) Validate() error {
- // Backwards compatibility with the bearer_token field.
- if len(c.BearerToken) > 0 && len(c.BearerTokenFile) > 0 {
- return fmt.Errorf("at most one of bearer_token & bearer_token_file must be configured")
- }
- if (c.BasicAuth != nil || c.OAuth2 != nil) && (len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0) {
- return fmt.Errorf("at most one of basic_auth, oauth2, bearer_token & bearer_token_file must be configured")
- }
- if c.BasicAuth != nil && (string(c.BasicAuth.Username) != "" && c.BasicAuth.UsernameFile != "") {
- return fmt.Errorf("at most one of basic_auth username & username_file must be configured")
- }
- if c.BasicAuth != nil && (string(c.BasicAuth.Password) != "" && c.BasicAuth.PasswordFile != "") {
- return fmt.Errorf("at most one of basic_auth password & password_file must be configured")
- }
- if c.Authorization != nil {
- if len(c.BearerToken) > 0 || len(c.BearerTokenFile) > 0 {
- return fmt.Errorf("authorization is not compatible with bearer_token & bearer_token_file")
- }
- if string(c.Authorization.Credentials) != "" && c.Authorization.CredentialsFile != "" {
- return fmt.Errorf("at most one of authorization credentials & credentials_file must be configured")
- }
- c.Authorization.Type = strings.TrimSpace(c.Authorization.Type)
- if len(c.Authorization.Type) == 0 {
- c.Authorization.Type = "Bearer"
- }
- if strings.ToLower(c.Authorization.Type) == "basic" {
- return fmt.Errorf(`authorization type cannot be set to "basic", use "basic_auth" instead`)
- }
- if c.BasicAuth != nil || c.OAuth2 != nil {
- return fmt.Errorf("at most one of basic_auth, oauth2 & authorization must be configured")
- }
- } else {
- if len(c.BearerToken) > 0 {
- c.Authorization = &Authorization{Credentials: c.BearerToken}
- c.Authorization.Type = "Bearer"
- c.BearerToken = ""
- }
- if len(c.BearerTokenFile) > 0 {
- c.Authorization = &Authorization{CredentialsFile: c.BearerTokenFile}
- c.Authorization.Type = "Bearer"
- c.BearerTokenFile = ""
- }
- }
- if c.OAuth2 != nil {
- if c.BasicAuth != nil {
- return fmt.Errorf("at most one of basic_auth, oauth2 & authorization must be configured")
- }
- if len(c.OAuth2.ClientID) == 0 {
- return fmt.Errorf("oauth2 client_id must be configured")
- }
- if len(c.OAuth2.ClientSecret) == 0 && len(c.OAuth2.ClientSecretFile) == 0 {
- return fmt.Errorf("either oauth2 client_secret or client_secret_file must be configured")
- }
- if len(c.OAuth2.TokenURL) == 0 {
- return fmt.Errorf("oauth2 token_url must be configured")
- }
- if len(c.OAuth2.ClientSecret) > 0 && len(c.OAuth2.ClientSecretFile) > 0 {
- return fmt.Errorf("at most one of oauth2 client_secret & client_secret_file must be configured")
- }
- }
- if err := c.ProxyConfig.Validate(); err != nil {
- return err
- }
- return nil
-}
-
-// UnmarshalYAML implements the yaml.Unmarshaler interface
-func (c *HTTPClientConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
- type plain HTTPClientConfig
- *c = DefaultHTTPClientConfig
- if err := unmarshal((*plain)(c)); err != nil {
- return err
- }
- return c.Validate()
-}
-
-// UnmarshalJSON implements the json.Marshaler interface for URL.
-func (c *HTTPClientConfig) UnmarshalJSON(data []byte) error {
- type plain HTTPClientConfig
- *c = DefaultHTTPClientConfig
- if err := json.Unmarshal(data, (*plain)(c)); err != nil {
- return err
- }
- return c.Validate()
-}
-
-// UnmarshalYAML implements the yaml.Unmarshaler interface.
-func (a *BasicAuth) UnmarshalYAML(unmarshal func(interface{}) error) error {
- type plain BasicAuth
- return unmarshal((*plain)(a))
-}
-
-// DialContextFunc defines the signature of the DialContext() function implemented
-// by net.Dialer.
-type DialContextFunc func(context.Context, string, string) (net.Conn, error)
-
-type httpClientOptions struct {
- dialContextFunc DialContextFunc
- keepAlivesEnabled bool
- http2Enabled bool
- idleConnTimeout time.Duration
- userAgent string
-}
-
-// HTTPClientOption defines an option that can be applied to the HTTP client.
-type HTTPClientOption func(options *httpClientOptions)
-
-// WithDialContextFunc allows you to override func gets used for the actual dialing. The default is `net.Dialer.DialContext`.
-func WithDialContextFunc(fn DialContextFunc) HTTPClientOption {
- return func(opts *httpClientOptions) {
- opts.dialContextFunc = fn
- }
-}
-
-// WithKeepAlivesDisabled allows to disable HTTP keepalive.
-func WithKeepAlivesDisabled() HTTPClientOption {
- return func(opts *httpClientOptions) {
- opts.keepAlivesEnabled = false
- }
-}
-
-// WithHTTP2Disabled allows to disable HTTP2.
-func WithHTTP2Disabled() HTTPClientOption {
- return func(opts *httpClientOptions) {
- opts.http2Enabled = false
- }
-}
-
-// WithIdleConnTimeout allows setting the idle connection timeout.
-func WithIdleConnTimeout(timeout time.Duration) HTTPClientOption {
- return func(opts *httpClientOptions) {
- opts.idleConnTimeout = timeout
- }
-}
-
-// WithUserAgent allows setting the user agent.
-func WithUserAgent(ua string) HTTPClientOption {
- return func(opts *httpClientOptions) {
- opts.userAgent = ua
- }
-}
-
-// NewClient returns a http.Client using the specified http.RoundTripper.
-func newClient(rt http.RoundTripper) *http.Client {
- return &http.Client{Transport: rt}
-}
-
-// NewClientFromConfig returns a new HTTP client configured for the
-// given config.HTTPClientConfig and config.HTTPClientOption.
-// The name is used as go-conntrack metric label.
-func NewClientFromConfig(cfg HTTPClientConfig, name string, optFuncs ...HTTPClientOption) (*http.Client, error) {
- rt, err := NewRoundTripperFromConfig(cfg, name, optFuncs...)
- if err != nil {
- return nil, err
- }
- client := newClient(rt)
- if !cfg.FollowRedirects {
- client.CheckRedirect = func(*http.Request, []*http.Request) error {
- return http.ErrUseLastResponse
- }
- }
- return client, nil
-}
-
-// NewRoundTripperFromConfig returns a new HTTP RoundTripper configured for the
-// given config.HTTPClientConfig and config.HTTPClientOption.
-// The name is used as go-conntrack metric label.
-func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, optFuncs ...HTTPClientOption) (http.RoundTripper, error) {
- opts := defaultHTTPClientOptions
- for _, f := range optFuncs {
- f(&opts)
- }
-
- var dialContext func(ctx context.Context, network, addr string) (net.Conn, error)
-
- if opts.dialContextFunc != nil {
- dialContext = conntrack.NewDialContextFunc(
- conntrack.DialWithDialContextFunc((func(context.Context, string, string) (net.Conn, error))(opts.dialContextFunc)),
- conntrack.DialWithTracing(),
- conntrack.DialWithName(name))
- } else {
- dialContext = conntrack.NewDialContextFunc(
- conntrack.DialWithTracing(),
- conntrack.DialWithName(name))
- }
-
- newRT := func(tlsConfig *tls.Config) (http.RoundTripper, error) {
- // The only timeout we care about is the configured scrape timeout.
- // It is applied on request. So we leave out any timings here.
- var rt http.RoundTripper = &http.Transport{
- Proxy: cfg.ProxyConfig.Proxy(),
- ProxyConnectHeader: cfg.ProxyConfig.GetProxyConnectHeader(),
- MaxIdleConns: 20000,
- MaxIdleConnsPerHost: 1000, // see https://github.com/golang/go/issues/13801
- DisableKeepAlives: !opts.keepAlivesEnabled,
- TLSClientConfig: tlsConfig,
- DisableCompression: true,
- IdleConnTimeout: opts.idleConnTimeout,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 1 * time.Second,
- DialContext: dialContext,
- }
- if opts.http2Enabled && cfg.EnableHTTP2 {
- // HTTP/2 support is golang had many problematic cornercases where
- // dead connections would be kept and used in connection pools.
- // https://github.com/golang/go/issues/32388
- // https://github.com/golang/go/issues/39337
- // https://github.com/golang/go/issues/39750
-
- http2t, err := http2.ConfigureTransports(rt.(*http.Transport))
- if err != nil {
- return nil, err
- }
- http2t.ReadIdleTimeout = time.Minute
- }
-
- // If a authorization_credentials is provided, create a round tripper that will set the
- // Authorization header correctly on each request.
- if cfg.Authorization != nil && len(cfg.Authorization.Credentials) > 0 {
- rt = NewAuthorizationCredentialsRoundTripper(cfg.Authorization.Type, cfg.Authorization.Credentials, rt)
- } else if cfg.Authorization != nil && len(cfg.Authorization.CredentialsFile) > 0 {
- rt = NewAuthorizationCredentialsFileRoundTripper(cfg.Authorization.Type, cfg.Authorization.CredentialsFile, rt)
- }
- // Backwards compatibility, be nice with importers who would not have
- // called Validate().
- if len(cfg.BearerToken) > 0 {
- rt = NewAuthorizationCredentialsRoundTripper("Bearer", cfg.BearerToken, rt)
- } else if len(cfg.BearerTokenFile) > 0 {
- rt = NewAuthorizationCredentialsFileRoundTripper("Bearer", cfg.BearerTokenFile, rt)
- }
-
- if cfg.BasicAuth != nil {
- rt = NewBasicAuthRoundTripper(cfg.BasicAuth.Username, cfg.BasicAuth.Password, cfg.BasicAuth.UsernameFile, cfg.BasicAuth.PasswordFile, rt)
- }
-
- if cfg.OAuth2 != nil {
- rt = NewOAuth2RoundTripper(cfg.OAuth2, rt, &opts)
- }
-
- if opts.userAgent != "" {
- rt = NewUserAgentRoundTripper(opts.userAgent, rt)
- }
-
- // Return a new configured RoundTripper.
- return rt, nil
- }
-
- tlsConfig, err := NewTLSConfig(&cfg.TLSConfig)
- if err != nil {
- return nil, err
- }
-
- if len(cfg.TLSConfig.CAFile) == 0 {
- // No need for a RoundTripper that reloads the CA file automatically.
- return newRT(tlsConfig)
- }
- return NewTLSRoundTripper(tlsConfig, cfg.TLSConfig.roundTripperSettings(), newRT)
-}
-
-type authorizationCredentialsRoundTripper struct {
- authType string
- authCredentials Secret
- rt http.RoundTripper
-}
-
-// NewAuthorizationCredentialsRoundTripper adds the provided credentials to a
-// request unless the authorization header has already been set.
-func NewAuthorizationCredentialsRoundTripper(authType string, authCredentials Secret, rt http.RoundTripper) http.RoundTripper {
- return &authorizationCredentialsRoundTripper{authType, authCredentials, rt}
-}
-
-func (rt *authorizationCredentialsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- if len(req.Header.Get("Authorization")) == 0 {
- req = cloneRequest(req)
- req.Header.Set("Authorization", fmt.Sprintf("%s %s", rt.authType, string(rt.authCredentials)))
- }
- return rt.rt.RoundTrip(req)
-}
-
-func (rt *authorizationCredentialsRoundTripper) CloseIdleConnections() {
- if ci, ok := rt.rt.(closeIdler); ok {
- ci.CloseIdleConnections()
- }
-}
-
-type authorizationCredentialsFileRoundTripper struct {
- authType string
- authCredentialsFile string
- rt http.RoundTripper
-}
-
-// NewAuthorizationCredentialsFileRoundTripper adds the authorization
-// credentials read from the provided file to a request unless the authorization
-// header has already been set. This file is read for every request.
-func NewAuthorizationCredentialsFileRoundTripper(authType, authCredentialsFile string, rt http.RoundTripper) http.RoundTripper {
- return &authorizationCredentialsFileRoundTripper{authType, authCredentialsFile, rt}
-}
-
-func (rt *authorizationCredentialsFileRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- if len(req.Header.Get("Authorization")) == 0 {
- b, err := os.ReadFile(rt.authCredentialsFile)
- if err != nil {
- return nil, fmt.Errorf("unable to read authorization credentials file %s: %s", rt.authCredentialsFile, err)
- }
- authCredentials := strings.TrimSpace(string(b))
-
- req = cloneRequest(req)
- req.Header.Set("Authorization", fmt.Sprintf("%s %s", rt.authType, authCredentials))
- }
-
- return rt.rt.RoundTrip(req)
-}
-
-func (rt *authorizationCredentialsFileRoundTripper) CloseIdleConnections() {
- if ci, ok := rt.rt.(closeIdler); ok {
- ci.CloseIdleConnections()
- }
-}
-
-type basicAuthRoundTripper struct {
- username string
- password Secret
- usernameFile string
- passwordFile string
- rt http.RoundTripper
-}
-
-// NewBasicAuthRoundTripper will apply a BASIC auth authorization header to a request unless it has
-// already been set.
-func NewBasicAuthRoundTripper(username string, password Secret, usernameFile, passwordFile string, rt http.RoundTripper) http.RoundTripper {
- return &basicAuthRoundTripper{username, password, usernameFile, passwordFile, rt}
-}
-
-func (rt *basicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- var username string
- var password string
- if len(req.Header.Get("Authorization")) != 0 {
- return rt.rt.RoundTrip(req)
- }
- if rt.usernameFile != "" {
- usernameBytes, err := os.ReadFile(rt.usernameFile)
- if err != nil {
- return nil, fmt.Errorf("unable to read basic auth username file %s: %s", rt.usernameFile, err)
- }
- username = strings.TrimSpace(string(usernameBytes))
- } else {
- username = rt.username
- }
- if rt.passwordFile != "" {
- passwordBytes, err := os.ReadFile(rt.passwordFile)
- if err != nil {
- return nil, fmt.Errorf("unable to read basic auth password file %s: %s", rt.passwordFile, err)
- }
- password = strings.TrimSpace(string(passwordBytes))
- } else {
- password = string(rt.password)
- }
- req = cloneRequest(req)
- req.SetBasicAuth(username, password)
- return rt.rt.RoundTrip(req)
-}
-
-func (rt *basicAuthRoundTripper) CloseIdleConnections() {
- if ci, ok := rt.rt.(closeIdler); ok {
- ci.CloseIdleConnections()
- }
-}
-
-type oauth2RoundTripper struct {
- config *OAuth2
- rt http.RoundTripper
- next http.RoundTripper
- secret string
- mtx sync.RWMutex
- opts *httpClientOptions
- client *http.Client
-}
-
-func NewOAuth2RoundTripper(config *OAuth2, next http.RoundTripper, opts *httpClientOptions) http.RoundTripper {
- return &oauth2RoundTripper{
- config: config,
- next: next,
- opts: opts,
- }
-}
-
-func (rt *oauth2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- var (
- secret string
- changed bool
- )
-
- if rt.config.ClientSecretFile != "" {
- data, err := os.ReadFile(rt.config.ClientSecretFile)
- if err != nil {
- return nil, fmt.Errorf("unable to read oauth2 client secret file %s: %s", rt.config.ClientSecretFile, err)
- }
- secret = strings.TrimSpace(string(data))
- rt.mtx.RLock()
- changed = secret != rt.secret
- rt.mtx.RUnlock()
- }
-
- if changed || rt.rt == nil {
- if rt.config.ClientSecret != "" {
- secret = string(rt.config.ClientSecret)
- }
-
- config := &clientcredentials.Config{
- ClientID: rt.config.ClientID,
- ClientSecret: secret,
- Scopes: rt.config.Scopes,
- TokenURL: rt.config.TokenURL,
- EndpointParams: mapToValues(rt.config.EndpointParams),
- }
-
- tlsConfig, err := NewTLSConfig(&rt.config.TLSConfig)
- if err != nil {
- return nil, err
- }
-
- tlsTransport := func(tlsConfig *tls.Config) (http.RoundTripper, error) {
- return &http.Transport{
- TLSClientConfig: tlsConfig,
- Proxy: rt.config.ProxyConfig.Proxy(),
- ProxyConnectHeader: rt.config.ProxyConfig.GetProxyConnectHeader(),
- DisableKeepAlives: !rt.opts.keepAlivesEnabled,
- MaxIdleConns: 20,
- MaxIdleConnsPerHost: 1, // see https://github.com/golang/go/issues/13801
- IdleConnTimeout: 10 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 1 * time.Second,
- }, nil
- }
-
- var t http.RoundTripper
- if len(rt.config.TLSConfig.CAFile) == 0 {
- t, _ = tlsTransport(tlsConfig)
- } else {
- t, err = NewTLSRoundTripper(tlsConfig, rt.config.TLSConfig.roundTripperSettings(), tlsTransport)
- if err != nil {
- return nil, err
- }
- }
-
- if ua := req.UserAgent(); ua != "" {
- t = NewUserAgentRoundTripper(ua, t)
- }
-
- client := &http.Client{Transport: t}
- ctx := context.WithValue(context.Background(), oauth2.HTTPClient, client)
- tokenSource := config.TokenSource(ctx)
-
- rt.mtx.Lock()
- rt.secret = secret
- rt.rt = &oauth2.Transport{
- Base: rt.next,
- Source: tokenSource,
- }
- if rt.client != nil {
- rt.client.CloseIdleConnections()
- }
- rt.client = client
- rt.mtx.Unlock()
- }
-
- rt.mtx.RLock()
- currentRT := rt.rt
- rt.mtx.RUnlock()
- return currentRT.RoundTrip(req)
-}
-
-func (rt *oauth2RoundTripper) CloseIdleConnections() {
- if rt.client != nil {
- rt.client.CloseIdleConnections()
- }
- if ci, ok := rt.next.(closeIdler); ok {
- ci.CloseIdleConnections()
- }
-}
-
-func mapToValues(m map[string]string) url.Values {
- v := url.Values{}
- for name, value := range m {
- v.Set(name, value)
- }
-
- return v
-}
-
-// cloneRequest returns a clone of the provided *http.Request.
-// The clone is a shallow copy of the struct and its Header map.
-func cloneRequest(r *http.Request) *http.Request {
- // Shallow copy of the struct.
- r2 := new(http.Request)
- *r2 = *r
- // Deep copy of the Header.
- r2.Header = make(http.Header)
- for k, s := range r.Header {
- r2.Header[k] = s
- }
- return r2
-}
-
-// NewTLSConfig creates a new tls.Config from the given TLSConfig.
-func NewTLSConfig(cfg *TLSConfig) (*tls.Config, error) {
- if err := cfg.Validate(); err != nil {
- return nil, err
- }
-
- tlsConfig := &tls.Config{
- InsecureSkipVerify: cfg.InsecureSkipVerify,
- MinVersion: uint16(cfg.MinVersion),
- MaxVersion: uint16(cfg.MaxVersion),
- }
-
- if cfg.MaxVersion != 0 && cfg.MinVersion != 0 {
- if cfg.MaxVersion < cfg.MinVersion {
- return nil, fmt.Errorf("tls_config.max_version must be greater than or equal to tls_config.min_version if both are specified")
- }
- }
-
- // If a CA cert is provided then let's read it in so we can validate the
- // scrape target's certificate properly.
- if len(cfg.CA) > 0 {
- if !updateRootCA(tlsConfig, []byte(cfg.CA)) {
- return nil, fmt.Errorf("unable to use inline CA cert")
- }
- } else if len(cfg.CAFile) > 0 {
- b, err := readCAFile(cfg.CAFile)
- if err != nil {
- return nil, err
- }
- if !updateRootCA(tlsConfig, b) {
- return nil, fmt.Errorf("unable to use specified CA cert %s", cfg.CAFile)
- }
- }
-
- if len(cfg.ServerName) > 0 {
- tlsConfig.ServerName = cfg.ServerName
- }
-
- // If a client cert & key is provided then configure TLS config accordingly.
- if cfg.usingClientCert() && cfg.usingClientKey() {
- // Verify that client cert and key are valid.
- if _, err := cfg.getClientCertificate(nil); err != nil {
- return nil, err
- }
- tlsConfig.GetClientCertificate = cfg.getClientCertificate
- }
-
- return tlsConfig, nil
-}
-
-// TLSConfig configures the options for TLS connections.
-type TLSConfig struct {
- // Text of the CA cert to use for the targets.
- CA string `yaml:"ca,omitempty" json:"ca,omitempty"`
- // Text of the client cert file for the targets.
- Cert string `yaml:"cert,omitempty" json:"cert,omitempty"`
- // Text of the client key file for the targets.
- Key Secret `yaml:"key,omitempty" json:"key,omitempty"`
- // The CA cert to use for the targets.
- CAFile string `yaml:"ca_file,omitempty" json:"ca_file,omitempty"`
- // The client cert file for the targets.
- CertFile string `yaml:"cert_file,omitempty" json:"cert_file,omitempty"`
- // The client key file for the targets.
- KeyFile string `yaml:"key_file,omitempty" json:"key_file,omitempty"`
- // Used to verify the hostname for the targets.
- ServerName string `yaml:"server_name,omitempty" json:"server_name,omitempty"`
- // Disable target certificate validation.
- InsecureSkipVerify bool `yaml:"insecure_skip_verify" json:"insecure_skip_verify"`
- // Minimum TLS version.
- MinVersion TLSVersion `yaml:"min_version,omitempty" json:"min_version,omitempty"`
- // Maximum TLS version.
- MaxVersion TLSVersion `yaml:"max_version,omitempty" json:"max_version,omitempty"`
-}
-
-// SetDirectory joins any relative file paths with dir.
-func (c *TLSConfig) SetDirectory(dir string) {
- if c == nil {
- return
- }
- c.CAFile = JoinDir(dir, c.CAFile)
- c.CertFile = JoinDir(dir, c.CertFile)
- c.KeyFile = JoinDir(dir, c.KeyFile)
-}
-
-// UnmarshalYAML implements the yaml.Unmarshaler interface.
-func (c *TLSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
- type plain TLSConfig
- if err := unmarshal((*plain)(c)); err != nil {
- return err
- }
- return c.Validate()
-}
-
-// Validate validates the TLSConfig to check that only one of the inlined or
-// file-based fields for the TLS CA, client certificate, and client key are
-// used.
-func (c *TLSConfig) Validate() error {
- if len(c.CA) > 0 && len(c.CAFile) > 0 {
- return fmt.Errorf("at most one of ca and ca_file must be configured")
- }
- if len(c.Cert) > 0 && len(c.CertFile) > 0 {
- return fmt.Errorf("at most one of cert and cert_file must be configured")
- }
- if len(c.Key) > 0 && len(c.KeyFile) > 0 {
- return fmt.Errorf("at most one of key and key_file must be configured")
- }
-
- if c.usingClientCert() && !c.usingClientKey() {
- return fmt.Errorf("exactly one of key or key_file must be configured when a client certificate is configured")
- } else if c.usingClientKey() && !c.usingClientCert() {
- return fmt.Errorf("exactly one of cert or cert_file must be configured when a client key is configured")
- }
-
- return nil
-}
-
-func (c *TLSConfig) usingClientCert() bool {
- return len(c.Cert) > 0 || len(c.CertFile) > 0
-}
-
-func (c *TLSConfig) usingClientKey() bool {
- return len(c.Key) > 0 || len(c.KeyFile) > 0
-}
-
-func (c *TLSConfig) roundTripperSettings() TLSRoundTripperSettings {
- return TLSRoundTripperSettings{
- CA: c.CA,
- CAFile: c.CAFile,
- Cert: c.Cert,
- CertFile: c.CertFile,
- Key: string(c.Key),
- KeyFile: c.KeyFile,
- }
-}
-
-// getClientCertificate reads the pair of client cert and key from disk and returns a tls.Certificate.
-func (c *TLSConfig) getClientCertificate(_ *tls.CertificateRequestInfo) (*tls.Certificate, error) {
- var (
- certData, keyData []byte
- err error
- )
-
- if c.CertFile != "" {
- certData, err = os.ReadFile(c.CertFile)
- if err != nil {
- return nil, fmt.Errorf("unable to read specified client cert (%s): %s", c.CertFile, err)
- }
- } else {
- certData = []byte(c.Cert)
- }
-
- if c.KeyFile != "" {
- keyData, err = os.ReadFile(c.KeyFile)
- if err != nil {
- return nil, fmt.Errorf("unable to read specified client key (%s): %s", c.KeyFile, err)
- }
- } else {
- keyData = []byte(c.Key)
- }
-
- cert, err := tls.X509KeyPair(certData, keyData)
- if err != nil {
- return nil, fmt.Errorf("unable to use specified client cert (%s) & key (%s): %s", c.CertFile, c.KeyFile, err)
- }
-
- return &cert, nil
-}
-
-// readCAFile reads the CA cert file from disk.
-func readCAFile(f string) ([]byte, error) {
- data, err := os.ReadFile(f)
- if err != nil {
- return nil, fmt.Errorf("unable to load specified CA cert %s: %s", f, err)
- }
- return data, nil
-}
-
-// updateRootCA parses the given byte slice as a series of PEM encoded certificates and updates tls.Config.RootCAs.
-func updateRootCA(cfg *tls.Config, b []byte) bool {
- caCertPool := x509.NewCertPool()
- if !caCertPool.AppendCertsFromPEM(b) {
- return false
- }
- cfg.RootCAs = caCertPool
- return true
-}
-
-// tlsRoundTripper is a RoundTripper that updates automatically its TLS
-// configuration whenever the content of the CA file changes.
-type tlsRoundTripper struct {
- settings TLSRoundTripperSettings
-
- // newRT returns a new RoundTripper.
- newRT func(*tls.Config) (http.RoundTripper, error)
-
- mtx sync.RWMutex
- rt http.RoundTripper
- hashCAData []byte
- hashCertData []byte
- hashKeyData []byte
- tlsConfig *tls.Config
-}
-
-type TLSRoundTripperSettings struct {
- CA, CAFile string
- Cert, CertFile string
- Key, KeyFile string
-}
-
-func NewTLSRoundTripper(
- cfg *tls.Config,
- settings TLSRoundTripperSettings,
- newRT func(*tls.Config) (http.RoundTripper, error),
-) (http.RoundTripper, error) {
- t := &tlsRoundTripper{
- settings: settings,
- newRT: newRT,
- tlsConfig: cfg,
- }
-
- rt, err := t.newRT(t.tlsConfig)
- if err != nil {
- return nil, err
- }
- t.rt = rt
- _, t.hashCAData, t.hashCertData, t.hashKeyData, err = t.getTLSDataWithHash()
- if err != nil {
- return nil, err
- }
-
- return t, nil
-}
-
-func (t *tlsRoundTripper) getTLSDataWithHash() ([]byte, []byte, []byte, []byte, error) {
- var (
- caBytes, certBytes, keyBytes []byte
-
- err error
- )
-
- if t.settings.CAFile != "" {
- caBytes, err = os.ReadFile(t.settings.CAFile)
- if err != nil {
- return nil, nil, nil, nil, err
- }
- } else if t.settings.CA != "" {
- caBytes = []byte(t.settings.CA)
- }
-
- if t.settings.CertFile != "" {
- certBytes, err = os.ReadFile(t.settings.CertFile)
- if err != nil {
- return nil, nil, nil, nil, err
- }
- } else if t.settings.Cert != "" {
- certBytes = []byte(t.settings.Cert)
- }
-
- if t.settings.KeyFile != "" {
- keyBytes, err = os.ReadFile(t.settings.KeyFile)
- if err != nil {
- return nil, nil, nil, nil, err
- }
- } else if t.settings.Key != "" {
- keyBytes = []byte(t.settings.Key)
- }
-
- var caHash, certHash, keyHash [32]byte
-
- if len(caBytes) > 0 {
- caHash = sha256.Sum256(caBytes)
- }
- if len(certBytes) > 0 {
- certHash = sha256.Sum256(certBytes)
- }
- if len(keyBytes) > 0 {
- keyHash = sha256.Sum256(keyBytes)
- }
-
- return caBytes, caHash[:], certHash[:], keyHash[:], nil
-}
-
-// RoundTrip implements the http.RoundTrip interface.
-func (t *tlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- caData, caHash, certHash, keyHash, err := t.getTLSDataWithHash()
- if err != nil {
- return nil, err
- }
-
- t.mtx.RLock()
- equal := bytes.Equal(caHash[:], t.hashCAData) &&
- bytes.Equal(certHash[:], t.hashCertData) &&
- bytes.Equal(keyHash[:], t.hashKeyData)
- rt := t.rt
- t.mtx.RUnlock()
- if equal {
- // The CA cert hasn't changed, use the existing RoundTripper.
- return rt.RoundTrip(req)
- }
-
- // Create a new RoundTripper.
- // The cert and key files are read separately by the client
- // using GetClientCertificate.
- tlsConfig := t.tlsConfig.Clone()
- if !updateRootCA(tlsConfig, caData) {
- return nil, fmt.Errorf("unable to use specified CA cert %s", t.settings.CAFile)
- }
- rt, err = t.newRT(tlsConfig)
- if err != nil {
- return nil, err
- }
- t.CloseIdleConnections()
-
- t.mtx.Lock()
- t.rt = rt
- t.hashCAData = caHash[:]
- t.hashCertData = certHash[:]
- t.hashKeyData = keyHash[:]
- t.mtx.Unlock()
-
- return rt.RoundTrip(req)
-}
-
-func (t *tlsRoundTripper) CloseIdleConnections() {
- t.mtx.RLock()
- defer t.mtx.RUnlock()
- if ci, ok := t.rt.(closeIdler); ok {
- ci.CloseIdleConnections()
- }
-}
-
-type userAgentRoundTripper struct {
- userAgent string
- rt http.RoundTripper
-}
-
-// NewUserAgentRoundTripper adds the user agent every request header.
-func NewUserAgentRoundTripper(userAgent string, rt http.RoundTripper) http.RoundTripper {
- return &userAgentRoundTripper{userAgent, rt}
-}
-
-func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
- req = cloneRequest(req)
- req.Header.Set("User-Agent", rt.userAgent)
- return rt.rt.RoundTrip(req)
-}
-
-func (rt *userAgentRoundTripper) CloseIdleConnections() {
- if ci, ok := rt.rt.(closeIdler); ok {
- ci.CloseIdleConnections()
- }
-}
-
-func (c HTTPClientConfig) String() string {
- b, err := yaml.Marshal(c)
- if err != nil {
- return fmt.Sprintf("", err)
- }
- return string(b)
-}
-
-type ProxyConfig struct {
- // HTTP proxy server to use to connect to the targets.
- ProxyURL URL `yaml:"proxy_url,omitempty" json:"proxy_url,omitempty"`
- // NoProxy contains addresses that should not use a proxy.
- NoProxy string `yaml:"no_proxy,omitempty" json:"no_proxy,omitempty"`
- // ProxyFromEnvironment makes use of net/http ProxyFromEnvironment function
- // to determine proxies.
- ProxyFromEnvironment bool `yaml:"proxy_from_environment,omitempty" json:"proxy_from_environment,omitempty"`
- // ProxyConnectHeader optionally specifies headers to send to
- // proxies during CONNECT requests. Assume that at least _some_ of
- // these headers are going to contain secrets and use Secret as the
- // value type instead of string.
- ProxyConnectHeader Header `yaml:"proxy_connect_header,omitempty" json:"proxy_connect_header,omitempty"`
-
- proxyFunc func(*http.Request) (*url.URL, error)
-}
-
-// UnmarshalYAML implements the yaml.Unmarshaler interface.
-func (c *ProxyConfig) Validate() error {
- if len(c.ProxyConnectHeader) > 0 && (!c.ProxyFromEnvironment && (c.ProxyURL.URL == nil || c.ProxyURL.String() == "")) {
- return fmt.Errorf("if proxy_connect_header is configured, proxy_url or proxy_from_environment must also be configured")
- }
- if c.ProxyFromEnvironment && c.ProxyURL.URL != nil && c.ProxyURL.String() != "" {
- return fmt.Errorf("if proxy_from_environment is configured, proxy_url must not be configured")
- }
- if c.ProxyFromEnvironment && c.NoProxy != "" {
- return fmt.Errorf("if proxy_from_environment is configured, no_proxy must not be configured")
- }
- if c.ProxyURL.URL == nil && c.NoProxy != "" {
- return fmt.Errorf("if no_proxy is configured, proxy_url must also be configured")
- }
- return nil
-}
-
-// Proxy returns the Proxy URL for a request.
-func (c *ProxyConfig) Proxy() (fn func(*http.Request) (*url.URL, error)) {
- if c == nil {
- return nil
- }
- defer func() {
- fn = c.proxyFunc
- }()
- if c.proxyFunc != nil {
- return
- }
- if c.ProxyFromEnvironment {
- proxyFn := httpproxy.FromEnvironment().ProxyFunc()
- c.proxyFunc = func(req *http.Request) (*url.URL, error) {
- return proxyFn(req.URL)
- }
- return
- }
- if c.ProxyURL.URL != nil && c.ProxyURL.URL.String() != "" {
- if c.NoProxy == "" {
- c.proxyFunc = http.ProxyURL(c.ProxyURL.URL)
- return
- }
- proxy := &httpproxy.Config{
- HTTPProxy: c.ProxyURL.String(),
- HTTPSProxy: c.ProxyURL.String(),
- NoProxy: c.NoProxy,
- }
- proxyFn := proxy.ProxyFunc()
- c.proxyFunc = func(req *http.Request) (*url.URL, error) {
- return proxyFn(req.URL)
- }
- }
- return
-}
-
-// ProxyConnectHeader() return the Proxy Connext Headers.
-func (c *ProxyConfig) GetProxyConnectHeader() http.Header {
- return c.ProxyConnectHeader.HTTPHeader()
-}
diff --git a/vendor/github.com/soheilhy/cmux/.gitignore b/vendor/github.com/soheilhy/cmux/.gitignore
new file mode 100644
index 0000000000..daf913b1b3
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/.gitignore
@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
diff --git a/vendor/github.com/soheilhy/cmux/.travis.yml b/vendor/github.com/soheilhy/cmux/.travis.yml
new file mode 100644
index 0000000000..4d78a519fe
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/.travis.yml
@@ -0,0 +1,29 @@
+language: go
+
+go:
+ - 1.6
+ - 1.7
+ - 1.8
+ - tip
+
+matrix:
+ allow_failures:
+ - go: tip
+
+gobuild_args: -race
+
+before_install:
+ - if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then go get -u github.com/kisielk/errcheck; fi
+ - if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then go get -u golang.org/x/lint/golint; fi
+
+before_script:
+ - '! gofmt -s -l . | read'
+ - echo $TRAVIS_GO_VERSION
+ - if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then golint ./...; fi
+ - if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then errcheck ./...; fi
+ - if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then go tool vet .; fi
+ - if [[ $TRAVIS_GO_VERSION == 1.6* ]]; then go tool vet --shadow .; fi
+
+script:
+ - go test -bench . -v ./...
+ - go test -race -bench . -v ./...
diff --git a/vendor/github.com/soheilhy/cmux/CONTRIBUTORS b/vendor/github.com/soheilhy/cmux/CONTRIBUTORS
new file mode 100644
index 0000000000..49878f228a
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/CONTRIBUTORS
@@ -0,0 +1,12 @@
+# The list of people who have contributed code to the cmux repository.
+#
+# Auto-generated with:
+# git log --oneline --pretty=format:'%an <%aE>' | sort -u
+#
+Andreas Jaekle
+Dmitri Shuralyov
+Ethan Mosbaugh
+Soheil Hassas Yeganeh
+Soheil Hassas Yeganeh
+Tamir Duberstein
+Tamir Duberstein
diff --git a/vendor/gopkg.in/square/go-jose.v2/LICENSE b/vendor/github.com/soheilhy/cmux/LICENSE
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/LICENSE
rename to vendor/github.com/soheilhy/cmux/LICENSE
diff --git a/vendor/github.com/soheilhy/cmux/README.md b/vendor/github.com/soheilhy/cmux/README.md
new file mode 100644
index 0000000000..c4191b70b0
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/README.md
@@ -0,0 +1,83 @@
+# cmux: Connection Mux ![Travis Build Status](https://api.travis-ci.org/soheilhy/args.svg?branch=master "Travis Build Status") [![GoDoc](https://godoc.org/github.com/soheilhy/cmux?status.svg)](http://godoc.org/github.com/soheilhy/cmux)
+
+cmux is a generic Go library to multiplex connections based on
+their payload. Using cmux, you can serve gRPC, SSH, HTTPS, HTTP,
+Go RPC, and pretty much any other protocol on the same TCP listener.
+
+## How-To
+Simply create your main listener, create a cmux for that listener,
+and then match connections:
+```go
+// Create the main listener.
+l, err := net.Listen("tcp", ":23456")
+if err != nil {
+ log.Fatal(err)
+}
+
+// Create a cmux.
+m := cmux.New(l)
+
+// Match connections in order:
+// First grpc, then HTTP, and otherwise Go RPC/TCP.
+grpcL := m.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))
+httpL := m.Match(cmux.HTTP1Fast())
+trpcL := m.Match(cmux.Any()) // Any means anything that is not yet matched.
+
+// Create your protocol servers.
+grpcS := grpc.NewServer()
+grpchello.RegisterGreeterServer(grpcS, &server{})
+
+httpS := &http.Server{
+ Handler: &helloHTTP1Handler{},
+}
+
+trpcS := rpc.NewServer()
+trpcS.Register(&ExampleRPCRcvr{})
+
+// Use the muxed listeners for your servers.
+go grpcS.Serve(grpcL)
+go httpS.Serve(httpL)
+go trpcS.Accept(trpcL)
+
+// Start serving!
+m.Serve()
+```
+
+Take a look at [other examples in the GoDoc](http://godoc.org/github.com/soheilhy/cmux/#pkg-examples).
+
+## Docs
+* [GoDocs](https://godoc.org/github.com/soheilhy/cmux)
+
+## Performance
+There is room for improvment but, since we are only matching
+the very first bytes of a connection, the performance overheads on
+long-lived connections (i.e., RPCs and pipelined HTTP streams)
+is negligible.
+
+*TODO(soheil)*: Add benchmarks.
+
+## Limitations
+* *TLS*: `net/http` uses a type assertion to identify TLS connections; since
+cmux's lookahead-implementing connection wraps the underlying TLS connection,
+this type assertion fails.
+Because of that, you can serve HTTPS using cmux but `http.Request.TLS`
+would not be set in your handlers.
+
+* *Different Protocols on The Same Connection*: `cmux` matches the connection
+when it's accepted. For example, one connection can be either gRPC or REST, but
+not both. That is, we assume that a client connection is either used for gRPC
+or REST.
+
+* *Java gRPC Clients*: Java gRPC client blocks until it receives a SETTINGS
+frame from the server. If you are using the Java client to connect to a cmux'ed
+gRPC server please match with writers:
+```go
+grpcl := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
+```
+
+# Copyright and License
+Copyright 2016 The CMux Authors. All rights reserved.
+
+See [CONTRIBUTORS](https://github.com/soheilhy/cmux/blob/master/CONTRIBUTORS)
+for the CMux Authors. Code is released under
+[the Apache 2 license](https://github.com/soheilhy/cmux/blob/master/LICENSE).
diff --git a/vendor/github.com/soheilhy/cmux/buffer.go b/vendor/github.com/soheilhy/cmux/buffer.go
new file mode 100644
index 0000000000..f8cf30a1e6
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/buffer.go
@@ -0,0 +1,67 @@
+// Copyright 2016 The CMux Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+
+package cmux
+
+import (
+ "bytes"
+ "io"
+)
+
+// bufferedReader is an optimized implementation of io.Reader that behaves like
+// ```
+// io.MultiReader(bytes.NewReader(buffer.Bytes()), io.TeeReader(source, buffer))
+// ```
+// without allocating.
+type bufferedReader struct {
+ source io.Reader
+ buffer bytes.Buffer
+ bufferRead int
+ bufferSize int
+ sniffing bool
+ lastErr error
+}
+
+func (s *bufferedReader) Read(p []byte) (int, error) {
+ if s.bufferSize > s.bufferRead {
+ // If we have already read something from the buffer before, we return the
+ // same data and the last error if any. We need to immediately return,
+ // otherwise we may block for ever, if we try to be smart and call
+ // source.Read() seeking a little bit of more data.
+ bn := copy(p, s.buffer.Bytes()[s.bufferRead:s.bufferSize])
+ s.bufferRead += bn
+ return bn, s.lastErr
+ } else if !s.sniffing && s.buffer.Cap() != 0 {
+ // We don't need the buffer anymore.
+ // Reset it to release the internal slice.
+ s.buffer = bytes.Buffer{}
+ }
+
+ // If there is nothing more to return in the sniffed buffer, read from the
+ // source.
+ sn, sErr := s.source.Read(p)
+ if sn > 0 && s.sniffing {
+ s.lastErr = sErr
+ if wn, wErr := s.buffer.Write(p[:sn]); wErr != nil {
+ return wn, wErr
+ }
+ }
+ return sn, sErr
+}
+
+func (s *bufferedReader) reset(snif bool) {
+ s.sniffing = snif
+ s.bufferRead = 0
+ s.bufferSize = s.buffer.Len()
+}
diff --git a/vendor/github.com/soheilhy/cmux/cmux.go b/vendor/github.com/soheilhy/cmux/cmux.go
new file mode 100644
index 0000000000..5ba921e72d
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/cmux.go
@@ -0,0 +1,307 @@
+// Copyright 2016 The CMux Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+
+package cmux
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "sync"
+ "time"
+)
+
+// Matcher matches a connection based on its content.
+type Matcher func(io.Reader) bool
+
+// MatchWriter is a match that can also write response (say to do handshake).
+type MatchWriter func(io.Writer, io.Reader) bool
+
+// ErrorHandler handles an error and returns whether
+// the mux should continue serving the listener.
+type ErrorHandler func(error) bool
+
+var _ net.Error = ErrNotMatched{}
+
+// ErrNotMatched is returned whenever a connection is not matched by any of
+// the matchers registered in the multiplexer.
+type ErrNotMatched struct {
+ c net.Conn
+}
+
+func (e ErrNotMatched) Error() string {
+ return fmt.Sprintf("mux: connection %v not matched by an matcher",
+ e.c.RemoteAddr())
+}
+
+// Temporary implements the net.Error interface.
+func (e ErrNotMatched) Temporary() bool { return true }
+
+// Timeout implements the net.Error interface.
+func (e ErrNotMatched) Timeout() bool { return false }
+
+type errListenerClosed string
+
+func (e errListenerClosed) Error() string { return string(e) }
+func (e errListenerClosed) Temporary() bool { return false }
+func (e errListenerClosed) Timeout() bool { return false }
+
+// ErrListenerClosed is returned from muxListener.Accept when the underlying
+// listener is closed.
+var ErrListenerClosed = errListenerClosed("mux: listener closed")
+
+// ErrServerClosed is returned from muxListener.Accept when mux server is closed.
+var ErrServerClosed = errors.New("mux: server closed")
+
+// for readability of readTimeout
+var noTimeout time.Duration
+
+// New instantiates a new connection multiplexer.
+func New(l net.Listener) CMux {
+ return &cMux{
+ root: l,
+ bufLen: 1024,
+ errh: func(_ error) bool { return true },
+ donec: make(chan struct{}),
+ readTimeout: noTimeout,
+ }
+}
+
+// CMux is a multiplexer for network connections.
+type CMux interface {
+ // Match returns a net.Listener that sees (i.e., accepts) only
+ // the connections matched by at least one of the matcher.
+ //
+ // The order used to call Match determines the priority of matchers.
+ Match(...Matcher) net.Listener
+ // MatchWithWriters returns a net.Listener that accepts only the
+ // connections that matched by at least of the matcher writers.
+ //
+ // Prefer Matchers over MatchWriters, since the latter can write on the
+ // connection before the actual handler.
+ //
+ // The order used to call Match determines the priority of matchers.
+ MatchWithWriters(...MatchWriter) net.Listener
+ // Serve starts multiplexing the listener. Serve blocks and perhaps
+ // should be invoked concurrently within a go routine.
+ Serve() error
+ // Closes cmux server and stops accepting any connections on listener
+ Close()
+ // HandleError registers an error handler that handles listener errors.
+ HandleError(ErrorHandler)
+ // sets a timeout for the read of matchers
+ SetReadTimeout(time.Duration)
+}
+
+type matchersListener struct {
+ ss []MatchWriter
+ l muxListener
+}
+
+type cMux struct {
+ root net.Listener
+ bufLen int
+ errh ErrorHandler
+ sls []matchersListener
+ readTimeout time.Duration
+ donec chan struct{}
+ mu sync.Mutex
+}
+
+func matchersToMatchWriters(matchers []Matcher) []MatchWriter {
+ mws := make([]MatchWriter, 0, len(matchers))
+ for _, m := range matchers {
+ cm := m
+ mws = append(mws, func(w io.Writer, r io.Reader) bool {
+ return cm(r)
+ })
+ }
+ return mws
+}
+
+func (m *cMux) Match(matchers ...Matcher) net.Listener {
+ mws := matchersToMatchWriters(matchers)
+ return m.MatchWithWriters(mws...)
+}
+
+func (m *cMux) MatchWithWriters(matchers ...MatchWriter) net.Listener {
+ ml := muxListener{
+ Listener: m.root,
+ connc: make(chan net.Conn, m.bufLen),
+ donec: make(chan struct{}),
+ }
+ m.sls = append(m.sls, matchersListener{ss: matchers, l: ml})
+ return ml
+}
+
+func (m *cMux) SetReadTimeout(t time.Duration) {
+ m.readTimeout = t
+}
+
+func (m *cMux) Serve() error {
+ var wg sync.WaitGroup
+
+ defer func() {
+ m.closeDoneChans()
+ wg.Wait()
+
+ for _, sl := range m.sls {
+ close(sl.l.connc)
+ // Drain the connections enqueued for the listener.
+ for c := range sl.l.connc {
+ _ = c.Close()
+ }
+ }
+ }()
+
+ for {
+ c, err := m.root.Accept()
+ if err != nil {
+ if !m.handleErr(err) {
+ return err
+ }
+ continue
+ }
+
+ wg.Add(1)
+ go m.serve(c, m.donec, &wg)
+ }
+}
+
+func (m *cMux) serve(c net.Conn, donec <-chan struct{}, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ muc := newMuxConn(c)
+ if m.readTimeout > noTimeout {
+ _ = c.SetReadDeadline(time.Now().Add(m.readTimeout))
+ }
+ for _, sl := range m.sls {
+ for _, s := range sl.ss {
+ matched := s(muc.Conn, muc.startSniffing())
+ if matched {
+ muc.doneSniffing()
+ if m.readTimeout > noTimeout {
+ _ = c.SetReadDeadline(time.Time{})
+ }
+ select {
+ case sl.l.connc <- muc:
+ case <-donec:
+ _ = c.Close()
+ }
+ return
+ }
+ }
+ }
+
+ _ = c.Close()
+ err := ErrNotMatched{c: c}
+ if !m.handleErr(err) {
+ _ = m.root.Close()
+ }
+}
+
+func (m *cMux) Close() {
+ m.closeDoneChans()
+}
+
+func (m *cMux) closeDoneChans() {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+
+ select {
+ case <-m.donec:
+ // Already closed. Don't close again
+ default:
+ close(m.donec)
+ }
+ for _, sl := range m.sls {
+ select {
+ case <-sl.l.donec:
+ // Already closed. Don't close again
+ default:
+ close(sl.l.donec)
+ }
+ }
+}
+
+func (m *cMux) HandleError(h ErrorHandler) {
+ m.errh = h
+}
+
+func (m *cMux) handleErr(err error) bool {
+ if !m.errh(err) {
+ return false
+ }
+
+ if ne, ok := err.(net.Error); ok {
+ return ne.Temporary()
+ }
+
+ return false
+}
+
+type muxListener struct {
+ net.Listener
+ connc chan net.Conn
+ donec chan struct{}
+}
+
+func (l muxListener) Accept() (net.Conn, error) {
+ select {
+ case c, ok := <-l.connc:
+ if !ok {
+ return nil, ErrListenerClosed
+ }
+ return c, nil
+ case <-l.donec:
+ return nil, ErrServerClosed
+ }
+}
+
+// MuxConn wraps a net.Conn and provides transparent sniffing of connection data.
+type MuxConn struct {
+ net.Conn
+ buf bufferedReader
+}
+
+func newMuxConn(c net.Conn) *MuxConn {
+ return &MuxConn{
+ Conn: c,
+ buf: bufferedReader{source: c},
+ }
+}
+
+// From the io.Reader documentation:
+//
+// When Read encounters an error or end-of-file condition after
+// successfully reading n > 0 bytes, it returns the number of
+// bytes read. It may return the (non-nil) error from the same call
+// or return the error (and n == 0) from a subsequent call.
+// An instance of this general case is that a Reader returning
+// a non-zero number of bytes at the end of the input stream may
+// return either err == EOF or err == nil. The next Read should
+// return 0, EOF.
+func (m *MuxConn) Read(p []byte) (int, error) {
+ return m.buf.Read(p)
+}
+
+func (m *MuxConn) startSniffing() io.Reader {
+ m.buf.reset(true)
+ return &m.buf
+}
+
+func (m *MuxConn) doneSniffing() {
+ m.buf.reset(false)
+}
diff --git a/vendor/github.com/soheilhy/cmux/doc.go b/vendor/github.com/soheilhy/cmux/doc.go
new file mode 100644
index 0000000000..aaa8f31589
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/doc.go
@@ -0,0 +1,18 @@
+// Copyright 2016 The CMux Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+
+// Package cmux is a library to multiplex network connections based on
+// their payload. Using cmux, you can serve different protocols from the
+// same listener.
+package cmux
diff --git a/vendor/github.com/soheilhy/cmux/matchers.go b/vendor/github.com/soheilhy/cmux/matchers.go
new file mode 100644
index 0000000000..878ae98cc3
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/matchers.go
@@ -0,0 +1,267 @@
+// Copyright 2016 The CMux Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+
+package cmux
+
+import (
+ "bufio"
+ "crypto/tls"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strings"
+
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+)
+
+// Any is a Matcher that matches any connection.
+func Any() Matcher {
+ return func(r io.Reader) bool { return true }
+}
+
+// PrefixMatcher returns a matcher that matches a connection if it
+// starts with any of the strings in strs.
+func PrefixMatcher(strs ...string) Matcher {
+ pt := newPatriciaTreeString(strs...)
+ return pt.matchPrefix
+}
+
+func prefixByteMatcher(list ...[]byte) Matcher {
+ pt := newPatriciaTree(list...)
+ return pt.matchPrefix
+}
+
+var defaultHTTPMethods = []string{
+ "OPTIONS",
+ "GET",
+ "HEAD",
+ "POST",
+ "PUT",
+ "DELETE",
+ "TRACE",
+ "CONNECT",
+}
+
+// HTTP1Fast only matches the methods in the HTTP request.
+//
+// This matcher is very optimistic: if it returns true, it does not mean that
+// the request is a valid HTTP response. If you want a correct but slower HTTP1
+// matcher, use HTTP1 instead.
+func HTTP1Fast(extMethods ...string) Matcher {
+ return PrefixMatcher(append(defaultHTTPMethods, extMethods...)...)
+}
+
+// TLS matches HTTPS requests.
+//
+// By default, any TLS handshake packet is matched. An optional whitelist
+// of versions can be passed in to restrict the matcher, for example:
+// TLS(tls.VersionTLS11, tls.VersionTLS12)
+func TLS(versions ...int) Matcher {
+ if len(versions) == 0 {
+ versions = []int{
+ tls.VersionSSL30,
+ tls.VersionTLS10,
+ tls.VersionTLS11,
+ tls.VersionTLS12,
+ }
+ }
+ prefixes := [][]byte{}
+ for _, v := range versions {
+ prefixes = append(prefixes, []byte{22, byte(v >> 8 & 0xff), byte(v & 0xff)})
+ }
+ return prefixByteMatcher(prefixes...)
+}
+
+const maxHTTPRead = 4096
+
+// HTTP1 parses the first line or upto 4096 bytes of the request to see if
+// the conection contains an HTTP request.
+func HTTP1() Matcher {
+ return func(r io.Reader) bool {
+ br := bufio.NewReader(&io.LimitedReader{R: r, N: maxHTTPRead})
+ l, part, err := br.ReadLine()
+ if err != nil || part {
+ return false
+ }
+
+ _, _, proto, ok := parseRequestLine(string(l))
+ if !ok {
+ return false
+ }
+
+ v, _, ok := http.ParseHTTPVersion(proto)
+ return ok && v == 1
+ }
+}
+
+// grabbed from net/http.
+func parseRequestLine(line string) (method, uri, proto string, ok bool) {
+ s1 := strings.Index(line, " ")
+ s2 := strings.Index(line[s1+1:], " ")
+ if s1 < 0 || s2 < 0 {
+ return
+ }
+ s2 += s1 + 1
+ return line[:s1], line[s1+1 : s2], line[s2+1:], true
+}
+
+// HTTP2 parses the frame header of the first frame to detect whether the
+// connection is an HTTP2 connection.
+func HTTP2() Matcher {
+ return hasHTTP2Preface
+}
+
+// HTTP1HeaderField returns a matcher matching the header fields of the first
+// request of an HTTP 1 connection.
+func HTTP1HeaderField(name, value string) Matcher {
+ return func(r io.Reader) bool {
+ return matchHTTP1Field(r, name, func(gotValue string) bool {
+ return gotValue == value
+ })
+ }
+}
+
+// HTTP1HeaderFieldPrefix returns a matcher matching the header fields of the
+// first request of an HTTP 1 connection. If the header with key name has a
+// value prefixed with valuePrefix, this will match.
+func HTTP1HeaderFieldPrefix(name, valuePrefix string) Matcher {
+ return func(r io.Reader) bool {
+ return matchHTTP1Field(r, name, func(gotValue string) bool {
+ return strings.HasPrefix(gotValue, valuePrefix)
+ })
+ }
+}
+
+// HTTP2HeaderField returns a matcher matching the header fields of the first
+// headers frame.
+func HTTP2HeaderField(name, value string) Matcher {
+ return func(r io.Reader) bool {
+ return matchHTTP2Field(ioutil.Discard, r, name, func(gotValue string) bool {
+ return gotValue == value
+ })
+ }
+}
+
+// HTTP2HeaderFieldPrefix returns a matcher matching the header fields of the
+// first headers frame. If the header with key name has a value prefixed with
+// valuePrefix, this will match.
+func HTTP2HeaderFieldPrefix(name, valuePrefix string) Matcher {
+ return func(r io.Reader) bool {
+ return matchHTTP2Field(ioutil.Discard, r, name, func(gotValue string) bool {
+ return strings.HasPrefix(gotValue, valuePrefix)
+ })
+ }
+}
+
+// HTTP2MatchHeaderFieldSendSettings matches the header field and writes the
+// settings to the server. Prefer HTTP2HeaderField over this one, if the client
+// does not block on receiving a SETTING frame.
+func HTTP2MatchHeaderFieldSendSettings(name, value string) MatchWriter {
+ return func(w io.Writer, r io.Reader) bool {
+ return matchHTTP2Field(w, r, name, func(gotValue string) bool {
+ return gotValue == value
+ })
+ }
+}
+
+// HTTP2MatchHeaderFieldPrefixSendSettings matches the header field prefix
+// and writes the settings to the server. Prefer HTTP2HeaderFieldPrefix over
+// this one, if the client does not block on receiving a SETTING frame.
+func HTTP2MatchHeaderFieldPrefixSendSettings(name, valuePrefix string) MatchWriter {
+ return func(w io.Writer, r io.Reader) bool {
+ return matchHTTP2Field(w, r, name, func(gotValue string) bool {
+ return strings.HasPrefix(gotValue, valuePrefix)
+ })
+ }
+}
+
+func hasHTTP2Preface(r io.Reader) bool {
+ var b [len(http2.ClientPreface)]byte
+ last := 0
+
+ for {
+ n, err := r.Read(b[last:])
+ if err != nil {
+ return false
+ }
+
+ last += n
+ eq := string(b[:last]) == http2.ClientPreface[:last]
+ if last == len(http2.ClientPreface) {
+ return eq
+ }
+ if !eq {
+ return false
+ }
+ }
+}
+
+func matchHTTP1Field(r io.Reader, name string, matches func(string) bool) (matched bool) {
+ req, err := http.ReadRequest(bufio.NewReader(r))
+ if err != nil {
+ return false
+ }
+
+ return matches(req.Header.Get(name))
+}
+
+func matchHTTP2Field(w io.Writer, r io.Reader, name string, matches func(string) bool) (matched bool) {
+ if !hasHTTP2Preface(r) {
+ return false
+ }
+
+ done := false
+ framer := http2.NewFramer(w, r)
+ hdec := hpack.NewDecoder(uint32(4<<10), func(hf hpack.HeaderField) {
+ if hf.Name == name {
+ done = true
+ if matches(hf.Value) {
+ matched = true
+ }
+ }
+ })
+ for {
+ f, err := framer.ReadFrame()
+ if err != nil {
+ return false
+ }
+
+ switch f := f.(type) {
+ case *http2.SettingsFrame:
+ // Sender acknoweldged the SETTINGS frame. No need to write
+ // SETTINGS again.
+ if f.IsAck() {
+ break
+ }
+ if err := framer.WriteSettings(); err != nil {
+ return false
+ }
+ case *http2.ContinuationFrame:
+ if _, err := hdec.Write(f.HeaderBlockFragment()); err != nil {
+ return false
+ }
+ done = done || f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0
+ case *http2.HeadersFrame:
+ if _, err := hdec.Write(f.HeaderBlockFragment()); err != nil {
+ return false
+ }
+ done = done || f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0
+ }
+
+ if done {
+ return matched
+ }
+ }
+}
diff --git a/vendor/github.com/soheilhy/cmux/patricia.go b/vendor/github.com/soheilhy/cmux/patricia.go
new file mode 100644
index 0000000000..c3e3d85bde
--- /dev/null
+++ b/vendor/github.com/soheilhy/cmux/patricia.go
@@ -0,0 +1,179 @@
+// Copyright 2016 The CMux Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// permissions and limitations under the License.
+
+package cmux
+
+import (
+ "bytes"
+ "io"
+)
+
+// patriciaTree is a simple patricia tree that handles []byte instead of string
+// and cannot be changed after instantiation.
+type patriciaTree struct {
+ root *ptNode
+ maxDepth int // max depth of the tree.
+}
+
+func newPatriciaTree(bs ...[]byte) *patriciaTree {
+ max := 0
+ for _, b := range bs {
+ if max < len(b) {
+ max = len(b)
+ }
+ }
+ return &patriciaTree{
+ root: newNode(bs),
+ maxDepth: max + 1,
+ }
+}
+
+func newPatriciaTreeString(strs ...string) *patriciaTree {
+ b := make([][]byte, len(strs))
+ for i, s := range strs {
+ b[i] = []byte(s)
+ }
+ return newPatriciaTree(b...)
+}
+
+func (t *patriciaTree) matchPrefix(r io.Reader) bool {
+ buf := make([]byte, t.maxDepth)
+ n, _ := io.ReadFull(r, buf)
+ return t.root.match(buf[:n], true)
+}
+
+func (t *patriciaTree) match(r io.Reader) bool {
+ buf := make([]byte, t.maxDepth)
+ n, _ := io.ReadFull(r, buf)
+ return t.root.match(buf[:n], false)
+}
+
+type ptNode struct {
+ prefix []byte
+ next map[byte]*ptNode
+ terminal bool
+}
+
+func newNode(strs [][]byte) *ptNode {
+ if len(strs) == 0 {
+ return &ptNode{
+ prefix: []byte{},
+ terminal: true,
+ }
+ }
+
+ if len(strs) == 1 {
+ return &ptNode{
+ prefix: strs[0],
+ terminal: true,
+ }
+ }
+
+ p, strs := splitPrefix(strs)
+ n := &ptNode{
+ prefix: p,
+ }
+
+ nexts := make(map[byte][][]byte)
+ for _, s := range strs {
+ if len(s) == 0 {
+ n.terminal = true
+ continue
+ }
+ nexts[s[0]] = append(nexts[s[0]], s[1:])
+ }
+
+ n.next = make(map[byte]*ptNode)
+ for first, rests := range nexts {
+ n.next[first] = newNode(rests)
+ }
+
+ return n
+}
+
+func splitPrefix(bss [][]byte) (prefix []byte, rest [][]byte) {
+ if len(bss) == 0 || len(bss[0]) == 0 {
+ return prefix, bss
+ }
+
+ if len(bss) == 1 {
+ return bss[0], [][]byte{{}}
+ }
+
+ for i := 0; ; i++ {
+ var cur byte
+ eq := true
+ for j, b := range bss {
+ if len(b) <= i {
+ eq = false
+ break
+ }
+
+ if j == 0 {
+ cur = b[i]
+ continue
+ }
+
+ if cur != b[i] {
+ eq = false
+ break
+ }
+ }
+
+ if !eq {
+ break
+ }
+
+ prefix = append(prefix, cur)
+ }
+
+ rest = make([][]byte, 0, len(bss))
+ for _, b := range bss {
+ rest = append(rest, b[len(prefix):])
+ }
+
+ return prefix, rest
+}
+
+func (n *ptNode) match(b []byte, prefix bool) bool {
+ l := len(n.prefix)
+ if l > 0 {
+ if l > len(b) {
+ l = len(b)
+ }
+ if !bytes.Equal(b[:l], n.prefix) {
+ return false
+ }
+ }
+
+ if n.terminal && (prefix || len(n.prefix) == len(b)) {
+ return true
+ }
+
+ if l >= len(b) {
+ return false
+ }
+
+ nextN, ok := n.next[b[l]]
+ if !ok {
+ return false
+ }
+
+ if l == len(b) {
+ b = b[l:l]
+ } else {
+ b = b[l+1:]
+ }
+ return nextN.match(b, prefix)
+}
diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE
new file mode 100644
index 0000000000..4b0421cf9e
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors.
+
+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/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
new file mode 100644
index 0000000000..b774da88d8
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
@@ -0,0 +1,458 @@
+package assert
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "time"
+)
+
+type CompareType int
+
+const (
+ compareLess CompareType = iota - 1
+ compareEqual
+ compareGreater
+)
+
+var (
+ intType = reflect.TypeOf(int(1))
+ int8Type = reflect.TypeOf(int8(1))
+ int16Type = reflect.TypeOf(int16(1))
+ int32Type = reflect.TypeOf(int32(1))
+ int64Type = reflect.TypeOf(int64(1))
+
+ uintType = reflect.TypeOf(uint(1))
+ uint8Type = reflect.TypeOf(uint8(1))
+ uint16Type = reflect.TypeOf(uint16(1))
+ uint32Type = reflect.TypeOf(uint32(1))
+ uint64Type = reflect.TypeOf(uint64(1))
+
+ float32Type = reflect.TypeOf(float32(1))
+ float64Type = reflect.TypeOf(float64(1))
+
+ stringType = reflect.TypeOf("")
+
+ timeType = reflect.TypeOf(time.Time{})
+ bytesType = reflect.TypeOf([]byte{})
+)
+
+func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
+ obj1Value := reflect.ValueOf(obj1)
+ obj2Value := reflect.ValueOf(obj2)
+
+ // throughout this switch we try and avoid calling .Convert() if possible,
+ // as this has a pretty big performance impact
+ switch kind {
+ case reflect.Int:
+ {
+ intobj1, ok := obj1.(int)
+ if !ok {
+ intobj1 = obj1Value.Convert(intType).Interface().(int)
+ }
+ intobj2, ok := obj2.(int)
+ if !ok {
+ intobj2 = obj2Value.Convert(intType).Interface().(int)
+ }
+ if intobj1 > intobj2 {
+ return compareGreater, true
+ }
+ if intobj1 == intobj2 {
+ return compareEqual, true
+ }
+ if intobj1 < intobj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int8:
+ {
+ int8obj1, ok := obj1.(int8)
+ if !ok {
+ int8obj1 = obj1Value.Convert(int8Type).Interface().(int8)
+ }
+ int8obj2, ok := obj2.(int8)
+ if !ok {
+ int8obj2 = obj2Value.Convert(int8Type).Interface().(int8)
+ }
+ if int8obj1 > int8obj2 {
+ return compareGreater, true
+ }
+ if int8obj1 == int8obj2 {
+ return compareEqual, true
+ }
+ if int8obj1 < int8obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int16:
+ {
+ int16obj1, ok := obj1.(int16)
+ if !ok {
+ int16obj1 = obj1Value.Convert(int16Type).Interface().(int16)
+ }
+ int16obj2, ok := obj2.(int16)
+ if !ok {
+ int16obj2 = obj2Value.Convert(int16Type).Interface().(int16)
+ }
+ if int16obj1 > int16obj2 {
+ return compareGreater, true
+ }
+ if int16obj1 == int16obj2 {
+ return compareEqual, true
+ }
+ if int16obj1 < int16obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int32:
+ {
+ int32obj1, ok := obj1.(int32)
+ if !ok {
+ int32obj1 = obj1Value.Convert(int32Type).Interface().(int32)
+ }
+ int32obj2, ok := obj2.(int32)
+ if !ok {
+ int32obj2 = obj2Value.Convert(int32Type).Interface().(int32)
+ }
+ if int32obj1 > int32obj2 {
+ return compareGreater, true
+ }
+ if int32obj1 == int32obj2 {
+ return compareEqual, true
+ }
+ if int32obj1 < int32obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Int64:
+ {
+ int64obj1, ok := obj1.(int64)
+ if !ok {
+ int64obj1 = obj1Value.Convert(int64Type).Interface().(int64)
+ }
+ int64obj2, ok := obj2.(int64)
+ if !ok {
+ int64obj2 = obj2Value.Convert(int64Type).Interface().(int64)
+ }
+ if int64obj1 > int64obj2 {
+ return compareGreater, true
+ }
+ if int64obj1 == int64obj2 {
+ return compareEqual, true
+ }
+ if int64obj1 < int64obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint:
+ {
+ uintobj1, ok := obj1.(uint)
+ if !ok {
+ uintobj1 = obj1Value.Convert(uintType).Interface().(uint)
+ }
+ uintobj2, ok := obj2.(uint)
+ if !ok {
+ uintobj2 = obj2Value.Convert(uintType).Interface().(uint)
+ }
+ if uintobj1 > uintobj2 {
+ return compareGreater, true
+ }
+ if uintobj1 == uintobj2 {
+ return compareEqual, true
+ }
+ if uintobj1 < uintobj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint8:
+ {
+ uint8obj1, ok := obj1.(uint8)
+ if !ok {
+ uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8)
+ }
+ uint8obj2, ok := obj2.(uint8)
+ if !ok {
+ uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8)
+ }
+ if uint8obj1 > uint8obj2 {
+ return compareGreater, true
+ }
+ if uint8obj1 == uint8obj2 {
+ return compareEqual, true
+ }
+ if uint8obj1 < uint8obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint16:
+ {
+ uint16obj1, ok := obj1.(uint16)
+ if !ok {
+ uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16)
+ }
+ uint16obj2, ok := obj2.(uint16)
+ if !ok {
+ uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16)
+ }
+ if uint16obj1 > uint16obj2 {
+ return compareGreater, true
+ }
+ if uint16obj1 == uint16obj2 {
+ return compareEqual, true
+ }
+ if uint16obj1 < uint16obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint32:
+ {
+ uint32obj1, ok := obj1.(uint32)
+ if !ok {
+ uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32)
+ }
+ uint32obj2, ok := obj2.(uint32)
+ if !ok {
+ uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32)
+ }
+ if uint32obj1 > uint32obj2 {
+ return compareGreater, true
+ }
+ if uint32obj1 == uint32obj2 {
+ return compareEqual, true
+ }
+ if uint32obj1 < uint32obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Uint64:
+ {
+ uint64obj1, ok := obj1.(uint64)
+ if !ok {
+ uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64)
+ }
+ uint64obj2, ok := obj2.(uint64)
+ if !ok {
+ uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64)
+ }
+ if uint64obj1 > uint64obj2 {
+ return compareGreater, true
+ }
+ if uint64obj1 == uint64obj2 {
+ return compareEqual, true
+ }
+ if uint64obj1 < uint64obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Float32:
+ {
+ float32obj1, ok := obj1.(float32)
+ if !ok {
+ float32obj1 = obj1Value.Convert(float32Type).Interface().(float32)
+ }
+ float32obj2, ok := obj2.(float32)
+ if !ok {
+ float32obj2 = obj2Value.Convert(float32Type).Interface().(float32)
+ }
+ if float32obj1 > float32obj2 {
+ return compareGreater, true
+ }
+ if float32obj1 == float32obj2 {
+ return compareEqual, true
+ }
+ if float32obj1 < float32obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.Float64:
+ {
+ float64obj1, ok := obj1.(float64)
+ if !ok {
+ float64obj1 = obj1Value.Convert(float64Type).Interface().(float64)
+ }
+ float64obj2, ok := obj2.(float64)
+ if !ok {
+ float64obj2 = obj2Value.Convert(float64Type).Interface().(float64)
+ }
+ if float64obj1 > float64obj2 {
+ return compareGreater, true
+ }
+ if float64obj1 == float64obj2 {
+ return compareEqual, true
+ }
+ if float64obj1 < float64obj2 {
+ return compareLess, true
+ }
+ }
+ case reflect.String:
+ {
+ stringobj1, ok := obj1.(string)
+ if !ok {
+ stringobj1 = obj1Value.Convert(stringType).Interface().(string)
+ }
+ stringobj2, ok := obj2.(string)
+ if !ok {
+ stringobj2 = obj2Value.Convert(stringType).Interface().(string)
+ }
+ if stringobj1 > stringobj2 {
+ return compareGreater, true
+ }
+ if stringobj1 == stringobj2 {
+ return compareEqual, true
+ }
+ if stringobj1 < stringobj2 {
+ return compareLess, true
+ }
+ }
+ // Check for known struct types we can check for compare results.
+ case reflect.Struct:
+ {
+ // All structs enter here. We're not interested in most types.
+ if !canConvert(obj1Value, timeType) {
+ break
+ }
+
+ // time.Time can compared!
+ timeObj1, ok := obj1.(time.Time)
+ if !ok {
+ timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
+ }
+
+ timeObj2, ok := obj2.(time.Time)
+ if !ok {
+ timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
+ }
+
+ return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
+ }
+ case reflect.Slice:
+ {
+ // We only care about the []byte type.
+ if !canConvert(obj1Value, bytesType) {
+ break
+ }
+
+ // []byte can be compared!
+ bytesObj1, ok := obj1.([]byte)
+ if !ok {
+ bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
+
+ }
+ bytesObj2, ok := obj2.([]byte)
+ if !ok {
+ bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
+ }
+
+ return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
+ }
+ }
+
+ return compareEqual, false
+}
+
+// Greater asserts that the first element is greater than the second
+//
+// assert.Greater(t, 2, 1)
+// assert.Greater(t, float64(2), float64(1))
+// assert.Greater(t, "b", "a")
+func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
+}
+
+// GreaterOrEqual asserts that the first element is greater than or equal to the second
+//
+// assert.GreaterOrEqual(t, 2, 1)
+// assert.GreaterOrEqual(t, 2, 2)
+// assert.GreaterOrEqual(t, "b", "a")
+// assert.GreaterOrEqual(t, "b", "b")
+func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
+}
+
+// Less asserts that the first element is less than the second
+//
+// assert.Less(t, 1, 2)
+// assert.Less(t, float64(1), float64(2))
+// assert.Less(t, "a", "b")
+func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
+}
+
+// LessOrEqual asserts that the first element is less than or equal to the second
+//
+// assert.LessOrEqual(t, 1, 2)
+// assert.LessOrEqual(t, 2, 2)
+// assert.LessOrEqual(t, "a", "b")
+// assert.LessOrEqual(t, "b", "b")
+func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
+}
+
+// Positive asserts that the specified element is positive
+//
+// assert.Positive(t, 1)
+// assert.Positive(t, 1.23)
+func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ zero := reflect.Zero(reflect.TypeOf(e))
+ return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
+}
+
+// Negative asserts that the specified element is negative
+//
+// assert.Negative(t, -1)
+// assert.Negative(t, -1.23)
+func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ zero := reflect.Zero(reflect.TypeOf(e))
+ return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
+}
+
+func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ e1Kind := reflect.ValueOf(e1).Kind()
+ e2Kind := reflect.ValueOf(e2).Kind()
+ if e1Kind != e2Kind {
+ return Fail(t, "Elements should be the same type", msgAndArgs...)
+ }
+
+ compareResult, isComparable := compare(e1, e2, e1Kind)
+ if !isComparable {
+ return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
+ }
+
+ if !containsValue(allowedComparesResults, compareResult) {
+ return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
+ }
+
+ return true
+}
+
+func containsValue(values []CompareType, value CompareType) bool {
+ for _, v := range values {
+ if v == value {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
new file mode 100644
index 0000000000..da867903e2
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
@@ -0,0 +1,16 @@
+//go:build go1.17
+// +build go1.17
+
+// TODO: once support for Go 1.16 is dropped, this file can be
+// merged/removed with assertion_compare_go1.17_test.go and
+// assertion_compare_legacy.go
+
+package assert
+
+import "reflect"
+
+// Wrapper around reflect.Value.CanConvert, for compatibility
+// reasons.
+func canConvert(value reflect.Value, to reflect.Type) bool {
+ return value.CanConvert(to)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
new file mode 100644
index 0000000000..1701af2a3c
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
@@ -0,0 +1,16 @@
+//go:build !go1.17
+// +build !go1.17
+
+// TODO: once support for Go 1.16 is dropped, this file can be
+// merged/removed with assertion_compare_go1.17_test.go and
+// assertion_compare_can_convert.go
+
+package assert
+
+import "reflect"
+
+// Older versions of Go does not have the reflect.Value.CanConvert
+// method.
+func canConvert(value reflect.Value, to reflect.Type) bool {
+ return false
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
new file mode 100644
index 0000000000..84dbd6c790
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -0,0 +1,805 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Conditionf uses a Comparison to assert a complex condition.
+func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Condition(t, comp, append([]interface{}{msg}, args...)...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
+// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
+// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
+func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Emptyf(t, obj, "error message %s", "formatted")
+func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Empty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// assert.Equalf(t, 123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
+func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
+}
+
+// EqualExportedValuesf asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
+// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
+func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
+func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Errorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Error(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
+func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// Eventuallyf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
+}
+
+// EventuallyWithTf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
+func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Failf reports a failure through
+func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// FailNowf fails test
+func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// assert.Falsef(t, myBool, "error message %s", "formatted")
+func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return False(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// Greaterf asserts that the first element is greater than the second
+//
+// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
+// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
+// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
+func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Greater(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// GreaterOrEqualf asserts that the first element is greater than or equal to the second
+//
+// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
+func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
+func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
+// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsDecreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
+// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsIncreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
+// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
+// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
+func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Len(t, object, length, append([]interface{}{msg}, args...)...)
+}
+
+// Lessf asserts that the first element is less than the second
+//
+// assert.Lessf(t, 1, 2, "error message %s", "formatted")
+// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
+// assert.Lessf(t, "a", "b", "error message %s", "formatted")
+func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Less(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// LessOrEqualf asserts that the first element is less than or equal to the second
+//
+// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
+// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
+// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
+// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
+func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
+}
+
+// Negativef asserts that the specified element is negative
+//
+// assert.Negativef(t, -1, "error message %s", "formatted")
+// assert.Negativef(t, -1.23, "error message %s", "formatted")
+func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Negative(t, e, append([]interface{}{msg}, args...)...)
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// assert.Nilf(t, err, "error message %s", "formatted")
+func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoErrorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoError(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
+func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
+//
+// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
+func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// assert.NotNilf(t, err, "error message %s", "formatted")
+func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
+func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
+// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
+func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZero(t, i, append([]interface{}{msg}, args...)...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
+func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
+}
+
+// Positivef asserts that the specified element is positive
+//
+// assert.Positivef(t, 1, "error message %s", "formatted")
+// assert.Positivef(t, 1.23, "error message %s", "formatted")
+func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Positive(t, e, append([]interface{}{msg}, args...)...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
+// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
+func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// Samef asserts that two pointers reference the same object.
+//
+// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// assert.Truef(t, myBool, "error message %s", "formatted")
+func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return True(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// WithinRangef asserts that a time is within a time range (inclusive).
+//
+// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
+func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...)
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zero(t, i, append([]interface{}{msg}, args...)...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
new file mode 100644
index 0000000000..d2bb0b8177
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
@@ -0,0 +1,5 @@
+{{.CommentFormat}}
+func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
+ if h, ok := t.(tHelper); ok { h.Helper() }
+ return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
new file mode 100644
index 0000000000..b1d94aec53
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -0,0 +1,1598 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Condition uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Condition(a.t, comp, msgAndArgs...)
+}
+
+// Conditionf uses a Comparison to assert a complex condition.
+func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Conditionf(a.t, comp, msg, args...)
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Contains("Hello World", "World")
+// a.Contains(["Hello", "World"], "World")
+// a.Contains({"Hello": "World"}, "Hello")
+func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Contains(a.t, s, contains, msgAndArgs...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Containsf("Hello World", "World", "error message %s", "formatted")
+// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
+// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
+func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Containsf(a.t, s, contains, msg, args...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExists(a.t, path, msgAndArgs...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return DirExistsf(a.t, path, msg, args...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
+func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatch(a.t, listA, listB, msgAndArgs...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ElementsMatchf(a.t, listA, listB, msg, args...)
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Empty(obj)
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Empty(a.t, object, msgAndArgs...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Emptyf(obj, "error message %s", "formatted")
+func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Emptyf(a.t, object, msg, args...)
+}
+
+// Equal asserts that two objects are equal.
+//
+// a.Equal(123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equal(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualError(err, expectedErrorString)
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
+func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualErrorf(a.t, theError, errString, msg, args...)
+}
+
+// EqualExportedValues asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
+// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
+func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualExportedValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualExportedValuesf asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
+// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
+func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualExportedValuesf(a.t, expected, actual, msg, args...)
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValues(uint32(123), int32(123))
+func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
+func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// a.Equalf(123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Equalf(a.t, expected, actual, msg, args...)
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Error(err) {
+// assert.Equal(t, expectedError, err)
+// }
+func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Error(a.t, err, msgAndArgs...)
+}
+
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorAs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorAsf(a.t, err, target, msg, args...)
+}
+
+// ErrorContains asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// a.ErrorContains(err, expectedErrorSubString)
+func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorContains(a.t, theError, contains, msgAndArgs...)
+}
+
+// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
+func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorContainsf(a.t, theError, contains, msg, args...)
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return ErrorIsf(a.t, err, target, msg, args...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Errorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Errorf(a.t, err, msg, args...)
+}
+
+// Eventually asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// EventuallyWithT asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// a.EventuallyWithT(func(c *assert.CollectT) {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// EventuallyWithTf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Eventuallyf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Eventuallyf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// a.Exactly(int32(123), int64(123))
+func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted")
+func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Exactlyf(a.t, expected, actual, msg, args...)
+}
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNow fails test
+func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNow(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNowf fails test
+func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FailNowf(a.t, failureMessage, msg, args...)
+}
+
+// Failf reports a failure through
+func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Failf(a.t, failureMessage, msg, args...)
+}
+
+// False asserts that the specified value is false.
+//
+// a.False(myBool)
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return False(a.t, value, msgAndArgs...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// a.Falsef(myBool, "error message %s", "formatted")
+func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Falsef(a.t, value, msg, args...)
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExists(a.t, path, msgAndArgs...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return FileExistsf(a.t, path, msg, args...)
+}
+
+// Greater asserts that the first element is greater than the second
+//
+// a.Greater(2, 1)
+// a.Greater(float64(2), float64(1))
+// a.Greater("b", "a")
+func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Greater(a.t, e1, e2, msgAndArgs...)
+}
+
+// GreaterOrEqual asserts that the first element is greater than or equal to the second
+//
+// a.GreaterOrEqual(2, 1)
+// a.GreaterOrEqual(2, 2)
+// a.GreaterOrEqual("b", "a")
+// a.GreaterOrEqual("b", "b")
+func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return GreaterOrEqual(a.t, e1, e2, msgAndArgs...)
+}
+
+// GreaterOrEqualf asserts that the first element is greater than or equal to the second
+//
+// a.GreaterOrEqualf(2, 1, "error message %s", "formatted")
+// a.GreaterOrEqualf(2, 2, "error message %s", "formatted")
+// a.GreaterOrEqualf("b", "a", "error message %s", "formatted")
+// a.GreaterOrEqualf("b", "b", "error message %s", "formatted")
+func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return GreaterOrEqualf(a.t, e1, e2, msg, args...)
+}
+
+// Greaterf asserts that the first element is greater than the second
+//
+// a.Greaterf(2, 1, "error message %s", "formatted")
+// a.Greaterf(float64(2), float64(1), "error message %s", "formatted")
+// a.Greaterf("b", "a", "error message %s", "formatted")
+func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Greaterf(a.t, e1, e2, msg, args...)
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPError(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPErrorf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...)
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...)
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// a.Implements((*MyInterface)(nil), new(MyObject))
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Implementsf(a.t, interfaceObject, object, msg, args...)
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// a.InDelta(math.Pi, 22/7.0, 0.01)
+func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
+func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InDeltaf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// IsDecreasing asserts that the collection is decreasing
+//
+// a.IsDecreasing([]int{2, 1, 0})
+// a.IsDecreasing([]float{2, 1})
+// a.IsDecreasing([]string{"b", "a"})
+func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
+// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
+// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsDecreasingf(a.t, object, msg, args...)
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+// a.IsIncreasing([]int{1, 2, 3})
+// a.IsIncreasing([]float{1, 2})
+// a.IsIncreasing([]string{"a", "b"})
+func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
+// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
+// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsIncreasingf(a.t, object, msg, args...)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+// a.IsNonDecreasing([]int{1, 1, 2})
+// a.IsNonDecreasing([]float{1, 2})
+// a.IsNonDecreasing([]string{"a", "b"})
+func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
+// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
+// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonDecreasingf(a.t, object, msg, args...)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+// a.IsNonIncreasing([]int{2, 1, 1})
+// a.IsNonIncreasing([]float{2, 1})
+// a.IsNonIncreasing([]string{"b", "a"})
+func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
+// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
+// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsNonIncreasingf(a.t, object, msg, args...)
+}
+
+// IsType asserts that the specified objects are of the same type.
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsType(a.t, expectedType, object, msgAndArgs...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return IsTypef(a.t, expectedType, object, msg, args...)
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return JSONEqf(a.t, expected, actual, msg, args...)
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// a.Len(mySlice, 3)
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Len(a.t, object, length, msgAndArgs...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// a.Lenf(mySlice, 3, "error message %s", "formatted")
+func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Lenf(a.t, object, length, msg, args...)
+}
+
+// Less asserts that the first element is less than the second
+//
+// a.Less(1, 2)
+// a.Less(float64(1), float64(2))
+// a.Less("a", "b")
+func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Less(a.t, e1, e2, msgAndArgs...)
+}
+
+// LessOrEqual asserts that the first element is less than or equal to the second
+//
+// a.LessOrEqual(1, 2)
+// a.LessOrEqual(2, 2)
+// a.LessOrEqual("a", "b")
+// a.LessOrEqual("b", "b")
+func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return LessOrEqual(a.t, e1, e2, msgAndArgs...)
+}
+
+// LessOrEqualf asserts that the first element is less than or equal to the second
+//
+// a.LessOrEqualf(1, 2, "error message %s", "formatted")
+// a.LessOrEqualf(2, 2, "error message %s", "formatted")
+// a.LessOrEqualf("a", "b", "error message %s", "formatted")
+// a.LessOrEqualf("b", "b", "error message %s", "formatted")
+func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return LessOrEqualf(a.t, e1, e2, msg, args...)
+}
+
+// Lessf asserts that the first element is less than the second
+//
+// a.Lessf(1, 2, "error message %s", "formatted")
+// a.Lessf(float64(1), float64(2), "error message %s", "formatted")
+// a.Lessf("a", "b", "error message %s", "formatted")
+func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Lessf(a.t, e1, e2, msg, args...)
+}
+
+// Negative asserts that the specified element is negative
+//
+// a.Negative(-1)
+// a.Negative(-1.23)
+func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Negative(a.t, e, msgAndArgs...)
+}
+
+// Negativef asserts that the specified element is negative
+//
+// a.Negativef(-1, "error message %s", "formatted")
+// a.Negativef(-1.23, "error message %s", "formatted")
+func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Negativef(a.t, e, msg, args...)
+}
+
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Never(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Neverf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Nil asserts that the specified object is nil.
+//
+// a.Nil(err)
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nil(a.t, object, msgAndArgs...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// a.Nilf(err, "error message %s", "formatted")
+func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Nilf(a.t, object, msg, args...)
+}
+
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExists(a.t, path, msgAndArgs...)
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExistsf(a.t, path, msg, args...)
+}
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoError(err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoError(a.t, err, msgAndArgs...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoErrorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoErrorf(a.t, err, msg, args...)
+}
+
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExists(a.t, path, msgAndArgs...)
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExistsf(a.t, path, msg, args...)
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContains("Hello World", "Earth")
+// a.NotContains(["Hello", "World"], "Earth")
+// a.NotContains({"Hello": "World"}, "Earth")
+func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
+// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
+// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
+func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotContainsf(a.t, s, contains, msg, args...)
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmpty(obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmpty(a.t, object, msgAndArgs...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmptyf(obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEmptyf(a.t, object, msg, args...)
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// a.NotEqual(obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualValues asserts that two objects are not equal even when converted to the same type
+//
+// a.NotEqualValues(obj1, obj2)
+func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
+//
+// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted")
+func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotEqualf(a.t, expected, actual, msg, args...)
+}
+
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorIsf(a.t, err, target, msg, args...)
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// a.NotNil(err)
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNil(a.t, object, msgAndArgs...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// a.NotNilf(err, "error message %s", "formatted")
+func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotNilf(a.t, object, msg, args...)
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanics(func(){ RemainCalm() })
+func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanics(a.t, f, msgAndArgs...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
+func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotPanicsf(a.t, f, msg, args...)
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
+// a.NotRegexp("^start", "it's not starting")
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexp(a.t, rx, str, msgAndArgs...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
+// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotRegexpf(a.t, rx, str, msg, args...)
+}
+
+// NotSame asserts that two pointers do not reference the same object.
+//
+// a.NotSame(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSame(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// a.NotSamef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSamef(a.t, expected, actual, msg, args...)
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubset(a.t, list, subset, msgAndArgs...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSubsetf(a.t, list, subset, msg, args...)
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZero(a.t, i, msgAndArgs...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotZerof(a.t, i, msg, args...)
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panics(func(){ GoCrazy() })
+func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panics(a.t, f, msgAndArgs...)
+}
+
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithError("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithError(a.t, errString, f, msgAndArgs...)
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithErrorf(a.t, errString, f, msg, args...)
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValue(a.t, expected, f, msgAndArgs...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithValuef(a.t, expected, f, msg, args...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Panicsf(a.t, f, msg, args...)
+}
+
+// Positive asserts that the specified element is positive
+//
+// a.Positive(1)
+// a.Positive(1.23)
+func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Positive(a.t, e, msgAndArgs...)
+}
+
+// Positivef asserts that the specified element is positive
+//
+// a.Positivef(1, "error message %s", "formatted")
+// a.Positivef(1.23, "error message %s", "formatted")
+func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Positivef(a.t, e, msg, args...)
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// a.Regexp(regexp.MustCompile("start"), "it's starting")
+// a.Regexp("start...$", "it's not starting")
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexp(a.t, rx, str, msgAndArgs...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
+// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Regexpf(a.t, rx, str, msg, args...)
+}
+
+// Same asserts that two pointers reference the same object.
+//
+// a.Same(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Same(a.t, expected, actual, msgAndArgs...)
+}
+
+// Samef asserts that two pointers reference the same object.
+//
+// a.Samef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Samef(a.t, expected, actual, msg, args...)
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subset(a.t, list, subset, msgAndArgs...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Subsetf(a.t, list, subset, msg, args...)
+}
+
+// True asserts that the specified value is true.
+//
+// a.True(myBool)
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return True(a.t, value, msgAndArgs...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// a.Truef(myBool, "error message %s", "formatted")
+func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Truef(a.t, value, msg, args...)
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
+func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinDurationf(a.t, expected, actual, delta, msg, args...)
+}
+
+// WithinRange asserts that a time is within a time range (inclusive).
+//
+// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
+func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinRange(a.t, actual, start, end, msgAndArgs...)
+}
+
+// WithinRangef asserts that a time is within a time range (inclusive).
+//
+// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
+func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return WithinRangef(a.t, actual, start, end, msg, args...)
+}
+
+// YAMLEq asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEqf(a.t, expected, actual, msg, args...)
+}
+
+// Zero asserts that i is the zero value for its type.
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zero(a.t, i, msgAndArgs...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Zerof(a.t, i, msg, args...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
new file mode 100644
index 0000000000..188bb9e174
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
@@ -0,0 +1,5 @@
+{{.CommentWithoutT "a"}}
+func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
+ if h, ok := a.t.(tHelper); ok { h.Helper() }
+ return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go
new file mode 100644
index 0000000000..00df62a059
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go
@@ -0,0 +1,81 @@
+package assert
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// isOrdered checks that collection contains orderable elements.
+func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
+ objKind := reflect.TypeOf(object).Kind()
+ if objKind != reflect.Slice && objKind != reflect.Array {
+ return false
+ }
+
+ objValue := reflect.ValueOf(object)
+ objLen := objValue.Len()
+
+ if objLen <= 1 {
+ return true
+ }
+
+ value := objValue.Index(0)
+ valueInterface := value.Interface()
+ firstValueKind := value.Kind()
+
+ for i := 1; i < objLen; i++ {
+ prevValue := value
+ prevValueInterface := valueInterface
+
+ value = objValue.Index(i)
+ valueInterface = value.Interface()
+
+ compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind)
+
+ if !isComparable {
+ return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...)
+ }
+
+ if !containsValue(allowedComparesResults, compareResult) {
+ return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...)
+ }
+ }
+
+ return true
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+// assert.IsIncreasing(t, []int{1, 2, 3})
+// assert.IsIncreasing(t, []float{1, 2})
+// assert.IsIncreasing(t, []string{"a", "b"})
+func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+// assert.IsNonIncreasing(t, []int{2, 1, 1})
+// assert.IsNonIncreasing(t, []float{2, 1})
+// assert.IsNonIncreasing(t, []string{"b", "a"})
+func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
+}
+
+// IsDecreasing asserts that the collection is decreasing
+//
+// assert.IsDecreasing(t, []int{2, 1, 0})
+// assert.IsDecreasing(t, []float{2, 1})
+// assert.IsDecreasing(t, []string{"b", "a"})
+func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+// assert.IsNonDecreasing(t, []int{1, 1, 2})
+// assert.IsNonDecreasing(t, []float{1, 2})
+// assert.IsNonDecreasing(t, []string{"a", "b"})
+func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
new file mode 100644
index 0000000000..a55d1bba92
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -0,0 +1,2054 @@
+package assert
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+ "os"
+ "reflect"
+ "regexp"
+ "runtime"
+ "runtime/debug"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/pmezard/go-difflib/difflib"
+ yaml "gopkg.in/yaml.v3"
+)
+
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+}
+
+// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
+// for table driven tests.
+type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool
+
+// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
+// for table driven tests.
+type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool
+
+// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
+// for table driven tests.
+type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
+
+// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
+// for table driven tests.
+type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
+
+// Comparison is a custom function that returns true on success and false on failure
+type Comparison func() (success bool)
+
+/*
+ Helper functions
+*/
+
+// ObjectsAreEqual determines if two objects are considered equal.
+//
+// This function does no assertion of any kind.
+func ObjectsAreEqual(expected, actual interface{}) bool {
+ if expected == nil || actual == nil {
+ return expected == actual
+ }
+
+ exp, ok := expected.([]byte)
+ if !ok {
+ return reflect.DeepEqual(expected, actual)
+ }
+
+ act, ok := actual.([]byte)
+ if !ok {
+ return false
+ }
+ if exp == nil || act == nil {
+ return exp == nil && act == nil
+ }
+ return bytes.Equal(exp, act)
+}
+
+// copyExportedFields iterates downward through nested data structures and creates a copy
+// that only contains the exported struct fields.
+func copyExportedFields(expected interface{}) interface{} {
+ if isNil(expected) {
+ return expected
+ }
+
+ expectedType := reflect.TypeOf(expected)
+ expectedKind := expectedType.Kind()
+ expectedValue := reflect.ValueOf(expected)
+
+ switch expectedKind {
+ case reflect.Struct:
+ result := reflect.New(expectedType).Elem()
+ for i := 0; i < expectedType.NumField(); i++ {
+ field := expectedType.Field(i)
+ isExported := field.IsExported()
+ if isExported {
+ fieldValue := expectedValue.Field(i)
+ if isNil(fieldValue) || isNil(fieldValue.Interface()) {
+ continue
+ }
+ newValue := copyExportedFields(fieldValue.Interface())
+ result.Field(i).Set(reflect.ValueOf(newValue))
+ }
+ }
+ return result.Interface()
+
+ case reflect.Ptr:
+ result := reflect.New(expectedType.Elem())
+ unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface())
+ result.Elem().Set(reflect.ValueOf(unexportedRemoved))
+ return result.Interface()
+
+ case reflect.Array, reflect.Slice:
+ result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
+ for i := 0; i < expectedValue.Len(); i++ {
+ index := expectedValue.Index(i)
+ if isNil(index) {
+ continue
+ }
+ unexportedRemoved := copyExportedFields(index.Interface())
+ result.Index(i).Set(reflect.ValueOf(unexportedRemoved))
+ }
+ return result.Interface()
+
+ case reflect.Map:
+ result := reflect.MakeMap(expectedType)
+ for _, k := range expectedValue.MapKeys() {
+ index := expectedValue.MapIndex(k)
+ unexportedRemoved := copyExportedFields(index.Interface())
+ result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved))
+ }
+ return result.Interface()
+
+ default:
+ return expected
+ }
+}
+
+// ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are
+// considered equal. This comparison of only exported fields is applied recursively to nested data
+// structures.
+//
+// This function does no assertion of any kind.
+func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
+ expectedCleaned := copyExportedFields(expected)
+ actualCleaned := copyExportedFields(actual)
+ return ObjectsAreEqualValues(expectedCleaned, actualCleaned)
+}
+
+// ObjectsAreEqualValues gets whether two objects are equal, or if their
+// values are equal.
+func ObjectsAreEqualValues(expected, actual interface{}) bool {
+ if ObjectsAreEqual(expected, actual) {
+ return true
+ }
+
+ actualType := reflect.TypeOf(actual)
+ if actualType == nil {
+ return false
+ }
+ expectedValue := reflect.ValueOf(expected)
+ if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+ // Attempt comparison after type conversion
+ return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
+ }
+
+ return false
+}
+
+/* CallerInfo is necessary because the assert functions use the testing object
+internally, causing it to print the file:line of the assert method, rather than where
+the problem actually occurred in calling code.*/
+
+// CallerInfo returns an array of strings containing the file and line number
+// of each stack frame leading from the current test to the assert call that
+// failed.
+func CallerInfo() []string {
+
+ var pc uintptr
+ var ok bool
+ var file string
+ var line int
+ var name string
+
+ callers := []string{}
+ for i := 0; ; i++ {
+ pc, file, line, ok = runtime.Caller(i)
+ if !ok {
+ // The breaks below failed to terminate the loop, and we ran off the
+ // end of the call stack.
+ break
+ }
+
+ // This is a huge edge case, but it will panic if this is the case, see #180
+ if file == "" {
+ break
+ }
+
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ break
+ }
+ name = f.Name()
+
+ // testing.tRunner is the standard library function that calls
+ // tests. Subtests are called directly by tRunner, without going through
+ // the Test/Benchmark/Example function that contains the t.Run calls, so
+ // with subtests we should break when we hit tRunner, without adding it
+ // to the list of callers.
+ if name == "testing.tRunner" {
+ break
+ }
+
+ parts := strings.Split(file, "/")
+ if len(parts) > 1 {
+ filename := parts[len(parts)-1]
+ dir := parts[len(parts)-2]
+ if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" {
+ callers = append(callers, fmt.Sprintf("%s:%d", file, line))
+ }
+ }
+
+ // Drop the package
+ segments := strings.Split(name, ".")
+ name = segments[len(segments)-1]
+ if isTest(name, "Test") ||
+ isTest(name, "Benchmark") ||
+ isTest(name, "Example") {
+ break
+ }
+ }
+
+ return callers
+}
+
+// Stolen from the `go test` tool.
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+ if !strings.HasPrefix(name, prefix) {
+ return false
+ }
+ if len(name) == len(prefix) { // "Test" is ok
+ return true
+ }
+ r, _ := utf8.DecodeRuneInString(name[len(prefix):])
+ return !unicode.IsLower(r)
+}
+
+func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
+ if len(msgAndArgs) == 0 || msgAndArgs == nil {
+ return ""
+ }
+ if len(msgAndArgs) == 1 {
+ msg := msgAndArgs[0]
+ if msgAsStr, ok := msg.(string); ok {
+ return msgAsStr
+ }
+ return fmt.Sprintf("%+v", msg)
+ }
+ if len(msgAndArgs) > 1 {
+ return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
+ }
+ return ""
+}
+
+// Aligns the provided message so that all lines after the first line start at the same location as the first line.
+// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
+// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the
+// basis on which the alignment occurs).
+func indentMessageLines(message string, longestLabelLen int) string {
+ outBuf := new(bytes.Buffer)
+
+ for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
+ // no need to align first line because it starts at the correct location (after the label)
+ if i != 0 {
+ // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
+ outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
+ }
+ outBuf.WriteString(scanner.Text())
+ }
+
+ return outBuf.String()
+}
+
+type failNower interface {
+ FailNow()
+}
+
+// FailNow fails test
+func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(t, failureMessage, msgAndArgs...)
+
+ // We cannot extend TestingT with FailNow() and
+ // maintain backwards compatibility, so we fallback
+ // to panicking when FailNow is not available in
+ // TestingT.
+ // See issue #263
+
+ if t, ok := t.(failNower); ok {
+ t.FailNow()
+ } else {
+ panic("test failed and t is missing `FailNow()`")
+ }
+ return false
+}
+
+// Fail reports a failure through
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ content := []labeledContent{
+ {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")},
+ {"Error", failureMessage},
+ }
+
+ // Add test name if the Go version supports it
+ if n, ok := t.(interface {
+ Name() string
+ }); ok {
+ content = append(content, labeledContent{"Test", n.Name()})
+ }
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+ if len(message) > 0 {
+ content = append(content, labeledContent{"Messages", message})
+ }
+
+ t.Errorf("\n%s", ""+labeledOutput(content...))
+
+ return false
+}
+
+type labeledContent struct {
+ label string
+ content string
+}
+
+// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
+//
+// \t{{label}}:{{align_spaces}}\t{{content}}\n
+//
+// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
+// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
+// alignment is achieved, "\t{{content}}\n" is added for the output.
+//
+// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line.
+func labeledOutput(content ...labeledContent) string {
+ longestLabel := 0
+ for _, v := range content {
+ if len(v.label) > longestLabel {
+ longestLabel = len(v.label)
+ }
+ }
+ var output string
+ for _, v := range content {
+ output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
+ }
+ return output
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ interfaceType := reflect.TypeOf(interfaceObject).Elem()
+
+ if object == nil {
+ return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...)
+ }
+ if !reflect.TypeOf(object).Implements(interfaceType) {
+ return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
+ }
+
+ return true
+}
+
+// IsType asserts that the specified objects are of the same type.
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
+ return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(t, 123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
+
+ if !ObjectsAreEqual(expected, actual) {
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual : %s%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// validateEqualArgs checks whether provided arguments can be safely used in the
+// Equal/NotEqual functions.
+func validateEqualArgs(expected, actual interface{}) error {
+ if expected == nil && actual == nil {
+ return nil
+ }
+
+ if isFunction(expected) || isFunction(actual) {
+ return errors.New("cannot take func type as argument")
+ }
+ return nil
+}
+
+// Same asserts that two pointers reference the same object.
+//
+// assert.Same(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !samePointers(expected, actual) {
+ return Fail(t, fmt.Sprintf("Not same: \n"+
+ "expected: %p %#v\n"+
+ "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
+ }
+
+ return true
+}
+
+// NotSame asserts that two pointers do not reference the same object.
+//
+// assert.NotSame(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if samePointers(expected, actual) {
+ return Fail(t, fmt.Sprintf(
+ "Expected and actual point to the same object: %p %#v",
+ expected, expected), msgAndArgs...)
+ }
+ return true
+}
+
+// samePointers compares two generic interface objects and returns whether
+// they point to the same object
+func samePointers(first, second interface{}) bool {
+ firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
+ if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
+ return false
+ }
+
+ firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
+ if firstType != secondType {
+ return false
+ }
+
+ // compare pointer addresses
+ return first == second
+}
+
+// formatUnequalValues takes two values of arbitrary types and returns string
+// representations appropriate to be presented to the user.
+//
+// If the values are not of like type, the returned strings will be prefixed
+// with the type name, and the value will be enclosed in parenthesis similar
+// to a type conversion in the Go grammar.
+func formatUnequalValues(expected, actual interface{}) (e string, a string) {
+ if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
+ return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)),
+ fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual))
+ }
+ switch expected.(type) {
+ case time.Duration:
+ return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
+ }
+ return truncatingFormat(expected), truncatingFormat(actual)
+}
+
+// truncatingFormat formats the data and truncates it if it's too long.
+//
+// This helps keep formatted error messages lines from exceeding the
+// bufio.MaxScanTokenSize max line length that the go testing framework imposes.
+func truncatingFormat(data interface{}) string {
+ value := fmt.Sprintf("%#v", data)
+ max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed.
+ if len(value) > max {
+ value = value[0:max] + "<... truncated>"
+ }
+ return value
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValues(t, uint32(123), int32(123))
+func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if !ObjectsAreEqualValues(expected, actual) {
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual : %s%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// EqualExportedValues asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
+// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
+func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ aType := reflect.TypeOf(expected)
+ bType := reflect.TypeOf(actual)
+
+ if aType != bType {
+ return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
+ }
+
+ if aType.Kind() != reflect.Struct {
+ return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
+ }
+
+ if bType.Kind() != reflect.Struct {
+ return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
+ }
+
+ expected = copyExportedFields(expected)
+ actual = copyExportedFields(actual)
+
+ if !ObjectsAreEqualValues(expected, actual) {
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+
+ "expected: %s\n"+
+ "actual : %s%s", expected, actual, diff), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// assert.Exactly(t, int32(123), int64(123))
+func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ aType := reflect.TypeOf(expected)
+ bType := reflect.TypeOf(actual)
+
+ if aType != bType {
+ return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
+ }
+
+ return Equal(t, expected, actual, msgAndArgs...)
+
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(t, err)
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if !isNil(object) {
+ return true
+ }
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "Expected value not to be nil.", msgAndArgs...)
+}
+
+// containsKind checks if a specified kind in the slice of kinds.
+func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
+ for i := 0; i < len(kinds); i++ {
+ if kind == kinds[i] {
+ return true
+ }
+ }
+
+ return false
+}
+
+// isNil checks if a specified object is nil or not, without Failing.
+func isNil(object interface{}) bool {
+ if object == nil {
+ return true
+ }
+
+ value := reflect.ValueOf(object)
+ kind := value.Kind()
+ isNilableKind := containsKind(
+ []reflect.Kind{
+ reflect.Chan, reflect.Func,
+ reflect.Interface, reflect.Map,
+ reflect.Ptr, reflect.Slice, reflect.UnsafePointer},
+ kind)
+
+ if isNilableKind && value.IsNil() {
+ return true
+ }
+
+ return false
+}
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(t, err)
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if isNil(object) {
+ return true
+ }
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
+}
+
+// isEmpty gets whether the specified object is considered empty or not.
+func isEmpty(object interface{}) bool {
+
+ // get nil case out of the way
+ if object == nil {
+ return true
+ }
+
+ objValue := reflect.ValueOf(object)
+
+ switch objValue.Kind() {
+ // collection types are empty when they have no element
+ case reflect.Chan, reflect.Map, reflect.Slice:
+ return objValue.Len() == 0
+ // pointers are empty if nil or if the value they point to is empty
+ case reflect.Ptr:
+ if objValue.IsNil() {
+ return true
+ }
+ deref := objValue.Elem().Interface()
+ return isEmpty(deref)
+ // for all other types, compare against the zero value
+ // array types are empty when they match their zero-initialized state
+ default:
+ zero := reflect.Zero(objValue.Type())
+ return reflect.DeepEqual(object, zero.Interface())
+ }
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Empty(t, obj)
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ pass := isEmpty(object)
+ if !pass {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmpty(t, obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ pass := !isEmpty(object)
+ if !pass {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// getLen try to get length of object.
+// return (false, 0) if impossible.
+func getLen(x interface{}) (ok bool, length int) {
+ v := reflect.ValueOf(x)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+ return true, v.Len()
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(t, mySlice, 3)
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ ok, l := getLen(object)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
+ }
+
+ if l != length {
+ return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
+ }
+ return true
+}
+
+// True asserts that the specified value is true.
+//
+// assert.True(t, myBool)
+func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+ if !value {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "Should be true", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// False asserts that the specified value is false.
+//
+// assert.False(t, myBool)
+func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+ if value {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "Should be false", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(t, obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
+
+ if ObjectsAreEqual(expected, actual) {
+ return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotEqualValues asserts that two objects are not equal even when converted to the same type
+//
+// assert.NotEqualValues(t, obj1, obj2)
+func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if ObjectsAreEqualValues(expected, actual) {
+ return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
+ }
+
+ return true
+}
+
+// containsElement try loop over the list check if the list includes the element.
+// return (false, false) if impossible.
+// return (true, false) if element was not found.
+// return (true, true) if element was found.
+func containsElement(list interface{}, element interface{}) (ok, found bool) {
+
+ listValue := reflect.ValueOf(list)
+ listType := reflect.TypeOf(list)
+ if listType == nil {
+ return false, false
+ }
+ listKind := listType.Kind()
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ found = false
+ }
+ }()
+
+ if listKind == reflect.String {
+ elementValue := reflect.ValueOf(element)
+ return true, strings.Contains(listValue.String(), elementValue.String())
+ }
+
+ if listKind == reflect.Map {
+ mapKeys := listValue.MapKeys()
+ for i := 0; i < len(mapKeys); i++ {
+ if ObjectsAreEqual(mapKeys[i].Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+ }
+
+ for i := 0; i < listValue.Len(); i++ {
+ if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Contains(t, "Hello World", "World")
+// assert.Contains(t, ["Hello", "World"], "World")
+// assert.Contains(t, {"Hello": "World"}, "Hello")
+func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ok, found := containsElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContains(t, "Hello World", "Earth")
+// assert.NotContains(t, ["Hello", "World"], "Earth")
+// assert.NotContains(t, {"Hello": "World"}, "Earth")
+func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ok, found := containsElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if found {
+ return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if subset == nil {
+ return true // we consider nil to be equal to the nil set
+ }
+
+ listKind := reflect.TypeOf(list).Kind()
+ if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ subsetKind := reflect.TypeOf(subset).Kind()
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ if subsetKind == reflect.Map && listKind == reflect.Map {
+ subsetMap := reflect.ValueOf(subset)
+ actualMap := reflect.ValueOf(list)
+
+ for _, k := range subsetMap.MapKeys() {
+ ev := subsetMap.MapIndex(k)
+ av := actualMap.MapIndex(k)
+
+ if !av.IsValid() {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
+ }
+ if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...)
+ }
+ }
+
+ return true
+ }
+
+ subsetList := reflect.ValueOf(subset)
+ for i := 0; i < subsetList.Len(); i++ {
+ element := subsetList.Index(i).Interface()
+ ok, found := containsElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...)
+ }
+ }
+
+ return true
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if subset == nil {
+ return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
+ }
+
+ listKind := reflect.TypeOf(list).Kind()
+ if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ subsetKind := reflect.TypeOf(subset).Kind()
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ if subsetKind == reflect.Map && listKind == reflect.Map {
+ subsetMap := reflect.ValueOf(subset)
+ actualMap := reflect.ValueOf(list)
+
+ for _, k := range subsetMap.MapKeys() {
+ ev := subsetMap.MapIndex(k)
+ av := actualMap.MapIndex(k)
+
+ if !av.IsValid() {
+ return true
+ }
+ if !ObjectsAreEqual(ev.Interface(), av.Interface()) {
+ return true
+ }
+ }
+
+ return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+ }
+
+ subsetList := reflect.ValueOf(subset)
+ for i := 0; i < subsetList.Len(); i++ {
+ element := subsetList.Index(i).Interface()
+ ok, found := containsElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return true
+ }
+ }
+
+ return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
+func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if isEmpty(listA) && isEmpty(listB) {
+ return true
+ }
+
+ if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) {
+ return false
+ }
+
+ extraA, extraB := diffLists(listA, listB)
+
+ if len(extraA) == 0 && len(extraB) == 0 {
+ return true
+ }
+
+ return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...)
+}
+
+// isList checks that the provided value is array or slice.
+func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) {
+ kind := reflect.TypeOf(list).Kind()
+ if kind != reflect.Array && kind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind),
+ msgAndArgs...)
+ }
+ return true
+}
+
+// diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B.
+// If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and
+// 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored.
+func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) {
+ aValue := reflect.ValueOf(listA)
+ bValue := reflect.ValueOf(listB)
+
+ aLen := aValue.Len()
+ bLen := bValue.Len()
+
+ // Mark indexes in bValue that we already used
+ visited := make([]bool, bLen)
+ for i := 0; i < aLen; i++ {
+ element := aValue.Index(i).Interface()
+ found := false
+ for j := 0; j < bLen; j++ {
+ if visited[j] {
+ continue
+ }
+ if ObjectsAreEqual(bValue.Index(j).Interface(), element) {
+ visited[j] = true
+ found = true
+ break
+ }
+ }
+ if !found {
+ extraA = append(extraA, element)
+ }
+ }
+
+ for j := 0; j < bLen; j++ {
+ if visited[j] {
+ continue
+ }
+ extraB = append(extraB, bValue.Index(j).Interface())
+ }
+
+ return
+}
+
+func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string {
+ var msg bytes.Buffer
+
+ msg.WriteString("elements differ")
+ if len(extraA) > 0 {
+ msg.WriteString("\n\nextra elements in list A:\n")
+ msg.WriteString(spewConfig.Sdump(extraA))
+ }
+ if len(extraB) > 0 {
+ msg.WriteString("\n\nextra elements in list B:\n")
+ msg.WriteString(spewConfig.Sdump(extraB))
+ }
+ msg.WriteString("\n\nlistA:\n")
+ msg.WriteString(spewConfig.Sdump(listA))
+ msg.WriteString("\n\nlistB:\n")
+ msg.WriteString(spewConfig.Sdump(listB))
+
+ return msg.String()
+}
+
+// Condition uses a Comparison to assert a complex condition.
+func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ result := comp()
+ if !result {
+ Fail(t, "Condition failed!", msgAndArgs...)
+ }
+ return result
+}
+
+// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
+// methods, and represents a simple func that takes no arguments, and returns nothing.
+type PanicTestFunc func()
+
+// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
+func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) {
+ didPanic = true
+
+ defer func() {
+ message = recover()
+ if didPanic {
+ stack = string(debug.Stack())
+ }
+ }()
+
+ // call the target function
+ f()
+ didPanic = false
+
+ return
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(t, func(){ GoCrazy() })
+func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ funcDidPanic, panicValue, panickedStack := didPanic(f)
+ if !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+ if panicValue != expected {
+ return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...)
+ }
+
+ return true
+}
+
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ funcDidPanic, panicValue, panickedStack := didPanic(f)
+ if !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+ panicErr, ok := panicValue.(error)
+ if !ok || panicErr.Error() != errString {
+ return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...)
+ }
+
+ return true
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(t, func(){ RemainCalm() })
+func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...)
+ }
+
+ return true
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
+func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ dt := expected.Sub(actual)
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+// WithinRange asserts that a time is within a time range (inclusive).
+//
+// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
+func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if end.Before(start) {
+ return Fail(t, "Start should be before end", msgAndArgs...)
+ }
+
+ if actual.Before(start) {
+ return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...)
+ } else if actual.After(end) {
+ return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...)
+ }
+
+ return true
+}
+
+func toFloat(x interface{}) (float64, bool) {
+ var xf float64
+ xok := true
+
+ switch xn := x.(type) {
+ case uint:
+ xf = float64(xn)
+ case uint8:
+ xf = float64(xn)
+ case uint16:
+ xf = float64(xn)
+ case uint32:
+ xf = float64(xn)
+ case uint64:
+ xf = float64(xn)
+ case int:
+ xf = float64(xn)
+ case int8:
+ xf = float64(xn)
+ case int16:
+ xf = float64(xn)
+ case int32:
+ xf = float64(xn)
+ case int64:
+ xf = float64(xn)
+ case float32:
+ xf = float64(xn)
+ case float64:
+ xf = xn
+ case time.Duration:
+ xf = float64(xn)
+ default:
+ xok = false
+ }
+
+ return xf, xok
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, 22/7.0, 0.01)
+func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+
+ if !aok || !bok {
+ return Fail(t, "Parameters must be numerical", msgAndArgs...)
+ }
+
+ if math.IsNaN(af) && math.IsNaN(bf) {
+ return true
+ }
+
+ if math.IsNaN(af) {
+ return Fail(t, "Expected must not be NaN", msgAndArgs...)
+ }
+
+ if math.IsNaN(bf) {
+ return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
+ }
+
+ dt := af - bf
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, "Parameters must be slice", msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Map ||
+ reflect.TypeOf(expected).Kind() != reflect.Map {
+ return Fail(t, "Arguments must be maps", msgAndArgs...)
+ }
+
+ expectedMap := reflect.ValueOf(expected)
+ actualMap := reflect.ValueOf(actual)
+
+ if expectedMap.Len() != actualMap.Len() {
+ return Fail(t, "Arguments must have the same number of keys", msgAndArgs...)
+ }
+
+ for _, k := range expectedMap.MapKeys() {
+ ev := expectedMap.MapIndex(k)
+ av := actualMap.MapIndex(k)
+
+ if !ev.IsValid() {
+ return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...)
+ }
+
+ if !av.IsValid() {
+ return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...)
+ }
+
+ if !InDelta(
+ t,
+ ev.Interface(),
+ av.Interface(),
+ delta,
+ msgAndArgs...,
+ ) {
+ return false
+ }
+ }
+
+ return true
+}
+
+func calcRelativeError(expected, actual interface{}) (float64, error) {
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+ if !aok || !bok {
+ return 0, fmt.Errorf("Parameters must be numerical")
+ }
+ if math.IsNaN(af) && math.IsNaN(bf) {
+ return 0, nil
+ }
+ if math.IsNaN(af) {
+ return 0, errors.New("expected value must not be NaN")
+ }
+ if af == 0 {
+ return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
+ }
+ if math.IsNaN(bf) {
+ return 0, errors.New("actual value must not be NaN")
+ }
+
+ return math.Abs(af-bf) / math.Abs(af), nil
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if math.IsNaN(epsilon) {
+ return Fail(t, "epsilon must not be NaN")
+ }
+ actualEpsilon, err := calcRelativeError(expected, actual)
+ if err != nil {
+ return Fail(t, err.Error(), msgAndArgs...)
+ }
+ if actualEpsilon > epsilon {
+ return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
+ " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
+ }
+
+ return true
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if expected == nil || actual == nil ||
+ reflect.TypeOf(actual).Kind() != reflect.Slice ||
+ reflect.TypeOf(expected).Kind() != reflect.Slice {
+ return Fail(t, "Parameters must be slice", msgAndArgs...)
+ }
+
+ actualSlice := reflect.ValueOf(actual)
+ expectedSlice := reflect.ValueOf(expected)
+
+ for i := 0; i < actualSlice.Len(); i++ {
+ result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon)
+ if !result {
+ return result
+ }
+ }
+
+ return true
+}
+
+/*
+ Errors
+*/
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(t, err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if err != nil {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err) {
+// assert.Equal(t, expectedError, err)
+// }
+func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if err == nil {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Fail(t, "An error is expected but got nil.", msgAndArgs...)
+ }
+
+ return true
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualError(t, err, expectedErrorString)
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !Error(t, theError, msgAndArgs...) {
+ return false
+ }
+ expected := errString
+ actual := theError.Error()
+ // don't need to use deep equals here, we know they are both strings
+ if expected != actual {
+ return Fail(t, fmt.Sprintf("Error message not equal:\n"+
+ "expected: %q\n"+
+ "actual : %q", expected, actual), msgAndArgs...)
+ }
+ return true
+}
+
+// ErrorContains asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// assert.ErrorContains(t, err, expectedErrorSubString)
+func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !Error(t, theError, msgAndArgs...) {
+ return false
+ }
+
+ actual := theError.Error()
+ if !strings.Contains(actual, contains) {
+ return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...)
+ }
+
+ return true
+}
+
+// matchRegexp return true if a specified regexp matches a string.
+func matchRegexp(rx interface{}, str interface{}) bool {
+
+ var r *regexp.Regexp
+ if rr, ok := rx.(*regexp.Regexp); ok {
+ r = rr
+ } else {
+ r = regexp.MustCompile(fmt.Sprint(rx))
+ }
+
+ return (r.FindStringIndex(fmt.Sprint(str)) != nil)
+
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ match := matchRegexp(rx, str)
+
+ if !match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return match
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ match := matchRegexp(rx, str)
+
+ if match {
+ Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
+ }
+
+ return !match
+
+}
+
+// Zero asserts that i is the zero value for its type.
+func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
+ return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
+ }
+ return true
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
+ }
+ return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
+ }
+ if info.IsDir() {
+ return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...)
+ }
+ return true
+}
+
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ return true
+ }
+ if info.IsDir() {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
+ }
+ return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
+ }
+ if !info.IsDir() {
+ return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...)
+ }
+ return true
+}
+
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return true
+ }
+ return true
+ }
+ if !info.IsDir() {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...)
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ var expectedJSONAsInterface, actualJSONAsInterface interface{}
+
+ if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
+ }
+
+ if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
+ }
+
+ return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
+}
+
+// YAMLEq asserts that two YAML strings are equivalent.
+func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ var expectedYAMLAsInterface, actualYAMLAsInterface interface{}
+
+ if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...)
+ }
+
+ if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil {
+ return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...)
+ }
+
+ return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...)
+}
+
+func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
+ t := reflect.TypeOf(v)
+ k := t.Kind()
+
+ if k == reflect.Ptr {
+ t = t.Elem()
+ k = t.Kind()
+ }
+ return t, k
+}
+
+// diff returns a diff of both values as long as both are of the same type and
+// are a struct, map, slice, array or string. Otherwise it returns an empty string.
+func diff(expected interface{}, actual interface{}) string {
+ if expected == nil || actual == nil {
+ return ""
+ }
+
+ et, ek := typeAndKind(expected)
+ at, _ := typeAndKind(actual)
+
+ if et != at {
+ return ""
+ }
+
+ if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String {
+ return ""
+ }
+
+ var e, a string
+
+ switch et {
+ case reflect.TypeOf(""):
+ e = reflect.ValueOf(expected).String()
+ a = reflect.ValueOf(actual).String()
+ case reflect.TypeOf(time.Time{}):
+ e = spewConfigStringerEnabled.Sdump(expected)
+ a = spewConfigStringerEnabled.Sdump(actual)
+ default:
+ e = spewConfig.Sdump(expected)
+ a = spewConfig.Sdump(actual)
+ }
+
+ diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
+ A: difflib.SplitLines(e),
+ B: difflib.SplitLines(a),
+ FromFile: "Expected",
+ FromDate: "",
+ ToFile: "Actual",
+ ToDate: "",
+ Context: 1,
+ })
+
+ return "\n\nDiff:\n" + diff
+}
+
+func isFunction(arg interface{}) bool {
+ if arg == nil {
+ return false
+ }
+ return reflect.TypeOf(arg).Kind() == reflect.Func
+}
+
+var spewConfig = spew.ConfigState{
+ Indent: " ",
+ DisablePointerAddresses: true,
+ DisableCapacities: true,
+ SortKeys: true,
+ DisableMethods: true,
+ MaxDepth: 10,
+}
+
+var spewConfigStringerEnabled = spew.ConfigState{
+ Indent: " ",
+ DisablePointerAddresses: true,
+ DisableCapacities: true,
+ SortKeys: true,
+ MaxDepth: 10,
+}
+
+type tHelper interface {
+ Helper()
+}
+
+// Eventually asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
+func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ch := make(chan bool, 1)
+
+ timer := time.NewTimer(waitFor)
+ defer timer.Stop()
+
+ ticker := time.NewTicker(tick)
+ defer ticker.Stop()
+
+ for tick := ticker.C; ; {
+ select {
+ case <-timer.C:
+ return Fail(t, "Condition never satisfied", msgAndArgs...)
+ case <-tick:
+ tick = nil
+ go func() { ch <- condition() }()
+ case v := <-ch:
+ if v {
+ return true
+ }
+ tick = ticker.C
+ }
+ }
+}
+
+// CollectT implements the TestingT interface and collects all errors.
+type CollectT struct {
+ errors []error
+}
+
+// Errorf collects the error.
+func (c *CollectT) Errorf(format string, args ...interface{}) {
+ c.errors = append(c.errors, fmt.Errorf(format, args...))
+}
+
+// FailNow panics.
+func (c *CollectT) FailNow() {
+ panic("Assertion failed")
+}
+
+// Reset clears the collected errors.
+func (c *CollectT) Reset() {
+ c.errors = nil
+}
+
+// Copy copies the collected errors to the supplied t.
+func (c *CollectT) Copy(t TestingT) {
+ if tt, ok := t.(tHelper); ok {
+ tt.Helper()
+ }
+ for _, err := range c.errors {
+ t.Errorf("%v", err)
+ }
+}
+
+// EventuallyWithT asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// assert.EventuallyWithT(t, func(c *assert.CollectT) {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ collect := new(CollectT)
+ ch := make(chan bool, 1)
+
+ timer := time.NewTimer(waitFor)
+ defer timer.Stop()
+
+ ticker := time.NewTicker(tick)
+ defer ticker.Stop()
+
+ for tick := ticker.C; ; {
+ select {
+ case <-timer.C:
+ collect.Copy(t)
+ return Fail(t, "Condition never satisfied", msgAndArgs...)
+ case <-tick:
+ tick = nil
+ collect.Reset()
+ go func() {
+ condition(collect)
+ ch <- len(collect.errors) == 0
+ }()
+ case v := <-ch:
+ if v {
+ return true
+ }
+ tick = ticker.C
+ }
+ }
+}
+
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond)
+func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ch := make(chan bool, 1)
+
+ timer := time.NewTimer(waitFor)
+ defer timer.Stop()
+
+ ticker := time.NewTicker(tick)
+ defer ticker.Stop()
+
+ for tick := ticker.C; ; {
+ select {
+ case <-timer.C:
+ return true
+ case <-tick:
+ tick = nil
+ go func() { ch <- condition() }()
+ case v := <-ch:
+ if v {
+ return Fail(t, "Condition satisfied", msgAndArgs...)
+ }
+ tick = ticker.C
+ }
+ }
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if errors.Is(err, target) {
+ return true
+ }
+
+ var expectedText string
+ if target != nil {
+ expectedText = target.Error()
+ }
+
+ chain := buildErrorChainString(err)
+
+ return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+
+ "expected: %q\n"+
+ "in chain: %s", expectedText, chain,
+ ), msgAndArgs...)
+}
+
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !errors.Is(err, target) {
+ return true
+ }
+
+ var expectedText string
+ if target != nil {
+ expectedText = target.Error()
+ }
+
+ chain := buildErrorChainString(err)
+
+ return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
+ "found: %q\n"+
+ "in chain: %s", expectedText, chain,
+ ), msgAndArgs...)
+}
+
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if errors.As(err, target) {
+ return true
+ }
+
+ chain := buildErrorChainString(err)
+
+ return Fail(t, fmt.Sprintf("Should be in error chain:\n"+
+ "expected: %q\n"+
+ "in chain: %s", target, chain,
+ ), msgAndArgs...)
+}
+
+func buildErrorChainString(err error) string {
+ if err == nil {
+ return ""
+ }
+
+ e := errors.Unwrap(err)
+ chain := fmt.Sprintf("%q", err.Error())
+ for e != nil {
+ chain += fmt.Sprintf("\n\t%q", e.Error())
+ e = errors.Unwrap(e)
+ }
+ return chain
+}
diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go
new file mode 100644
index 0000000000..4953981d38
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/doc.go
@@ -0,0 +1,46 @@
+// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
+//
+// # Example Usage
+//
+// The following is a complete example using assert in a standard test function:
+//
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(t, a, b, "The two words should be the same.")
+//
+// }
+//
+// if you assert many times, use the format below:
+//
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+// assert := assert.New(t)
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(a, b, "The two words should be the same.")
+// }
+//
+// # Assertions
+//
+// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
+// All assertion functions take, as the first argument, the `*testing.T` object provided by the
+// testing framework. This allows the assertion funcs to write the failings and other details to
+// the correct place.
+//
+// Every assertion function also takes an optional string message as the final argument,
+// allowing custom error messages to be appended to the message the assertion method outputs.
+package assert
diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go
new file mode 100644
index 0000000000..ac9dc9d1d6
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/errors.go
@@ -0,0 +1,10 @@
+package assert
+
+import (
+ "errors"
+)
+
+// AnError is an error instance useful for testing. If the code does not care
+// about error specifics, and only needs to return the error for example, this
+// error should be used to make the test code more readable.
+var AnError = errors.New("assert.AnError general error for testing")
diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
new file mode 100644
index 0000000000..df189d2348
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
@@ -0,0 +1,16 @@
+package assert
+
+// Assertions provides assertion methods around the
+// TestingT interface.
+type Assertions struct {
+ t TestingT
+}
+
+// New makes a new Assertions object for the specified TestingT.
+func New(t TestingT) *Assertions {
+ return &Assertions{
+ t: t,
+ }
+}
+
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go
new file mode 100644
index 0000000000..d8038c28a7
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go
@@ -0,0 +1,162 @@
+package assert
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "strings"
+)
+
+// httpCode is a helper that returns HTTP code of the response. It returns -1 and
+// an error if building a new request fails.
+func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url, nil)
+ if err != nil {
+ return -1, err
+ }
+ req.URL.RawQuery = values.Encode()
+ handler(w, req)
+ return w.Code, nil
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
+ if !isSuccessCode {
+ Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isSuccessCode
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
+ if !isRedirectCode {
+ Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isRedirectCode
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ isErrorCode := code >= http.StatusBadRequest
+ if !isErrorCode {
+ Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isErrorCode
+}
+
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
+ }
+
+ successful := code == statuscode
+ if !successful {
+ Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code))
+ }
+
+ return successful
+}
+
+// HTTPBody is a helper that returns HTTP body of the response. It returns
+// empty string if building a new request fails.
+func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
+ if err != nil {
+ return ""
+ }
+ handler(w, req)
+ return w.Body.String()
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if !contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return contains
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ body := HTTPBody(handler, method, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return !contains
+}
diff --git a/vendor/github.com/stretchr/testify/require/doc.go b/vendor/github.com/stretchr/testify/require/doc.go
new file mode 100644
index 0000000000..9684347245
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/require/doc.go
@@ -0,0 +1,29 @@
+// Package require implements the same assertions as the `assert` package but
+// stops test execution when a test fails.
+//
+// # Example Usage
+//
+// The following is a complete example using require in a standard test function:
+//
+// import (
+// "testing"
+// "github.com/stretchr/testify/require"
+// )
+//
+// func TestSomething(t *testing.T) {
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// require.Equal(t, a, b, "The two words should be the same.")
+//
+// }
+//
+// # Assertions
+//
+// The `require` package have same global functions as in the `assert` package,
+// but instead of returning a boolean result they call `t.FailNow()`.
+//
+// Every assertion function also takes an optional string message as the final argument,
+// allowing custom error messages to be appended to the message the assertion method outputs.
+package require
diff --git a/vendor/github.com/stretchr/testify/require/forward_requirements.go b/vendor/github.com/stretchr/testify/require/forward_requirements.go
new file mode 100644
index 0000000000..1dcb2338c4
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/require/forward_requirements.go
@@ -0,0 +1,16 @@
+package require
+
+// Assertions provides assertion methods around the
+// TestingT interface.
+type Assertions struct {
+ t TestingT
+}
+
+// New makes a new Assertions object for the specified TestingT.
+func New(t TestingT) *Assertions {
+ return &Assertions{
+ t: t,
+ }
+}
+
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go
new file mode 100644
index 0000000000..63f8521476
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/require/require.go
@@ -0,0 +1,2031 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package require
+
+import (
+ assert "github.com/stretchr/testify/assert"
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Condition uses a Comparison to assert a complex condition.
+func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Condition(t, comp, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Conditionf uses a Comparison to assert a complex condition.
+func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Conditionf(t, comp, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Contains(t, "Hello World", "World")
+// assert.Contains(t, ["Hello", "World"], "World")
+// assert.Contains(t, {"Hello": "World"}, "Hello")
+func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Contains(t, s, contains, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
+// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
+// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
+func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Containsf(t, s, contains, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExists(t TestingT, path string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.DirExists(t, path, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExistsf(t TestingT, path string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.DirExistsf(t, path, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
+func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ElementsMatch(t, listA, listB, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ElementsMatchf(t, listA, listB, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Empty(t, obj)
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Empty(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Emptyf(t, obj, "error message %s", "formatted")
+func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Emptyf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(t, 123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Equal(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualError(t, err, expectedErrorString)
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EqualError(t, theError, errString, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
+func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EqualErrorf(t, theError, errString, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EqualExportedValues asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
+// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
+func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EqualExportedValues(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EqualExportedValuesf asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
+// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
+func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EqualExportedValuesf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValues(t, uint32(123), int32(123))
+func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EqualValues(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
+func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EqualValuesf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Equalf asserts that two objects are equal.
+//
+// assert.Equalf(t, 123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Equalf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err) {
+// assert.Equal(t, expectedError, err)
+// }
+func Error(t TestingT, err error, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Error(t, err, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ErrorAs(t, err, target, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ErrorAsf(t, err, target, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ErrorContains asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// assert.ErrorContains(t, err, expectedErrorSubString)
+func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ErrorContains(t, theError, contains, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
+func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ErrorContainsf(t, theError, contains, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ErrorIs(t, err, target, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.ErrorIsf(t, err, target, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Errorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func Errorf(t TestingT, err error, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Errorf(t, err, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Eventually asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
+func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EventuallyWithT asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// assert.EventuallyWithT(t, func(c *assert.CollectT) {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EventuallyWithT(t, condition, waitFor, tick, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// EventuallyWithTf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.EventuallyWithTf(t, condition, waitFor, tick, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Eventuallyf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// assert.Exactly(t, int32(123), int64(123))
+func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Exactly(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
+func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Exactlyf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Fail reports a failure through
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Fail(t, failureMessage, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// FailNow fails test
+func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.FailNow(t, failureMessage, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// FailNowf fails test
+func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.FailNowf(t, failureMessage, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Failf reports a failure through
+func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Failf(t, failureMessage, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// False asserts that the specified value is false.
+//
+// assert.False(t, myBool)
+func False(t TestingT, value bool, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.False(t, value, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Falsef asserts that the specified value is false.
+//
+// assert.Falsef(t, myBool, "error message %s", "formatted")
+func Falsef(t TestingT, value bool, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Falsef(t, value, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func FileExists(t TestingT, path string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.FileExists(t, path, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func FileExistsf(t TestingT, path string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.FileExistsf(t, path, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Greater asserts that the first element is greater than the second
+//
+// assert.Greater(t, 2, 1)
+// assert.Greater(t, float64(2), float64(1))
+// assert.Greater(t, "b", "a")
+func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Greater(t, e1, e2, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// GreaterOrEqual asserts that the first element is greater than or equal to the second
+//
+// assert.GreaterOrEqual(t, 2, 1)
+// assert.GreaterOrEqual(t, 2, 2)
+// assert.GreaterOrEqual(t, "b", "a")
+// assert.GreaterOrEqual(t, "b", "b")
+func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.GreaterOrEqual(t, e1, e2, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// GreaterOrEqualf asserts that the first element is greater than or equal to the second
+//
+// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
+// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
+func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.GreaterOrEqualf(t, e1, e2, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Greaterf asserts that the first element is greater than the second
+//
+// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
+// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
+// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
+func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Greaterf(t, e1, e2, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPStatusCode(t, handler, method, url, values, statuscode, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPStatusCodef(t, handler, method, url, values, statuscode, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Implements(t, interfaceObject, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Implementsf(t, interfaceObject, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, 22/7.0, 0.01)
+func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InDelta(t, expected, actual, delta, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
+func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InDeltaf(t, expected, actual, delta, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsDecreasing asserts that the collection is decreasing
+//
+// assert.IsDecreasing(t, []int{2, 1, 0})
+// assert.IsDecreasing(t, []float{2, 1})
+// assert.IsDecreasing(t, []string{"b", "a"})
+func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsDecreasing(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
+// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsDecreasingf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+// assert.IsIncreasing(t, []int{1, 2, 3})
+// assert.IsIncreasing(t, []float{1, 2})
+// assert.IsIncreasing(t, []string{"a", "b"})
+func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsIncreasing(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
+// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsIncreasingf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+// assert.IsNonDecreasing(t, []int{1, 1, 2})
+// assert.IsNonDecreasing(t, []float{1, 2})
+// assert.IsNonDecreasing(t, []string{"a", "b"})
+func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsNonDecreasing(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
+// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsNonDecreasingf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+// assert.IsNonIncreasing(t, []int{2, 1, 1})
+// assert.IsNonIncreasing(t, []float{2, 1})
+// assert.IsNonIncreasing(t, []string{"b", "a"})
+func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsNonIncreasing(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
+// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsNonIncreasingf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsType asserts that the specified objects are of the same type.
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsType(t, expectedType, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.IsTypef(t, expectedType, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.JSONEq(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.JSONEqf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(t, mySlice, 3)
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Len(t, object, length, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
+func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Lenf(t, object, length, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Less asserts that the first element is less than the second
+//
+// assert.Less(t, 1, 2)
+// assert.Less(t, float64(1), float64(2))
+// assert.Less(t, "a", "b")
+func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Less(t, e1, e2, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// LessOrEqual asserts that the first element is less than or equal to the second
+//
+// assert.LessOrEqual(t, 1, 2)
+// assert.LessOrEqual(t, 2, 2)
+// assert.LessOrEqual(t, "a", "b")
+// assert.LessOrEqual(t, "b", "b")
+func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.LessOrEqual(t, e1, e2, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// LessOrEqualf asserts that the first element is less than or equal to the second
+//
+// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
+// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
+// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
+// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
+func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.LessOrEqualf(t, e1, e2, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Lessf asserts that the first element is less than the second
+//
+// assert.Lessf(t, 1, 2, "error message %s", "formatted")
+// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
+// assert.Lessf(t, "a", "b", "error message %s", "formatted")
+func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Lessf(t, e1, e2, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Negative asserts that the specified element is negative
+//
+// assert.Negative(t, -1)
+// assert.Negative(t, -1.23)
+func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Negative(t, e, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Negativef asserts that the specified element is negative
+//
+// assert.Negativef(t, -1, "error message %s", "formatted")
+// assert.Negativef(t, -1.23, "error message %s", "formatted")
+func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Negativef(t, e, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond)
+func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Never(t, condition, waitFor, tick, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Neverf(t, condition, waitFor, tick, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(t, err)
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Nil(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// assert.Nilf(t, err, "error message %s", "formatted")
+func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Nilf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoDirExists(t, path, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoDirExistsf(t, path, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(t, err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoError(t, err, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoErrorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoErrorf(t TestingT, err error, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoErrorf(t, err, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoFileExists(t, path, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoFileExistsf(t, path, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContains(t, "Hello World", "Earth")
+// assert.NotContains(t, ["Hello", "World"], "Earth")
+// assert.NotContains(t, {"Hello": "World"}, "Earth")
+func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotContains(t, s, contains, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
+func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotContainsf(t, s, contains, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmpty(t, obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotEmpty(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotEmptyf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(t, obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotEqual(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotEqualValues asserts that two objects are not equal even when converted to the same type
+//
+// assert.NotEqualValues(t, obj1, obj2)
+func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotEqualValues(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
+//
+// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
+func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotEqualValuesf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotEqualf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotErrorIs(t, err, target, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotErrorIsf(t, err, target, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(t, err)
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotNil(t, object, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// assert.NotNilf(t, err, "error message %s", "formatted")
+func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotNilf(t, object, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(t, func(){ RemainCalm() })
+func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotPanics(t, f, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
+func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotPanicsf(t, f, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotRegexp(t, rx, str, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
+// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
+func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotRegexpf(t, rx, str, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotSame asserts that two pointers do not reference the same object.
+//
+// assert.NotSame(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotSame(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotSamef(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotSubset(t, list, subset, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotSubsetf(t, list, subset, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotZero(t, i, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotZerof(t, i, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(t, func(){ GoCrazy() })
+func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Panics(t, f, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.PanicsWithError(t, errString, f, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.PanicsWithErrorf(t, errString, f, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.PanicsWithValue(t, expected, f, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.PanicsWithValuef(t, expected, f, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
+func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Panicsf(t, f, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Positive asserts that the specified element is positive
+//
+// assert.Positive(t, 1)
+// assert.Positive(t, 1.23)
+func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Positive(t, e, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Positivef asserts that the specified element is positive
+//
+// assert.Positivef(t, 1, "error message %s", "formatted")
+// assert.Positivef(t, 1.23, "error message %s", "formatted")
+func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Positivef(t, e, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Regexp(t, rx, str, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
+// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
+func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Regexpf(t, rx, str, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Same asserts that two pointers reference the same object.
+//
+// assert.Same(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Same(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Samef asserts that two pointers reference the same object.
+//
+// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Samef(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Subset(t, list, subset, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Subsetf(t, list, subset, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// True asserts that the specified value is true.
+//
+// assert.True(t, myBool)
+func True(t TestingT, value bool, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.True(t, value, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Truef asserts that the specified value is true.
+//
+// assert.Truef(t, myBool, "error message %s", "formatted")
+func Truef(t TestingT, value bool, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Truef(t, value, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
+func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.WithinDurationf(t, expected, actual, delta, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// WithinRange asserts that a time is within a time range (inclusive).
+//
+// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
+func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.WithinRange(t, actual, start, end, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// WithinRangef asserts that a time is within a time range (inclusive).
+//
+// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
+func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.WithinRangef(t, actual, start, end, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// YAMLEq asserts that two YAML strings are equivalent.
+func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.YAMLEq(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.YAMLEqf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Zero asserts that i is the zero value for its type.
+func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Zero(t, i, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Zerof asserts that i is the zero value for its type.
+func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Zerof(t, i, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
diff --git a/vendor/github.com/stretchr/testify/require/require.go.tmpl b/vendor/github.com/stretchr/testify/require/require.go.tmpl
new file mode 100644
index 0000000000..55e42ddebd
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/require/require.go.tmpl
@@ -0,0 +1,6 @@
+{{.Comment}}
+func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
+ if h, ok := t.(tHelper); ok { h.Helper() }
+ if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
+ t.FailNow()
+}
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go
new file mode 100644
index 0000000000..3b5b09330a
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go
@@ -0,0 +1,1599 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package require
+
+import (
+ assert "github.com/stretchr/testify/assert"
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Condition uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Condition(a.t, comp, msgAndArgs...)
+}
+
+// Conditionf uses a Comparison to assert a complex condition.
+func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Conditionf(a.t, comp, msg, args...)
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Contains("Hello World", "World")
+// a.Contains(["Hello", "World"], "World")
+// a.Contains({"Hello": "World"}, "Hello")
+func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Contains(a.t, s, contains, msgAndArgs...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Containsf("Hello World", "World", "error message %s", "formatted")
+// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
+// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
+func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Containsf(a.t, s, contains, msg, args...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ DirExists(a.t, path, msgAndArgs...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ DirExistsf(a.t, path, msg, args...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
+func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ElementsMatch(a.t, listA, listB, msgAndArgs...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ElementsMatchf(a.t, listA, listB, msg, args...)
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Empty(obj)
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Empty(a.t, object, msgAndArgs...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Emptyf(obj, "error message %s", "formatted")
+func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Emptyf(a.t, object, msg, args...)
+}
+
+// Equal asserts that two objects are equal.
+//
+// a.Equal(123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Equal(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualError(err, expectedErrorString)
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
+func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EqualErrorf(a.t, theError, errString, msg, args...)
+}
+
+// EqualExportedValues asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true
+// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false
+func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EqualExportedValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualExportedValuesf asserts that the types of two objects are equal and their public
+// fields are also equal. This is useful for comparing structs that have private fields
+// that could potentially differ.
+//
+// type S struct {
+// Exported int
+// notExported int
+// }
+// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
+// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
+func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EqualExportedValuesf(a.t, expected, actual, msg, args...)
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValues(uint32(123), int32(123))
+func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
+func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// a.Equalf(123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Equalf(a.t, expected, actual, msg, args...)
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Error(err) {
+// assert.Equal(t, expectedError, err)
+// }
+func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Error(a.t, err, msgAndArgs...)
+}
+
+// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ErrorAs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value.
+// This is a wrapper for errors.As.
+func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ErrorAsf(a.t, err, target, msg, args...)
+}
+
+// ErrorContains asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// a.ErrorContains(err, expectedErrorSubString)
+func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ErrorContains(a.t, theError, contains, msgAndArgs...)
+}
+
+// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
+// and that the error contains the specified substring.
+//
+// actualObj, err := SomeFunction()
+// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
+func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ErrorContainsf(a.t, theError, contains, msg, args...)
+}
+
+// ErrorIs asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// ErrorIsf asserts that at least one of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ ErrorIsf(a.t, err, target, msg, args...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Errorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func (a *Assertions) Errorf(err error, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Errorf(a.t, err, msg, args...)
+}
+
+// Eventually asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// EventuallyWithT asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// a.EventuallyWithT(func(c *assert.CollectT) {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// EventuallyWithTf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick. In contrast to Eventually,
+// it supplies a CollectT to the condition function, so that the condition
+// function can use the CollectT to call other assertions.
+// The condition is considered "met" if no errors are raised in a tick.
+// The supplied CollectT collects all errors from one tick (if there are any).
+// If the condition is not met before waitFor, the collected errors of
+// the last tick are copied to t.
+//
+// externalValue := false
+// go func() {
+// time.Sleep(8*time.Second)
+// externalValue = true
+// }()
+// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
+// // add assertions as needed; any assertion failure will fail the current tick
+// assert.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Eventuallyf asserts that given condition will be met in waitFor time,
+// periodically checking target function each tick.
+//
+// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Eventuallyf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// a.Exactly(int32(123), int64(123))
+func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted")
+func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Exactlyf(a.t, expected, actual, msg, args...)
+}
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNow fails test
+func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ FailNow(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNowf fails test
+func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ FailNowf(a.t, failureMessage, msg, args...)
+}
+
+// Failf reports a failure through
+func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Failf(a.t, failureMessage, msg, args...)
+}
+
+// False asserts that the specified value is false.
+//
+// a.False(myBool)
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ False(a.t, value, msgAndArgs...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// a.Falsef(myBool, "error message %s", "formatted")
+func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Falsef(a.t, value, msg, args...)
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ FileExists(a.t, path, msgAndArgs...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ FileExistsf(a.t, path, msg, args...)
+}
+
+// Greater asserts that the first element is greater than the second
+//
+// a.Greater(2, 1)
+// a.Greater(float64(2), float64(1))
+// a.Greater("b", "a")
+func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Greater(a.t, e1, e2, msgAndArgs...)
+}
+
+// GreaterOrEqual asserts that the first element is greater than or equal to the second
+//
+// a.GreaterOrEqual(2, 1)
+// a.GreaterOrEqual(2, 2)
+// a.GreaterOrEqual("b", "a")
+// a.GreaterOrEqual("b", "b")
+func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ GreaterOrEqual(a.t, e1, e2, msgAndArgs...)
+}
+
+// GreaterOrEqualf asserts that the first element is greater than or equal to the second
+//
+// a.GreaterOrEqualf(2, 1, "error message %s", "formatted")
+// a.GreaterOrEqualf(2, 2, "error message %s", "formatted")
+// a.GreaterOrEqualf("b", "a", "error message %s", "formatted")
+// a.GreaterOrEqualf("b", "b", "error message %s", "formatted")
+func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ GreaterOrEqualf(a.t, e1, e2, msg, args...)
+}
+
+// Greaterf asserts that the first element is greater than the second
+//
+// a.Greaterf(2, 1, "error message %s", "formatted")
+// a.Greaterf(float64(2), float64(1), "error message %s", "formatted")
+// a.Greaterf("b", "a", "error message %s", "formatted")
+func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Greaterf(a.t, e1, e2, msg, args...)
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPError(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPErrorf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPStatusCode asserts that a specified handler returns a specified status code.
+//
+// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...)
+}
+
+// HTTPStatusCodef asserts that a specified handler returns a specified status code.
+//
+// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...)
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// a.Implements((*MyInterface)(nil), new(MyObject))
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Implementsf(a.t, interfaceObject, object, msg, args...)
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// a.InDelta(math.Pi, 22/7.0, 0.01)
+func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
+func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InDeltaf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// IsDecreasing asserts that the collection is decreasing
+//
+// a.IsDecreasing([]int{2, 1, 0})
+// a.IsDecreasing([]float{2, 1})
+// a.IsDecreasing([]string{"b", "a"})
+func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsDecreasingf asserts that the collection is decreasing
+//
+// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted")
+// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted")
+// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsDecreasingf(a.t, object, msg, args...)
+}
+
+// IsIncreasing asserts that the collection is increasing
+//
+// a.IsIncreasing([]int{1, 2, 3})
+// a.IsIncreasing([]float{1, 2})
+// a.IsIncreasing([]string{"a", "b"})
+func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsIncreasingf asserts that the collection is increasing
+//
+// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted")
+// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted")
+// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsIncreasingf(a.t, object, msg, args...)
+}
+
+// IsNonDecreasing asserts that the collection is not decreasing
+//
+// a.IsNonDecreasing([]int{1, 1, 2})
+// a.IsNonDecreasing([]float{1, 2})
+// a.IsNonDecreasing([]string{"a", "b"})
+func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsNonDecreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonDecreasingf asserts that the collection is not decreasing
+//
+// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted")
+// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted")
+// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted")
+func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsNonDecreasingf(a.t, object, msg, args...)
+}
+
+// IsNonIncreasing asserts that the collection is not increasing
+//
+// a.IsNonIncreasing([]int{2, 1, 1})
+// a.IsNonIncreasing([]float{2, 1})
+// a.IsNonIncreasing([]string{"b", "a"})
+func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsNonIncreasing(a.t, object, msgAndArgs...)
+}
+
+// IsNonIncreasingf asserts that the collection is not increasing
+//
+// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted")
+// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted")
+// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted")
+func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsNonIncreasingf(a.t, object, msg, args...)
+}
+
+// IsType asserts that the specified objects are of the same type.
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsType(a.t, expectedType, object, msgAndArgs...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ IsTypef(a.t, expectedType, object, msg, args...)
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ JSONEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ JSONEqf(a.t, expected, actual, msg, args...)
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// a.Len(mySlice, 3)
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Len(a.t, object, length, msgAndArgs...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// a.Lenf(mySlice, 3, "error message %s", "formatted")
+func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Lenf(a.t, object, length, msg, args...)
+}
+
+// Less asserts that the first element is less than the second
+//
+// a.Less(1, 2)
+// a.Less(float64(1), float64(2))
+// a.Less("a", "b")
+func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Less(a.t, e1, e2, msgAndArgs...)
+}
+
+// LessOrEqual asserts that the first element is less than or equal to the second
+//
+// a.LessOrEqual(1, 2)
+// a.LessOrEqual(2, 2)
+// a.LessOrEqual("a", "b")
+// a.LessOrEqual("b", "b")
+func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ LessOrEqual(a.t, e1, e2, msgAndArgs...)
+}
+
+// LessOrEqualf asserts that the first element is less than or equal to the second
+//
+// a.LessOrEqualf(1, 2, "error message %s", "formatted")
+// a.LessOrEqualf(2, 2, "error message %s", "formatted")
+// a.LessOrEqualf("a", "b", "error message %s", "formatted")
+// a.LessOrEqualf("b", "b", "error message %s", "formatted")
+func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ LessOrEqualf(a.t, e1, e2, msg, args...)
+}
+
+// Lessf asserts that the first element is less than the second
+//
+// a.Lessf(1, 2, "error message %s", "formatted")
+// a.Lessf(float64(1), float64(2), "error message %s", "formatted")
+// a.Lessf("a", "b", "error message %s", "formatted")
+func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Lessf(a.t, e1, e2, msg, args...)
+}
+
+// Negative asserts that the specified element is negative
+//
+// a.Negative(-1)
+// a.Negative(-1.23)
+func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Negative(a.t, e, msgAndArgs...)
+}
+
+// Negativef asserts that the specified element is negative
+//
+// a.Negativef(-1, "error message %s", "formatted")
+// a.Negativef(-1.23, "error message %s", "formatted")
+func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Negativef(a.t, e, msg, args...)
+}
+
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Never(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Neverf(a.t, condition, waitFor, tick, msg, args...)
+}
+
+// Nil asserts that the specified object is nil.
+//
+// a.Nil(err)
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Nil(a.t, object, msgAndArgs...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// a.Nilf(err, "error message %s", "formatted")
+func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Nilf(a.t, object, msg, args...)
+}
+
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoDirExists(a.t, path, msgAndArgs...)
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoDirExistsf(a.t, path, msg, args...)
+}
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoError(err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoError(a.t, err, msgAndArgs...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoErrorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoErrorf(a.t, err, msg, args...)
+}
+
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoFileExists(a.t, path, msgAndArgs...)
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoFileExistsf(a.t, path, msg, args...)
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContains("Hello World", "Earth")
+// a.NotContains(["Hello", "World"], "Earth")
+// a.NotContains({"Hello": "World"}, "Earth")
+func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
+// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
+// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
+func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotContainsf(a.t, s, contains, msg, args...)
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmpty(obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotEmpty(a.t, object, msgAndArgs...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmptyf(obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotEmptyf(a.t, object, msg, args...)
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// a.NotEqual(obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualValues asserts that two objects are not equal even when converted to the same type
+//
+// a.NotEqualValues(obj1, obj2)
+func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotEqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
+//
+// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted")
+func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotEqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotEqualf(a.t, expected, actual, msg, args...)
+}
+
+// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotErrorIs(a.t, err, target, msgAndArgs...)
+}
+
+// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// This is a wrapper for errors.Is.
+func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotErrorIsf(a.t, err, target, msg, args...)
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// a.NotNil(err)
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotNil(a.t, object, msgAndArgs...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// a.NotNilf(err, "error message %s", "formatted")
+func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotNilf(a.t, object, msg, args...)
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanics(func(){ RemainCalm() })
+func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotPanics(a.t, f, msgAndArgs...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
+func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotPanicsf(a.t, f, msg, args...)
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
+// a.NotRegexp("^start", "it's not starting")
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotRegexp(a.t, rx, str, msgAndArgs...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
+// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotRegexpf(a.t, rx, str, msg, args...)
+}
+
+// NotSame asserts that two pointers do not reference the same object.
+//
+// a.NotSame(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotSame(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// a.NotSamef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotSamef(a.t, expected, actual, msg, args...)
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotSubset(a.t, list, subset, msgAndArgs...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotSubsetf(a.t, list, subset, msg, args...)
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotZero(a.t, i, msgAndArgs...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotZerof(a.t, i, msg, args...)
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panics(func(){ GoCrazy() })
+func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Panics(a.t, f, msgAndArgs...)
+}
+
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithError("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ PanicsWithError(a.t, errString, f, msgAndArgs...)
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ PanicsWithErrorf(a.t, errString, f, msg, args...)
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ PanicsWithValue(a.t, expected, f, msgAndArgs...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ PanicsWithValuef(a.t, expected, f, msg, args...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Panicsf(a.t, f, msg, args...)
+}
+
+// Positive asserts that the specified element is positive
+//
+// a.Positive(1)
+// a.Positive(1.23)
+func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Positive(a.t, e, msgAndArgs...)
+}
+
+// Positivef asserts that the specified element is positive
+//
+// a.Positivef(1, "error message %s", "formatted")
+// a.Positivef(1.23, "error message %s", "formatted")
+func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Positivef(a.t, e, msg, args...)
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// a.Regexp(regexp.MustCompile("start"), "it's starting")
+// a.Regexp("start...$", "it's not starting")
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Regexp(a.t, rx, str, msgAndArgs...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
+// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Regexpf(a.t, rx, str, msg, args...)
+}
+
+// Same asserts that two pointers reference the same object.
+//
+// a.Same(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Same(a.t, expected, actual, msgAndArgs...)
+}
+
+// Samef asserts that two pointers reference the same object.
+//
+// a.Samef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Samef(a.t, expected, actual, msg, args...)
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Subset(a.t, list, subset, msgAndArgs...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Subsetf(a.t, list, subset, msg, args...)
+}
+
+// True asserts that the specified value is true.
+//
+// a.True(myBool)
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ True(a.t, value, msgAndArgs...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// a.Truef(myBool, "error message %s", "formatted")
+func (a *Assertions) Truef(value bool, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Truef(a.t, value, msg, args...)
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
+func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ WithinDurationf(a.t, expected, actual, delta, msg, args...)
+}
+
+// WithinRange asserts that a time is within a time range (inclusive).
+//
+// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
+func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ WithinRange(a.t, actual, start, end, msgAndArgs...)
+}
+
+// WithinRangef asserts that a time is within a time range (inclusive).
+//
+// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
+func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ WithinRangef(a.t, actual, start, end, msg, args...)
+}
+
+// YAMLEq asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ YAMLEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ YAMLEqf(a.t, expected, actual, msg, args...)
+}
+
+// Zero asserts that i is the zero value for its type.
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Zero(a.t, i, msgAndArgs...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Zerof(a.t, i, msg, args...)
+}
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl
new file mode 100644
index 0000000000..54124df1d3
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl
@@ -0,0 +1,5 @@
+{{.CommentWithoutT "a"}}
+func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) {
+ if h, ok := a.t.(tHelper); ok { h.Helper() }
+ {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
+}
diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go
new file mode 100644
index 0000000000..91772dfeb9
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/require/requirements.go
@@ -0,0 +1,29 @@
+package require
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+ FailNow()
+}
+
+type tHelper interface {
+ Helper()
+}
+
+// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
+// for table driven tests.
+type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{})
+
+// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
+// for table driven tests.
+type ValueAssertionFunc func(TestingT, interface{}, ...interface{})
+
+// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
+// for table driven tests.
+type BoolAssertionFunc func(TestingT, bool, ...interface{})
+
+// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
+// for table driven tests.
+type ErrorAssertionFunc func(TestingT, error, ...interface{})
+
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/tmc/grpc-websocket-proxy/LICENSE b/vendor/github.com/tmc/grpc-websocket-proxy/LICENSE
new file mode 100644
index 0000000000..95d0bc81f1
--- /dev/null
+++ b/vendor/github.com/tmc/grpc-websocket-proxy/LICENSE
@@ -0,0 +1,7 @@
+Copyright (C) 2016 Travis Cline
+
+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/tmc/grpc-websocket-proxy/wsproxy/doc.go b/vendor/github.com/tmc/grpc-websocket-proxy/wsproxy/doc.go
new file mode 100644
index 0000000000..baf9545e28
--- /dev/null
+++ b/vendor/github.com/tmc/grpc-websocket-proxy/wsproxy/doc.go
@@ -0,0 +1,2 @@
+// Package wsproxy implements a websocket proxy for grpc-gateway backed services
+package wsproxy
diff --git a/vendor/github.com/tmc/grpc-websocket-proxy/wsproxy/websocket_proxy.go b/vendor/github.com/tmc/grpc-websocket-proxy/wsproxy/websocket_proxy.go
new file mode 100644
index 0000000000..70921627af
--- /dev/null
+++ b/vendor/github.com/tmc/grpc-websocket-proxy/wsproxy/websocket_proxy.go
@@ -0,0 +1,350 @@
+package wsproxy
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/gorilla/websocket"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/net/context"
+)
+
+// MethodOverrideParam defines the special URL parameter that is translated into the subsequent proxied streaming http request's method.
+//
+// Deprecated: it is preferable to use the Options parameters to WebSocketProxy to supply parameters.
+var MethodOverrideParam = "method"
+
+// TokenCookieName defines the cookie name that is translated to an 'Authorization: Bearer' header in the streaming http request's headers.
+//
+// Deprecated: it is preferable to use the Options parameters to WebSocketProxy to supply parameters.
+var TokenCookieName = "token"
+
+// RequestMutatorFunc can supply an alternate outgoing request.
+type RequestMutatorFunc func(incoming *http.Request, outgoing *http.Request) *http.Request
+
+// Proxy provides websocket transport upgrade to compatible endpoints.
+type Proxy struct {
+ h http.Handler
+ logger Logger
+ maxRespBodyBufferBytes int
+ methodOverrideParam string
+ tokenCookieName string
+ requestMutator RequestMutatorFunc
+ headerForwarder func(header string) bool
+ pingInterval time.Duration
+ pingWait time.Duration
+ pongWait time.Duration
+}
+
+// Logger collects log messages.
+type Logger interface {
+ Warnln(...interface{})
+ Debugln(...interface{})
+}
+
+func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if !websocket.IsWebSocketUpgrade(r) {
+ p.h.ServeHTTP(w, r)
+ return
+ }
+ p.proxy(w, r)
+}
+
+// Option allows customization of the proxy.
+type Option func(*Proxy)
+
+// WithMaxRespBodyBufferSize allows specification of a custom size for the
+// buffer used while reading the response body. By default, the bufio.Scanner
+// used to read the response body sets the maximum token size to MaxScanTokenSize.
+func WithMaxRespBodyBufferSize(nBytes int) Option {
+ return func(p *Proxy) {
+ p.maxRespBodyBufferBytes = nBytes
+ }
+}
+
+// WithMethodParamOverride allows specification of the special http parameter that is used in the proxied streaming request.
+func WithMethodParamOverride(param string) Option {
+ return func(p *Proxy) {
+ p.methodOverrideParam = param
+ }
+}
+
+// WithTokenCookieName allows specification of the cookie that is supplied as an upstream 'Authorization: Bearer' http header.
+func WithTokenCookieName(param string) Option {
+ return func(p *Proxy) {
+ p.tokenCookieName = param
+ }
+}
+
+// WithRequestMutator allows a custom RequestMutatorFunc to be supplied.
+func WithRequestMutator(fn RequestMutatorFunc) Option {
+ return func(p *Proxy) {
+ p.requestMutator = fn
+ }
+}
+
+// WithForwardedHeaders allows controlling which headers are forwarded.
+func WithForwardedHeaders(fn func(header string) bool) Option {
+ return func(p *Proxy) {
+ p.headerForwarder = fn
+ }
+}
+
+// WithLogger allows a custom FieldLogger to be supplied
+func WithLogger(logger Logger) Option {
+ return func(p *Proxy) {
+ p.logger = logger
+ }
+}
+
+// WithPingControl allows specification of ping pong control. The interval
+// parameter specifies the pingInterval between pings. The allowed wait time
+// for a pong response is (pingInterval * 10) / 9.
+func WithPingControl(interval time.Duration) Option {
+ return func(proxy *Proxy) {
+ proxy.pingInterval = interval
+ proxy.pongWait = (interval * 10) / 9
+ proxy.pingWait = proxy.pongWait / 6
+ }
+}
+
+var defaultHeadersToForward = map[string]bool{
+ "Origin": true,
+ "origin": true,
+ "Referer": true,
+ "referer": true,
+}
+
+func defaultHeaderForwarder(header string) bool {
+ return defaultHeadersToForward[header]
+}
+
+// WebsocketProxy attempts to expose the underlying handler as a bidi websocket stream with newline-delimited
+// JSON as the content encoding.
+//
+// The HTTP Authorization header is either populated from the Sec-Websocket-Protocol field or by a cookie.
+// The cookie name is specified by the TokenCookieName value.
+//
+// example:
+// Sec-Websocket-Protocol: Bearer, foobar
+// is converted to:
+// Authorization: Bearer foobar
+//
+// Method can be overwritten with the MethodOverrideParam get parameter in the requested URL
+func WebsocketProxy(h http.Handler, opts ...Option) http.Handler {
+ p := &Proxy{
+ h: h,
+ logger: logrus.New(),
+ methodOverrideParam: MethodOverrideParam,
+ tokenCookieName: TokenCookieName,
+ headerForwarder: defaultHeaderForwarder,
+ }
+ for _, o := range opts {
+ o(p)
+ }
+ return p
+}
+
+// TODO(tmc): allow modification of upgrader settings?
+var upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+ CheckOrigin: func(r *http.Request) bool { return true },
+}
+
+func isClosedConnError(err error) bool {
+ str := err.Error()
+ if strings.Contains(str, "use of closed network connection") {
+ return true
+ }
+ return websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway)
+}
+
+func (p *Proxy) proxy(w http.ResponseWriter, r *http.Request) {
+ var responseHeader http.Header
+ // If Sec-WebSocket-Protocol starts with "Bearer", respond in kind.
+ // TODO(tmc): consider customizability/extension point here.
+ if strings.HasPrefix(r.Header.Get("Sec-WebSocket-Protocol"), "Bearer") {
+ responseHeader = http.Header{
+ "Sec-WebSocket-Protocol": []string{"Bearer"},
+ }
+ }
+ conn, err := upgrader.Upgrade(w, r, responseHeader)
+ if err != nil {
+ p.logger.Warnln("error upgrading websocket:", err)
+ return
+ }
+ defer conn.Close()
+
+ ctx, cancelFn := context.WithCancel(context.Background())
+ defer cancelFn()
+
+ requestBodyR, requestBodyW := io.Pipe()
+ request, err := http.NewRequestWithContext(r.Context(), r.Method, r.URL.String(), requestBodyR)
+ if err != nil {
+ p.logger.Warnln("error preparing request:", err)
+ return
+ }
+ if swsp := r.Header.Get("Sec-WebSocket-Protocol"); swsp != "" {
+ request.Header.Set("Authorization", transformSubProtocolHeader(swsp))
+ }
+ for header := range r.Header {
+ if p.headerForwarder(header) {
+ request.Header.Set(header, r.Header.Get(header))
+ }
+ }
+ // If token cookie is present, populate Authorization header from the cookie instead.
+ if cookie, err := r.Cookie(p.tokenCookieName); err == nil {
+ request.Header.Set("Authorization", "Bearer "+cookie.Value)
+ }
+ if m := r.URL.Query().Get(p.methodOverrideParam); m != "" {
+ request.Method = m
+ }
+
+ if p.requestMutator != nil {
+ request = p.requestMutator(r, request)
+ }
+
+ responseBodyR, responseBodyW := io.Pipe()
+ response := newInMemoryResponseWriter(responseBodyW)
+ go func() {
+ <-ctx.Done()
+ p.logger.Debugln("closing pipes")
+ requestBodyW.CloseWithError(io.EOF)
+ responseBodyW.CloseWithError(io.EOF)
+ response.closed <- true
+ }()
+
+ go func() {
+ defer cancelFn()
+ p.h.ServeHTTP(response, request)
+ }()
+
+ // read loop -- take messages from websocket and write to http request
+ go func() {
+ if p.pingInterval > 0 && p.pingWait > 0 && p.pongWait > 0 {
+ conn.SetReadDeadline(time.Now().Add(p.pongWait))
+ conn.SetPongHandler(func(string) error { conn.SetReadDeadline(time.Now().Add(p.pongWait)); return nil })
+ }
+ defer func() {
+ cancelFn()
+ }()
+ for {
+ select {
+ case <-ctx.Done():
+ p.logger.Debugln("read loop done")
+ return
+ default:
+ }
+ p.logger.Debugln("[read] reading from socket.")
+ _, payload, err := conn.ReadMessage()
+ if err != nil {
+ if isClosedConnError(err) {
+ p.logger.Debugln("[read] websocket closed:", err)
+ return
+ }
+ p.logger.Warnln("error reading websocket message:", err)
+ return
+ }
+ p.logger.Debugln("[read] read payload:", string(payload))
+ p.logger.Debugln("[read] writing to requestBody:")
+ n, err := requestBodyW.Write(payload)
+ requestBodyW.Write([]byte("\n"))
+ p.logger.Debugln("[read] wrote to requestBody", n)
+ if err != nil {
+ p.logger.Warnln("[read] error writing message to upstream http server:", err)
+ return
+ }
+ }
+ }()
+ // ping write loop
+ if p.pingInterval > 0 && p.pingWait > 0 && p.pongWait > 0 {
+ go func() {
+ ticker := time.NewTicker(p.pingInterval)
+ defer func() {
+ ticker.Stop()
+ conn.Close()
+ }()
+ for {
+ select {
+ case <-ctx.Done():
+ p.logger.Debugln("ping loop done")
+ return
+ case <-ticker.C:
+ conn.SetWriteDeadline(time.Now().Add(p.pingWait))
+ if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {
+ return
+ }
+ }
+ }
+ }()
+ }
+ // write loop -- take messages from response and write to websocket
+ scanner := bufio.NewScanner(responseBodyR)
+
+ // if maxRespBodyBufferSize has been specified, use custom buffer for scanner
+ var scannerBuf []byte
+ if p.maxRespBodyBufferBytes > 0 {
+ scannerBuf = make([]byte, 0, 64*1024)
+ scanner.Buffer(scannerBuf, p.maxRespBodyBufferBytes)
+ }
+
+ for scanner.Scan() {
+ if len(scanner.Bytes()) == 0 {
+ p.logger.Warnln("[write] empty scan", scanner.Err())
+ continue
+ }
+ p.logger.Debugln("[write] scanned", scanner.Text())
+ if err = conn.WriteMessage(websocket.TextMessage, scanner.Bytes()); err != nil {
+ p.logger.Warnln("[write] error writing websocket message:", err)
+ return
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ p.logger.Warnln("scanner err:", err)
+ }
+}
+
+type inMemoryResponseWriter struct {
+ io.Writer
+ header http.Header
+ code int
+ closed chan bool
+}
+
+func newInMemoryResponseWriter(w io.Writer) *inMemoryResponseWriter {
+ return &inMemoryResponseWriter{
+ Writer: w,
+ header: http.Header{},
+ closed: make(chan bool, 1),
+ }
+}
+
+// IE and Edge do not delimit Sec-WebSocket-Protocol strings with spaces
+func transformSubProtocolHeader(header string) string {
+ tokens := strings.SplitN(header, "Bearer,", 2)
+
+ if len(tokens) < 2 {
+ return ""
+ }
+
+ return fmt.Sprintf("Bearer %v", strings.Trim(tokens[1], " "))
+}
+
+func (w *inMemoryResponseWriter) Write(b []byte) (int, error) {
+ return w.Writer.Write(b)
+}
+func (w *inMemoryResponseWriter) Header() http.Header {
+ return w.header
+}
+func (w *inMemoryResponseWriter) WriteHeader(code int) {
+ w.code = code
+}
+func (w *inMemoryResponseWriter) CloseNotify() <-chan bool {
+ return w.closed
+}
+func (w *inMemoryResponseWriter) Flush() {}
diff --git a/vendor/github.com/xiang90/probing/.gitignore b/vendor/github.com/xiang90/probing/.gitignore
new file mode 100644
index 0000000000..daf913b1b3
--- /dev/null
+++ b/vendor/github.com/xiang90/probing/.gitignore
@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
diff --git a/vendor/github.com/jpillora/backoff/LICENSE b/vendor/github.com/xiang90/probing/LICENSE
similarity index 96%
rename from vendor/github.com/jpillora/backoff/LICENSE
rename to vendor/github.com/xiang90/probing/LICENSE
index 1cc708081b..cde8b8b05f 100644
--- a/vendor/github.com/jpillora/backoff/LICENSE
+++ b/vendor/github.com/xiang90/probing/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2017 Jaime Pillora
+Copyright (c) 2015 Xiang Li
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -19,3 +19,4 @@ 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/xiang90/probing/README.md b/vendor/github.com/xiang90/probing/README.md
new file mode 100644
index 0000000000..2ff682057a
--- /dev/null
+++ b/vendor/github.com/xiang90/probing/README.md
@@ -0,0 +1,39 @@
+## Getting Started
+
+### Install the handler
+
+We first need to serve the probing HTTP handler.
+
+```go
+ http.HandleFunc("/health", probing.NewHandler())
+ err := http.ListenAndServe(":12345", nil)
+ if err != nil {
+ log.Fatal("ListenAndServe: ", err)
+ }
+```
+
+### Start to probe
+
+Now we can start to probe the endpoint.
+
+``` go
+ id := "example"
+ probingInterval = 5 * time.Second
+ url := "http://example.com:12345/health"
+ p.AddHTTP(id, probingInterval, url)
+
+ time.Sleep(13 * time.Second)
+ status, err := p.Status(id)
+ fmt.Printf("Total Probing: %d, Total Loss: %d, Estimated RTT: %v, Estimated Clock Difference: %v\n",
+ status.Total(), status.Loss(), status.SRTT(), status.ClockDiff())
+ // Total Probing: 2, Total Loss: 0, Estimated RTT: 320.771µs, Estimated Clock Difference: -35.869µs
+```
+
+### TODOs:
+
+- TCP probing
+- UDP probing
+- Gossip based probing
+- More accurate RTT estimation
+- More accurate Clock difference estimation
+- Use a clock interface rather than the real clock
diff --git a/vendor/github.com/xiang90/probing/prober.go b/vendor/github.com/xiang90/probing/prober.go
new file mode 100644
index 0000000000..9431c101e3
--- /dev/null
+++ b/vendor/github.com/xiang90/probing/prober.go
@@ -0,0 +1,139 @@
+package probing
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "sync"
+ "time"
+)
+
+var (
+ ErrNotFound = errors.New("probing: id not found")
+ ErrExist = errors.New("probing: id exists")
+)
+
+type Prober interface {
+ AddHTTP(id string, probingInterval time.Duration, endpoints []string) error
+ Remove(id string) error
+ RemoveAll()
+ Reset(id string) error
+ Status(id string) (Status, error)
+}
+
+type prober struct {
+ mu sync.Mutex
+ targets map[string]*status
+ tr http.RoundTripper
+}
+
+func NewProber(tr http.RoundTripper) Prober {
+ p := &prober{targets: make(map[string]*status)}
+ if tr == nil {
+ p.tr = http.DefaultTransport
+ } else {
+ p.tr = tr
+ }
+ return p
+}
+
+func (p *prober) AddHTTP(id string, probingInterval time.Duration, endpoints []string) error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if _, ok := p.targets[id]; ok {
+ return ErrExist
+ }
+
+ s := &status{stopC: make(chan struct{})}
+ p.targets[id] = s
+
+ ticker := time.NewTicker(probingInterval)
+
+ go func() {
+ pinned := 0
+ for {
+ select {
+ case <-ticker.C:
+ start := time.Now()
+ req, err := http.NewRequest("GET", endpoints[pinned], nil)
+ if err != nil {
+ panic(err)
+ }
+ resp, err := p.tr.RoundTrip(req)
+ if err == nil && resp.StatusCode != http.StatusOK {
+ err = fmt.Errorf("got unexpected HTTP status code %s from %s", resp.Status, endpoints[pinned])
+ resp.Body.Close()
+ }
+ if err != nil {
+ s.recordFailure(err)
+ pinned = (pinned + 1) % len(endpoints)
+ continue
+ }
+
+ var hh Health
+ d := json.NewDecoder(resp.Body)
+ err = d.Decode(&hh)
+ resp.Body.Close()
+ if err != nil || !hh.OK {
+ s.recordFailure(err)
+ pinned = (pinned + 1) % len(endpoints)
+ continue
+ }
+
+ s.record(time.Since(start), hh.Now)
+ case <-s.stopC:
+ ticker.Stop()
+ return
+ }
+ }
+ }()
+
+ return nil
+}
+
+func (p *prober) Remove(id string) error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ s, ok := p.targets[id]
+ if !ok {
+ return ErrNotFound
+ }
+ close(s.stopC)
+ delete(p.targets, id)
+ return nil
+}
+
+func (p *prober) RemoveAll() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ for _, s := range p.targets {
+ close(s.stopC)
+ }
+ p.targets = make(map[string]*status)
+}
+
+func (p *prober) Reset(id string) error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ s, ok := p.targets[id]
+ if !ok {
+ return ErrNotFound
+ }
+ s.reset()
+ return nil
+}
+
+func (p *prober) Status(id string) (Status, error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ s, ok := p.targets[id]
+ if !ok {
+ return nil, ErrNotFound
+ }
+ return s, nil
+}
diff --git a/vendor/github.com/xiang90/probing/server.go b/vendor/github.com/xiang90/probing/server.go
new file mode 100644
index 0000000000..0e7b797d25
--- /dev/null
+++ b/vendor/github.com/xiang90/probing/server.go
@@ -0,0 +1,25 @@
+package probing
+
+import (
+ "encoding/json"
+ "net/http"
+ "time"
+)
+
+func NewHandler() http.Handler {
+ return &httpHealth{}
+}
+
+type httpHealth struct {
+}
+
+type Health struct {
+ OK bool
+ Now time.Time
+}
+
+func (h *httpHealth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ health := Health{OK: true, Now: time.Now()}
+ e := json.NewEncoder(w)
+ e.Encode(health)
+}
diff --git a/vendor/github.com/xiang90/probing/status.go b/vendor/github.com/xiang90/probing/status.go
new file mode 100644
index 0000000000..bb5f6599fc
--- /dev/null
+++ b/vendor/github.com/xiang90/probing/status.go
@@ -0,0 +1,108 @@
+package probing
+
+import (
+ "sync"
+ "time"
+)
+
+var (
+ // weight factor
+ α = 0.125
+)
+
+type Status interface {
+ Total() int64
+ Loss() int64
+ Health() bool
+ Err() error
+ // Estimated smoothed round trip time
+ SRTT() time.Duration
+ // Estimated clock difference
+ ClockDiff() time.Duration
+ StopNotify() <-chan struct{}
+}
+
+type status struct {
+ mu sync.Mutex
+ srtt time.Duration
+ total int64
+ loss int64
+ health bool
+ err error
+ clockdiff time.Duration
+ stopC chan struct{}
+}
+
+// SRTT = (1-α) * SRTT + α * RTT
+func (s *status) SRTT() time.Duration {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.srtt
+}
+
+func (s *status) Total() int64 {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.total
+}
+
+func (s *status) Loss() int64 {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.loss
+}
+
+func (s *status) Health() bool {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.health
+}
+
+func (s *status) Err() error {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.err
+}
+
+func (s *status) ClockDiff() time.Duration {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.clockdiff
+}
+
+func (s *status) StopNotify() <-chan struct{} {
+ return s.stopC
+}
+
+func (s *status) record(rtt time.Duration, when time.Time) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ s.total += 1
+ s.health = true
+ s.srtt = time.Duration((1-α)*float64(s.srtt) + α*float64(rtt))
+ s.clockdiff = time.Now().Sub(when) - s.srtt/2
+ s.err = nil
+}
+
+func (s *status) recordFailure(err error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ s.total++
+ s.health = false
+ s.loss += 1
+ s.err = err
+}
+
+func (s *status) reset() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ s.srtt = 0
+ s.total = 0
+ s.loss = 0
+ s.health = false
+ s.clockdiff = 0
+ s.err = nil
+}
diff --git a/vendor/go.etcd.io/bbolt/.gitignore b/vendor/go.etcd.io/bbolt/.gitignore
new file mode 100644
index 0000000000..9fa948ebf9
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/.gitignore
@@ -0,0 +1,10 @@
+*.prof
+*.test
+*.swp
+/bin/
+cover.out
+cover-*.out
+/.idea
+*.iml
+/cmd/bbolt/bbolt
+
diff --git a/vendor/go.etcd.io/bbolt/LICENSE b/vendor/go.etcd.io/bbolt/LICENSE
new file mode 100644
index 0000000000..004e77fe5d
--- /dev/null
+++ b/vendor/go.etcd.io/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/go.etcd.io/bbolt/Makefile b/vendor/go.etcd.io/bbolt/Makefile
new file mode 100644
index 0000000000..18154c6388
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/Makefile
@@ -0,0 +1,63 @@
+BRANCH=`git rev-parse --abbrev-ref HEAD`
+COMMIT=`git rev-parse --short HEAD`
+GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)"
+
+TESTFLAGS_RACE=-race=false
+ifdef ENABLE_RACE
+ TESTFLAGS_RACE=-race=true
+endif
+
+TESTFLAGS_CPU=
+ifdef CPU
+ TESTFLAGS_CPU=-cpu=$(CPU)
+endif
+TESTFLAGS = $(TESTFLAGS_RACE) $(TESTFLAGS_CPU) $(EXTRA_TESTFLAGS)
+
+.PHONY: fmt
+fmt:
+ !(gofmt -l -s -d $(shell find . -name \*.go) | grep '[a-z]')
+
+.PHONY: lint
+lint:
+ golangci-lint run ./...
+
+.PHONY: test
+test:
+ @echo "hashmap freelist test"
+ TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} -timeout 30m
+ TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} ./cmd/bbolt
+
+ @echo "array freelist test"
+ TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} -timeout 30m
+ TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} ./cmd/bbolt
+
+.PHONY: coverage
+coverage:
+ @echo "hashmap freelist test"
+ TEST_FREELIST_TYPE=hashmap go test -v -timeout 30m \
+ -coverprofile cover-freelist-hashmap.out -covermode atomic
+
+ @echo "array freelist test"
+ TEST_FREELIST_TYPE=array go test -v -timeout 30m \
+ -coverprofile cover-freelist-array.out -covermode atomic
+
+.PHONY: gofail-enable
+gofail-enable: install-gofail
+ gofail enable .
+
+.PHONY: gofail-disable
+gofail-disable:
+ gofail disable .
+
+.PHONY: install-gofail
+install-gofail:
+ go install go.etcd.io/gofail
+
+.PHONY: test-failpoint
+test-failpoint:
+ @echo "[failpoint] hashmap freelist test"
+ TEST_FREELIST_TYPE=hashmap go test -v ${TESTFLAGS} -timeout 30m ./tests/failpoint
+
+ @echo "[failpoint] array freelist test"
+ TEST_FREELIST_TYPE=array go test -v ${TESTFLAGS} -timeout 30m ./tests/failpoint
+
diff --git a/vendor/go.etcd.io/bbolt/README.md b/vendor/go.etcd.io/bbolt/README.md
new file mode 100644
index 0000000000..2be669a60a
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/README.md
@@ -0,0 +1,967 @@
+bbolt
+=====
+
+[![Go Report Card](https://goreportcard.com/badge/github.com/etcd-io/bbolt?style=flat-square)](https://goreportcard.com/report/github.com/etcd-io/bbolt)
+[![Coverage](https://codecov.io/gh/etcd-io/bbolt/branch/master/graph/badge.svg)](https://codecov.io/gh/etcd-io/bbolt)
+[![Build Status Travis](https://img.shields.io/travis/etcd-io/bboltlabs.svg?style=flat-square&&branch=master)](https://travis-ci.com/etcd-io/bbolt)
+[![Godoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/github.com/etcd-io/bbolt)
+[![Releases](https://img.shields.io/github/release/etcd-io/bbolt/all.svg?style=flat-square)](https://github.com/etcd-io/bbolt/releases)
+[![LICENSE](https://img.shields.io/github/license/etcd-io/bbolt.svg?style=flat-square)](https://github.com/etcd-io/bbolt/blob/master/LICENSE)
+
+bbolt is a fork of [Ben Johnson's][gh_ben] [Bolt][bolt] key/value
+store. The purpose of this fork is to provide the Go community with an active
+maintenance and development target for Bolt; the goal is improved reliability
+and stability. bbolt includes bug fixes, performance enhancements, and features
+not found in Bolt while preserving backwards compatibility with the Bolt API.
+
+Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas]
+[LMDB project][lmdb]. The goal of the project is to provide a simple,
+fast, and reliable database for projects that don't require a full database
+server such as Postgres or MySQL.
+
+Since Bolt is meant to be used as such a low-level piece of functionality,
+simplicity is key. The API will be small and only focus on getting values
+and setting values. That's it.
+
+[gh_ben]: https://github.com/benbjohnson
+[bolt]: https://github.com/boltdb/bolt
+[hyc_symas]: https://twitter.com/hyc_symas
+[lmdb]: https://www.symas.com/symas-embedded-database-lmdb
+
+## Project Status
+
+Bolt is stable, the API is fixed, and the file format is fixed. Full unit
+test coverage and randomized black box testing are used to ensure database
+consistency and thread safety. Bolt is currently used in high-load production
+environments serving databases as large as 1TB. Many companies such as
+Shopify and Heroku use Bolt-backed services every day.
+
+## Project versioning
+
+bbolt uses [semantic versioning](http://semver.org).
+API should not change between patch and minor releases.
+New minor versions may add additional features to the API.
+
+## Table of Contents
+
+ - [Getting Started](#getting-started)
+ - [Installing](#installing)
+ - [Opening a database](#opening-a-database)
+ - [Transactions](#transactions)
+ - [Read-write transactions](#read-write-transactions)
+ - [Read-only transactions](#read-only-transactions)
+ - [Batch read-write transactions](#batch-read-write-transactions)
+ - [Managing transactions manually](#managing-transactions-manually)
+ - [Using buckets](#using-buckets)
+ - [Using key/value pairs](#using-keyvalue-pairs)
+ - [Autoincrementing integer for the bucket](#autoincrementing-integer-for-the-bucket)
+ - [Iterating over keys](#iterating-over-keys)
+ - [Prefix scans](#prefix-scans)
+ - [Range scans](#range-scans)
+ - [ForEach()](#foreach)
+ - [Nested buckets](#nested-buckets)
+ - [Database backups](#database-backups)
+ - [Statistics](#statistics)
+ - [Read-Only Mode](#read-only-mode)
+ - [Mobile Use (iOS/Android)](#mobile-use-iosandroid)
+ - [Resources](#resources)
+ - [Comparison with other databases](#comparison-with-other-databases)
+ - [Postgres, MySQL, & other relational databases](#postgres-mysql--other-relational-databases)
+ - [LevelDB, RocksDB](#leveldb-rocksdb)
+ - [LMDB](#lmdb)
+ - [Caveats & Limitations](#caveats--limitations)
+ - [Reading the Source](#reading-the-source)
+ - [Other Projects Using Bolt](#other-projects-using-bolt)
+
+## Getting Started
+
+### Installing
+
+To start using Bolt, install Go and run `go get`:
+```sh
+$ go get go.etcd.io/bbolt@latest
+```
+
+This will retrieve the library and update your `go.mod` and `go.sum` files.
+
+To run the command line utility, execute:
+```sh
+$ go run go.etcd.io/bbolt/cmd/bbolt@latest
+```
+
+Run `go install` to install the `bbolt` command line utility into
+your `$GOBIN` path, which defaults to `$GOPATH/bin` or `$HOME/go/bin` if the
+`GOPATH` environment variable is not set.
+```sh
+$ go install go.etcd.io/bbolt/cmd/bbolt@latest
+```
+
+### Importing bbolt
+
+To use bbolt as an embedded key-value store, import as:
+
+```go
+import bolt "go.etcd.io/bbolt"
+
+db, err := bolt.Open(path, 0666, nil)
+if err != nil {
+ return err
+}
+defer db.Close()
+```
+
+
+### Opening a database
+
+The top-level object in Bolt is a `DB`. It is represented as a single file on
+your disk and represents a consistent snapshot of your data.
+
+To open your database, simply use the `bolt.Open()` function:
+
+```go
+package main
+
+import (
+ "log"
+
+ bolt "go.etcd.io/bbolt"
+)
+
+func main() {
+ // Open the my.db data file in your current directory.
+ // It will be created if it doesn't exist.
+ db, err := bolt.Open("my.db", 0600, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+
+ ...
+}
+```
+
+Please note that Bolt obtains a file lock on the data file so multiple processes
+cannot open the same database at the same time. Opening an already open Bolt
+database will cause it to hang until the other process closes it. To prevent
+an indefinite wait you can pass a timeout option to the `Open()` function:
+
+```go
+db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
+```
+
+
+### Transactions
+
+Bolt allows only one read-write transaction at a time but allows as many
+read-only transactions as you want at a time. Each transaction has a consistent
+view of the data as it existed when the transaction started.
+
+Individual transactions and all objects created from them (e.g. buckets, keys)
+are not thread safe. To work with data in multiple goroutines you must start
+a transaction for each one or use locking to ensure only one goroutine accesses
+a transaction at a time. Creating transaction from the `DB` is thread safe.
+
+Transactions should not depend on one another and generally shouldn't be opened
+simultaneously in the same goroutine. This can cause a deadlock as the read-write
+transaction needs to periodically re-map the data file but it cannot do so while
+any read-only transaction is open. Even a nested read-only transaction can cause
+a deadlock, as the child transaction can block the parent transaction from releasing
+its resources.
+
+#### Read-write transactions
+
+To start a read-write transaction, you can use the `DB.Update()` function:
+
+```go
+err := db.Update(func(tx *bolt.Tx) error {
+ ...
+ return nil
+})
+```
+
+Inside the closure, you have a consistent view of the database. You commit the
+transaction by returning `nil` at the end. You can also rollback the transaction
+at any point by returning an error. All database operations are allowed inside
+a read-write transaction.
+
+Always check the return error as it will report any disk failures that can cause
+your transaction to not complete. If you return an error within your closure
+it will be passed through.
+
+
+#### Read-only transactions
+
+To start a read-only transaction, you can use the `DB.View()` function:
+
+```go
+err := db.View(func(tx *bolt.Tx) error {
+ ...
+ return nil
+})
+```
+
+You also get a consistent view of the database within this closure, however,
+no mutating operations are allowed within a read-only transaction. You can only
+retrieve buckets, retrieve values, and copy the database within a read-only
+transaction.
+
+
+#### Batch read-write transactions
+
+Each `DB.Update()` waits for disk to commit the writes. This overhead
+can be minimized by combining multiple updates with the `DB.Batch()`
+function:
+
+```go
+err := db.Batch(func(tx *bolt.Tx) error {
+ ...
+ return nil
+})
+```
+
+Concurrent Batch calls are opportunistically combined into larger
+transactions. Batch is only useful when there are multiple goroutines
+calling it.
+
+The trade-off is that `Batch` can call the given
+function multiple times, if parts of the transaction fail. The
+function must be idempotent and side effects must take effect only
+after a successful return from `DB.Batch()`.
+
+For example: don't display messages from inside the function, instead
+set variables in the enclosing scope:
+
+```go
+var id uint64
+err := db.Batch(func(tx *bolt.Tx) error {
+ // Find last key in bucket, decode as bigendian uint64, increment
+ // by one, encode back to []byte, and add new key.
+ ...
+ id = newValue
+ return nil
+})
+if err != nil {
+ return ...
+}
+fmt.Println("Allocated ID %d", id)
+```
+
+
+#### Managing transactions manually
+
+The `DB.View()` and `DB.Update()` functions are wrappers around the `DB.Begin()`
+function. These helper functions will start the transaction, execute a function,
+and then safely close your transaction if an error is returned. This is the
+recommended way to use Bolt transactions.
+
+However, sometimes you may want to manually start and end your transactions.
+You can use the `DB.Begin()` function directly but **please** be sure to close
+the transaction.
+
+```go
+// Start a writable transaction.
+tx, err := db.Begin(true)
+if err != nil {
+ return err
+}
+defer tx.Rollback()
+
+// Use the transaction...
+_, err := tx.CreateBucket([]byte("MyBucket"))
+if err != nil {
+ return err
+}
+
+// Commit the transaction and check for error.
+if err := tx.Commit(); err != nil {
+ return err
+}
+```
+
+The first argument to `DB.Begin()` is a boolean stating if the transaction
+should be writable.
+
+
+### Using buckets
+
+Buckets are collections of key/value pairs within the database. All keys in a
+bucket must be unique. You can create a bucket using the `Tx.CreateBucket()`
+function:
+
+```go
+db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("MyBucket"))
+ if err != nil {
+ return fmt.Errorf("create bucket: %s", err)
+ }
+ return nil
+})
+```
+
+You can also create a bucket only if it doesn't exist by using the
+`Tx.CreateBucketIfNotExists()` function. It's a common pattern to call this
+function for all your top-level buckets after you open your database so you can
+guarantee that they exist for future transactions.
+
+To delete a bucket, simply call the `Tx.DeleteBucket()` function.
+
+
+### Using key/value pairs
+
+To save a key/value pair to a bucket, use the `Bucket.Put()` function:
+
+```go
+db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("MyBucket"))
+ err := b.Put([]byte("answer"), []byte("42"))
+ return err
+})
+```
+
+This will set the value of the `"answer"` key to `"42"` in the `MyBucket`
+bucket. To retrieve this value, we can use the `Bucket.Get()` function:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("MyBucket"))
+ v := b.Get([]byte("answer"))
+ fmt.Printf("The answer is: %s\n", v)
+ return nil
+})
+```
+
+The `Get()` function does not return an error because its operation is
+guaranteed to work (unless there is some kind of system failure). If the key
+exists then it will return its byte slice value. If it doesn't exist then it
+will return `nil`. It's important to note that you can have a zero-length value
+set to a key which is different than the key not existing.
+
+Use the `Bucket.Delete()` function to delete a key from the bucket.
+
+Please note that values returned from `Get()` are only valid while the
+transaction is open. If you need to use a value outside of the transaction
+then you must use `copy()` to copy it to another byte slice.
+
+
+### Autoincrementing integer for the bucket
+By using the `NextSequence()` function, you can let Bolt determine a sequence
+which can be used as the unique identifier for your key/value pairs. See the
+example below.
+
+```go
+// CreateUser saves u to the store. The new user ID is set on u once the data is persisted.
+func (s *Store) CreateUser(u *User) error {
+ return s.db.Update(func(tx *bolt.Tx) error {
+ // Retrieve the users bucket.
+ // This should be created when the DB is first opened.
+ b := tx.Bucket([]byte("users"))
+
+ // Generate ID for the user.
+ // This returns an error only if the Tx is closed or not writeable.
+ // That can't happen in an Update() call so I ignore the error check.
+ id, _ := b.NextSequence()
+ u.ID = int(id)
+
+ // Marshal user data into bytes.
+ buf, err := json.Marshal(u)
+ if err != nil {
+ return err
+ }
+
+ // Persist bytes to users bucket.
+ return b.Put(itob(u.ID), buf)
+ })
+}
+
+// itob returns an 8-byte big endian representation of v.
+func itob(v int) []byte {
+ b := make([]byte, 8)
+ binary.BigEndian.PutUint64(b, uint64(v))
+ return b
+}
+
+type User struct {
+ ID int
+ ...
+}
+```
+
+### Iterating over keys
+
+Bolt stores its keys in byte-sorted order within a bucket. This makes sequential
+iteration over these keys extremely fast. To iterate over keys we'll use a
+`Cursor`:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume bucket exists and has keys
+ b := tx.Bucket([]byte("MyBucket"))
+
+ c := b.Cursor()
+
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ fmt.Printf("key=%s, value=%s\n", k, v)
+ }
+
+ return nil
+})
+```
+
+The cursor allows you to move to a specific point in the list of keys and move
+forward or backward through the keys one at a time.
+
+The following functions are available on the cursor:
+
+```
+First() Move to the first key.
+Last() Move to the last key.
+Seek() Move to a specific key.
+Next() Move to the next key.
+Prev() Move to the previous key.
+```
+
+Each of those functions has a return signature of `(key []byte, value []byte)`.
+When you have iterated to the end of the cursor then `Next()` will return a
+`nil` key. You must seek to a position using `First()`, `Last()`, or `Seek()`
+before calling `Next()` or `Prev()`. If you do not seek to a position then
+these functions will return a `nil` key.
+
+During iteration, if the key is non-`nil` but the value is `nil`, that means
+the key refers to a bucket rather than a value. Use `Bucket.Bucket()` to
+access the sub-bucket.
+
+
+#### Prefix scans
+
+To iterate over a key prefix, you can combine `Seek()` and `bytes.HasPrefix()`:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume bucket exists and has keys
+ c := tx.Bucket([]byte("MyBucket")).Cursor()
+
+ prefix := []byte("1234")
+ for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() {
+ fmt.Printf("key=%s, value=%s\n", k, v)
+ }
+
+ return nil
+})
+```
+
+#### Range scans
+
+Another common use case is scanning over a range such as a time range. If you
+use a sortable time encoding such as RFC3339 then you can query a specific
+date range like this:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume our events bucket exists and has RFC3339 encoded time keys.
+ c := tx.Bucket([]byte("Events")).Cursor()
+
+ // Our time range spans the 90's decade.
+ min := []byte("1990-01-01T00:00:00Z")
+ max := []byte("2000-01-01T00:00:00Z")
+
+ // Iterate over the 90's.
+ for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; k, v = c.Next() {
+ fmt.Printf("%s: %s\n", k, v)
+ }
+
+ return nil
+})
+```
+
+Note that, while RFC3339 is sortable, the Golang implementation of RFC3339Nano does not use a fixed number of digits after the decimal point and is therefore not sortable.
+
+
+#### ForEach()
+
+You can also use the function `ForEach()` if you know you'll be iterating over
+all the keys in a bucket:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume bucket exists and has keys
+ b := tx.Bucket([]byte("MyBucket"))
+
+ b.ForEach(func(k, v []byte) error {
+ fmt.Printf("key=%s, value=%s\n", k, v)
+ return nil
+ })
+ return nil
+})
+```
+
+Please note that keys and values in `ForEach()` are only valid while
+the transaction is open. If you need to use a key or value outside of
+the transaction, you must use `copy()` to copy it to another byte
+slice.
+
+### Nested buckets
+
+You can also store a bucket in a key to create nested buckets. The API is the
+same as the bucket management API on the `DB` object:
+
+```go
+func (*Bucket) CreateBucket(key []byte) (*Bucket, error)
+func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error)
+func (*Bucket) DeleteBucket(key []byte) error
+```
+
+Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings.
+
+```go
+
+// createUser creates a new user in the given account.
+func createUser(accountID int, u *User) error {
+ // Start the transaction.
+ tx, err := db.Begin(true)
+ if err != nil {
+ return err
+ }
+ defer tx.Rollback()
+
+ // Retrieve the root bucket for the account.
+ // Assume this has already been created when the account was set up.
+ root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10)))
+
+ // Setup the users bucket.
+ bkt, err := root.CreateBucketIfNotExists([]byte("USERS"))
+ if err != nil {
+ return err
+ }
+
+ // Generate an ID for the new user.
+ userID, err := bkt.NextSequence()
+ if err != nil {
+ return err
+ }
+ u.ID = userID
+
+ // Marshal and save the encoded user.
+ if buf, err := json.Marshal(u); err != nil {
+ return err
+ } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil {
+ return err
+ }
+
+ // Commit the transaction.
+ if err := tx.Commit(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+```
+
+
+
+
+### Database backups
+
+Bolt is a single file so it's easy to backup. You can use the `Tx.WriteTo()`
+function to write a consistent view of the database to a writer. If you call
+this from a read-only transaction, it will perform a hot backup and not block
+your other database reads and writes.
+
+By default, it will use a regular file handle which will utilize the operating
+system's page cache. See the [`Tx`](https://godoc.org/go.etcd.io/bbolt#Tx)
+documentation for information about optimizing for larger-than-RAM datasets.
+
+One common use case is to backup over HTTP so you can use tools like `cURL` to
+do database backups:
+
+```go
+func BackupHandleFunc(w http.ResponseWriter, req *http.Request) {
+ err := db.View(func(tx *bolt.Tx) error {
+ w.Header().Set("Content-Type", "application/octet-stream")
+ w.Header().Set("Content-Disposition", `attachment; filename="my.db"`)
+ w.Header().Set("Content-Length", strconv.Itoa(int(tx.Size())))
+ _, err := tx.WriteTo(w)
+ return err
+ })
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+}
+```
+
+Then you can backup using this command:
+
+```sh
+$ curl http://localhost/backup > my.db
+```
+
+Or you can open your browser to `http://localhost/backup` and it will download
+automatically.
+
+If you want to backup to another file you can use the `Tx.CopyFile()` helper
+function.
+
+
+### Statistics
+
+The database keeps a running count of many of the internal operations it
+performs so you can better understand what's going on. By grabbing a snapshot
+of these stats at two points in time we can see what operations were performed
+in that time range.
+
+For example, we could start a goroutine to log stats every 10 seconds:
+
+```go
+go func() {
+ // Grab the initial stats.
+ prev := db.Stats()
+
+ for {
+ // Wait for 10s.
+ time.Sleep(10 * time.Second)
+
+ // Grab the current stats and diff them.
+ stats := db.Stats()
+ diff := stats.Sub(&prev)
+
+ // Encode stats to JSON and print to STDERR.
+ json.NewEncoder(os.Stderr).Encode(diff)
+
+ // Save stats for the next loop.
+ prev = stats
+ }
+}()
+```
+
+It's also useful to pipe these stats to a service such as statsd for monitoring
+or to provide an HTTP endpoint that will perform a fixed-length sample.
+
+
+### Read-Only Mode
+
+Sometimes it is useful to create a shared, read-only Bolt database. To this,
+set the `Options.ReadOnly` flag when opening your database. Read-only mode
+uses a shared lock to allow multiple processes to read from the database but
+it will block any processes from opening the database in read-write mode.
+
+```go
+db, err := bolt.Open("my.db", 0666, &bolt.Options{ReadOnly: true})
+if err != nil {
+ log.Fatal(err)
+}
+```
+
+### Mobile Use (iOS/Android)
+
+Bolt is able to run on mobile devices by leveraging the binding feature of the
+[gomobile](https://github.com/golang/mobile) tool. Create a struct that will
+contain your database logic and a reference to a `*bolt.DB` with a initializing
+constructor that takes in a filepath where the database file will be stored.
+Neither Android nor iOS require extra permissions or cleanup from using this method.
+
+```go
+func NewBoltDB(filepath string) *BoltDB {
+ db, err := bolt.Open(filepath+"/demo.db", 0600, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return &BoltDB{db}
+}
+
+type BoltDB struct {
+ db *bolt.DB
+ ...
+}
+
+func (b *BoltDB) Path() string {
+ return b.db.Path()
+}
+
+func (b *BoltDB) Close() {
+ b.db.Close()
+}
+```
+
+Database logic should be defined as methods on this wrapper struct.
+
+To initialize this struct from the native language (both platforms now sync
+their local storage to the cloud. These snippets disable that functionality for the
+database file):
+
+#### Android
+
+```java
+String path;
+if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.LOLLIPOP){
+ path = getNoBackupFilesDir().getAbsolutePath();
+} else{
+ path = getFilesDir().getAbsolutePath();
+}
+Boltmobiledemo.BoltDB boltDB = Boltmobiledemo.NewBoltDB(path)
+```
+
+#### iOS
+
+```objc
+- (void)demo {
+ NSString* path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
+ NSUserDomainMask,
+ YES) objectAtIndex:0];
+ GoBoltmobiledemoBoltDB * demo = GoBoltmobiledemoNewBoltDB(path);
+ [self addSkipBackupAttributeToItemAtPath:demo.path];
+ //Some DB Logic would go here
+ [demo close];
+}
+
+- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
+{
+ NSURL* URL= [NSURL fileURLWithPath: filePathString];
+ assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
+
+ NSError *error = nil;
+ BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
+ forKey: NSURLIsExcludedFromBackupKey error: &error];
+ if(!success){
+ NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
+ }
+ return success;
+}
+
+```
+
+## Resources
+
+For more information on getting started with Bolt, check out the following articles:
+
+* [Intro to BoltDB: Painless Performant Persistence](http://npf.io/2014/07/intro-to-boltdb-painless-performant-persistence/) by [Nate Finch](https://github.com/natefinch).
+* [Bolt -- an embedded key/value database for Go](https://www.progville.com/go/bolt-embedded-db-golang/) by Progville
+
+
+## Comparison with other databases
+
+### Postgres, MySQL, & other relational databases
+
+Relational databases structure data into rows and are only accessible through
+the use of SQL. This approach provides flexibility in how you store and query
+your data but also incurs overhead in parsing and planning SQL statements. Bolt
+accesses all data by a byte slice key. This makes Bolt fast to read and write
+data by key but provides no built-in support for joining values together.
+
+Most relational databases (with the exception of SQLite) are standalone servers
+that run separately from your application. This gives your systems
+flexibility to connect multiple application servers to a single database
+server but also adds overhead in serializing and transporting data over the
+network. Bolt runs as a library included in your application so all data access
+has to go through your application's process. This brings data closer to your
+application but limits multi-process access to the data.
+
+
+### LevelDB, RocksDB
+
+LevelDB and its derivatives (RocksDB, HyperLevelDB) are similar to Bolt in that
+they are libraries bundled into the application, however, their underlying
+structure is a log-structured merge-tree (LSM tree). An LSM tree optimizes
+random writes by using a write ahead log and multi-tiered, sorted files called
+SSTables. Bolt uses a B+tree internally and only a single file. Both approaches
+have trade-offs.
+
+If you require a high random write throughput (>10,000 w/sec) or you need to use
+spinning disks then LevelDB could be a good choice. If your application is
+read-heavy or does a lot of range scans then Bolt could be a good choice.
+
+One other important consideration is that LevelDB does not have transactions.
+It supports batch writing of key/values pairs and it supports read snapshots
+but it will not give you the ability to do a compare-and-swap operation safely.
+Bolt supports fully serializable ACID transactions.
+
+
+### LMDB
+
+Bolt was originally a port of LMDB so it is architecturally similar. Both use
+a B+tree, have ACID semantics with fully serializable transactions, and support
+lock-free MVCC using a single writer and multiple readers.
+
+The two projects have somewhat diverged. LMDB heavily focuses on raw performance
+while Bolt has focused on simplicity and ease of use. For example, LMDB allows
+several unsafe actions such as direct writes for the sake of performance. Bolt
+opts to disallow actions which can leave the database in a corrupted state. The
+only exception to this in Bolt is `DB.NoSync`.
+
+There are also a few differences in API. LMDB requires a maximum mmap size when
+opening an `mdb_env` whereas Bolt will handle incremental mmap resizing
+automatically. LMDB overloads the getter and setter functions with multiple
+flags whereas Bolt splits these specialized cases into their own functions.
+
+
+## Caveats & Limitations
+
+It's important to pick the right tool for the job and Bolt is no exception.
+Here are a few things to note when evaluating and using Bolt:
+
+* Bolt is good for read intensive workloads. Sequential write performance is
+ also fast but random writes can be slow. You can use `DB.Batch()` or add a
+ write-ahead log to help mitigate this issue.
+
+* Bolt uses a B+tree internally so there can be a lot of random page access.
+ SSDs provide a significant performance boost over spinning disks.
+
+* Try to avoid long running read transactions. Bolt uses copy-on-write so
+ old pages cannot be reclaimed while an old transaction is using them.
+
+* Byte slices returned from Bolt are only valid during a transaction. Once the
+ transaction has been committed or rolled back then the memory they point to
+ can be reused by a new page or can be unmapped from virtual memory and you'll
+ see an `unexpected fault address` panic when accessing it.
+
+* Bolt uses an exclusive write lock on the database file so it cannot be
+ shared by multiple processes.
+
+* Be careful when using `Bucket.FillPercent`. Setting a high fill percent for
+ buckets that have random inserts will cause your database to have very poor
+ page utilization.
+
+* Use larger buckets in general. Smaller buckets causes poor page utilization
+ once they become larger than the page size (typically 4KB).
+
+* Bulk loading a lot of random writes into a new bucket can be slow as the
+ page will not split until the transaction is committed. Randomly inserting
+ more than 100,000 key/value pairs into a single new bucket in a single
+ transaction is not advised.
+
+* Bolt uses a memory-mapped file so the underlying operating system handles the
+ caching of the data. Typically, the OS will cache as much of the file as it
+ can in memory and will release memory as needed to other processes. This means
+ that Bolt can show very high memory usage when working with large databases.
+ However, this is expected and the OS will release memory as needed. Bolt can
+ handle databases much larger than the available physical RAM, provided its
+ memory-map fits in the process virtual address space. It may be problematic
+ on 32-bits systems.
+
+* The data structures in the Bolt database are memory mapped so the data file
+ will be endian specific. This means that you cannot copy a Bolt file from a
+ little endian machine to a big endian machine and have it work. For most
+ users this is not a concern since most modern CPUs are little endian.
+
+* Because of the way pages are laid out on disk, Bolt cannot truncate data files
+ and return free pages back to the disk. Instead, Bolt maintains a free list
+ of unused pages within its data file. These free pages can be reused by later
+ transactions. This works well for many use cases as databases generally tend
+ to grow. However, it's important to note that deleting large chunks of data
+ will not allow you to reclaim that space on disk.
+
+ For more information on page allocation, [see this comment][page-allocation].
+
+[page-allocation]: https://github.com/boltdb/bolt/issues/308#issuecomment-74811638
+
+
+## Reading the Source
+
+Bolt is a relatively small code base (<5KLOC) for an embedded, serializable,
+transactional key/value database so it can be a good starting point for people
+interested in how databases work.
+
+The best places to start are the main entry points into Bolt:
+
+- `Open()` - Initializes the reference to the database. It's responsible for
+ creating the database if it doesn't exist, obtaining an exclusive lock on the
+ file, reading the meta pages, & memory-mapping the file.
+
+- `DB.Begin()` - Starts a read-only or read-write transaction depending on the
+ value of the `writable` argument. This requires briefly obtaining the "meta"
+ lock to keep track of open transactions. Only one read-write transaction can
+ exist at a time so the "rwlock" is acquired during the life of a read-write
+ transaction.
+
+- `Bucket.Put()` - Writes a key/value pair into a bucket. After validating the
+ arguments, a cursor is used to traverse the B+tree to the page and position
+ where they key & value will be written. Once the position is found, the bucket
+ materializes the underlying page and the page's parent pages into memory as
+ "nodes". These nodes are where mutations occur during read-write transactions.
+ These changes get flushed to disk during commit.
+
+- `Bucket.Get()` - Retrieves a key/value pair from a bucket. This uses a cursor
+ to move to the page & position of a key/value pair. During a read-only
+ transaction, the key and value data is returned as a direct reference to the
+ underlying mmap file so there's no allocation overhead. For read-write
+ transactions, this data may reference the mmap file or one of the in-memory
+ node values.
+
+- `Cursor` - This object is simply for traversing the B+tree of on-disk pages
+ or in-memory nodes. It can seek to a specific key, move to the first or last
+ value, or it can move forward or backward. The cursor handles the movement up
+ and down the B+tree transparently to the end user.
+
+- `Tx.Commit()` - Converts the in-memory dirty nodes and the list of free pages
+ into pages to be written to disk. Writing to disk then occurs in two phases.
+ First, the dirty pages are written to disk and an `fsync()` occurs. Second, a
+ new meta page with an incremented transaction ID is written and another
+ `fsync()` occurs. This two phase write ensures that partially written data
+ pages are ignored in the event of a crash since the meta page pointing to them
+ is never written. Partially written meta pages are invalidated because they
+ are written with a checksum.
+
+If you have additional notes that could be helpful for others, please submit
+them via pull request.
+
+
+## Other Projects Using Bolt
+
+Below is a list of public, open source projects that use Bolt:
+
+* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend.
+* [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside.
+* [bolter](https://github.com/hasit/bolter) - Command-line app for viewing BoltDB file in your terminal.
+* [boltcli](https://github.com/spacewander/boltcli) - the redis-cli for boltdb with Lua script support.
+* [BoltHold](https://github.com/timshannon/bolthold) - An embeddable NoSQL store for Go types built on BoltDB
+* [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt.
+* [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners.
+* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files.
+* [BoltDB Viewer](https://github.com/zc310/rich_boltdb) - A BoltDB Viewer Can run on Windows、Linux、Android system.
+* [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend.
+* [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet.
+* [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining
+ simple tx and key scans.
+* [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend.
+* [ChainStore](https://github.com/pressly/chainstore) - Simple key-value interface to a variety of storage engines organized as a chain of operations.
+* [🌰 Chestnut](https://github.com/jrapoport/chestnut) - Chestnut is encrypted storage for Go.
+* [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware.
+* [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb.
+* [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency.
+* [drive](https://github.com/odeke-em/drive) - drive is an unofficial Google Drive command line client for \*NIX operating systems.
+* [event-shuttle](https://github.com/sclasen/event-shuttle) - A Unix system service to collect and reliably deliver messages to Kafka.
+* [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data.
+* [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service.
+* [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB.
+* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter.
+* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains
+* [gokv](https://github.com/philippgille/gokv) - Simple key-value store abstraction and implementations for Go (Redis, Consul, etcd, bbolt, BadgerDB, LevelDB, Memcached, DynamoDB, S3, PostgreSQL, MongoDB, CockroachDB and many more)
+* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin".
+* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics.
+* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters.
+* [ipxed](https://github.com/kelseyhightower/ipxed) - Web interface and api for ipxed.
+* [Ironsmith](https://github.com/timshannon/ironsmith) - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies
+* [Kala](https://github.com/ajvb/kala) - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs.
+* [Key Value Access Language (KVAL)](https://github.com/kval-access-language) - A proposed grammar for key-value datastores offering a bbolt binding.
+* [LedisDB](https://github.com/siddontang/ledisdb) - A high performance NoSQL, using Bolt as optional storage.
+* [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores.
+* [mbuckets](https://github.com/abhigupta912/mbuckets) - A Bolt wrapper that allows easy operations on multi level (nested) buckets.
+* [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite.
+* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files.
+* [NATS](https://github.com/nats-io/nats-streaming-server) - NATS Streaming uses bbolt for message and metadata storage.
+* [Prometheus Annotation Server](https://github.com/oliver006/prom_annotation_server) - Annotation server for PromDash & Prometheus service monitoring system.
+* [Rain](https://github.com/cenkalti/rain) - BitTorrent client and library.
+* [reef-pi](https://github.com/reef-pi/reef-pi) - reef-pi is an award winning, modular, DIY reef tank controller using easy to learn electronics based on a Raspberry Pi.
+* [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service
+* [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read.
+* [stow](https://github.com/djherbis/stow) - a persistence manager for objects
+ backed by boltdb.
+* [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB.
+* [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings.
+* [Skybox Analytics](https://github.com/skybox/skybox) - A standalone funnel analysis tool for web analytics.
+* [Scuttlebutt](https://github.com/benbjohnson/scuttlebutt) - Uses Bolt to store and process all Twitter mentions of GitHub projects.
+* [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server.
+* [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development.
+* [Wiki](https://github.com/peterhellberg/wiki) - A tiny wiki using Goji, BoltDB and Blackfriday.
+
+If you are using Bolt in a project please send a pull request to add it to the list.
diff --git a/vendor/go.etcd.io/bbolt/bolt_386.go b/vendor/go.etcd.io/bbolt/bolt_386.go
new file mode 100644
index 0000000000..aee25960ff
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_386.go
@@ -0,0 +1,7 @@
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_amd64.go b/vendor/go.etcd.io/bbolt/bolt_amd64.go
new file mode 100644
index 0000000000..5dd8f3f2ae
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_amd64.go
@@ -0,0 +1,7 @@
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_arm.go b/vendor/go.etcd.io/bbolt/bolt_arm.go
new file mode 100644
index 0000000000..aee25960ff
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_arm.go
@@ -0,0 +1,7 @@
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_arm64.go b/vendor/go.etcd.io/bbolt/bolt_arm64.go
new file mode 100644
index 0000000000..447bc19733
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_arm64.go
@@ -0,0 +1,10 @@
+//go:build arm64
+// +build arm64
+
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_linux.go b/vendor/go.etcd.io/bbolt/bolt_linux.go
new file mode 100644
index 0000000000..7707bcacf0
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_linux.go
@@ -0,0 +1,10 @@
+package bbolt
+
+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/go.etcd.io/bbolt/bolt_loong64.go b/vendor/go.etcd.io/bbolt/bolt_loong64.go
new file mode 100644
index 0000000000..31c17c1d07
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_loong64.go
@@ -0,0 +1,10 @@
+//go:build loong64
+// +build loong64
+
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_mips64x.go b/vendor/go.etcd.io/bbolt/bolt_mips64x.go
new file mode 100644
index 0000000000..a9385beb68
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_mips64x.go
@@ -0,0 +1,10 @@
+//go:build mips64 || mips64le
+// +build mips64 mips64le
+
+package bbolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x8000000000 // 512GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
diff --git a/vendor/go.etcd.io/bbolt/bolt_mipsx.go b/vendor/go.etcd.io/bbolt/bolt_mipsx.go
new file mode 100644
index 0000000000..ed734ff7f3
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_mipsx.go
@@ -0,0 +1,10 @@
+//go:build mips || mipsle
+// +build mips mipsle
+
+package bbolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x40000000 // 1GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0xFFFFFFF
diff --git a/vendor/go.etcd.io/bbolt/bolt_openbsd.go b/vendor/go.etcd.io/bbolt/bolt_openbsd.go
new file mode 100644
index 0000000000..bf47aa1a60
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_openbsd.go
@@ -0,0 +1,16 @@
+package bbolt
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+func msync(db *DB) error {
+ return unix.Msync(db.data[:db.datasz], unix.MS_INVALIDATE)
+}
+
+func fdatasync(db *DB) error {
+ if db.data != nil {
+ return msync(db)
+ }
+ return db.file.Sync()
+}
diff --git a/vendor/go.etcd.io/bbolt/bolt_ppc.go b/vendor/go.etcd.io/bbolt/bolt_ppc.go
new file mode 100644
index 0000000000..e403f57d8a
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_ppc.go
@@ -0,0 +1,10 @@
+//go:build ppc
+// +build ppc
+
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_ppc64.go b/vendor/go.etcd.io/bbolt/bolt_ppc64.go
new file mode 100644
index 0000000000..fcd86529f9
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_ppc64.go
@@ -0,0 +1,10 @@
+//go:build ppc64
+// +build ppc64
+
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_ppc64le.go b/vendor/go.etcd.io/bbolt/bolt_ppc64le.go
new file mode 100644
index 0000000000..20234aca46
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_ppc64le.go
@@ -0,0 +1,10 @@
+//go:build ppc64le
+// +build ppc64le
+
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_riscv64.go b/vendor/go.etcd.io/bbolt/bolt_riscv64.go
new file mode 100644
index 0000000000..060f30c73c
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_riscv64.go
@@ -0,0 +1,10 @@
+//go:build riscv64
+// +build riscv64
+
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_s390x.go b/vendor/go.etcd.io/bbolt/bolt_s390x.go
new file mode 100644
index 0000000000..92d2755adb
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_s390x.go
@@ -0,0 +1,10 @@
+//go:build s390x
+// +build s390x
+
+package bbolt
+
+// 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/go.etcd.io/bbolt/bolt_unix.go b/vendor/go.etcd.io/bbolt/bolt_unix.go
new file mode 100644
index 0000000000..757ae4d1a4
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_unix.go
@@ -0,0 +1,87 @@
+//go:build !windows && !plan9 && !solaris && !aix
+// +build !windows,!plan9,!solaris,!aix
+
+package bbolt
+
+import (
+ "fmt"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ if timeout != 0 {
+ t = time.Now()
+ }
+ fd := db.file.Fd()
+ flag := syscall.LOCK_NB
+ if exclusive {
+ flag |= syscall.LOCK_EX
+ } else {
+ flag |= syscall.LOCK_SH
+ }
+ for {
+ // Attempt to obtain an exclusive lock.
+ err := syscall.Flock(int(fd), flag)
+ if err == nil {
+ return nil
+ } else if err != syscall.EWOULDBLOCK {
+ return err
+ }
+
+ // If we timed out then return an error.
+ if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout {
+ return ErrTimeout
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(flockRetryTimeout)
+ }
+}
+
+// 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 := 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.
+ err = unix.Madvise(b, syscall.MADV_RANDOM)
+ if err != nil && err != syscall.ENOSYS {
+ // Ignore not implemented error in kernel because it still works.
+ 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/go.etcd.io/bbolt/bolt_unix_aix.go b/vendor/go.etcd.io/bbolt/bolt_unix_aix.go
new file mode 100644
index 0000000000..6dea4294dc
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_unix_aix.go
@@ -0,0 +1,91 @@
+//go:build aix
+// +build aix
+
+package bbolt
+
+import (
+ "fmt"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ if timeout != 0 {
+ t = time.Now()
+ }
+ fd := db.file.Fd()
+ var lockType int16
+ if exclusive {
+ lockType = syscall.F_WRLCK
+ } else {
+ lockType = syscall.F_RDLCK
+ }
+ for {
+ // Attempt to obtain an exclusive lock.
+ lock := syscall.Flock_t{Type: lockType}
+ err := syscall.FcntlFlock(fd, syscall.F_SETLK, &lock)
+ if err == nil {
+ return nil
+ } else if err != syscall.EAGAIN {
+ return err
+ }
+
+ // If we timed out then return an error.
+ if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout {
+ return ErrTimeout
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(flockRetryTimeout)
+ }
+}
+
+// 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/go.etcd.io/bbolt/bolt_unix_solaris.go b/vendor/go.etcd.io/bbolt/bolt_unix_solaris.go
new file mode 100644
index 0000000000..babad65786
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_unix_solaris.go
@@ -0,0 +1,88 @@
+package bbolt
+
+import (
+ "fmt"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ if timeout != 0 {
+ t = time.Now()
+ }
+ fd := db.file.Fd()
+ var lockType int16
+ if exclusive {
+ lockType = syscall.F_WRLCK
+ } else {
+ lockType = syscall.F_RDLCK
+ }
+ for {
+ // Attempt to obtain an exclusive lock.
+ lock := syscall.Flock_t{Type: lockType}
+ err := syscall.FcntlFlock(fd, syscall.F_SETLK, &lock)
+ if err == nil {
+ return nil
+ } else if err != syscall.EAGAIN {
+ return err
+ }
+
+ // If we timed out then return an error.
+ if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout {
+ return ErrTimeout
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(flockRetryTimeout)
+ }
+}
+
+// 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/go.etcd.io/bbolt/bolt_windows.go b/vendor/go.etcd.io/bbolt/bolt_windows.go
new file mode 100644
index 0000000000..e5dde27454
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bolt_windows.go
@@ -0,0 +1,117 @@
+package bbolt
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+// 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, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ if timeout != 0 {
+ t = time.Now()
+ }
+ var flags uint32 = windows.LOCKFILE_FAIL_IMMEDIATELY
+ if exclusive {
+ flags |= windows.LOCKFILE_EXCLUSIVE_LOCK
+ }
+ for {
+ // Fix for https://github.com/etcd-io/bbolt/issues/121. Use byte-range
+ // -1..0 as the lock on the database file.
+ var m1 uint32 = (1 << 32) - 1 // -1 in a uint32
+ err := windows.LockFileEx(windows.Handle(db.file.Fd()), flags, 0, 1, 0, &windows.Overlapped{
+ Offset: m1,
+ OffsetHigh: m1,
+ })
+
+ if err == nil {
+ return nil
+ } else if err != windows.ERROR_LOCK_VIOLATION {
+ return err
+ }
+
+ // If we timed oumercit then return an error.
+ if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout {
+ return ErrTimeout
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(flockRetryTimeout)
+ }
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(db *DB) error {
+ var m1 uint32 = (1 << 32) - 1 // -1 in a uint32
+ return windows.UnlockFileEx(windows.Handle(db.file.Fd()), 0, 1, 0, &windows.Overlapped{
+ Offset: m1,
+ OffsetHigh: m1,
+ })
+}
+
+// mmap memory maps a DB's data file.
+// Based on: https://github.com/edsrzf/mmap-go
+func mmap(db *DB, sz int) error {
+ var sizelo, sizehi uint32
+
+ 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)
+ }
+ sizehi = uint32(sz >> 32)
+ sizelo = uint32(sz) & 0xffffffff
+ }
+
+ // Open a file mapping handle.
+ h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizehi, sizelo, nil)
+ if h == 0 {
+ return os.NewSyscallError("CreateFileMapping", errno)
+ }
+
+ // Create the memory map.
+ addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, 0)
+ if addr == 0 {
+ // Do our best and report error returned from MapViewOfFile.
+ _ = syscall.CloseHandle(h)
+ 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]))
+ var err1 error
+ if err := syscall.UnmapViewOfFile(addr); err != nil {
+ err1 = os.NewSyscallError("UnmapViewOfFile", err)
+ }
+ db.data = nil
+ db.datasz = 0
+ return err1
+}
diff --git a/vendor/go.etcd.io/bbolt/boltsync_unix.go b/vendor/go.etcd.io/bbolt/boltsync_unix.go
new file mode 100644
index 0000000000..81e09a5310
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/boltsync_unix.go
@@ -0,0 +1,9 @@
+//go:build !windows && !plan9 && !linux && !openbsd
+// +build !windows,!plan9,!linux,!openbsd
+
+package bbolt
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(db *DB) error {
+ return db.file.Sync()
+}
diff --git a/vendor/go.etcd.io/bbolt/bucket.go b/vendor/go.etcd.io/bbolt/bucket.go
new file mode 100644
index 0000000000..054467af30
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/bucket.go
@@ -0,0 +1,791 @@
+package bbolt
+
+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 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.IncCursorCount(1)
+
+ // 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)
+
+ // Unaligned access requires a copy to be made.
+ const unalignedMask = unsafe.Alignof(struct {
+ bucket
+ page
+ }{}) - 1
+ unaligned := uintptr(unsafe.Pointer(&value[0]))&unalignedMask != 0
+ if unaligned {
+ value = cloneBytes(value)
+ }
+
+ // 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 && !unaligned {
+ 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
+ }
+ 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 exist, 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.ForEachBucket(func(k []byte) error {
+ 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()
+ k, _, flags := c.seek(key)
+
+ // Return nil if the key doesn't exist.
+ if !bytes.Equal(key, k) {
+ return nil
+ }
+
+ // 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
+}
+
+// Sequence returns the current integer for the bucket without incrementing it.
+func (b *Bucket) Sequence() uint64 { return b.bucket.sequence }
+
+// SetSequence updates the sequence number for the bucket.
+func (b *Bucket) SetSequence(v uint64) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return 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)
+ }
+
+ // Set the sequence.
+ b.bucket.sequence = v
+ 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.
+// Because ForEach uses a Cursor, the iteration over keys is in lexicographical order.
+// 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
+}
+
+func (b *Bucket) ForEachBucket(fn func(k []byte) error) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ }
+ c := b.Cursor()
+ for k, _, flags := c.first(); k != nil; k, _, flags = c.next() {
+ if flags&bucketLeafFlag != 0 {
+ if err := fn(k); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// Stats 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, pgstack []pgid) {
+ 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 * uintptr(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 += uintptr(lastElement.pos + lastElement.ksize + lastElement.vsize)
+ }
+
+ if b.root == 0 {
+ // For inlined bucket just update the inline stats
+ s.InlineBucketInuse += int(used)
+ } else {
+ // For non-inlined bucket update all the leaf stats
+ s.LeafPageN++
+ s.LeafInuse += int(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 * uintptr(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 += uintptr(lastElement.pos + lastElement.ksize)
+ s.BranchInuse += int(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, []pgid)) {
+ // If we have an inline page then just use that.
+ if b.page != nil {
+ fn(b.page, 0, []pgid{b.root})
+ return
+ }
+
+ // Otherwise traverse the page hierarchy.
+ b.tx.forEachPage(b.root, 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 + uintptr(len(inode.key)) + uintptr(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() uintptr {
+ return uintptr(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.IncNodeCount(1)
+
+ 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/go.etcd.io/bbolt/compact.go b/vendor/go.etcd.io/bbolt/compact.go
new file mode 100644
index 0000000000..5f1d4c3b50
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/compact.go
@@ -0,0 +1,119 @@
+package bbolt
+
+// Compact will create a copy of the source DB and in the destination DB. This may
+// reclaim space that the source database no longer has use for. txMaxSize can be
+// used to limit the transactions size of this process and may trigger intermittent
+// commits. A value of zero will ignore transaction sizes.
+// TODO: merge with: https://github.com/etcd-io/etcd/blob/b7f0f52a16dbf83f18ca1d803f7892d750366a94/mvcc/backend/backend.go#L349
+func Compact(dst, src *DB, txMaxSize int64) error {
+ // commit regularly, or we'll run out of memory for large datasets if using one transaction.
+ var size int64
+ tx, err := dst.Begin(true)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if tempErr := tx.Rollback(); tempErr != nil {
+ err = tempErr
+ }
+ }()
+
+ if err := walk(src, func(keys [][]byte, k, v []byte, seq uint64) error {
+ // On each key/value, check if we have exceeded tx size.
+ sz := int64(len(k) + len(v))
+ if size+sz > txMaxSize && txMaxSize != 0 {
+ // Commit previous transaction.
+ if err := tx.Commit(); err != nil {
+ return err
+ }
+
+ // Start new transaction.
+ tx, err = dst.Begin(true)
+ if err != nil {
+ return err
+ }
+ size = 0
+ }
+ size += sz
+
+ // Create bucket on the root transaction if this is the first level.
+ nk := len(keys)
+ if nk == 0 {
+ bkt, err := tx.CreateBucket(k)
+ if err != nil {
+ return err
+ }
+ if err := bkt.SetSequence(seq); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ // Create buckets on subsequent levels, if necessary.
+ b := tx.Bucket(keys[0])
+ if nk > 1 {
+ for _, k := range keys[1:] {
+ b = b.Bucket(k)
+ }
+ }
+
+ // Fill the entire page for best compaction.
+ b.FillPercent = 1.0
+
+ // If there is no value then this is a bucket call.
+ if v == nil {
+ bkt, err := b.CreateBucket(k)
+ if err != nil {
+ return err
+ }
+ if err := bkt.SetSequence(seq); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ // Otherwise treat it as a key/value pair.
+ return b.Put(k, v)
+ }); err != nil {
+ return err
+ }
+ err = tx.Commit()
+
+ return err
+}
+
+// walkFunc is the type of the function called for keys (buckets and "normal"
+// values) discovered by Walk. keys is the list of keys to descend to the bucket
+// owning the discovered key/value pair k/v.
+type walkFunc func(keys [][]byte, k, v []byte, seq uint64) error
+
+// walk walks recursively the bolt database db, calling walkFn for each key it finds.
+func walk(db *DB, walkFn walkFunc) error {
+ return db.View(func(tx *Tx) error {
+ return tx.ForEach(func(name []byte, b *Bucket) error {
+ return walkBucket(b, nil, name, nil, b.Sequence(), walkFn)
+ })
+ })
+}
+
+func walkBucket(b *Bucket, keypath [][]byte, k, v []byte, seq uint64, fn walkFunc) error {
+ // Execute callback.
+ if err := fn(keypath, k, v, seq); err != nil {
+ return err
+ }
+
+ // If this is not a bucket then stop.
+ if v != nil {
+ return nil
+ }
+
+ // Iterate over each child key/value.
+ keypath = append(keypath, k)
+ return b.ForEach(func(k, v []byte) error {
+ if v == nil {
+ bkt := b.Bucket(k)
+ return walkBucket(bkt, keypath, k, nil, bkt.Sequence(), fn)
+ }
+ return walkBucket(b, keypath, k, v, b.Sequence(), fn)
+ })
+}
diff --git a/vendor/go.etcd.io/bbolt/cursor.go b/vendor/go.etcd.io/bbolt/cursor.go
new file mode 100644
index 0000000000..5dafb0cac3
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/cursor.go
@@ -0,0 +1,420 @@
+package bbolt
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+)
+
+// Cursor represents an iterator that can traverse over all key/value pairs in a bucket
+// in lexicographical 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")
+ k, v, flags := c.first()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+func (c *Cursor) first() (key []byte, value []byte, flags uint32) {
+ 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.goToFirstElementOnTheStack()
+
+ // 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, flags
+ }
+ return k, v, flags
+}
+
+// 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()
+
+ // If this is an empty page (calling Delete may result in empty pages)
+ // we call prev to find the last page that is not empty
+ for len(c.stack) > 0 && c.stack[len(c.stack)-1].count() == 0 {
+ c.prev()
+ }
+
+ if len(c.stack) == 0 {
+ return nil, nil
+ }
+
+ 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")
+ k, v, flags := c.prev()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Seek moves the cursor to a given key using a b-tree search 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) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+
+ 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) {
+ // Start from root page/node and traverse to correct page.
+ c.stack = c.stack[:0]
+ c.search(seek, c.bucket.root)
+
+ // 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) goToFirstElementOnTheStack() {
+ 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.goToFirstElementOnTheStack()
+
+ // 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()
+ }
+}
+
+// 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.
+func (c *Cursor) prev() (key []byte, value []byte, flags uint32) {
+ // 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, 0
+ }
+
+ // Move down the stack to find the last element of the last leaf under this branch.
+ c.last()
+ 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 the cursor is pointing to the end of page/node then return nil.
+ 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(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/go.etcd.io/bbolt/db.go b/vendor/go.etcd.io/bbolt/db.go
new file mode 100644
index 0000000000..4175bdf3dd
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/db.go
@@ -0,0 +1,1389 @@
+package bbolt
+
+import (
+ "errors"
+ "fmt"
+ "hash/fnv"
+ "io"
+ "os"
+ "runtime"
+ "sort"
+ "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
+
+const pgidNoFreelist pgid = 0xffffffffffffffff
+
+// 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()
+
+// The time elapsed between consecutive file locking attempts.
+const flockRetryTimeout = 50 * time.Millisecond
+
+// FreelistType is the type of the freelist backend
+type FreelistType string
+
+const (
+ // FreelistArrayType indicates backend freelist type is array
+ FreelistArrayType = FreelistType("array")
+ // FreelistMapType indicates backend freelist type is hashmap
+ FreelistMapType = FreelistType("hashmap")
+)
+
+// 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 {
+ // Put `stats` at the first field to ensure it's 64-bit aligned. Note that
+ // the first word in an allocated struct can be relied upon to be 64-bit
+ // aligned. Refer to https://pkg.go.dev/sync/atomic#pkg-note-BUG. Also
+ // refer to discussion in https://github.com/etcd-io/bbolt/issues/577.
+ stats Stats
+
+ // 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 syncing freelist to disk. This improves the database
+ // write performance under normal operation, but requires a full database
+ // re-sync during recovery.
+ NoFreelistSync bool
+
+ // FreelistType sets the backend freelist type. There are two options. Array which is simple but endures
+ // dramatic performance degradation if database is large and fragmentation in freelist is common.
+ // The alternative one is using hashmap, it is faster in almost all circumstances
+ // but it doesn't guarantee that it offers the smallest page id available. In normal case it is safe.
+ // The default type is array
+ FreelistType FreelistType
+
+ // 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
+
+ // When `true`, bbolt will always load the free pages when opening the DB.
+ // When opening db in write mode, this flag will always automatically
+ // set to `true`.
+ PreLoadFreelist 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
+
+ // Mlock locks database file in memory when set to true.
+ // It prevents major page faults, however used memory can't be reclaimed.
+ //
+ // Supported only on Unix via mlock/munlock syscalls.
+ Mlock bool
+
+ path string
+ openFile func(string, int, os.FileMode) (*os.File, error)
+ file *os.File
+ // `dataref` isn't used at all on Windows, and the golangci-lint
+ // always fails on Windows platform.
+ //nolint
+ 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
+ freelistLoad sync.Once
+
+ 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) {
+ db := &DB{
+ opened: true,
+ }
+ // Set default options if no options are provided.
+ if options == nil {
+ options = DefaultOptions
+ }
+ db.NoSync = options.NoSync
+ db.NoGrowSync = options.NoGrowSync
+ db.MmapFlags = options.MmapFlags
+ db.NoFreelistSync = options.NoFreelistSync
+ db.PreLoadFreelist = options.PreLoadFreelist
+ db.FreelistType = options.FreelistType
+ db.Mlock = options.Mlock
+
+ // 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
+ } else {
+ // always load free pages in write mode
+ db.PreLoadFreelist = true
+ }
+
+ db.openFile = options.OpenFile
+ if db.openFile == nil {
+ db.openFile = os.OpenFile
+ }
+
+ // Open data file and separate sync handler for metadata writes.
+ var err error
+ if db.file, err = db.openFile(path, flag|os.O_CREATE, mode); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+ db.path = db.file.Name()
+
+ // 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, !db.readOnly, options.Timeout); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+
+ // Default values for test hooks
+ db.ops.writeAt = db.file.WriteAt
+
+ if db.pageSize = options.PageSize; db.pageSize == 0 {
+ // Set the default page size to the OS page size.
+ db.pageSize = defaultPageSize
+ }
+
+ // Initialize the database if it doesn't exist.
+ if info, err := db.file.Stat(); err != nil {
+ _ = db.close()
+ return nil, err
+ } else if info.Size() == 0 {
+ // Initialize new files with meta pages.
+ if err := db.init(); err != nil {
+ // clean up file descriptor on initialization fail
+ _ = db.close()
+ return nil, err
+ }
+ } else {
+ // try to get the page size from the metadata pages
+ if pgSize, err := db.getPageSize(); err == nil {
+ db.pageSize = pgSize
+ } else {
+ _ = db.close()
+ return nil, ErrInvalid
+ }
+ }
+
+ // 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
+ }
+
+ if db.PreLoadFreelist {
+ db.loadFreelist()
+ }
+
+ if db.readOnly {
+ return db, nil
+ }
+
+ // Flush freelist when transitioning from no sync to sync so
+ // NoFreelistSync unaware boltdb can open the db later.
+ if !db.NoFreelistSync && !db.hasSyncedFreelist() {
+ tx, err := db.Begin(true)
+ if tx != nil {
+ err = tx.Commit()
+ }
+ if err != nil {
+ _ = db.close()
+ return nil, err
+ }
+ }
+
+ // Mark the database as opened and return.
+ return db, nil
+}
+
+// getPageSize reads the pageSize from the meta pages. It tries
+// to read the first meta page firstly. If the first page is invalid,
+// then it tries to read the second page using the default page size.
+func (db *DB) getPageSize() (int, error) {
+ var (
+ meta0CanRead, meta1CanRead bool
+ )
+
+ // Read the first meta page to determine the page size.
+ if pgSize, canRead, err := db.getPageSizeFromFirstMeta(); err != nil {
+ // We cannot read the page size from page 0, but can read page 0.
+ meta0CanRead = canRead
+ } else {
+ return pgSize, nil
+ }
+
+ // Read the second meta page to determine the page size.
+ if pgSize, canRead, err := db.getPageSizeFromSecondMeta(); err != nil {
+ // We cannot read the page size from page 1, but can read page 1.
+ meta1CanRead = canRead
+ } else {
+ return pgSize, nil
+ }
+
+ // If we can't read the page size from both pages, but can read
+ // either page, then we assume it's the same as the OS or the one
+ // given, since that's how the page size was chosen in the first place.
+ //
+ // If both pages are invalid, and (this OS uses a different page size
+ // from what the database was created with or the given page size is
+ // different from what the database was created with), then we are out
+ // of luck and cannot access the database.
+ if meta0CanRead || meta1CanRead {
+ return db.pageSize, nil
+ }
+
+ return 0, ErrInvalid
+}
+
+// getPageSizeFromFirstMeta reads the pageSize from the first meta page
+func (db *DB) getPageSizeFromFirstMeta() (int, bool, error) {
+ var buf [0x1000]byte
+ var metaCanRead bool
+ if bw, err := db.file.ReadAt(buf[:], 0); err == nil && bw == len(buf) {
+ metaCanRead = true
+ if m := db.pageInBuffer(buf[:], 0).meta(); m.validate() == nil {
+ return int(m.pageSize), metaCanRead, nil
+ }
+ }
+ return 0, metaCanRead, ErrInvalid
+}
+
+// getPageSizeFromSecondMeta reads the pageSize from the second meta page
+func (db *DB) getPageSizeFromSecondMeta() (int, bool, error) {
+ var (
+ fileSize int64
+ metaCanRead bool
+ )
+
+ // get the db file size
+ if info, err := db.file.Stat(); err != nil {
+ return 0, metaCanRead, err
+ } else {
+ fileSize = info.Size()
+ }
+
+ // We need to read the second meta page, so we should skip the first page;
+ // but we don't know the exact page size yet, it's chicken & egg problem.
+ // The solution is to try all the possible page sizes, which starts from 1KB
+ // and until 16MB (1024<<14) or the end of the db file
+ //
+ // TODO: should we support larger page size?
+ for i := 0; i <= 14; i++ {
+ var buf [0x1000]byte
+ var pos int64 = 1024 << uint(i)
+ if pos >= fileSize-1024 {
+ break
+ }
+ bw, err := db.file.ReadAt(buf[:], pos)
+ if (err == nil && bw == len(buf)) || (err == io.EOF && int64(bw) == (fileSize-pos)) {
+ metaCanRead = true
+ if m := db.pageInBuffer(buf[:], 0).meta(); m.validate() == nil {
+ return int(m.pageSize), metaCanRead, nil
+ }
+ }
+ }
+
+ return 0, metaCanRead, ErrInvalid
+}
+
+// loadFreelist reads the freelist if it is synced, or reconstructs it
+// by scanning the DB if it is not synced. It assumes there are no
+// concurrent accesses being made to the freelist.
+func (db *DB) loadFreelist() {
+ db.freelistLoad.Do(func() {
+ db.freelist = newFreelist(db.FreelistType)
+ if !db.hasSyncedFreelist() {
+ // Reconstruct free list by scanning the DB.
+ db.freelist.readIDs(db.freepages())
+ } else {
+ // Read free list from freelist page.
+ db.freelist.read(db.page(db.meta().freelist))
+ }
+ db.stats.FreePageN = db.freelist.free_count()
+ })
+}
+
+func (db *DB) hasSyncedFreelist() bool {
+ return db.meta().freelist != pgidNoFreelist
+}
+
+// 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) (err 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.
+ fileSize := int(info.Size())
+ var size = fileSize
+ if size < minsz {
+ size = minsz
+ }
+ size, err = db.mmapSize(size)
+ if err != nil {
+ return err
+ }
+
+ if db.Mlock {
+ // Unlock db memory
+ if err := db.munlock(fileSize); 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.
+ // gofail: var mapError string
+ // return errors.New(mapError)
+ if err = mmap(db, size); err != nil {
+ return err
+ }
+
+ // Perform unmmap on any error to reset all data fields:
+ // dataref, data, datasz, meta0 and meta1.
+ defer func() {
+ if err != nil {
+ if unmapErr := db.munmap(); unmapErr != nil {
+ err = fmt.Errorf("%w; rollback unmap also failed: %v", err, unmapErr)
+ }
+ }
+ }()
+
+ if db.Mlock {
+ // Don't allow swapping of data file
+ if err := db.mlock(fileSize); 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
+}
+
+func (db *DB) invalidate() {
+ db.dataref = nil
+ db.data = nil
+ db.datasz = 0
+
+ db.meta0 = nil
+ db.meta1 = nil
+}
+
+// munmap unmaps the data file from memory.
+func (db *DB) munmap() error {
+ defer db.invalidate()
+
+ // gofail: var unmapError string
+ // return errors.New(unmapError)
+ 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
+}
+
+func (db *DB) munlock(fileSize int) error {
+ // gofail: var munlockError string
+ // return errors.New(munlockError)
+ if err := munlock(db, fileSize); err != nil {
+ return fmt.Errorf("munlock error: " + err.Error())
+ }
+ return nil
+}
+
+func (db *DB) mlock(fileSize int) error {
+ // gofail: var mlockError string
+ // return errors.New(mlockError)
+ if err := mlock(db, fileSize); err != nil {
+ return fmt.Errorf("mlock error: " + err.Error())
+ }
+ return nil
+}
+
+func (db *DB) mrelock(fileSizeFrom, fileSizeTo int) error {
+ if err := db.munlock(fileSizeFrom); err != nil {
+ return err
+ }
+ if err := db.mlock(fileSizeTo); err != nil {
+ return err
+ }
+ return nil
+}
+
+// init creates a new database file and initializes its meta pages.
+func (db *DB) init() error {
+ // 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
+ }
+ db.filesz = len(buf)
+
+ return nil
+}
+
+// Close releases all database resources.
+// It will block waiting for any open transactions to finish
+// before closing the database and returning.
+func (db *DB) Close() error {
+ db.rwlock.Lock()
+ defer db.rwlock.Unlock()
+
+ db.metalock.Lock()
+ defer db.metalock.Unlock()
+
+ db.mmaplock.Lock()
+ defer db.mmaplock.Unlock()
+
+ 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
+
+ var errs []error
+ // Close the mmap.
+ if err := db.munmap(); err != nil {
+ errs = append(errs, 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 {
+ errs = append(errs, fmt.Errorf("bolt.Close(): funlock error: %w", err))
+ }
+ }
+
+ // Close the file descriptor.
+ if err := db.file.Close(); err != nil {
+ errs = append(errs, fmt.Errorf("db file close: %w", err))
+ }
+ db.file = nil
+ }
+
+ db.path = ""
+
+ if len(errs) > 0 {
+ return errs[0]
+ }
+ 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
+ }
+
+ // Exit if the database is not correctly mapped.
+ if db.data == nil {
+ db.mmaplock.RUnlock()
+ db.metalock.Unlock()
+ return nil, ErrInvalidMapping
+ }
+
+ // 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
+ }
+
+ // Exit if the database is not correctly mapped.
+ if db.data == nil {
+ db.rwlock.Unlock()
+ return nil, ErrInvalidMapping
+ }
+
+ // Create a transaction associated with the database.
+ t := &Tx{writable: true}
+ t.init(db)
+ db.rwtx = t
+ db.freePages()
+ return t, nil
+}
+
+// freePages releases any pages associated with closed read-only transactions.
+func (db *DB) freePages() {
+ // Free all pending pages prior to earliest open transaction.
+ sort.Sort(txsById(db.txs))
+ minid := txid(0xFFFFFFFFFFFFFFFF)
+ if len(db.txs) > 0 {
+ minid = db.txs[0].meta.txid
+ }
+ if minid > 0 {
+ db.freelist.release(minid - 1)
+ }
+ // Release unused txid extents.
+ for _, t := range db.txs {
+ db.freelist.releaseRange(minid, t.meta.txid-1)
+ minid = t.meta.txid + 1
+ }
+ db.freelist.releaseRange(minid, txid(0xFFFFFFFFFFFFFFFF))
+ // Any page both allocated and freed in an extent is safe to release.
+}
+
+type txsById []*Tx
+
+func (t txsById) Len() int { return len(t) }
+func (t txsById) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
+func (t txsById) Less(i, j int) bool { return t[i].meta.txid < t[j].meta.txid }
+
+// 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 {
+ last := len(db.txs) - 1
+ db.txs[i] = db.txs[last]
+ db.txs[last] = nil
+ db.txs = db.txs[:last]
+ 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
+ }
+
+ return t.Rollback()
+}
+
+// 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 {
+ 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 {
+ _assert(db.data != nil, "database file isn't correctly mapped")
+ 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(txid txid, 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(txid, 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)
+ }
+ if db.Mlock {
+ // unlock old file and lock new one
+ if err := db.mrelock(db.filesz, sz); err != nil {
+ return fmt.Errorf("mlock/munlock error: %s", err)
+ }
+ }
+ }
+
+ db.filesz = sz
+ return nil
+}
+
+func (db *DB) IsReadOnly() bool {
+ return db.readOnly
+}
+
+func (db *DB) freepages() []pgid {
+ tx, err := db.beginTx()
+ defer func() {
+ err = tx.Rollback()
+ if err != nil {
+ panic("freepages: failed to rollback tx")
+ }
+ }()
+ if err != nil {
+ panic("freepages: failed to open read only tx")
+ }
+
+ reachable := make(map[pgid]*page)
+ nofreed := make(map[pgid]bool)
+ ech := make(chan error)
+ go func() {
+ for e := range ech {
+ panic(fmt.Sprintf("freepages: failed to get all reachable pages (%v)", e))
+ }
+ }()
+ tx.checkBucket(&tx.root, reachable, nofreed, HexKVStringer(), ech)
+ close(ech)
+
+ // TODO: If check bucket reported any corruptions (ech) we shouldn't proceed to freeing the pages.
+
+ var fids []pgid
+ for i := pgid(2); i < db.meta().pgid; i++ {
+ if _, ok := reachable[i]; !ok {
+ fids = append(fids, i)
+ }
+ }
+ return fids
+}
+
+// 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
+
+ // Do not sync freelist to disk. This improves the database write performance
+ // under normal operation, but requires a full database re-sync during recovery.
+ NoFreelistSync bool
+
+ // PreLoadFreelist sets whether to load the free pages when opening
+ // the db file. Note when opening db in write mode, bbolt will always
+ // load the free pages.
+ PreLoadFreelist bool
+
+ // FreelistType sets the backend freelist type. There are two options. Array which is simple but endures
+ // dramatic performance degradation if database is large and fragmentation in freelist is common.
+ // The alternative one is using hashmap, it is faster in almost all circumstances
+ // but it doesn't guarantee that it offers the smallest page id available. In normal case it is safe.
+ // The default type is array
+ FreelistType FreelistType
+
+ // 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
+
+ // PageSize overrides the default OS page size.
+ PageSize int
+
+ // NoSync sets the initial value of DB.NoSync. Normally this can just be
+ // set directly on the DB itself when returned from Open(), but this option
+ // is useful in APIs which expose Options but not the underlying DB.
+ NoSync bool
+
+ // OpenFile is used to open files. It defaults to os.OpenFile. This option
+ // is useful for writing hermetic tests.
+ OpenFile func(string, int, os.FileMode) (*os.File, error)
+
+ // Mlock locks database file in memory when set to true.
+ // It prevents potential page faults, however
+ // used memory can't be reclaimed. (UNIX only)
+ Mlock bool
+}
+
+// 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,
+ FreelistType: FreelistArrayType,
+}
+
+// Stats represents statistics about the database.
+type Stats struct {
+ // Put `TxStats` at the first field to ensure it's 64-bit aligned. Note
+ // that the first word in an allocated struct can be relied upon to be
+ // 64-bit aligned. Refer to https://pkg.go.dev/sync/atomic#pkg-note-BUG.
+ // Also refer to discussion in https://github.com/etcd-io/bbolt/issues/577.
+ TxStats TxStats // global, ongoing stats.
+
+ // 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
+}
+
+// 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 = s.TxN - other.TxN
+ diff.TxStats = s.TxStats.Sub(&other.TxStats)
+ return diff
+}
+
+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 != 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 && m.freelist != pgidNoFreelist {
+ // TODO: reject pgidNoFreeList if !NoFreelistSync
+ 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...))
+ }
+}
diff --git a/vendor/go.etcd.io/bbolt/doc.go b/vendor/go.etcd.io/bbolt/doc.go
new file mode 100644
index 0000000000..d1007e4b04
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/doc.go
@@ -0,0 +1,40 @@
+/*
+package bbolt 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 bbolt
diff --git a/vendor/go.etcd.io/bbolt/errors.go b/vendor/go.etcd.io/bbolt/errors.go
new file mode 100644
index 0000000000..f2c3b20ed8
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/errors.go
@@ -0,0 +1,78 @@
+package bbolt
+
+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")
+
+ // ErrInvalidMapping is returned when the database file fails to get mapped.
+ ErrInvalidMapping = errors.New("database isn't correctly mapped")
+
+ // 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")
+
+ // ErrFreePagesNotLoaded is returned when a readonly transaction without
+ // preloading the free pages is trying to access the free pages.
+ ErrFreePagesNotLoaded = errors.New("free pages are not pre-loaded")
+)
+
+// 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/go.etcd.io/bbolt/freelist.go b/vendor/go.etcd.io/bbolt/freelist.go
new file mode 100644
index 0000000000..50f2d0e174
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/freelist.go
@@ -0,0 +1,405 @@
+package bbolt
+
+import (
+ "fmt"
+ "sort"
+ "unsafe"
+)
+
+// txPending holds a list of pgids and corresponding allocation txns
+// that are pending to be freed.
+type txPending struct {
+ ids []pgid
+ alloctx []txid // txids allocating the ids
+ lastReleaseBegin txid // beginning txid of last matching releaseRange
+}
+
+// pidSet holds the set of starting pgids which have the same span size
+type pidSet map[pgid]struct{}
+
+// 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 {
+ freelistType FreelistType // freelist type
+ ids []pgid // all free and available free page ids.
+ allocs map[pgid]txid // mapping of txid that allocated a pgid.
+ pending map[txid]*txPending // mapping of soon-to-be free page ids by tx.
+ cache map[pgid]struct{} // fast lookup of all free and pending page ids.
+ freemaps map[uint64]pidSet // key is the size of continuous pages(span), value is a set which contains the starting pgids of same size
+ forwardMap map[pgid]uint64 // key is start pgid, value is its span size
+ backwardMap map[pgid]uint64 // key is end pgid, value is its span size
+ allocate func(txid txid, n int) pgid // the freelist allocate func
+ free_count func() int // the function which gives you free page number
+ mergeSpans func(ids pgids) // the mergeSpan func
+ getFreePageIDs func() []pgid // get free pgids func
+ readIDs func(pgids []pgid) // readIDs func reads list of pages and init the freelist
+}
+
+// newFreelist returns an empty, initialized freelist.
+func newFreelist(freelistType FreelistType) *freelist {
+ f := &freelist{
+ freelistType: freelistType,
+ allocs: make(map[pgid]txid),
+ pending: make(map[txid]*txPending),
+ cache: make(map[pgid]struct{}),
+ freemaps: make(map[uint64]pidSet),
+ forwardMap: make(map[pgid]uint64),
+ backwardMap: make(map[pgid]uint64),
+ }
+
+ if freelistType == FreelistMapType {
+ f.allocate = f.hashmapAllocate
+ f.free_count = f.hashmapFreeCount
+ f.mergeSpans = f.hashmapMergeSpans
+ f.getFreePageIDs = f.hashmapGetFreePageIDs
+ f.readIDs = f.hashmapReadIDs
+ } else {
+ f.allocate = f.arrayAllocate
+ f.free_count = f.arrayFreeCount
+ f.mergeSpans = f.arrayMergeSpans
+ f.getFreePageIDs = f.arrayGetFreePageIDs
+ f.readIDs = f.arrayReadIDs
+ }
+
+ return f
+}
+
+// size returns the size of the page after serialization.
+func (f *freelist) size() int {
+ n := f.count()
+ if n >= 0xFFFF {
+ // The first element will be used to store the count. See freelist.write.
+ n++
+ }
+ return int(pageHeaderSize) + (int(unsafe.Sizeof(pgid(0))) * n)
+}
+
+// count returns count of pages on the freelist
+func (f *freelist) count() int {
+ return f.free_count() + f.pending_count()
+}
+
+// arrayFreeCount returns count of free pages(array version)
+func (f *freelist) arrayFreeCount() int {
+ return len(f.ids)
+}
+
+// pending_count returns count of pending pages
+func (f *freelist) pending_count() int {
+ var count int
+ for _, txp := range f.pending {
+ count += len(txp.ids)
+ }
+ return count
+}
+
+// copyall copies a list of all free ids and all pending ids in one sorted list.
+// f.count returns the minimum length required for dst.
+func (f *freelist) copyall(dst []pgid) {
+ m := make(pgids, 0, f.pending_count())
+ for _, txp := range f.pending {
+ m = append(m, txp.ids...)
+ }
+ sort.Sort(m)
+ mergepgids(dst, f.getFreePageIDs(), m)
+}
+
+// arrayAllocate 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) arrayAllocate(txid txid, 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)
+ }
+ f.allocs[initial] = txid
+ 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.
+ txp := f.pending[txid]
+ if txp == nil {
+ txp = &txPending{}
+ f.pending[txid] = txp
+ }
+ allocTxid, ok := f.allocs[p.id]
+ if ok {
+ delete(f.allocs, p.id)
+ } else if (p.flags & freelistPageFlag) != 0 {
+ // Freelist is always allocated by prior tx.
+ allocTxid = txid - 1
+ }
+
+ for id := p.id; id <= p.id+pgid(p.overflow); id++ {
+ // Verify that page is not already free.
+ if _, ok := f.cache[id]; ok {
+ panic(fmt.Sprintf("page %d already freed", id))
+ }
+ // Add to the freelist and cache.
+ txp.ids = append(txp.ids, id)
+ txp.alloctx = append(txp.alloctx, allocTxid)
+ f.cache[id] = struct{}{}
+ }
+}
+
+// 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, txp := 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, txp.ids...)
+ delete(f.pending, tid)
+ }
+ }
+ f.mergeSpans(m)
+}
+
+// releaseRange moves pending pages allocated within an extent [begin,end] to the free list.
+func (f *freelist) releaseRange(begin, end txid) {
+ if begin > end {
+ return
+ }
+ var m pgids
+ for tid, txp := range f.pending {
+ if tid < begin || tid > end {
+ continue
+ }
+ // Don't recompute freed pages if ranges haven't updated.
+ if txp.lastReleaseBegin == begin {
+ continue
+ }
+ for i := 0; i < len(txp.ids); i++ {
+ if atx := txp.alloctx[i]; atx < begin || atx > end {
+ continue
+ }
+ m = append(m, txp.ids[i])
+ txp.ids[i] = txp.ids[len(txp.ids)-1]
+ txp.ids = txp.ids[:len(txp.ids)-1]
+ txp.alloctx[i] = txp.alloctx[len(txp.alloctx)-1]
+ txp.alloctx = txp.alloctx[:len(txp.alloctx)-1]
+ i--
+ }
+ txp.lastReleaseBegin = begin
+ if len(txp.ids) == 0 {
+ delete(f.pending, tid)
+ }
+ }
+ f.mergeSpans(m)
+}
+
+// rollback removes the pages from a given pending tx.
+func (f *freelist) rollback(txid txid) {
+ // Remove page ids from cache.
+ txp := f.pending[txid]
+ if txp == nil {
+ return
+ }
+ var m pgids
+ for i, pgid := range txp.ids {
+ delete(f.cache, pgid)
+ tx := txp.alloctx[i]
+ if tx == 0 {
+ continue
+ }
+ if tx != txid {
+ // Pending free aborted; restore page back to alloc list.
+ f.allocs[pgid] = tx
+ } else {
+ // Freed page was allocated by this txn; OK to throw away.
+ m = append(m, pgid)
+ }
+ }
+ // Remove pages from pending list and mark as free if allocated by txid.
+ delete(f.pending, txid)
+ f.mergeSpans(m)
+}
+
+// freed returns whether a given page is in the free list.
+func (f *freelist) freed(pgId pgid) bool {
+ _, ok := f.cache[pgId]
+ return ok
+}
+
+// read initializes the freelist from a freelist page.
+func (f *freelist) read(p *page) {
+ if (p.flags & freelistPageFlag) == 0 {
+ panic(fmt.Sprintf("invalid freelist page: %d, page type is %s", p.id, p.typ()))
+ }
+ // 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.
+ var idx, count = 0, int(p.count)
+ if count == 0xFFFF {
+ idx = 1
+ c := *(*pgid)(unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)))
+ count = int(c)
+ if count < 0 {
+ panic(fmt.Sprintf("leading element count %d overflows int", c))
+ }
+ }
+
+ // Copy the list of page ids from the freelist.
+ if count == 0 {
+ f.ids = nil
+ } else {
+ var ids []pgid
+ data := unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), unsafe.Sizeof(ids[0]), idx)
+ unsafeSlice(unsafe.Pointer(&ids), data, count)
+
+ // copy the ids, so we don't modify on the freelist page directly
+ idsCopy := make([]pgid, count)
+ copy(idsCopy, ids)
+ // Make sure they're sorted.
+ sort.Sort(pgids(idsCopy))
+
+ f.readIDs(idsCopy)
+ }
+}
+
+// arrayReadIDs initializes the freelist from a given list of ids.
+func (f *freelist) arrayReadIDs(ids []pgid) {
+ f.ids = ids
+ f.reindex()
+}
+
+func (f *freelist) arrayGetFreePageIDs() []pgid {
+ return f.ids
+}
+
+// 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.
+
+ // 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.
+ l := f.count()
+ if l == 0 {
+ p.count = uint16(l)
+ } else if l < 0xFFFF {
+ p.count = uint16(l)
+ var ids []pgid
+ data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
+ unsafeSlice(unsafe.Pointer(&ids), data, l)
+ f.copyall(ids)
+ } else {
+ p.count = 0xFFFF
+ var ids []pgid
+ data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
+ unsafeSlice(unsafe.Pointer(&ids), data, l+1)
+ ids[0] = pgid(l)
+ f.copyall(ids[1:])
+ }
+
+ 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 _, txp := range f.pending {
+ for _, pendingID := range txp.ids {
+ 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.getFreePageIDs() {
+ if !pcache[id] {
+ a = append(a, id)
+ }
+ }
+
+ f.readIDs(a)
+}
+
+// noSyncReload reads the freelist from pgids and filters out pending items.
+func (f *freelist) noSyncReload(pgids []pgid) {
+ // Build a cache of only pending pages.
+ pcache := make(map[pgid]bool)
+ for _, txp := range f.pending {
+ for _, pendingID := range txp.ids {
+ 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 pgids {
+ if !pcache[id] {
+ a = append(a, id)
+ }
+ }
+
+ f.readIDs(a)
+}
+
+// reindex rebuilds the free cache based on available and pending free lists.
+func (f *freelist) reindex() {
+ ids := f.getFreePageIDs()
+ f.cache = make(map[pgid]struct{}, len(ids))
+ for _, id := range ids {
+ f.cache[id] = struct{}{}
+ }
+ for _, txp := range f.pending {
+ for _, pendingID := range txp.ids {
+ f.cache[pendingID] = struct{}{}
+ }
+ }
+}
+
+// arrayMergeSpans try to merge list of pages(represented by pgids) with existing spans but using array
+func (f *freelist) arrayMergeSpans(ids pgids) {
+ sort.Sort(ids)
+ f.ids = pgids(f.ids).merge(ids)
+}
diff --git a/vendor/go.etcd.io/bbolt/freelist_hmap.go b/vendor/go.etcd.io/bbolt/freelist_hmap.go
new file mode 100644
index 0000000000..dbd67a1e73
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/freelist_hmap.go
@@ -0,0 +1,178 @@
+package bbolt
+
+import "sort"
+
+// hashmapFreeCount returns count of free pages(hashmap version)
+func (f *freelist) hashmapFreeCount() int {
+ // use the forwardMap to get the total count
+ count := 0
+ for _, size := range f.forwardMap {
+ count += int(size)
+ }
+ return count
+}
+
+// hashmapAllocate serves the same purpose as arrayAllocate, but use hashmap as backend
+func (f *freelist) hashmapAllocate(txid txid, n int) pgid {
+ if n == 0 {
+ return 0
+ }
+
+ // if we have a exact size match just return short path
+ if bm, ok := f.freemaps[uint64(n)]; ok {
+ for pid := range bm {
+ // remove the span
+ f.delSpan(pid, uint64(n))
+
+ f.allocs[pid] = txid
+
+ for i := pgid(0); i < pgid(n); i++ {
+ delete(f.cache, pid+i)
+ }
+ return pid
+ }
+ }
+
+ // lookup the map to find larger span
+ for size, bm := range f.freemaps {
+ if size < uint64(n) {
+ continue
+ }
+
+ for pid := range bm {
+ // remove the initial
+ f.delSpan(pid, size)
+
+ f.allocs[pid] = txid
+
+ remain := size - uint64(n)
+
+ // add remain span
+ f.addSpan(pid+pgid(n), remain)
+
+ for i := pgid(0); i < pgid(n); i++ {
+ delete(f.cache, pid+i)
+ }
+ return pid
+ }
+ }
+
+ return 0
+}
+
+// hashmapReadIDs reads pgids as input an initial the freelist(hashmap version)
+func (f *freelist) hashmapReadIDs(pgids []pgid) {
+ f.init(pgids)
+
+ // Rebuild the page cache.
+ f.reindex()
+}
+
+// hashmapGetFreePageIDs returns the sorted free page ids
+func (f *freelist) hashmapGetFreePageIDs() []pgid {
+ count := f.free_count()
+ if count == 0 {
+ return nil
+ }
+
+ m := make([]pgid, 0, count)
+ for start, size := range f.forwardMap {
+ for i := 0; i < int(size); i++ {
+ m = append(m, start+pgid(i))
+ }
+ }
+ sort.Sort(pgids(m))
+
+ return m
+}
+
+// hashmapMergeSpans try to merge list of pages(represented by pgids) with existing spans
+func (f *freelist) hashmapMergeSpans(ids pgids) {
+ for _, id := range ids {
+ // try to see if we can merge and update
+ f.mergeWithExistingSpan(id)
+ }
+}
+
+// mergeWithExistingSpan merges pid to the existing free spans, try to merge it backward and forward
+func (f *freelist) mergeWithExistingSpan(pid pgid) {
+ prev := pid - 1
+ next := pid + 1
+
+ preSize, mergeWithPrev := f.backwardMap[prev]
+ nextSize, mergeWithNext := f.forwardMap[next]
+ newStart := pid
+ newSize := uint64(1)
+
+ if mergeWithPrev {
+ //merge with previous span
+ start := prev + 1 - pgid(preSize)
+ f.delSpan(start, preSize)
+
+ newStart -= pgid(preSize)
+ newSize += preSize
+ }
+
+ if mergeWithNext {
+ // merge with next span
+ f.delSpan(next, nextSize)
+ newSize += nextSize
+ }
+
+ f.addSpan(newStart, newSize)
+}
+
+func (f *freelist) addSpan(start pgid, size uint64) {
+ f.backwardMap[start-1+pgid(size)] = size
+ f.forwardMap[start] = size
+ if _, ok := f.freemaps[size]; !ok {
+ f.freemaps[size] = make(map[pgid]struct{})
+ }
+
+ f.freemaps[size][start] = struct{}{}
+}
+
+func (f *freelist) delSpan(start pgid, size uint64) {
+ delete(f.forwardMap, start)
+ delete(f.backwardMap, start+pgid(size-1))
+ delete(f.freemaps[size], start)
+ if len(f.freemaps[size]) == 0 {
+ delete(f.freemaps, size)
+ }
+}
+
+// initial from pgids using when use hashmap version
+// pgids must be sorted
+func (f *freelist) init(pgids []pgid) {
+ if len(pgids) == 0 {
+ return
+ }
+
+ size := uint64(1)
+ start := pgids[0]
+
+ if !sort.SliceIsSorted([]pgid(pgids), func(i, j int) bool { return pgids[i] < pgids[j] }) {
+ panic("pgids not sorted")
+ }
+
+ f.freemaps = make(map[uint64]pidSet)
+ f.forwardMap = make(map[pgid]uint64)
+ f.backwardMap = make(map[pgid]uint64)
+
+ for i := 1; i < len(pgids); i++ {
+ // continuous page
+ if pgids[i] == pgids[i-1]+1 {
+ size++
+ } else {
+ f.addSpan(start, size)
+
+ size = 1
+ start = pgids[i]
+ }
+ }
+
+ // init the tail
+ if size != 0 && start != 0 {
+ f.addSpan(start, size)
+ }
+}
diff --git a/vendor/go.etcd.io/bbolt/mlock_unix.go b/vendor/go.etcd.io/bbolt/mlock_unix.go
new file mode 100644
index 0000000000..744a972f51
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/mlock_unix.go
@@ -0,0 +1,37 @@
+//go:build !windows
+// +build !windows
+
+package bbolt
+
+import "golang.org/x/sys/unix"
+
+// mlock locks memory of db file
+func mlock(db *DB, fileSize int) error {
+ sizeToLock := fileSize
+ if sizeToLock > db.datasz {
+ // Can't lock more than mmaped slice
+ sizeToLock = db.datasz
+ }
+ if err := unix.Mlock(db.dataref[:sizeToLock]); err != nil {
+ return err
+ }
+ return nil
+}
+
+// munlock unlocks memory of db file
+func munlock(db *DB, fileSize int) error {
+ if db.dataref == nil {
+ return nil
+ }
+
+ sizeToUnlock := fileSize
+ if sizeToUnlock > db.datasz {
+ // Can't unlock more than mmaped slice
+ sizeToUnlock = db.datasz
+ }
+
+ if err := unix.Munlock(db.dataref[:sizeToUnlock]); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/vendor/go.etcd.io/bbolt/mlock_windows.go b/vendor/go.etcd.io/bbolt/mlock_windows.go
new file mode 100644
index 0000000000..00b0fb431f
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/mlock_windows.go
@@ -0,0 +1,11 @@
+package bbolt
+
+// mlock locks memory of db file
+func mlock(_ *DB, _ int) error {
+ panic("mlock is supported only on UNIX systems")
+}
+
+// munlock unlocks memory of db file
+func munlock(_ *DB, _ int) error {
+ panic("munlock is supported only on UNIX systems")
+}
diff --git a/vendor/go.etcd.io/bbolt/node.go b/vendor/go.etcd.io/bbolt/node.go
new file mode 100644
index 0000000000..9c56150d88
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/node.go
@@ -0,0 +1,610 @@
+package bbolt
+
+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 + uintptr(len(item.key)) + uintptr(len(item.value))
+ }
+ return int(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 uintptr) bool {
+ sz, elsz := pageHeaderSize, n.pageElementSize()
+ for i := 0; i < len(n.inodes); i++ {
+ item := &n.inodes[i]
+ sz += elsz + uintptr(len(item.key)) + uintptr(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() uintptr {
+ 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.
+// The page should have p.id (might be 0 for meta or bucket-inline page) and p.overflow set
+// and the rest should be zeroed.
+func (n *node) write(p *page) {
+ _assert(p.count == 0 && p.flags == 0, "node cannot be written into a not empty 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.
+ // off tracks the offset into p of the start of the next data.
+ off := unsafe.Sizeof(*p) + n.pageElementSize()*uintptr(len(n.inodes))
+ for i, item := range n.inodes {
+ _assert(len(item.key) > 0, "write: zero-length inode key")
+
+ // Create a slice to write into of needed size and advance
+ // byte pointer for next iteration.
+ sz := len(item.key) + len(item.value)
+ b := unsafeByteSlice(unsafe.Pointer(p), off, 0, sz)
+ off += uintptr(sz)
+
+ // 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")
+ }
+
+ // Write data for the element to the end of the page.
+ l := copy(b, item.key)
+ copy(b[l:], item.value)
+ }
+
+ // 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 uintptr) []*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 uintptr) (*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.IncSplit(1)
+
+ 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 uintptr) {
+ 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 = uintptr(i)
+ inode := n.inodes[i]
+ elsize := n.pageElementSize() + uintptr(len(inode.key)) + uintptr(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 index >= minKeysPerPage && sz+elsize > uintptr(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(uintptr(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) / tx.db.pageSize)
+ 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.IncSpill(1)
+ }
+
+ // 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.IncRebalance(1)
+
+ // 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.IncNodeDeref(1)
+}
+
+// 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("")
+}
+*/
+
+func compareKeys(left, right []byte) int {
+ return bytes.Compare(left, right)
+}
+
+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/go.etcd.io/bbolt/page.go b/vendor/go.etcd.io/bbolt/page.go
new file mode 100644
index 0000000000..379645c97f
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/page.go
@@ -0,0 +1,214 @@
+package bbolt
+
+import (
+ "fmt"
+ "os"
+ "sort"
+ "unsafe"
+)
+
+const pageHeaderSize = unsafe.Sizeof(page{})
+
+const minKeysPerPage = 2
+
+const branchPageElementSize = unsafe.Sizeof(branchPageElement{})
+const leafPageElementSize = 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
+}
+
+// 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)(unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)))
+}
+
+func (p *page) fastCheck(id pgid) {
+ _assert(p.id == id, "Page expected to be: %v, but self identifies as %v", id, p.id)
+ // Only one flag of page-type can be set.
+ _assert(p.flags == branchPageFlag ||
+ p.flags == leafPageFlag ||
+ p.flags == metaPageFlag ||
+ p.flags == freelistPageFlag,
+ "page %v: has unexpected type/flags: %x", p.id, p.flags)
+}
+
+// leafPageElement retrieves the leaf node by index
+func (p *page) leafPageElement(index uint16) *leafPageElement {
+ return (*leafPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p),
+ leafPageElementSize, int(index)))
+}
+
+// leafPageElements retrieves a list of leaf nodes.
+func (p *page) leafPageElements() []leafPageElement {
+ if p.count == 0 {
+ return nil
+ }
+ var elems []leafPageElement
+ data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
+ unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
+ return elems
+}
+
+// branchPageElement retrieves the branch node by index
+func (p *page) branchPageElement(index uint16) *branchPageElement {
+ return (*branchPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p),
+ unsafe.Sizeof(branchPageElement{}), int(index)))
+}
+
+// branchPageElements retrieves a list of branch nodes.
+func (p *page) branchPageElements() []branchPageElement {
+ if p.count == 0 {
+ return nil
+ }
+ var elems []branchPageElement
+ data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
+ unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
+ return elems
+}
+
+// dump writes n bytes of the page to STDERR as hex output.
+func (p *page) hexdump(n int) {
+ buf := unsafeByteSlice(unsafe.Pointer(p), 0, 0, 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 {
+ return unsafeByteSlice(unsafe.Pointer(n), 0, int(n.pos), int(n.pos)+int(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 {
+ i := int(n.pos)
+ j := i + int(n.ksize)
+ return unsafeByteSlice(unsafe.Pointer(n), 0, i, j)
+}
+
+// value returns a byte slice of the node value.
+func (n *leafPageElement) value() []byte {
+ i := int(n.pos) + int(n.ksize)
+ j := i + int(n.vsize)
+ return unsafeByteSlice(unsafe.Pointer(n), 0, i, j)
+}
+
+// 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
+ }
+ if len(b) == 0 {
+ return a
+ }
+ merged := make(pgids, len(a)+len(b))
+ mergepgids(merged, a, b)
+ return merged
+}
+
+// mergepgids copies the sorted union of a and b into dst.
+// If dst is too small, it panics.
+func mergepgids(dst, a, b pgids) {
+ if len(dst) < len(a)+len(b) {
+ panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b)))
+ }
+ // Copy in the opposite slice if one is nil.
+ if len(a) == 0 {
+ copy(dst, b)
+ return
+ }
+ if len(b) == 0 {
+ copy(dst, a)
+ return
+ }
+
+ // Merged will hold all elements from both lists.
+ merged := dst[:0]
+
+ // 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.
+ _ = append(merged, follow...)
+}
diff --git a/vendor/go.etcd.io/bbolt/tx.go b/vendor/go.etcd.io/bbolt/tx.go
new file mode 100644
index 0000000000..2fac8c0a78
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/tx.go
@@ -0,0 +1,797 @@
+package bbolt
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strings"
+ "sync/atomic"
+ "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 {
+ return fn(k, tx.root.Bucket(k))
+ })
+}
+
+// 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.GetRebalance() > 0 {
+ tx.stats.IncRebalanceTime(time.Since(startTime))
+ }
+
+ opgid := tx.meta.pgid
+
+ // spill data onto dirty pages.
+ startTime = time.Now()
+ if err := tx.root.spill(); err != nil {
+ tx.rollback()
+ return err
+ }
+ tx.stats.IncSpillTime(time.Since(startTime))
+
+ // Free the old root bucket.
+ tx.meta.root.root = tx.root.root
+
+ // Free the old freelist because commit writes out a fresh freelist.
+ if tx.meta.freelist != pgidNoFreelist {
+ tx.db.freelist.free(tx.meta.txid, tx.db.page(tx.meta.freelist))
+ }
+
+ if !tx.db.NoFreelistSync {
+ err := tx.commitFreelist()
+ if err != nil {
+ return err
+ }
+ } else {
+ tx.meta.freelist = pgidNoFreelist
+ }
+
+ // 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.
+ 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.IncWriteTime(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
+}
+
+func (tx *Tx) commitFreelist() error {
+ // Allocate new pages for the new free list. This will overestimate
+ // the size of the freelist but not underestimate the size (which would be bad).
+ 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
+
+ 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.nonPhysicalRollback()
+ return nil
+}
+
+// nonPhysicalRollback is called when user calls Rollback directly, in this case we do not need to reload the free pages from disk.
+func (tx *Tx) nonPhysicalRollback() {
+ if tx.db == nil {
+ return
+ }
+ if tx.writable {
+ tx.db.freelist.rollback(tx.meta.txid)
+ }
+ tx.close()
+}
+
+// rollback needs to reload the free pages from disk in case some system error happens like fsync error.
+func (tx *Tx) rollback() {
+ if tx.db == nil {
+ return
+ }
+ if tx.writable {
+ tx.db.freelist.rollback(tx.meta.txid)
+ // When mmap fails, the `data`, `dataref` and `datasz` may be reset to
+ // zero values, and there is no way to reload free page IDs in this case.
+ if tx.db.data != nil {
+ if !tx.db.hasSyncedFreelist() {
+ // Reconstruct free page list by scanning the DB to get the whole free page list.
+ // Note: scaning the whole db is heavy if your db size is large in NoSyncFreeList mode.
+ tx.db.freelist.noSyncReload(tx.db.freepages())
+ } else {
+ // Read free page list from freelist page.
+ 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.
+//
+// Deprecated; 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 := tx.db.openFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0)
+ if err != nil {
+ return 0, err
+ }
+ defer func() {
+ if cerr := f.Close(); err == nil {
+ err = cerr
+ }
+ }()
+
+ // 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), io.SeekStart); 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, nil
+}
+
+// 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 := tx.db.openFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
+ if err != nil {
+ return err
+ }
+
+ _, err = tx.WriteTo(f)
+ if err != nil {
+ _ = f.Close()
+ return err
+ }
+ return f.Close()
+}
+
+// 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(tx.meta.txid, count)
+ if err != nil {
+ return nil, err
+ }
+
+ // Save to our page cache.
+ tx.pages[p.id] = p
+
+ // Update statistics.
+ tx.stats.IncPageCount(int64(count))
+ tx.stats.IncPageAlloc(int64(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 {
+ rem := (uint64(p.overflow) + 1) * uint64(tx.db.pageSize)
+ offset := int64(p.id) * int64(tx.db.pageSize)
+ var written uintptr
+
+ // Write out page in "max allocation" sized chunks.
+ for {
+ sz := rem
+ if sz > maxAllocSize-1 {
+ sz = maxAllocSize - 1
+ }
+ buf := unsafeByteSlice(unsafe.Pointer(p), written, 0, int(sz))
+
+ if _, err := tx.db.ops.writeAt(buf, offset); err != nil {
+ return err
+ }
+
+ // Update statistics.
+ tx.stats.IncWrite(1)
+
+ // Exit inner for loop if we've written all the chunks.
+ rem -= sz
+ if rem == 0 {
+ break
+ }
+
+ // Otherwise move offset forward and move pointer to next chunk.
+ offset += int64(sz)
+ written += uintptr(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 := unsafeByteSlice(unsafe.Pointer(p), 0, 0, tx.db.pageSize)
+
+ // See https://go.googlesource.com/go/+/f03c9202c43e0abb130669852082117ca50aa9b1
+ for i := range buf {
+ buf[i] = 0
+ }
+ tx.db.pagePool.Put(buf) //nolint:staticcheck
+ }
+
+ 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.IncWrite(1)
+
+ 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 {
+ p.fastCheck(id)
+ return p
+ }
+ }
+
+ // Otherwise return directly from the mmap.
+ p := tx.db.page(id)
+ p.fastCheck(id)
+ return p
+}
+
+// forEachPage iterates over every page within a given page and executes a function.
+func (tx *Tx) forEachPage(pgidnum pgid, fn func(*page, int, []pgid)) {
+ stack := make([]pgid, 10)
+ stack[0] = pgidnum
+ tx.forEachPageInternal(stack[:1], fn)
+}
+
+func (tx *Tx) forEachPageInternal(pgidstack []pgid, fn func(*page, int, []pgid)) {
+ p := tx.page(pgidstack[len(pgidstack)-1])
+
+ // Execute function.
+ fn(p, len(pgidstack)-1, pgidstack)
+
+ // Recursively loop over children.
+ if (p.flags & branchPageFlag) != 0 {
+ for i := 0; i < int(p.count); i++ {
+ elem := p.branchPageElement(uint16(i))
+ tx.forEachPageInternal(append(pgidstack, elem.pgid), 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
+ }
+
+ if tx.db.freelist == nil {
+ return nil, ErrFreePagesNotLoaded
+ }
+
+ // 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.
+ //
+ // DEPRECATED: Use GetPageCount() or IncPageCount()
+ PageCount int64 // number of page allocations
+ // DEPRECATED: Use GetPageAlloc() or IncPageAlloc()
+ PageAlloc int64 // total bytes allocated
+
+ // Cursor statistics.
+ //
+ // DEPRECATED: Use GetCursorCount() or IncCursorCount()
+ CursorCount int64 // number of cursors created
+
+ // Node statistics
+ //
+ // DEPRECATED: Use GetNodeCount() or IncNodeCount()
+ NodeCount int64 // number of node allocations
+ // DEPRECATED: Use GetNodeDeref() or IncNodeDeref()
+ NodeDeref int64 // number of node dereferences
+
+ // Rebalance statistics.
+ //
+ // DEPRECATED: Use GetRebalance() or IncRebalance()
+ Rebalance int64 // number of node rebalances
+ // DEPRECATED: Use GetRebalanceTime() or IncRebalanceTime()
+ RebalanceTime time.Duration // total time spent rebalancing
+
+ // Split/Spill statistics.
+ //
+ // DEPRECATED: Use GetSplit() or IncSplit()
+ Split int64 // number of nodes split
+ // DEPRECATED: Use GetSpill() or IncSpill()
+ Spill int64 // number of nodes spilled
+ // DEPRECATED: Use GetSpillTime() or IncSpillTime()
+ SpillTime time.Duration // total time spent spilling
+
+ // Write statistics.
+ //
+ // DEPRECATED: Use GetWrite() or IncWrite()
+ Write int64 // number of writes performed
+ // DEPRECATED: Use GetWriteTime() or IncWriteTime()
+ WriteTime time.Duration // total time spent writing to disk
+}
+
+func (s *TxStats) add(other *TxStats) {
+ s.IncPageCount(other.GetPageCount())
+ s.IncPageAlloc(other.GetPageAlloc())
+ s.IncCursorCount(other.GetCursorCount())
+ s.IncNodeCount(other.GetNodeCount())
+ s.IncNodeDeref(other.GetNodeDeref())
+ s.IncRebalance(other.GetRebalance())
+ s.IncRebalanceTime(other.GetRebalanceTime())
+ s.IncSplit(other.GetSplit())
+ s.IncSpill(other.GetSpill())
+ s.IncSpillTime(other.GetSpillTime())
+ s.IncWrite(other.GetWrite())
+ s.IncWriteTime(other.GetWriteTime())
+}
+
+// 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.GetPageCount() - other.GetPageCount()
+ diff.PageAlloc = s.GetPageAlloc() - other.GetPageAlloc()
+ diff.CursorCount = s.GetCursorCount() - other.GetCursorCount()
+ diff.NodeCount = s.GetNodeCount() - other.GetNodeCount()
+ diff.NodeDeref = s.GetNodeDeref() - other.GetNodeDeref()
+ diff.Rebalance = s.GetRebalance() - other.GetRebalance()
+ diff.RebalanceTime = s.GetRebalanceTime() - other.GetRebalanceTime()
+ diff.Split = s.GetSplit() - other.GetSplit()
+ diff.Spill = s.GetSpill() - other.GetSpill()
+ diff.SpillTime = s.GetSpillTime() - other.GetSpillTime()
+ diff.Write = s.GetWrite() - other.GetWrite()
+ diff.WriteTime = s.GetWriteTime() - other.GetWriteTime()
+ return diff
+}
+
+// GetPageCount returns PageCount atomically.
+func (s *TxStats) GetPageCount() int64 {
+ return atomic.LoadInt64(&s.PageCount)
+}
+
+// IncPageCount increases PageCount atomically and returns the new value.
+func (s *TxStats) IncPageCount(delta int64) int64 {
+ return atomic.AddInt64(&s.PageCount, delta)
+}
+
+// GetPageAlloc returns PageAlloc atomically.
+func (s *TxStats) GetPageAlloc() int64 {
+ return atomic.LoadInt64(&s.PageAlloc)
+}
+
+// IncPageAlloc increases PageAlloc atomically and returns the new value.
+func (s *TxStats) IncPageAlloc(delta int64) int64 {
+ return atomic.AddInt64(&s.PageAlloc, delta)
+}
+
+// GetCursorCount returns CursorCount atomically.
+func (s *TxStats) GetCursorCount() int64 {
+ return atomic.LoadInt64(&s.CursorCount)
+}
+
+// IncCursorCount increases CursorCount atomically and return the new value.
+func (s *TxStats) IncCursorCount(delta int64) int64 {
+ return atomic.AddInt64(&s.CursorCount, delta)
+}
+
+// GetNodeCount returns NodeCount atomically.
+func (s *TxStats) GetNodeCount() int64 {
+ return atomic.LoadInt64(&s.NodeCount)
+}
+
+// IncNodeCount increases NodeCount atomically and returns the new value.
+func (s *TxStats) IncNodeCount(delta int64) int64 {
+ return atomic.AddInt64(&s.NodeCount, delta)
+}
+
+// GetNodeDeref returns NodeDeref atomically.
+func (s *TxStats) GetNodeDeref() int64 {
+ return atomic.LoadInt64(&s.NodeDeref)
+}
+
+// IncNodeDeref increases NodeDeref atomically and returns the new value.
+func (s *TxStats) IncNodeDeref(delta int64) int64 {
+ return atomic.AddInt64(&s.NodeDeref, delta)
+}
+
+// GetRebalance returns Rebalance atomically.
+func (s *TxStats) GetRebalance() int64 {
+ return atomic.LoadInt64(&s.Rebalance)
+}
+
+// IncRebalance increases Rebalance atomically and returns the new value.
+func (s *TxStats) IncRebalance(delta int64) int64 {
+ return atomic.AddInt64(&s.Rebalance, delta)
+}
+
+// GetRebalanceTime returns RebalanceTime atomically.
+func (s *TxStats) GetRebalanceTime() time.Duration {
+ return atomicLoadDuration(&s.RebalanceTime)
+}
+
+// IncRebalanceTime increases RebalanceTime atomically and returns the new value.
+func (s *TxStats) IncRebalanceTime(delta time.Duration) time.Duration {
+ return atomicAddDuration(&s.RebalanceTime, delta)
+}
+
+// GetSplit returns Split atomically.
+func (s *TxStats) GetSplit() int64 {
+ return atomic.LoadInt64(&s.Split)
+}
+
+// IncSplit increases Split atomically and returns the new value.
+func (s *TxStats) IncSplit(delta int64) int64 {
+ return atomic.AddInt64(&s.Split, delta)
+}
+
+// GetSpill returns Spill atomically.
+func (s *TxStats) GetSpill() int64 {
+ return atomic.LoadInt64(&s.Spill)
+}
+
+// IncSpill increases Spill atomically and returns the new value.
+func (s *TxStats) IncSpill(delta int64) int64 {
+ return atomic.AddInt64(&s.Spill, delta)
+}
+
+// GetSpillTime returns SpillTime atomically.
+func (s *TxStats) GetSpillTime() time.Duration {
+ return atomicLoadDuration(&s.SpillTime)
+}
+
+// IncSpillTime increases SpillTime atomically and returns the new value.
+func (s *TxStats) IncSpillTime(delta time.Duration) time.Duration {
+ return atomicAddDuration(&s.SpillTime, delta)
+}
+
+// GetWrite returns Write atomically.
+func (s *TxStats) GetWrite() int64 {
+ return atomic.LoadInt64(&s.Write)
+}
+
+// IncWrite increases Write atomically and returns the new value.
+func (s *TxStats) IncWrite(delta int64) int64 {
+ return atomic.AddInt64(&s.Write, delta)
+}
+
+// GetWriteTime returns WriteTime atomically.
+func (s *TxStats) GetWriteTime() time.Duration {
+ return atomicLoadDuration(&s.WriteTime)
+}
+
+// IncWriteTime increases WriteTime atomically and returns the new value.
+func (s *TxStats) IncWriteTime(delta time.Duration) time.Duration {
+ return atomicAddDuration(&s.WriteTime, delta)
+}
+
+func atomicAddDuration(ptr *time.Duration, du time.Duration) time.Duration {
+ return time.Duration(atomic.AddInt64((*int64)(unsafe.Pointer(ptr)), int64(du)))
+}
+
+func atomicLoadDuration(ptr *time.Duration) time.Duration {
+ return time.Duration(atomic.LoadInt64((*int64)(unsafe.Pointer(ptr))))
+}
diff --git a/vendor/go.etcd.io/bbolt/tx_check.go b/vendor/go.etcd.io/bbolt/tx_check.go
new file mode 100644
index 0000000000..75c7c08436
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/tx_check.go
@@ -0,0 +1,226 @@
+package bbolt
+
+import (
+ "encoding/hex"
+ "fmt"
+)
+
+// 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 {
+ return tx.CheckWithOptions()
+}
+
+// CheckWithOptions allows users to provide a customized `KVStringer` implementation,
+// so that bolt can generate human-readable diagnostic messages.
+func (tx *Tx) CheckWithOptions(options ...CheckOption) <-chan error {
+ chkConfig := checkConfig{
+ kvStringer: HexKVStringer(),
+ }
+ for _, op := range options {
+ op(&chkConfig)
+ }
+
+ ch := make(chan error)
+ go tx.check(chkConfig.kvStringer, ch)
+ return ch
+}
+
+func (tx *Tx) check(kvStringer KVStringer, ch chan error) {
+ // Force loading free list if opened in ReadOnly mode.
+ tx.db.loadFreelist()
+
+ // Check if any pages are double freed.
+ freed := make(map[pgid]bool)
+ all := make([]pgid, tx.db.freelist.count())
+ tx.db.freelist.copyall(all)
+ for _, id := range 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
+ if tx.meta.freelist != pgidNoFreelist {
+ 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, kvStringer, 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,
+ kvStringer KVStringer, ch chan error) {
+ // Ignore inline buckets.
+ if b.root == 0 {
+ return
+ }
+
+ // Check every page used by this bucket.
+ b.tx.forEachPage(b.root, func(p *page, _ int, stack []pgid) {
+ if p.id > tx.meta.pgid {
+ ch <- fmt.Errorf("page %d: out of bounds: %d (stack: %v)", int(p.id), int(b.tx.meta.pgid), stack)
+ }
+
+ // 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 (stack: %v)", int(id), stack)
+ }
+ 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 (stack: %v)", int(p.id), p.typ(), stack)
+ }
+ })
+
+ tx.recursivelyCheckPages(b.root, kvStringer.KeyToString, ch)
+
+ // Check each bucket within this bucket.
+ _ = b.ForEachBucket(func(k []byte) error {
+ if child := b.Bucket(k); child != nil {
+ tx.checkBucket(child, reachable, freed, kvStringer, ch)
+ }
+ return nil
+ })
+}
+
+// recursivelyCheckPages confirms database consistency with respect to b-tree
+// key order constraints:
+// - keys on pages must be sorted
+// - keys on children pages are between 2 consecutive keys on the parent's branch page).
+func (tx *Tx) recursivelyCheckPages(pgId pgid, keyToString func([]byte) string, ch chan error) {
+ tx.recursivelyCheckPagesInternal(pgId, nil, nil, nil, keyToString, ch)
+}
+
+// recursivelyCheckPagesInternal verifies that all keys in the subtree rooted at `pgid` are:
+// - >=`minKeyClosed` (can be nil)
+// - <`maxKeyOpen` (can be nil)
+// - Are in right ordering relationship to their parents.
+// `pagesStack` is expected to contain IDs of pages from the tree root to `pgid` for the clean debugging message.
+func (tx *Tx) recursivelyCheckPagesInternal(
+ pgId pgid, minKeyClosed, maxKeyOpen []byte, pagesStack []pgid,
+ keyToString func([]byte) string, ch chan error) (maxKeyInSubtree []byte) {
+
+ p := tx.page(pgId)
+ pagesStack = append(pagesStack, pgId)
+ switch {
+ case p.flags&branchPageFlag != 0:
+ // For branch page we navigate ranges of all subpages.
+ runningMin := minKeyClosed
+ for i := range p.branchPageElements() {
+ elem := p.branchPageElement(uint16(i))
+ verifyKeyOrder(elem.pgid, "branch", i, elem.key(), runningMin, maxKeyOpen, ch, keyToString, pagesStack)
+
+ maxKey := maxKeyOpen
+ if i < len(p.branchPageElements())-1 {
+ maxKey = p.branchPageElement(uint16(i + 1)).key()
+ }
+ maxKeyInSubtree = tx.recursivelyCheckPagesInternal(elem.pgid, elem.key(), maxKey, pagesStack, keyToString, ch)
+ runningMin = maxKeyInSubtree
+ }
+ return maxKeyInSubtree
+ case p.flags&leafPageFlag != 0:
+ runningMin := minKeyClosed
+ for i := range p.leafPageElements() {
+ elem := p.leafPageElement(uint16(i))
+ verifyKeyOrder(pgId, "leaf", i, elem.key(), runningMin, maxKeyOpen, ch, keyToString, pagesStack)
+ runningMin = elem.key()
+ }
+ if p.count > 0 {
+ return p.leafPageElement(p.count - 1).key()
+ }
+ default:
+ ch <- fmt.Errorf("unexpected page type for pgId:%d", pgId)
+ }
+ return maxKeyInSubtree
+}
+
+/***
+ * verifyKeyOrder checks whether an entry with given #index on pgId (pageType: "branch|leaf") that has given "key",
+ * is within range determined by (previousKey..maxKeyOpen) and reports found violations to the channel (ch).
+ */
+func verifyKeyOrder(pgId pgid, pageType string, index int, key []byte, previousKey []byte, maxKeyOpen []byte, ch chan error, keyToString func([]byte) string, pagesStack []pgid) {
+ if index == 0 && previousKey != nil && compareKeys(previousKey, key) > 0 {
+ ch <- fmt.Errorf("the first key[%d]=(hex)%s on %s page(%d) needs to be >= the key in the ancestor (%s). Stack: %v",
+ index, keyToString(key), pageType, pgId, keyToString(previousKey), pagesStack)
+ }
+ if index > 0 {
+ cmpRet := compareKeys(previousKey, key)
+ if cmpRet > 0 {
+ ch <- fmt.Errorf("key[%d]=(hex)%s on %s page(%d) needs to be > (found <) than previous element (hex)%s. Stack: %v",
+ index, keyToString(key), pageType, pgId, keyToString(previousKey), pagesStack)
+ }
+ if cmpRet == 0 {
+ ch <- fmt.Errorf("key[%d]=(hex)%s on %s page(%d) needs to be > (found =) than previous element (hex)%s. Stack: %v",
+ index, keyToString(key), pageType, pgId, keyToString(previousKey), pagesStack)
+ }
+ }
+ if maxKeyOpen != nil && compareKeys(key, maxKeyOpen) >= 0 {
+ ch <- fmt.Errorf("key[%d]=(hex)%s on %s page(%d) needs to be < than key of the next element in ancestor (hex)%s. Pages stack: %v",
+ index, keyToString(key), pageType, pgId, keyToString(previousKey), pagesStack)
+ }
+}
+
+// ===========================================================================================
+
+type checkConfig struct {
+ kvStringer KVStringer
+}
+
+type CheckOption func(options *checkConfig)
+
+func WithKVStringer(kvStringer KVStringer) CheckOption {
+ return func(c *checkConfig) {
+ c.kvStringer = kvStringer
+ }
+}
+
+// KVStringer allows to prepare human-readable diagnostic messages.
+type KVStringer interface {
+ KeyToString([]byte) string
+ ValueToString([]byte) string
+}
+
+// HexKVStringer serializes both key & value to hex representation.
+func HexKVStringer() KVStringer {
+ return hexKvStringer{}
+}
+
+type hexKvStringer struct{}
+
+func (_ hexKvStringer) KeyToString(key []byte) string {
+ return hex.EncodeToString(key)
+}
+
+func (_ hexKvStringer) ValueToString(value []byte) string {
+ return hex.EncodeToString(value)
+}
diff --git a/vendor/go.etcd.io/bbolt/unsafe.go b/vendor/go.etcd.io/bbolt/unsafe.go
new file mode 100644
index 0000000000..c0e5037500
--- /dev/null
+++ b/vendor/go.etcd.io/bbolt/unsafe.go
@@ -0,0 +1,39 @@
+package bbolt
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func unsafeAdd(base unsafe.Pointer, offset uintptr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(base) + offset)
+}
+
+func unsafeIndex(base unsafe.Pointer, offset uintptr, elemsz uintptr, n int) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(base) + offset + uintptr(n)*elemsz)
+}
+
+func unsafeByteSlice(base unsafe.Pointer, offset uintptr, i, j int) []byte {
+ // See: https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
+ //
+ // This memory is not allocated from C, but it is unmanaged by Go's
+ // garbage collector and should behave similarly, and the compiler
+ // should produce similar code. Note that this conversion allows a
+ // subslice to begin after the base address, with an optional offset,
+ // while the URL above does not cover this case and only slices from
+ // index 0. However, the wiki never says that the address must be to
+ // the beginning of a C allocation (or even that malloc was used at
+ // all), so this is believed to be correct.
+ return (*[maxAllocSize]byte)(unsafeAdd(base, offset))[i:j:j]
+}
+
+// unsafeSlice modifies the data, len, and cap of a slice variable pointed to by
+// the slice parameter. This helper should be used over other direct
+// manipulation of reflect.SliceHeader to prevent misuse, namely, converting
+// from reflect.SliceHeader to a Go slice type.
+func unsafeSlice(slice, data unsafe.Pointer, len int) {
+ s := (*reflect.SliceHeader)(slice)
+ s.Data = uintptr(data)
+ s.Cap = len
+ s.Len = len
+}
diff --git a/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go b/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go
new file mode 100644
index 0000000000..62aba97cdb
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go
@@ -0,0 +1,3771 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: api/etcdserverpb/rpc.proto
+
+/*
+Package etcdserverpb is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package gw
+
+import (
+ "context"
+ "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/grpc-ecosystem/grpc-gateway/utilities"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/status"
+)
+
+// Suppress "imported and not used" errors
+var _ codes.Code
+var _ io.Reader
+var _ status.Status
+var _ = runtime.String
+var _ = utilities.NewDoubleArray
+var _ = descriptor.ForMessage
+
+func request_KV_Range_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.RangeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Range(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_KV_Range_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.RangeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Range(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_KV_Put_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.PutRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Put(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_KV_Put_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.PutRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Put(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_KV_DeleteRange_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.DeleteRangeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.DeleteRange(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_KV_DeleteRange_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.DeleteRangeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.DeleteRange(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_KV_Txn_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.TxnRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Txn(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_KV_Txn_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.TxnRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Txn(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_KV_Compact_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.CompactionRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Compact(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_KV_Compact_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.CompactionRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Compact(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Watch_Watch_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.WatchClient, req *http.Request, pathParams map[string]string) (etcdserverpb.Watch_WatchClient, runtime.ServerMetadata, error) {
+ var metadata runtime.ServerMetadata
+ stream, err := client.Watch(ctx)
+ if err != nil {
+ grpclog.Infof("Failed to start streaming: %v", err)
+ return nil, metadata, err
+ }
+ dec := marshaler.NewDecoder(req.Body)
+ handleSend := func() error {
+ var protoReq etcdserverpb.WatchRequest
+ err := dec.Decode(&protoReq)
+ if err == io.EOF {
+ return err
+ }
+ if err != nil {
+ grpclog.Infof("Failed to decode request: %v", err)
+ return err
+ }
+ if err := stream.Send(&protoReq); err != nil {
+ grpclog.Infof("Failed to send request: %v", err)
+ return err
+ }
+ return nil
+ }
+ if err := handleSend(); err != nil {
+ if cerr := stream.CloseSend(); cerr != nil {
+ grpclog.Infof("Failed to terminate client stream: %v", cerr)
+ }
+ if err == io.EOF {
+ return stream, metadata, nil
+ }
+ return nil, metadata, err
+ }
+ go func() {
+ for {
+ if err := handleSend(); err != nil {
+ break
+ }
+ }
+ if err := stream.CloseSend(); err != nil {
+ grpclog.Infof("Failed to terminate client stream: %v", err)
+ }
+ }()
+ header, err := stream.Header()
+ if err != nil {
+ grpclog.Infof("Failed to get header from client: %v", err)
+ return nil, metadata, err
+ }
+ metadata.HeaderMD = header
+ return stream, metadata, nil
+}
+
+func request_Lease_LeaseGrant_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseGrantRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.LeaseGrant(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lease_LeaseGrant_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseGrantRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.LeaseGrant(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Lease_LeaseRevoke_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseRevokeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lease_LeaseRevoke_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseRevokeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.LeaseRevoke(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Lease_LeaseRevoke_1(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseRevokeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lease_LeaseRevoke_1(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseRevokeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.LeaseRevoke(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Lease_LeaseKeepAlive_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (etcdserverpb.Lease_LeaseKeepAliveClient, runtime.ServerMetadata, error) {
+ var metadata runtime.ServerMetadata
+ stream, err := client.LeaseKeepAlive(ctx)
+ if err != nil {
+ grpclog.Infof("Failed to start streaming: %v", err)
+ return nil, metadata, err
+ }
+ dec := marshaler.NewDecoder(req.Body)
+ handleSend := func() error {
+ var protoReq etcdserverpb.LeaseKeepAliveRequest
+ err := dec.Decode(&protoReq)
+ if err == io.EOF {
+ return err
+ }
+ if err != nil {
+ grpclog.Infof("Failed to decode request: %v", err)
+ return err
+ }
+ if err := stream.Send(&protoReq); err != nil {
+ grpclog.Infof("Failed to send request: %v", err)
+ return err
+ }
+ return nil
+ }
+ if err := handleSend(); err != nil {
+ if cerr := stream.CloseSend(); cerr != nil {
+ grpclog.Infof("Failed to terminate client stream: %v", cerr)
+ }
+ if err == io.EOF {
+ return stream, metadata, nil
+ }
+ return nil, metadata, err
+ }
+ go func() {
+ for {
+ if err := handleSend(); err != nil {
+ break
+ }
+ }
+ if err := stream.CloseSend(); err != nil {
+ grpclog.Infof("Failed to terminate client stream: %v", err)
+ }
+ }()
+ header, err := stream.Header()
+ if err != nil {
+ grpclog.Infof("Failed to get header from client: %v", err)
+ return nil, metadata, err
+ }
+ metadata.HeaderMD = header
+ return stream, metadata, nil
+}
+
+func request_Lease_LeaseTimeToLive_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseTimeToLiveRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lease_LeaseTimeToLive_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseTimeToLiveRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.LeaseTimeToLive(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Lease_LeaseTimeToLive_1(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseTimeToLiveRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lease_LeaseTimeToLive_1(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseTimeToLiveRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.LeaseTimeToLive(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Lease_LeaseLeases_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseLeasesRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lease_LeaseLeases_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseLeasesRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.LeaseLeases(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Lease_LeaseLeases_1(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseLeasesRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lease_LeaseLeases_1(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.LeaseLeasesRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.LeaseLeases(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Cluster_MemberAdd_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberAddRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.MemberAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Cluster_MemberAdd_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberAddRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.MemberAdd(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Cluster_MemberRemove_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberRemoveRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.MemberRemove(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Cluster_MemberRemove_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberRemoveRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.MemberRemove(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Cluster_MemberUpdate_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberUpdateRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.MemberUpdate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Cluster_MemberUpdate_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberUpdateRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.MemberUpdate(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Cluster_MemberList_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberListRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.MemberList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Cluster_MemberList_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberListRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.MemberList(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Cluster_MemberPromote_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberPromoteRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.MemberPromote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Cluster_MemberPromote_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MemberPromoteRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.MemberPromote(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Maintenance_Alarm_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AlarmRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Alarm(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Maintenance_Alarm_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AlarmRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Alarm(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Maintenance_Status_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.StatusRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Status(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Maintenance_Status_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.StatusRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Status(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Maintenance_Defragment_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.DefragmentRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Defragment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Maintenance_Defragment_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.DefragmentRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Defragment(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Maintenance_Hash_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.HashRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Hash(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Maintenance_Hash_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.HashRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Hash(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Maintenance_HashKV_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.HashKVRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.HashKV(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Maintenance_HashKV_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.HashKVRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.HashKV(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Maintenance_Snapshot_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (etcdserverpb.Maintenance_SnapshotClient, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.SnapshotRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ stream, err := client.Snapshot(ctx, &protoReq)
+ if err != nil {
+ return nil, metadata, err
+ }
+ header, err := stream.Header()
+ if err != nil {
+ return nil, metadata, err
+ }
+ metadata.HeaderMD = header
+ return stream, metadata, nil
+
+}
+
+func request_Maintenance_MoveLeader_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MoveLeaderRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.MoveLeader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Maintenance_MoveLeader_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.MoveLeaderRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.MoveLeader(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Maintenance_Downgrade_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.DowngradeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Downgrade(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Maintenance_Downgrade_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.DowngradeRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Downgrade(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_AuthEnable_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthEnableRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.AuthEnable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_AuthEnable_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthEnableRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.AuthEnable(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_AuthDisable_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthDisableRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.AuthDisable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_AuthDisable_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthDisableRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.AuthDisable(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_AuthStatus_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthStatusRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.AuthStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_AuthStatus_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthStatusRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.AuthStatus(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthenticateRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Authenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthenticateRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Authenticate(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_UserAdd_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserAddRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UserAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_UserAdd_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserAddRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UserAdd(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_UserGet_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserGetRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UserGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_UserGet_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserGetRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UserGet(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_UserList_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserListRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UserList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_UserList_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserListRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UserList(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_UserDelete_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserDeleteRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UserDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_UserDelete_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserDeleteRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UserDelete(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_UserChangePassword_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserChangePasswordRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UserChangePassword(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_UserChangePassword_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserChangePasswordRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UserChangePassword(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_UserGrantRole_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserGrantRoleRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UserGrantRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_UserGrantRole_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserGrantRoleRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UserGrantRole(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_UserRevokeRole_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserRevokeRoleRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UserRevokeRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_UserRevokeRole_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthUserRevokeRoleRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UserRevokeRole(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_RoleAdd_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleAddRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.RoleAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_RoleAdd_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleAddRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.RoleAdd(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_RoleGet_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleGetRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.RoleGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_RoleGet_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleGetRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.RoleGet(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_RoleList_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleListRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.RoleList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_RoleList_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleListRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.RoleList(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_RoleDelete_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleDeleteRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.RoleDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_RoleDelete_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleDeleteRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.RoleDelete(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_RoleGrantPermission_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleGrantPermissionRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.RoleGrantPermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_RoleGrantPermission_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleGrantPermissionRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.RoleGrantPermission(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Auth_RoleRevokePermission_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleRevokePermissionRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.RoleRevokePermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Auth_RoleRevokePermission_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq etcdserverpb.AuthRoleRevokePermissionRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.RoleRevokePermission(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+// etcdserverpb.RegisterKVHandlerServer registers the http handlers for service KV to "mux".
+// UnaryRPC :call etcdserverpb.KVServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterKVHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.KVServer) error {
+
+ mux.Handle("POST", pattern_KV_Range_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_KV_Range_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Range_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_Put_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_KV_Put_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Put_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_DeleteRange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_KV_DeleteRange_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_DeleteRange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_Txn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_KV_Txn_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Txn_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_Compact_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_KV_Compact_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Compact_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// etcdserverpb.RegisterWatchHandlerServer registers the http handlers for service Watch to "mux".
+// UnaryRPC :call etcdserverpb.WatchServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterWatchHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.WatchServer) error {
+
+ mux.Handle("POST", pattern_Watch_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
+ _, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ })
+
+ return nil
+}
+
+// etcdserverpb.RegisterLeaseHandlerServer registers the http handlers for service Lease to "mux".
+// UnaryRPC :call etcdserverpb.LeaseServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterLeaseHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.LeaseServer) error {
+
+ mux.Handle("POST", pattern_Lease_LeaseGrant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lease_LeaseGrant_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseGrant_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseRevoke_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lease_LeaseRevoke_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseRevoke_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseRevoke_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lease_LeaseRevoke_1(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseRevoke_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseKeepAlive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
+ _, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseTimeToLive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lease_LeaseTimeToLive_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseTimeToLive_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseTimeToLive_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lease_LeaseTimeToLive_1(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseTimeToLive_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lease_LeaseLeases_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseLeases_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseLeases_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lease_LeaseLeases_1(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseLeases_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// etcdserverpb.RegisterClusterHandlerServer registers the http handlers for service Cluster to "mux".
+// UnaryRPC :call etcdserverpb.ClusterServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterClusterHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.ClusterServer) error {
+
+ mux.Handle("POST", pattern_Cluster_MemberAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Cluster_MemberAdd_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberRemove_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Cluster_MemberRemove_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberRemove_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Cluster_MemberUpdate_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberUpdate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Cluster_MemberList_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberPromote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Cluster_MemberPromote_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberPromote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// etcdserverpb.RegisterMaintenanceHandlerServer registers the http handlers for service Maintenance to "mux".
+// UnaryRPC :call etcdserverpb.MaintenanceServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterMaintenanceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.MaintenanceServer) error {
+
+ mux.Handle("POST", pattern_Maintenance_Alarm_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Maintenance_Alarm_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Alarm_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Maintenance_Status_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Status_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Defragment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Maintenance_Defragment_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Defragment_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Hash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Maintenance_Hash_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Hash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_HashKV_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Maintenance_HashKV_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_HashKV_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Snapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
+ _, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ })
+
+ mux.Handle("POST", pattern_Maintenance_MoveLeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Maintenance_MoveLeader_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_MoveLeader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Downgrade_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Maintenance_Downgrade_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Downgrade_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// etcdserverpb.RegisterAuthHandlerServer registers the http handlers for service Auth to "mux".
+// UnaryRPC :call etcdserverpb.AuthServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterAuthHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.AuthServer) error {
+
+ mux.Handle("POST", pattern_Auth_AuthEnable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_AuthEnable_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_AuthEnable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_AuthDisable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_AuthDisable_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_AuthDisable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_AuthStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_AuthStatus_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_AuthStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_Authenticate_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_Authenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_UserAdd_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_UserGet_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_UserList_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_UserDelete_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserChangePassword_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_UserChangePassword_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserChangePassword_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserGrantRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_UserGrantRole_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserGrantRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserRevokeRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_UserRevokeRole_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserRevokeRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_RoleAdd_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_RoleGet_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_RoleList_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_RoleDelete_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleGrantPermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_RoleGrantPermission_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleGrantPermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleRevokePermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Auth_RoleRevokePermission_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleRevokePermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// RegisterKVHandlerFromEndpoint is same as RegisterKVHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterKVHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterKVHandler(ctx, mux, conn)
+}
+
+// RegisterKVHandler registers the http handlers for service KV to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterKVHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterKVHandlerClient(ctx, mux, etcdserverpb.NewKVClient(conn))
+}
+
+// etcdserverpb.RegisterKVHandlerClient registers the http handlers for service KV
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "KVClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "KVClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "KVClient" to call the correct interceptors.
+func RegisterKVHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.KVClient) error {
+
+ mux.Handle("POST", pattern_KV_Range_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_KV_Range_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Range_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_Put_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_KV_Put_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Put_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_DeleteRange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_KV_DeleteRange_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_DeleteRange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_Txn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_KV_Txn_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Txn_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_KV_Compact_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_KV_Compact_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_KV_Compact_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_KV_Range_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "range"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_KV_Put_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "put"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_KV_DeleteRange_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "deleterange"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_KV_Txn_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "txn"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_KV_Compact_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "compaction"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_KV_Range_0 = runtime.ForwardResponseMessage
+
+ forward_KV_Put_0 = runtime.ForwardResponseMessage
+
+ forward_KV_DeleteRange_0 = runtime.ForwardResponseMessage
+
+ forward_KV_Txn_0 = runtime.ForwardResponseMessage
+
+ forward_KV_Compact_0 = runtime.ForwardResponseMessage
+)
+
+// RegisterWatchHandlerFromEndpoint is same as RegisterWatchHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterWatchHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterWatchHandler(ctx, mux, conn)
+}
+
+// RegisterWatchHandler registers the http handlers for service Watch to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterWatchHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterWatchHandlerClient(ctx, mux, etcdserverpb.NewWatchClient(conn))
+}
+
+// etcdserverpb.RegisterWatchHandlerClient registers the http handlers for service Watch
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "WatchClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "WatchClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "WatchClient" to call the correct interceptors.
+func RegisterWatchHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.WatchClient) error {
+
+ mux.Handle("POST", pattern_Watch_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Watch_Watch_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Watch_Watch_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Watch_Watch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v3", "watch"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_Watch_Watch_0 = runtime.ForwardResponseStream
+)
+
+// RegisterLeaseHandlerFromEndpoint is same as RegisterLeaseHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterLeaseHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterLeaseHandler(ctx, mux, conn)
+}
+
+// RegisterLeaseHandler registers the http handlers for service Lease to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterLeaseHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterLeaseHandlerClient(ctx, mux, etcdserverpb.NewLeaseClient(conn))
+}
+
+// etcdserverpb.RegisterLeaseHandlerClient registers the http handlers for service Lease
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "LeaseClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "LeaseClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "LeaseClient" to call the correct interceptors.
+func RegisterLeaseHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.LeaseClient) error {
+
+ mux.Handle("POST", pattern_Lease_LeaseGrant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseGrant_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseGrant_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseRevoke_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseRevoke_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseRevoke_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseRevoke_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseRevoke_1(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseRevoke_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseKeepAlive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseKeepAlive_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseKeepAlive_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseTimeToLive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseTimeToLive_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseTimeToLive_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseTimeToLive_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseTimeToLive_1(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseTimeToLive_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseLeases_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseLeases_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lease_LeaseLeases_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lease_LeaseLeases_1(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lease_LeaseLeases_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Lease_LeaseGrant_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "grant"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lease_LeaseRevoke_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "revoke"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lease_LeaseRevoke_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "revoke"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lease_LeaseKeepAlive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "keepalive"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lease_LeaseTimeToLive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "timetolive"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lease_LeaseTimeToLive_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "timetolive"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lease_LeaseLeases_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "leases"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lease_LeaseLeases_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "leases"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_Lease_LeaseGrant_0 = runtime.ForwardResponseMessage
+
+ forward_Lease_LeaseRevoke_0 = runtime.ForwardResponseMessage
+
+ forward_Lease_LeaseRevoke_1 = runtime.ForwardResponseMessage
+
+ forward_Lease_LeaseKeepAlive_0 = runtime.ForwardResponseStream
+
+ forward_Lease_LeaseTimeToLive_0 = runtime.ForwardResponseMessage
+
+ forward_Lease_LeaseTimeToLive_1 = runtime.ForwardResponseMessage
+
+ forward_Lease_LeaseLeases_0 = runtime.ForwardResponseMessage
+
+ forward_Lease_LeaseLeases_1 = runtime.ForwardResponseMessage
+)
+
+// RegisterClusterHandlerFromEndpoint is same as RegisterClusterHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterClusterHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterClusterHandler(ctx, mux, conn)
+}
+
+// RegisterClusterHandler registers the http handlers for service Cluster to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterClusterHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterClusterHandlerClient(ctx, mux, etcdserverpb.NewClusterClient(conn))
+}
+
+// etcdserverpb.RegisterClusterHandlerClient registers the http handlers for service Cluster
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ClusterClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ClusterClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "ClusterClient" to call the correct interceptors.
+func RegisterClusterHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.ClusterClient) error {
+
+ mux.Handle("POST", pattern_Cluster_MemberAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Cluster_MemberAdd_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberRemove_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Cluster_MemberRemove_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberRemove_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Cluster_MemberUpdate_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberUpdate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Cluster_MemberList_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Cluster_MemberPromote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Cluster_MemberPromote_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Cluster_MemberPromote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Cluster_MemberAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "add"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Cluster_MemberRemove_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "remove"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Cluster_MemberUpdate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "update"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Cluster_MemberList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "list"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Cluster_MemberPromote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "promote"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_Cluster_MemberAdd_0 = runtime.ForwardResponseMessage
+
+ forward_Cluster_MemberRemove_0 = runtime.ForwardResponseMessage
+
+ forward_Cluster_MemberUpdate_0 = runtime.ForwardResponseMessage
+
+ forward_Cluster_MemberList_0 = runtime.ForwardResponseMessage
+
+ forward_Cluster_MemberPromote_0 = runtime.ForwardResponseMessage
+)
+
+// RegisterMaintenanceHandlerFromEndpoint is same as RegisterMaintenanceHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterMaintenanceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterMaintenanceHandler(ctx, mux, conn)
+}
+
+// RegisterMaintenanceHandler registers the http handlers for service Maintenance to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterMaintenanceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterMaintenanceHandlerClient(ctx, mux, etcdserverpb.NewMaintenanceClient(conn))
+}
+
+// etcdserverpb.RegisterMaintenanceHandlerClient registers the http handlers for service Maintenance
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "MaintenanceClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "MaintenanceClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "MaintenanceClient" to call the correct interceptors.
+func RegisterMaintenanceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.MaintenanceClient) error {
+
+ mux.Handle("POST", pattern_Maintenance_Alarm_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_Alarm_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Alarm_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_Status_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Status_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Defragment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_Defragment_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Defragment_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Hash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_Hash_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Hash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_HashKV_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_HashKV_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_HashKV_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Snapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_Snapshot_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Snapshot_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_MoveLeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_MoveLeader_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_MoveLeader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Maintenance_Downgrade_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Maintenance_Downgrade_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Maintenance_Downgrade_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Maintenance_Alarm_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "alarm"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Maintenance_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "status"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Maintenance_Defragment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "defragment"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Maintenance_Hash_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Maintenance_HashKV_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "hashkv"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Maintenance_Snapshot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "snapshot"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Maintenance_MoveLeader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "transfer-leadership"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Maintenance_Downgrade_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "downgrade"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_Maintenance_Alarm_0 = runtime.ForwardResponseMessage
+
+ forward_Maintenance_Status_0 = runtime.ForwardResponseMessage
+
+ forward_Maintenance_Defragment_0 = runtime.ForwardResponseMessage
+
+ forward_Maintenance_Hash_0 = runtime.ForwardResponseMessage
+
+ forward_Maintenance_HashKV_0 = runtime.ForwardResponseMessage
+
+ forward_Maintenance_Snapshot_0 = runtime.ForwardResponseStream
+
+ forward_Maintenance_MoveLeader_0 = runtime.ForwardResponseMessage
+
+ forward_Maintenance_Downgrade_0 = runtime.ForwardResponseMessage
+)
+
+// RegisterAuthHandlerFromEndpoint is same as RegisterAuthHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterAuthHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterAuthHandler(ctx, mux, conn)
+}
+
+// RegisterAuthHandler registers the http handlers for service Auth to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterAuthHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterAuthHandlerClient(ctx, mux, etcdserverpb.NewAuthClient(conn))
+}
+
+// etcdserverpb.RegisterAuthHandlerClient registers the http handlers for service Auth
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "AuthClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "AuthClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "AuthClient" to call the correct interceptors.
+func RegisterAuthHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.AuthClient) error {
+
+ mux.Handle("POST", pattern_Auth_AuthEnable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_AuthEnable_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_AuthEnable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_AuthDisable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_AuthDisable_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_AuthDisable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_AuthStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_AuthStatus_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_AuthStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_Authenticate_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_Authenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_UserAdd_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_UserGet_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_UserList_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_UserDelete_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserChangePassword_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_UserChangePassword_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserChangePassword_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserGrantRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_UserGrantRole_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserGrantRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_UserRevokeRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_UserRevokeRole_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_UserRevokeRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_RoleAdd_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_RoleGet_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_RoleList_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_RoleDelete_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleGrantPermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_RoleGrantPermission_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleGrantPermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Auth_RoleRevokePermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Auth_RoleRevokePermission_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Auth_RoleRevokePermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Auth_AuthEnable_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "enable"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_AuthDisable_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "disable"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_AuthStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "status"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "authenticate"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_UserAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "add"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_UserGet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "get"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_UserList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "list"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_UserDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "delete"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_UserChangePassword_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "changepw"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_UserGrantRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "grant"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_UserRevokeRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "revoke"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_RoleAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "add"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_RoleGet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "get"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_RoleList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "list"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_RoleDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "delete"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_RoleGrantPermission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "grant"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Auth_RoleRevokePermission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "revoke"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_Auth_AuthEnable_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_AuthDisable_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_AuthStatus_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_Authenticate_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_UserAdd_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_UserGet_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_UserList_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_UserDelete_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_UserChangePassword_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_UserGrantRole_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_UserRevokeRole_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_RoleAdd_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_RoleGet_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_RoleList_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_RoleDelete_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_RoleGrantPermission_0 = runtime.ForwardResponseMessage
+
+ forward_Auth_RoleRevokePermission_0 = runtime.ForwardResponseMessage
+)
diff --git a/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go b/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go
index 34c1824426..8120907d91 100644
--- a/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go
+++ b/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go
@@ -6154,264 +6154,264 @@ func init() {
func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) }
var fileDescriptor_77a6da22d6a3feb1 = []byte{
- // 4107 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x5b, 0x73, 0x1b, 0xc9,
- 0x75, 0xe6, 0x00, 0xc4, 0xed, 0xe0, 0x42, 0xb0, 0x79, 0x11, 0x84, 0x95, 0x28, 0x6e, 0x6b, 0xa5,
- 0xe5, 0x4a, 0xbb, 0xc4, 0x9a, 0xb6, 0xb3, 0x55, 0x4a, 0xe2, 0x18, 0x22, 0xb1, 0x12, 0x97, 0x14,
- 0xc9, 0x1d, 0x42, 0xda, 0x4b, 0xb9, 0xc2, 0x1a, 0x02, 0x2d, 0x72, 0x42, 0x60, 0x06, 0x9e, 0x19,
- 0x40, 0xe4, 0xe6, 0xe2, 0x94, 0xcb, 0x71, 0x25, 0xaf, 0x76, 0x55, 0x2a, 0x79, 0x48, 0x5e, 0x52,
- 0x29, 0x97, 0x1f, 0xfc, 0x9c, 0xbf, 0x90, 0xa7, 0x5c, 0x2a, 0x7f, 0x20, 0xb5, 0xf1, 0x4b, 0xf2,
- 0x23, 0x52, 0xae, 0xbe, 0xcd, 0xf4, 0xdc, 0x40, 0xd9, 0xd8, 0xdd, 0x17, 0x11, 0x7d, 0xfa, 0xf4,
- 0xf9, 0x4e, 0x9f, 0xee, 0x3e, 0xe7, 0xf4, 0xe9, 0x11, 0x94, 0x9c, 0x51, 0x6f, 0x73, 0xe4, 0xd8,
- 0x9e, 0x8d, 0x2a, 0xc4, 0xeb, 0xf5, 0x5d, 0xe2, 0x4c, 0x88, 0x33, 0x3a, 0x6d, 0x2e, 0x9f, 0xd9,
- 0x67, 0x36, 0xeb, 0x68, 0xd1, 0x5f, 0x9c, 0xa7, 0xd9, 0xa0, 0x3c, 0x2d, 0x63, 0x64, 0xb6, 0x86,
- 0x93, 0x5e, 0x6f, 0x74, 0xda, 0xba, 0x98, 0x88, 0x9e, 0xa6, 0xdf, 0x63, 0x8c, 0xbd, 0xf3, 0xd1,
- 0x29, 0xfb, 0x23, 0xfa, 0x6e, 0x9d, 0xd9, 0xf6, 0xd9, 0x80, 0xf0, 0x5e, 0xcb, 0xb2, 0x3d, 0xc3,
- 0x33, 0x6d, 0xcb, 0xe5, 0xbd, 0xf8, 0xaf, 0x34, 0xa8, 0xe9, 0xc4, 0x1d, 0xd9, 0x96, 0x4b, 0x9e,
- 0x12, 0xa3, 0x4f, 0x1c, 0x74, 0x1b, 0xa0, 0x37, 0x18, 0xbb, 0x1e, 0x71, 0x4e, 0xcc, 0x7e, 0x43,
- 0x5b, 0xd7, 0x36, 0xe6, 0xf5, 0x92, 0xa0, 0xec, 0xf6, 0xd1, 0x1b, 0x50, 0x1a, 0x92, 0xe1, 0x29,
- 0xef, 0xcd, 0xb0, 0xde, 0x22, 0x27, 0xec, 0xf6, 0x51, 0x13, 0x8a, 0x0e, 0x99, 0x98, 0xae, 0x69,
- 0x5b, 0x8d, 0xec, 0xba, 0xb6, 0x91, 0xd5, 0xfd, 0x36, 0x1d, 0xe8, 0x18, 0x2f, 0xbd, 0x13, 0x8f,
- 0x38, 0xc3, 0xc6, 0x3c, 0x1f, 0x48, 0x09, 0x5d, 0xe2, 0x0c, 0xf1, 0x4f, 0x72, 0x50, 0xd1, 0x0d,
- 0xeb, 0x8c, 0xe8, 0xe4, 0x87, 0x63, 0xe2, 0x7a, 0xa8, 0x0e, 0xd9, 0x0b, 0x72, 0xc5, 0xe0, 0x2b,
- 0x3a, 0xfd, 0xc9, 0xc7, 0x5b, 0x67, 0xe4, 0x84, 0x58, 0x1c, 0xb8, 0x42, 0xc7, 0x5b, 0x67, 0xa4,
- 0x63, 0xf5, 0xd1, 0x32, 0xe4, 0x06, 0xe6, 0xd0, 0xf4, 0x04, 0x2a, 0x6f, 0x84, 0xd4, 0x99, 0x8f,
- 0xa8, 0xb3, 0x0d, 0xe0, 0xda, 0x8e, 0x77, 0x62, 0x3b, 0x7d, 0xe2, 0x34, 0x72, 0xeb, 0xda, 0x46,
- 0x6d, 0xeb, 0xad, 0x4d, 0x75, 0x19, 0x36, 0x55, 0x85, 0x36, 0x8f, 0x6d, 0xc7, 0x3b, 0xa4, 0xbc,
- 0x7a, 0xc9, 0x95, 0x3f, 0xd1, 0x87, 0x50, 0x66, 0x42, 0x3c, 0xc3, 0x39, 0x23, 0x5e, 0x23, 0xcf,
- 0xa4, 0xdc, 0xbb, 0x46, 0x4a, 0x97, 0x31, 0xeb, 0x0c, 0x9e, 0xff, 0x46, 0x18, 0x2a, 0x2e, 0x71,
- 0x4c, 0x63, 0x60, 0x7e, 0x61, 0x9c, 0x0e, 0x48, 0xa3, 0xb0, 0xae, 0x6d, 0x14, 0xf5, 0x10, 0x8d,
- 0xce, 0xff, 0x82, 0x5c, 0xb9, 0x27, 0xb6, 0x35, 0xb8, 0x6a, 0x14, 0x19, 0x43, 0x91, 0x12, 0x0e,
- 0xad, 0xc1, 0x15, 0x5b, 0x34, 0x7b, 0x6c, 0x79, 0xbc, 0xb7, 0xc4, 0x7a, 0x4b, 0x8c, 0xc2, 0xba,
- 0x37, 0xa0, 0x3e, 0x34, 0xad, 0x93, 0xa1, 0xdd, 0x3f, 0xf1, 0x0d, 0x02, 0xcc, 0x20, 0xb5, 0xa1,
- 0x69, 0x3d, 0xb3, 0xfb, 0xba, 0x34, 0x0b, 0xe5, 0x34, 0x2e, 0xc3, 0x9c, 0x65, 0xc1, 0x69, 0x5c,
- 0xaa, 0x9c, 0x9b, 0xb0, 0x44, 0x65, 0xf6, 0x1c, 0x62, 0x78, 0x24, 0x60, 0xae, 0x30, 0xe6, 0xc5,
- 0xa1, 0x69, 0x6d, 0xb3, 0x9e, 0x10, 0xbf, 0x71, 0x19, 0xe3, 0xaf, 0x0a, 0x7e, 0xe3, 0x32, 0xcc,
- 0x8f, 0x37, 0xa1, 0xe4, 0xdb, 0x1c, 0x15, 0x61, 0xfe, 0xe0, 0xf0, 0xa0, 0x53, 0x9f, 0x43, 0x00,
- 0xf9, 0xf6, 0xf1, 0x76, 0xe7, 0x60, 0xa7, 0xae, 0xa1, 0x32, 0x14, 0x76, 0x3a, 0xbc, 0x91, 0xc1,
- 0x8f, 0x01, 0x02, 0xeb, 0xa2, 0x02, 0x64, 0xf7, 0x3a, 0x9f, 0xd5, 0xe7, 0x28, 0xcf, 0x8b, 0x8e,
- 0x7e, 0xbc, 0x7b, 0x78, 0x50, 0xd7, 0xe8, 0xe0, 0x6d, 0xbd, 0xd3, 0xee, 0x76, 0xea, 0x19, 0xca,
- 0xf1, 0xec, 0x70, 0xa7, 0x9e, 0x45, 0x25, 0xc8, 0xbd, 0x68, 0xef, 0x3f, 0xef, 0xd4, 0xe7, 0xf1,
- 0xcf, 0x35, 0xa8, 0x8a, 0xf5, 0xe2, 0x67, 0x02, 0x7d, 0x07, 0xf2, 0xe7, 0xec, 0x5c, 0xb0, 0xad,
- 0x58, 0xde, 0xba, 0x15, 0x59, 0xdc, 0xd0, 0xd9, 0xd1, 0x05, 0x2f, 0xc2, 0x90, 0xbd, 0x98, 0xb8,
- 0x8d, 0xcc, 0x7a, 0x76, 0xa3, 0xbc, 0x55, 0xdf, 0xe4, 0xe7, 0x75, 0x73, 0x8f, 0x5c, 0xbd, 0x30,
- 0x06, 0x63, 0xa2, 0xd3, 0x4e, 0x84, 0x60, 0x7e, 0x68, 0x3b, 0x84, 0xed, 0xd8, 0xa2, 0xce, 0x7e,
- 0xd3, 0x6d, 0xcc, 0x16, 0x4d, 0xec, 0x56, 0xde, 0xc0, 0xbf, 0xd4, 0x00, 0x8e, 0xc6, 0x5e, 0xfa,
- 0xd1, 0x58, 0x86, 0xdc, 0x84, 0x0a, 0x16, 0xc7, 0x82, 0x37, 0xd8, 0x99, 0x20, 0x86, 0x4b, 0xfc,
- 0x33, 0x41, 0x1b, 0xe8, 0x06, 0x14, 0x46, 0x0e, 0x99, 0x9c, 0x5c, 0x4c, 0x18, 0x48, 0x51, 0xcf,
- 0xd3, 0xe6, 0xde, 0x04, 0xbd, 0x09, 0x15, 0xf3, 0xcc, 0xb2, 0x1d, 0x72, 0xc2, 0x65, 0xe5, 0x58,
- 0x6f, 0x99, 0xd3, 0x98, 0xde, 0x0a, 0x0b, 0x17, 0x9c, 0x57, 0x59, 0xf6, 0x29, 0x09, 0x5b, 0x50,
- 0x66, 0xaa, 0xce, 0x64, 0xbe, 0x77, 0x02, 0x1d, 0x33, 0x6c, 0x58, 0xdc, 0x84, 0x42, 0x6b, 0xfc,
- 0x03, 0x40, 0x3b, 0x64, 0x40, 0x3c, 0x32, 0x8b, 0xf7, 0x50, 0x6c, 0x92, 0x55, 0x6d, 0x82, 0x7f,
- 0xa6, 0xc1, 0x52, 0x48, 0xfc, 0x4c, 0xd3, 0x6a, 0x40, 0xa1, 0xcf, 0x84, 0x71, 0x0d, 0xb2, 0xba,
- 0x6c, 0xa2, 0x87, 0x50, 0x14, 0x0a, 0xb8, 0x8d, 0x6c, 0xca, 0xa6, 0x29, 0x70, 0x9d, 0x5c, 0xfc,
- 0xcb, 0x0c, 0x94, 0xc4, 0x44, 0x0f, 0x47, 0xa8, 0x0d, 0x55, 0x87, 0x37, 0x4e, 0xd8, 0x7c, 0x84,
- 0x46, 0xcd, 0x74, 0x27, 0xf4, 0x74, 0x4e, 0xaf, 0x88, 0x21, 0x8c, 0x8c, 0x7e, 0x1f, 0xca, 0x52,
- 0xc4, 0x68, 0xec, 0x09, 0x93, 0x37, 0xc2, 0x02, 0x82, 0xfd, 0xf7, 0x74, 0x4e, 0x07, 0xc1, 0x7e,
- 0x34, 0xf6, 0x50, 0x17, 0x96, 0xe5, 0x60, 0x3e, 0x1b, 0xa1, 0x46, 0x96, 0x49, 0x59, 0x0f, 0x4b,
- 0x89, 0x2f, 0xd5, 0xd3, 0x39, 0x1d, 0x89, 0xf1, 0x4a, 0xa7, 0xaa, 0x92, 0x77, 0xc9, 0x9d, 0x77,
- 0x4c, 0xa5, 0xee, 0xa5, 0x15, 0x57, 0xa9, 0x7b, 0x69, 0x3d, 0x2e, 0x41, 0x41, 0xb4, 0xf0, 0xbf,
- 0x64, 0x00, 0xe4, 0x6a, 0x1c, 0x8e, 0xd0, 0x0e, 0xd4, 0x1c, 0xd1, 0x0a, 0x59, 0xeb, 0x8d, 0x44,
- 0x6b, 0x89, 0x45, 0x9c, 0xd3, 0xab, 0x72, 0x10, 0x57, 0xee, 0x7b, 0x50, 0xf1, 0xa5, 0x04, 0x06,
- 0xbb, 0x99, 0x60, 0x30, 0x5f, 0x42, 0x59, 0x0e, 0xa0, 0x26, 0xfb, 0x04, 0x56, 0xfc, 0xf1, 0x09,
- 0x36, 0x7b, 0x73, 0x8a, 0xcd, 0x7c, 0x81, 0x4b, 0x52, 0x82, 0x6a, 0x35, 0x55, 0xb1, 0xc0, 0x6c,
- 0x37, 0x13, 0xcc, 0x16, 0x57, 0x8c, 0x1a, 0x0e, 0x68, 0xbc, 0xe4, 0x4d, 0xfc, 0xbf, 0x59, 0x28,
- 0x6c, 0xdb, 0xc3, 0x91, 0xe1, 0xd0, 0xd5, 0xc8, 0x3b, 0xc4, 0x1d, 0x0f, 0x3c, 0x66, 0xae, 0xda,
- 0xd6, 0xdd, 0xb0, 0x44, 0xc1, 0x26, 0xff, 0xea, 0x8c, 0x55, 0x17, 0x43, 0xe8, 0x60, 0x11, 0x1e,
- 0x33, 0xaf, 0x31, 0x58, 0x04, 0x47, 0x31, 0x44, 0x1e, 0xe4, 0x6c, 0x70, 0x90, 0x9b, 0x50, 0x98,
- 0x10, 0x27, 0x08, 0xe9, 0x4f, 0xe7, 0x74, 0x49, 0x40, 0xef, 0xc0, 0x42, 0x34, 0xbc, 0xe4, 0x04,
- 0x4f, 0xad, 0x17, 0x8e, 0x46, 0x77, 0xa1, 0x12, 0x8a, 0x71, 0x79, 0xc1, 0x57, 0x1e, 0x2a, 0x21,
- 0x6e, 0x55, 0xfa, 0x55, 0x1a, 0x8f, 0x2b, 0x4f, 0xe7, 0xa4, 0x67, 0x5d, 0x95, 0x9e, 0xb5, 0x28,
- 0x46, 0x09, 0xdf, 0x1a, 0x72, 0x32, 0xdf, 0x0f, 0x3b, 0x19, 0xfc, 0x7d, 0xa8, 0x86, 0x0c, 0x44,
- 0xe3, 0x4e, 0xe7, 0xe3, 0xe7, 0xed, 0x7d, 0x1e, 0xa4, 0x9e, 0xb0, 0xb8, 0xa4, 0xd7, 0x35, 0x1a,
- 0xeb, 0xf6, 0x3b, 0xc7, 0xc7, 0xf5, 0x0c, 0xaa, 0x42, 0xe9, 0xe0, 0xb0, 0x7b, 0xc2, 0xb9, 0xb2,
- 0xf8, 0x89, 0x2f, 0x41, 0x04, 0x39, 0x25, 0xb6, 0xcd, 0x29, 0xb1, 0x4d, 0x93, 0xb1, 0x2d, 0x13,
- 0xc4, 0x36, 0x16, 0xe6, 0xf6, 0x3b, 0xed, 0xe3, 0x4e, 0x7d, 0xfe, 0x71, 0x0d, 0x2a, 0xdc, 0xbe,
- 0x27, 0x63, 0x8b, 0x86, 0xda, 0x7f, 0xd2, 0x00, 0x82, 0xd3, 0x84, 0x5a, 0x50, 0xe8, 0x71, 0x9c,
- 0x86, 0xc6, 0x9c, 0xd1, 0x4a, 0xe2, 0x92, 0xe9, 0x92, 0x0b, 0x7d, 0x0b, 0x0a, 0xee, 0xb8, 0xd7,
- 0x23, 0xae, 0x0c, 0x79, 0x37, 0xa2, 0xfe, 0x50, 0x78, 0x2b, 0x5d, 0xf2, 0xd1, 0x21, 0x2f, 0x0d,
- 0x73, 0x30, 0x66, 0x01, 0x70, 0xfa, 0x10, 0xc1, 0x87, 0xff, 0x5e, 0x83, 0xb2, 0xb2, 0x79, 0x7f,
- 0x47, 0x27, 0x7c, 0x0b, 0x4a, 0x4c, 0x07, 0xd2, 0x17, 0x6e, 0xb8, 0xa8, 0x07, 0x04, 0xf4, 0x7b,
- 0x50, 0x92, 0x27, 0x40, 0x7a, 0xe2, 0x46, 0xb2, 0xd8, 0xc3, 0x91, 0x1e, 0xb0, 0xe2, 0x3d, 0x58,
- 0x64, 0x56, 0xe9, 0xd1, 0xe4, 0x5a, 0xda, 0x51, 0x4d, 0x3f, 0xb5, 0x48, 0xfa, 0xd9, 0x84, 0xe2,
- 0xe8, 0xfc, 0xca, 0x35, 0x7b, 0xc6, 0x40, 0x68, 0xe1, 0xb7, 0xf1, 0x47, 0x80, 0x54, 0x61, 0xb3,
- 0x4c, 0x17, 0x57, 0xa1, 0xfc, 0xd4, 0x70, 0xcf, 0x85, 0x4a, 0xf8, 0x21, 0x54, 0x69, 0x73, 0xef,
- 0xc5, 0x6b, 0xe8, 0xc8, 0x2e, 0x07, 0x92, 0x7b, 0x26, 0x9b, 0x23, 0x98, 0x3f, 0x37, 0xdc, 0x73,
- 0x36, 0xd1, 0xaa, 0xce, 0x7e, 0xa3, 0x77, 0xa0, 0xde, 0xe3, 0x93, 0x3c, 0x89, 0x5c, 0x19, 0x16,
- 0x04, 0xdd, 0xcf, 0x04, 0x3f, 0x85, 0x0a, 0x9f, 0xc3, 0x57, 0xad, 0x04, 0x5e, 0x84, 0x85, 0x63,
- 0xcb, 0x18, 0xb9, 0xe7, 0xb6, 0x8c, 0x6e, 0x74, 0xd2, 0xf5, 0x80, 0x36, 0x13, 0xe2, 0xdb, 0xb0,
- 0xe0, 0x90, 0xa1, 0x61, 0x5a, 0xa6, 0x75, 0x76, 0x72, 0x7a, 0xe5, 0x11, 0x57, 0x5c, 0x98, 0x6a,
- 0x3e, 0xf9, 0x31, 0xa5, 0x52, 0xd5, 0x4e, 0x07, 0xf6, 0xa9, 0x70, 0x73, 0xec, 0x37, 0xfe, 0x69,
- 0x06, 0x2a, 0x9f, 0x18, 0x5e, 0x4f, 0x2e, 0x1d, 0xda, 0x85, 0x9a, 0xef, 0xdc, 0x18, 0x45, 0xe8,
- 0x12, 0x09, 0xb1, 0x6c, 0x8c, 0x4c, 0xa5, 0x65, 0x74, 0xac, 0xf6, 0x54, 0x02, 0x13, 0x65, 0x58,
- 0x3d, 0x32, 0xf0, 0x45, 0x65, 0xd2, 0x45, 0x31, 0x46, 0x55, 0x94, 0x4a, 0x40, 0x87, 0x50, 0x1f,
- 0x39, 0xf6, 0x99, 0x43, 0x5c, 0xd7, 0x17, 0xc6, 0xc3, 0x18, 0x4e, 0x10, 0x76, 0x24, 0x58, 0x03,
- 0x71, 0x0b, 0xa3, 0x30, 0xe9, 0xf1, 0x42, 0x90, 0xcf, 0x70, 0xe7, 0xf4, 0x9f, 0x19, 0x40, 0xf1,
- 0x49, 0xfd, 0xb6, 0x29, 0xde, 0x3d, 0xa8, 0xb9, 0x9e, 0xe1, 0xc4, 0x36, 0x5b, 0x95, 0x51, 0x7d,
- 0x8f, 0xff, 0x36, 0xf8, 0x0a, 0x9d, 0x58, 0xb6, 0x67, 0xbe, 0xbc, 0x12, 0x59, 0x72, 0x4d, 0x92,
- 0x0f, 0x18, 0x15, 0x75, 0xa0, 0xf0, 0xd2, 0x1c, 0x78, 0xc4, 0x71, 0x1b, 0xb9, 0xf5, 0xec, 0x46,
- 0x6d, 0xeb, 0xe1, 0x75, 0xcb, 0xb0, 0xf9, 0x21, 0xe3, 0xef, 0x5e, 0x8d, 0x88, 0x2e, 0xc7, 0xaa,
- 0x99, 0x67, 0x3e, 0x94, 0x8d, 0xdf, 0x84, 0xe2, 0x2b, 0x2a, 0x82, 0xde, 0xb2, 0x0b, 0x3c, 0x59,
- 0x64, 0x6d, 0x7e, 0xc9, 0x7e, 0xe9, 0x18, 0x67, 0x43, 0x62, 0x79, 0xf2, 0x1e, 0x28, 0xdb, 0xf8,
- 0x1e, 0x40, 0x00, 0x43, 0x5d, 0xfe, 0xc1, 0xe1, 0xd1, 0xf3, 0x6e, 0x7d, 0x0e, 0x55, 0xa0, 0x78,
- 0x70, 0xb8, 0xd3, 0xd9, 0xef, 0xd0, 0xf8, 0x80, 0x5b, 0xd2, 0xa4, 0xa1, 0xb5, 0x54, 0x31, 0xb5,
- 0x10, 0x26, 0x5e, 0x85, 0xe5, 0xa4, 0x05, 0xa4, 0xb9, 0x68, 0x55, 0xec, 0xd2, 0x99, 0x8e, 0x8a,
- 0x0a, 0x9d, 0x09, 0x4f, 0xb7, 0x01, 0x05, 0xbe, 0x7b, 0xfb, 0x22, 0x39, 0x97, 0x4d, 0x6a, 0x08,
- 0xbe, 0x19, 0x49, 0x5f, 0xac, 0x92, 0xdf, 0x4e, 0x74, 0x2f, 0xb9, 0x44, 0xf7, 0x82, 0xee, 0x42,
- 0xd5, 0x3f, 0x0d, 0x86, 0x2b, 0x72, 0x81, 0x92, 0x5e, 0x91, 0x1b, 0x9d, 0xd2, 0x42, 0x46, 0x2f,
- 0x84, 0x8d, 0x8e, 0xee, 0x41, 0x9e, 0x4c, 0x88, 0xe5, 0xb9, 0x8d, 0x32, 0x8b, 0x18, 0x55, 0x99,
- 0xbb, 0x77, 0x28, 0x55, 0x17, 0x9d, 0xf8, 0xbb, 0xb0, 0xc8, 0xee, 0x48, 0x4f, 0x1c, 0xc3, 0x52,
- 0x2f, 0x73, 0xdd, 0xee, 0xbe, 0x30, 0x37, 0xfd, 0x89, 0x6a, 0x90, 0xd9, 0xdd, 0x11, 0x46, 0xc8,
- 0xec, 0xee, 0xe0, 0x1f, 0x6b, 0x80, 0xd4, 0x71, 0x33, 0xd9, 0x39, 0x22, 0x5c, 0xc2, 0x67, 0x03,
- 0xf8, 0x65, 0xc8, 0x11, 0xc7, 0xb1, 0x1d, 0x66, 0xd1, 0x92, 0xce, 0x1b, 0xf8, 0x2d, 0xa1, 0x83,
- 0x4e, 0x26, 0xf6, 0x85, 0x7f, 0x06, 0xb9, 0x34, 0xcd, 0x57, 0x75, 0x0f, 0x96, 0x42, 0x5c, 0x33,
- 0x45, 0xae, 0x0f, 0x61, 0x81, 0x09, 0xdb, 0x3e, 0x27, 0xbd, 0x8b, 0x91, 0x6d, 0x5a, 0x31, 0x3c,
- 0xba, 0x72, 0x81, 0x83, 0xa5, 0xf3, 0xe0, 0x13, 0xab, 0xf8, 0xc4, 0x6e, 0x77, 0x1f, 0x7f, 0x06,
- 0xab, 0x11, 0x39, 0x52, 0xfd, 0x3f, 0x82, 0x72, 0xcf, 0x27, 0xba, 0x22, 0xd7, 0xb9, 0x1d, 0x56,
- 0x2e, 0x3a, 0x54, 0x1d, 0x81, 0x0f, 0xe1, 0x46, 0x4c, 0xf4, 0x4c, 0x73, 0x7e, 0x1b, 0x56, 0x98,
- 0xc0, 0x3d, 0x42, 0x46, 0xed, 0x81, 0x39, 0x49, 0xb5, 0xf4, 0x48, 0x4c, 0x4a, 0x61, 0xfc, 0x7a,
- 0xf7, 0x05, 0xfe, 0x03, 0x81, 0xd8, 0x35, 0x87, 0xa4, 0x6b, 0xef, 0xa7, 0xeb, 0x46, 0xa3, 0xd9,
- 0x05, 0xb9, 0x72, 0x45, 0x5a, 0xc3, 0x7e, 0xe3, 0x7f, 0xd6, 0x84, 0xa9, 0xd4, 0xe1, 0x5f, 0xf3,
- 0x4e, 0x5e, 0x03, 0x38, 0xa3, 0x47, 0x86, 0xf4, 0x69, 0x07, 0xaf, 0xa8, 0x28, 0x14, 0x5f, 0x4f,
- 0xea, 0xbf, 0x2b, 0x42, 0xcf, 0x65, 0xb1, 0xcf, 0xd9, 0x3f, 0xbe, 0x97, 0xbb, 0x0d, 0x65, 0x46,
- 0x38, 0xf6, 0x0c, 0x6f, 0xec, 0xc6, 0x16, 0xe3, 0x2f, 0xc4, 0xb6, 0x97, 0x83, 0x66, 0x9a, 0xd7,
- 0xb7, 0x20, 0xcf, 0x2e, 0x13, 0x32, 0x95, 0xbe, 0x99, 0xb0, 0x1f, 0xb9, 0x1e, 0xba, 0x60, 0xc4,
- 0x3f, 0xd5, 0x20, 0xff, 0x8c, 0x95, 0x60, 0x15, 0xd5, 0xe6, 0xe5, 0x5a, 0x58, 0xc6, 0x90, 0x17,
- 0x86, 0x4a, 0x3a, 0xfb, 0xcd, 0x52, 0x4f, 0x42, 0x9c, 0xe7, 0xfa, 0x3e, 0x4f, 0x71, 0x4b, 0xba,
- 0xdf, 0xa6, 0x36, 0xeb, 0x0d, 0x4c, 0x62, 0x79, 0xac, 0x77, 0x9e, 0xf5, 0x2a, 0x14, 0x9a, 0x3d,
- 0x9b, 0xee, 0x3e, 0x31, 0x1c, 0x4b, 0x14, 0x4d, 0x8b, 0x7a, 0x40, 0xc0, 0xfb, 0x50, 0xe7, 0x7a,
- 0xb4, 0xfb, 0x7d, 0x25, 0xc1, 0xf4, 0xd1, 0xb4, 0x08, 0x5a, 0x48, 0x5a, 0x26, 0x2a, 0xed, 0x17,
- 0x1a, 0x2c, 0x2a, 0xe2, 0x66, 0xb2, 0xea, 0xbb, 0x90, 0xe7, 0x45, 0x6a, 0x91, 0xe9, 0x2c, 0x87,
- 0x47, 0x71, 0x18, 0x5d, 0xf0, 0xa0, 0x4d, 0x28, 0xf0, 0x5f, 0xf2, 0x0e, 0x90, 0xcc, 0x2e, 0x99,
- 0xf0, 0x3d, 0x58, 0x12, 0x24, 0x32, 0xb4, 0x93, 0x0e, 0x06, 0x5b, 0x0c, 0xfc, 0x67, 0xb0, 0x1c,
- 0x66, 0x9b, 0x69, 0x4a, 0x8a, 0x92, 0x99, 0xd7, 0x51, 0xb2, 0x2d, 0x95, 0x7c, 0x3e, 0xea, 0x2b,
- 0x79, 0x54, 0x74, 0xc7, 0xa8, 0xeb, 0x95, 0x09, 0xaf, 0x57, 0x30, 0x01, 0x29, 0xe2, 0x1b, 0x9d,
- 0xc0, 0x07, 0x72, 0x3b, 0xec, 0x9b, 0xae, 0xef, 0xc3, 0x31, 0x54, 0x06, 0xa6, 0x45, 0x0c, 0x47,
- 0x54, 0xce, 0x35, 0x5e, 0x39, 0x57, 0x69, 0xf8, 0x0b, 0x40, 0xea, 0xc0, 0x6f, 0x54, 0xe9, 0xfb,
- 0xd2, 0x64, 0x47, 0x8e, 0x3d, 0xb4, 0x53, 0xcd, 0x8e, 0xff, 0x1c, 0x56, 0x22, 0x7c, 0xdf, 0xa8,
- 0x9a, 0x4b, 0xb0, 0xb8, 0x43, 0x64, 0x42, 0x23, 0xdd, 0xde, 0x47, 0x80, 0x54, 0xe2, 0x4c, 0x91,
- 0xad, 0x05, 0x8b, 0xcf, 0xec, 0x09, 0x75, 0x91, 0x94, 0x1a, 0xf8, 0x06, 0x5e, 0x87, 0xf0, 0x4d,
- 0xe1, 0xb7, 0x29, 0xb8, 0x3a, 0x60, 0x26, 0xf0, 0x7f, 0xd7, 0xa0, 0xd2, 0x1e, 0x18, 0xce, 0x50,
- 0x02, 0x7f, 0x0f, 0xf2, 0xfc, 0x76, 0x2d, 0x0a, 0x5a, 0xf7, 0xc3, 0x62, 0x54, 0x5e, 0xde, 0x68,
- 0xf3, 0xbb, 0xb8, 0x18, 0x45, 0x15, 0x17, 0x6f, 0x5e, 0x3b, 0x91, 0x37, 0xb0, 0x1d, 0xf4, 0x1e,
- 0xe4, 0x0c, 0x3a, 0x84, 0x85, 0xa2, 0x5a, 0xb4, 0xae, 0xc1, 0xa4, 0xb1, 0x3b, 0x00, 0xe7, 0xc2,
- 0xdf, 0x81, 0xb2, 0x82, 0x80, 0x0a, 0x90, 0x7d, 0xd2, 0x11, 0x09, 0x7b, 0x7b, 0xbb, 0xbb, 0xfb,
- 0x82, 0x17, 0x74, 0x6a, 0x00, 0x3b, 0x1d, 0xbf, 0x9d, 0xc1, 0x9f, 0x8a, 0x51, 0xc2, 0xed, 0xab,
- 0xfa, 0x68, 0x69, 0xfa, 0x64, 0x5e, 0x4b, 0x9f, 0x4b, 0xa8, 0x8a, 0xe9, 0xcf, 0x1a, 0xc6, 0x98,
- 0xbc, 0x94, 0x30, 0xa6, 0x28, 0xaf, 0x0b, 0x46, 0xfc, 0x2b, 0x0d, 0xea, 0x3b, 0xf6, 0x2b, 0xeb,
- 0xcc, 0x31, 0xfa, 0xfe, 0x39, 0xf9, 0x30, 0xb2, 0x52, 0x9b, 0x91, 0xe2, 0x68, 0x84, 0x3f, 0x20,
- 0x44, 0x56, 0xac, 0x11, 0x94, 0x0d, 0x79, 0x2c, 0x94, 0x4d, 0xfc, 0x01, 0x2c, 0x44, 0x06, 0x51,
- 0xdb, 0xbf, 0x68, 0xef, 0xef, 0xee, 0x50, 0x5b, 0xb3, 0xc2, 0x5a, 0xe7, 0xa0, 0xfd, 0x78, 0xbf,
- 0x23, 0x1e, 0x90, 0xda, 0x07, 0xdb, 0x9d, 0xfd, 0x7a, 0x06, 0xf7, 0x60, 0x51, 0x81, 0x9f, 0xf5,
- 0x65, 0x20, 0x45, 0xbb, 0x05, 0xa8, 0x8a, 0x68, 0x2f, 0x0e, 0xe5, 0xbf, 0x65, 0xa0, 0x26, 0x29,
- 0x5f, 0x0f, 0x26, 0x5a, 0x85, 0x7c, 0xff, 0xf4, 0xd8, 0xfc, 0x42, 0xbe, 0x1c, 0x89, 0x16, 0xa5,
- 0x0f, 0x38, 0x0e, 0x7f, 0xbe, 0x15, 0x2d, 0x1a, 0xc6, 0x1d, 0xe3, 0xa5, 0xb7, 0x6b, 0xf5, 0xc9,
- 0x25, 0x4b, 0x0a, 0xe6, 0xf5, 0x80, 0xc0, 0x2a, 0x4c, 0xe2, 0x99, 0x97, 0xdd, 0xac, 0x94, 0x67,
- 0x5f, 0xf4, 0x00, 0xea, 0xf4, 0x77, 0x7b, 0x34, 0x1a, 0x98, 0xa4, 0xcf, 0x05, 0x14, 0x18, 0x4f,
- 0x8c, 0x4e, 0xd1, 0xd9, 0x5d, 0xc4, 0x6d, 0x14, 0x59, 0x58, 0x12, 0x2d, 0xb4, 0x0e, 0x65, 0xae,
- 0xdf, 0xae, 0xf5, 0xdc, 0x25, 0xec, 0xed, 0x33, 0xab, 0xab, 0xa4, 0x70, 0x9a, 0x01, 0xd1, 0x34,
- 0x63, 0x09, 0x16, 0xdb, 0x63, 0xef, 0xbc, 0x63, 0xd1, 0x58, 0x21, 0xad, 0xbc, 0x0c, 0x88, 0x12,
- 0x77, 0x4c, 0x57, 0xa5, 0x0a, 0xd6, 0xf0, 0x82, 0x74, 0x60, 0x89, 0x12, 0x89, 0xe5, 0x99, 0x3d,
- 0x25, 0xae, 0xca, 0xcc, 0x4b, 0x8b, 0x64, 0x5e, 0x86, 0xeb, 0xbe, 0xb2, 0x9d, 0xbe, 0xb0, 0xb9,
- 0xdf, 0xc6, 0xff, 0xa8, 0x71, 0xc8, 0xe7, 0x6e, 0x28, 0x7d, 0xfa, 0x2d, 0xc5, 0xa0, 0xf7, 0xa1,
- 0x60, 0x8f, 0xd8, 0x0b, 0xbf, 0x28, 0xc3, 0xac, 0x6e, 0xf2, 0x6f, 0x02, 0x36, 0x85, 0xe0, 0x43,
- 0xde, 0xab, 0x4b, 0x36, 0x74, 0x1f, 0x6a, 0xe7, 0x86, 0x7b, 0x4e, 0xfa, 0x47, 0x52, 0x26, 0xbf,
- 0xf9, 0x45, 0xa8, 0x78, 0x23, 0xd0, 0xef, 0x09, 0xf1, 0xa6, 0xe8, 0x87, 0x1f, 0xc2, 0x8a, 0xe4,
- 0x14, 0xaf, 0x13, 0x53, 0x98, 0x5f, 0xc1, 0x6d, 0xc9, 0xbc, 0x7d, 0x6e, 0x58, 0x67, 0x44, 0x02,
- 0xfe, 0xae, 0x16, 0x88, 0xcf, 0x27, 0x9b, 0x38, 0x9f, 0xc7, 0xd0, 0xf0, 0xe7, 0xc3, 0x6e, 0xd6,
- 0xf6, 0x40, 0x55, 0x74, 0xec, 0x8a, 0xf3, 0x54, 0xd2, 0xd9, 0x6f, 0x4a, 0x73, 0xec, 0x81, 0x9f,
- 0x4a, 0xd3, 0xdf, 0x78, 0x1b, 0x6e, 0x4a, 0x19, 0xe2, 0xce, 0x1b, 0x16, 0x12, 0x53, 0x3c, 0x49,
- 0x88, 0x30, 0x2c, 0x1d, 0x3a, 0x7d, 0xe1, 0x55, 0xce, 0xf0, 0x12, 0x30, 0x99, 0x9a, 0x22, 0x73,
- 0x85, 0x6f, 0x4a, 0xaa, 0x98, 0x92, 0x2d, 0x49, 0x32, 0x15, 0xa0, 0x92, 0xc5, 0x82, 0x51, 0x72,
- 0x6c, 0xc1, 0x62, 0xa2, 0x7f, 0x00, 0x6b, 0xbe, 0x12, 0xd4, 0x6e, 0x47, 0xc4, 0x19, 0x9a, 0xae,
- 0xab, 0xd4, 0xbd, 0x93, 0x26, 0x7e, 0x1f, 0xe6, 0x47, 0x44, 0x04, 0xa1, 0xf2, 0x16, 0x92, 0x9b,
- 0x52, 0x19, 0xcc, 0xfa, 0x71, 0x1f, 0xee, 0x48, 0xe9, 0xdc, 0xa2, 0x89, 0xe2, 0xa3, 0x4a, 0xc9,
- 0x6a, 0x60, 0x26, 0xa5, 0x1a, 0x98, 0x8d, 0xbc, 0xc5, 0x7c, 0xc4, 0x0d, 0x29, 0xcf, 0xfc, 0x4c,
- 0xc9, 0xc5, 0x1e, 0xb7, 0xa9, 0xef, 0x2a, 0x66, 0x12, 0xf6, 0xd7, 0xc2, 0x0b, 0x7c, 0x55, 0x1e,
- 0x9e, 0xb0, 0x19, 0xca, 0x87, 0x0e, 0xd9, 0xa4, 0x59, 0x33, 0x5d, 0x00, 0x5d, 0xad, 0x85, 0xce,
- 0xeb, 0x21, 0x1a, 0x3e, 0x85, 0xe5, 0xb0, 0x5f, 0x9b, 0x49, 0x97, 0x65, 0xc8, 0x79, 0xf6, 0x05,
- 0x91, 0xb1, 0x86, 0x37, 0xa4, 0xed, 0x7c, 0x9f, 0x37, 0x93, 0xed, 0x8c, 0x40, 0x18, 0x3b, 0x1d,
- 0xb3, 0xea, 0x4b, 0x37, 0x96, 0xbc, 0x03, 0xf1, 0x06, 0x3e, 0x80, 0xd5, 0xa8, 0x67, 0x9b, 0x49,
- 0xe5, 0x17, 0xfc, 0x2c, 0x25, 0x39, 0xbf, 0x99, 0xe4, 0x7e, 0x1c, 0xf8, 0x25, 0xc5, 0xb7, 0xcd,
- 0x24, 0x52, 0x87, 0x66, 0x92, 0xab, 0xfb, 0x2a, 0x8e, 0x8e, 0xef, 0xf9, 0x66, 0x12, 0xe6, 0x06,
- 0xc2, 0x66, 0x5f, 0xfe, 0xc0, 0x5d, 0x65, 0xa7, 0xba, 0x2b, 0x71, 0x48, 0x02, 0x87, 0xfa, 0x35,
- 0x6c, 0x3a, 0x81, 0x11, 0xf8, 0xf2, 0x59, 0x31, 0x68, 0x38, 0xf3, 0x31, 0x58, 0x43, 0x6e, 0x6c,
- 0x35, 0x02, 0xcc, 0xb4, 0x18, 0x9f, 0x04, 0x6e, 0x3c, 0x16, 0x24, 0x66, 0x12, 0xfc, 0x29, 0xac,
- 0xa7, 0xc7, 0x87, 0x59, 0x24, 0x3f, 0x68, 0x41, 0xc9, 0xbf, 0x0c, 0x29, 0xdf, 0x9b, 0x95, 0xa1,
- 0x70, 0x70, 0x78, 0x7c, 0xd4, 0xde, 0xee, 0xf0, 0x0f, 0xce, 0xb6, 0x0f, 0x75, 0xfd, 0xf9, 0x51,
- 0xb7, 0x9e, 0xd9, 0xfa, 0x75, 0x16, 0x32, 0x7b, 0x2f, 0xd0, 0x67, 0x90, 0xe3, 0x5f, 0x5f, 0x4c,
- 0xf9, 0xe4, 0xa6, 0x39, 0xed, 0x03, 0x13, 0x7c, 0xe3, 0xc7, 0xff, 0xf5, 0xeb, 0x9f, 0x67, 0x16,
- 0x71, 0xa5, 0x35, 0xf9, 0x76, 0xeb, 0x62, 0xd2, 0x62, 0x61, 0xea, 0x91, 0xf6, 0x00, 0x7d, 0x0c,
- 0xd9, 0xa3, 0xb1, 0x87, 0x52, 0x3f, 0xc5, 0x69, 0xa6, 0x7f, 0x73, 0x82, 0x57, 0x98, 0xd0, 0x05,
- 0x0c, 0x42, 0xe8, 0x68, 0xec, 0x51, 0x91, 0x3f, 0x84, 0xb2, 0xfa, 0xc5, 0xc8, 0xb5, 0xdf, 0xe7,
- 0x34, 0xaf, 0xff, 0x1a, 0x05, 0xdf, 0x66, 0x50, 0x37, 0x30, 0x12, 0x50, 0xfc, 0x9b, 0x16, 0x75,
- 0x16, 0xdd, 0x4b, 0x0b, 0xa5, 0x7e, 0xbd, 0xd3, 0x4c, 0xff, 0x40, 0x25, 0x36, 0x0b, 0xef, 0xd2,
- 0xa2, 0x22, 0xff, 0x44, 0x7c, 0x9b, 0xd2, 0xf3, 0xd0, 0x9d, 0x84, 0x6f, 0x13, 0xd4, 0x57, 0xf8,
- 0xe6, 0x7a, 0x3a, 0x83, 0x00, 0xb9, 0xc5, 0x40, 0x56, 0xf1, 0xa2, 0x00, 0xe9, 0xf9, 0x2c, 0x8f,
- 0xb4, 0x07, 0x5b, 0x3d, 0xc8, 0xb1, 0x17, 0x2e, 0xf4, 0xb9, 0xfc, 0xd1, 0x4c, 0x78, 0xea, 0x4b,
- 0x59, 0xe8, 0xd0, 0xdb, 0x18, 0x5e, 0x66, 0x40, 0x35, 0x5c, 0xa2, 0x40, 0xec, 0x7d, 0xeb, 0x91,
- 0xf6, 0x60, 0x43, 0x7b, 0x5f, 0xdb, 0xfa, 0x55, 0x0e, 0x72, 0xac, 0xb4, 0x8b, 0x2e, 0x00, 0x82,
- 0xd7, 0x9e, 0xe8, 0xec, 0x62, 0xef, 0x47, 0xd1, 0xd9, 0xc5, 0x1f, 0x8a, 0x70, 0x93, 0x81, 0x2e,
- 0xe3, 0x05, 0x0a, 0xca, 0x2a, 0xc6, 0x2d, 0x56, 0x04, 0xa7, 0x76, 0xfc, 0x1b, 0x4d, 0x54, 0xb6,
- 0xf9, 0x59, 0x42, 0x49, 0xd2, 0x42, 0x4f, 0x3e, 0xd1, 0xed, 0x90, 0xf0, 0xdc, 0x83, 0xbf, 0xcb,
- 0x00, 0x5b, 0xb8, 0x1e, 0x00, 0x3a, 0x8c, 0xe3, 0x91, 0xf6, 0xe0, 0xf3, 0x06, 0x5e, 0x12, 0x56,
- 0x8e, 0xf4, 0xa0, 0x1f, 0x41, 0x2d, 0xfc, 0xa4, 0x81, 0xee, 0x26, 0x60, 0x45, 0x5f, 0x46, 0x9a,
- 0x6f, 0x4d, 0x67, 0x12, 0x3a, 0xad, 0x31, 0x9d, 0x04, 0x38, 0x47, 0xbe, 0x20, 0x64, 0x64, 0x50,
- 0x26, 0xb1, 0x06, 0xe8, 0x1f, 0x34, 0xf1, 0xe2, 0x14, 0xbc, 0x51, 0xa0, 0x24, 0xe9, 0xb1, 0x17,
- 0x90, 0xe6, 0xbd, 0x6b, 0xb8, 0x84, 0x12, 0x7f, 0xc8, 0x94, 0xf8, 0x00, 0x2f, 0x07, 0x4a, 0x78,
- 0xe6, 0x90, 0x78, 0xb6, 0xd0, 0xe2, 0xf3, 0x5b, 0xf8, 0x46, 0xc8, 0x38, 0xa1, 0xde, 0x60, 0xb1,
- 0xf8, 0x3b, 0x43, 0xe2, 0x62, 0x85, 0xde, 0x2d, 0x12, 0x17, 0x2b, 0xfc, 0x48, 0x91, 0xb4, 0x58,
- 0xfc, 0x55, 0x21, 0x69, 0xb1, 0xfc, 0x9e, 0xad, 0xff, 0x9b, 0x87, 0xc2, 0x36, 0xff, 0x26, 0x1c,
- 0xd9, 0x50, 0xf2, 0xcb, 0xf4, 0x68, 0x2d, 0xa9, 0xce, 0x18, 0x5c, 0x6b, 0x9a, 0x77, 0x52, 0xfb,
- 0x85, 0x42, 0x6f, 0x32, 0x85, 0xde, 0xc0, 0xab, 0x14, 0x59, 0x7c, 0x76, 0xde, 0xe2, 0xc5, 0xac,
- 0x96, 0xd1, 0xef, 0x53, 0x43, 0xfc, 0x29, 0x54, 0xd4, 0x3a, 0x3a, 0x7a, 0x33, 0xb1, 0xb6, 0xa9,
- 0x96, 0xe2, 0x9b, 0x78, 0x1a, 0x8b, 0x40, 0x7e, 0x8b, 0x21, 0xaf, 0xe1, 0x9b, 0x09, 0xc8, 0x0e,
- 0x63, 0x0d, 0x81, 0xf3, 0x1a, 0x78, 0x32, 0x78, 0xa8, 0xc4, 0x9e, 0x0c, 0x1e, 0x2e, 0xa1, 0x4f,
- 0x05, 0x1f, 0x33, 0x56, 0x0a, 0xee, 0x02, 0x04, 0x95, 0x6c, 0x94, 0x68, 0x4b, 0xe5, 0x5e, 0x17,
- 0x75, 0x0e, 0xf1, 0x22, 0x38, 0xc6, 0x0c, 0x56, 0xec, 0xbb, 0x08, 0xec, 0xc0, 0x74, 0x3d, 0x7e,
- 0x30, 0xab, 0xa1, 0xd2, 0x34, 0x4a, 0x9c, 0x4f, 0xb8, 0xbe, 0xdd, 0xbc, 0x3b, 0x95, 0x47, 0xa0,
- 0xdf, 0x63, 0xe8, 0x77, 0x70, 0x33, 0x01, 0x7d, 0xc4, 0x79, 0xe9, 0x66, 0xfb, 0xff, 0x3c, 0x94,
- 0x9f, 0x19, 0xa6, 0xe5, 0x11, 0xcb, 0xb0, 0x7a, 0x04, 0x9d, 0x42, 0x8e, 0x45, 0xea, 0xa8, 0x23,
- 0x56, 0xcb, 0xb6, 0x51, 0x47, 0x1c, 0xaa, 0x69, 0xe2, 0x75, 0x06, 0xdc, 0xc4, 0x2b, 0x14, 0x78,
- 0x18, 0x88, 0x6e, 0xb1, 0x52, 0x24, 0x9d, 0xf4, 0x4b, 0xc8, 0x8b, 0xd7, 0xbe, 0x88, 0xa0, 0x50,
- 0xf1, 0xa7, 0x79, 0x2b, 0xb9, 0x33, 0x69, 0x2f, 0xab, 0x30, 0x2e, 0xe3, 0xa3, 0x38, 0x13, 0x80,
- 0xa0, 0xc6, 0x1e, 0x5d, 0xd1, 0x58, 0x49, 0xbe, 0xb9, 0x9e, 0xce, 0x90, 0x64, 0x53, 0x15, 0xb3,
- 0xef, 0xf3, 0x52, 0xdc, 0x3f, 0x86, 0xf9, 0xa7, 0x86, 0x7b, 0x8e, 0x22, 0xb1, 0x57, 0xf9, 0x56,
- 0xac, 0xd9, 0x4c, 0xea, 0x12, 0x28, 0x77, 0x18, 0xca, 0x4d, 0xee, 0xca, 0x54, 0x94, 0x73, 0xc3,
- 0xa5, 0x41, 0x0d, 0xf5, 0x21, 0xcf, 0x3f, 0x1d, 0x8b, 0xda, 0x2f, 0xf4, 0xf9, 0x59, 0xd4, 0x7e,
- 0xe1, 0xaf, 0xcd, 0xae, 0x47, 0x19, 0x41, 0x51, 0x7e, 0xab, 0x85, 0x22, 0x0f, 0xf7, 0x91, 0xef,
- 0xba, 0x9a, 0x6b, 0x69, 0xdd, 0x02, 0xeb, 0x2e, 0xc3, 0xba, 0x8d, 0x1b, 0xb1, 0xb5, 0x12, 0x9c,
- 0x8f, 0xb4, 0x07, 0xef, 0x6b, 0xe8, 0x47, 0x00, 0xc1, 0xb3, 0x44, 0xec, 0x04, 0x46, 0x5f, 0x38,
- 0x62, 0x27, 0x30, 0xf6, 0xa2, 0x81, 0x37, 0x19, 0xee, 0x06, 0xbe, 0x1b, 0xc5, 0xf5, 0x1c, 0xc3,
- 0x72, 0x5f, 0x12, 0xe7, 0x3d, 0x5e, 0x65, 0x75, 0xcf, 0xcd, 0x11, 0x9d, 0xb2, 0x03, 0x25, 0xbf,
- 0xea, 0x1c, 0xf5, 0xb6, 0xd1, 0x6a, 0x78, 0xd4, 0xdb, 0xc6, 0xca, 0xd5, 0x61, 0xb7, 0x13, 0xda,
- 0x2d, 0x92, 0x95, 0x1e, 0xc0, 0x5f, 0xd4, 0x61, 0x9e, 0x66, 0xdd, 0x34, 0x39, 0x09, 0xea, 0x26,
- 0xd1, 0xd9, 0xc7, 0xaa, 0xa8, 0xd1, 0xd9, 0xc7, 0x4b, 0x2e, 0xe1, 0xe4, 0x84, 0x5e, 0xb2, 0x5a,
- 0xbc, 0x44, 0x41, 0x67, 0x6a, 0x43, 0x59, 0x29, 0xac, 0xa0, 0x04, 0x61, 0xe1, 0xf2, 0x6c, 0x34,
- 0xdc, 0x25, 0x54, 0x65, 0xf0, 0x1b, 0x0c, 0x6f, 0x85, 0x87, 0x3b, 0x86, 0xd7, 0xe7, 0x1c, 0x14,
- 0x50, 0xcc, 0x4e, 0x9c, 0xfb, 0x84, 0xd9, 0x85, 0xcf, 0xfe, 0x7a, 0x3a, 0x43, 0xea, 0xec, 0x82,
- 0x83, 0xff, 0x0a, 0x2a, 0x6a, 0x79, 0x05, 0x25, 0x28, 0x1f, 0x29, 0x29, 0x47, 0xe3, 0x48, 0x52,
- 0x75, 0x26, 0xec, 0xd9, 0x18, 0xa4, 0xa1, 0xb0, 0x51, 0xe0, 0x01, 0x14, 0x44, 0xbd, 0x25, 0xc9,
- 0xa4, 0xe1, 0xf2, 0x73, 0x92, 0x49, 0x23, 0xc5, 0x9a, 0x70, 0xf6, 0xcc, 0x10, 0xe9, 0x95, 0x52,
- 0xc6, 0x6a, 0x81, 0xf6, 0x84, 0x78, 0x69, 0x68, 0x41, 0x25, 0x33, 0x0d, 0x4d, 0xb9, 0xce, 0xa7,
- 0xa1, 0x9d, 0x11, 0x4f, 0xf8, 0x03, 0x79, 0x4d, 0x46, 0x29, 0xc2, 0xd4, 0xf8, 0x88, 0xa7, 0xb1,
- 0x24, 0x5d, 0x6e, 0x02, 0x40, 0x19, 0x1c, 0x2f, 0x01, 0x82, 0x6a, 0x50, 0x34, 0x63, 0x4d, 0xac,
- 0x82, 0x47, 0x33, 0xd6, 0xe4, 0x82, 0x52, 0xd8, 0xf7, 0x05, 0xb8, 0xfc, 0x6e, 0x45, 0x91, 0x7f,
- 0xa6, 0x01, 0x8a, 0x17, 0x8e, 0xd0, 0xc3, 0x64, 0xe9, 0x89, 0xb5, 0xf5, 0xe6, 0xbb, 0xaf, 0xc7,
- 0x9c, 0x14, 0xce, 0x02, 0x95, 0x7a, 0x8c, 0x7b, 0xf4, 0x8a, 0x2a, 0xf5, 0x97, 0x1a, 0x54, 0x43,
- 0x55, 0x27, 0x74, 0x3f, 0x65, 0x4d, 0x23, 0x25, 0xf7, 0xe6, 0xdb, 0xd7, 0xf2, 0x25, 0xa5, 0xf2,
- 0xca, 0x0e, 0x90, 0x77, 0x9a, 0x9f, 0x68, 0x50, 0x0b, 0x57, 0xa9, 0x50, 0x8a, 0xec, 0x58, 0xc9,
- 0xbe, 0xb9, 0x71, 0x3d, 0xe3, 0xf4, 0xe5, 0x09, 0xae, 0x33, 0x03, 0x28, 0x88, 0xba, 0x56, 0xd2,
- 0xc6, 0x0f, 0x17, 0xfb, 0x93, 0x36, 0x7e, 0xa4, 0x28, 0x96, 0xb0, 0xf1, 0x1d, 0x7b, 0x40, 0x94,
- 0x63, 0x26, 0x0a, 0x5f, 0x69, 0x68, 0xd3, 0x8f, 0x59, 0xa4, 0x6a, 0x96, 0x86, 0x16, 0x1c, 0x33,
- 0x59, 0xf1, 0x42, 0x29, 0xc2, 0xae, 0x39, 0x66, 0xd1, 0x82, 0x59, 0xc2, 0x31, 0x63, 0x80, 0xca,
- 0x31, 0x0b, 0x6a, 0x53, 0x49, 0xc7, 0x2c, 0xf6, 0x76, 0x91, 0x74, 0xcc, 0xe2, 0xe5, 0xad, 0x84,
- 0x75, 0x64, 0xb8, 0xa1, 0x63, 0xb6, 0x94, 0x50, 0xc6, 0x42, 0xef, 0xa6, 0x18, 0x31, 0xf1, 0x49,
- 0xa4, 0xf9, 0xde, 0x6b, 0x72, 0xa7, 0xee, 0x71, 0x6e, 0x7e, 0xb9, 0xc7, 0xff, 0x56, 0x83, 0xe5,
- 0xa4, 0x12, 0x18, 0x4a, 0xc1, 0x49, 0x79, 0x4a, 0x69, 0x6e, 0xbe, 0x2e, 0xfb, 0x74, 0x6b, 0xf9,
- 0xbb, 0xfe, 0x71, 0xfd, 0x5f, 0xbf, 0x5c, 0xd3, 0xfe, 0xe3, 0xcb, 0x35, 0xed, 0xbf, 0xbf, 0x5c,
- 0xd3, 0xfe, 0xee, 0x7f, 0xd6, 0xe6, 0x4e, 0xf3, 0xec, 0x3f, 0x1a, 0x7f, 0xfb, 0x37, 0x01, 0x00,
- 0x00, 0xff, 0xff, 0xee, 0x4f, 0x63, 0x90, 0xed, 0x3c, 0x00, 0x00,
+ // 4110 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0xdd, 0x73, 0x1b, 0xc9,
+ 0x71, 0xe7, 0x02, 0x24, 0x01, 0x34, 0x3e, 0x08, 0x0e, 0x29, 0x0a, 0xc2, 0x49, 0x14, 0x6f, 0x74,
+ 0xd2, 0xf1, 0xa4, 0x3b, 0xe2, 0x4c, 0xdb, 0xb9, 0x2a, 0x25, 0x71, 0x0c, 0x91, 0x38, 0x89, 0x47,
+ 0x8a, 0xe4, 0x2d, 0x21, 0xdd, 0x47, 0xb9, 0xc2, 0x5a, 0x02, 0x23, 0x72, 0x43, 0x60, 0x17, 0xde,
+ 0x5d, 0x40, 0xe4, 0xe5, 0xc3, 0x2e, 0x97, 0xe3, 0x4a, 0x5e, 0xed, 0xaa, 0x54, 0xf2, 0x90, 0xbc,
+ 0xa4, 0x52, 0x2e, 0x3f, 0xf8, 0x39, 0xff, 0x42, 0x9e, 0xf2, 0x51, 0xf9, 0x07, 0x52, 0x17, 0xbf,
+ 0x24, 0x7f, 0x85, 0x6b, 0xbe, 0x76, 0x67, 0xf6, 0x83, 0x92, 0x8d, 0xbb, 0x7b, 0x11, 0x31, 0x3d,
+ 0x3d, 0xfd, 0xeb, 0xe9, 0x99, 0xe9, 0xee, 0xe9, 0x59, 0x41, 0xc9, 0x1b, 0xf5, 0x36, 0x46, 0x9e,
+ 0x1b, 0xb8, 0xa8, 0x42, 0x82, 0x5e, 0xdf, 0x27, 0xde, 0x84, 0x78, 0xa3, 0x93, 0xe6, 0xf2, 0xa9,
+ 0x7b, 0xea, 0xb2, 0x8e, 0x16, 0xfd, 0xc5, 0x79, 0x9a, 0x0d, 0xca, 0xd3, 0xb2, 0x46, 0x76, 0x6b,
+ 0x38, 0xe9, 0xf5, 0x46, 0x27, 0xad, 0xf3, 0x89, 0xe8, 0x69, 0x86, 0x3d, 0xd6, 0x38, 0x38, 0x1b,
+ 0x9d, 0xb0, 0x3f, 0xa2, 0xef, 0xe6, 0xa9, 0xeb, 0x9e, 0x0e, 0x08, 0xef, 0x75, 0x1c, 0x37, 0xb0,
+ 0x02, 0xdb, 0x75, 0x7c, 0xde, 0x8b, 0xff, 0xda, 0x80, 0x9a, 0x49, 0xfc, 0x91, 0xeb, 0xf8, 0xe4,
+ 0x09, 0xb1, 0xfa, 0xc4, 0x43, 0xb7, 0x00, 0x7a, 0x83, 0xb1, 0x1f, 0x10, 0xef, 0xd8, 0xee, 0x37,
+ 0x8c, 0x35, 0x63, 0x7d, 0xd6, 0x2c, 0x09, 0xca, 0x4e, 0x1f, 0xbd, 0x01, 0xa5, 0x21, 0x19, 0x9e,
+ 0xf0, 0xde, 0x1c, 0xeb, 0x2d, 0x72, 0xc2, 0x4e, 0x1f, 0x35, 0xa1, 0xe8, 0x91, 0x89, 0xed, 0xdb,
+ 0xae, 0xd3, 0xc8, 0xaf, 0x19, 0xeb, 0x79, 0x33, 0x6c, 0xd3, 0x81, 0x9e, 0xf5, 0x22, 0x38, 0x0e,
+ 0x88, 0x37, 0x6c, 0xcc, 0xf2, 0x81, 0x94, 0xd0, 0x25, 0xde, 0x10, 0xff, 0x74, 0x0e, 0x2a, 0xa6,
+ 0xe5, 0x9c, 0x12, 0x93, 0xfc, 0x70, 0x4c, 0xfc, 0x00, 0xd5, 0x21, 0x7f, 0x4e, 0x2e, 0x19, 0x7c,
+ 0xc5, 0xa4, 0x3f, 0xf9, 0x78, 0xe7, 0x94, 0x1c, 0x13, 0x87, 0x03, 0x57, 0xe8, 0x78, 0xe7, 0x94,
+ 0x74, 0x9c, 0x3e, 0x5a, 0x86, 0xb9, 0x81, 0x3d, 0xb4, 0x03, 0x81, 0xca, 0x1b, 0x9a, 0x3a, 0xb3,
+ 0x31, 0x75, 0xb6, 0x00, 0x7c, 0xd7, 0x0b, 0x8e, 0x5d, 0xaf, 0x4f, 0xbc, 0xc6, 0xdc, 0x9a, 0xb1,
+ 0x5e, 0xdb, 0x7c, 0x6b, 0x43, 0x5d, 0x86, 0x0d, 0x55, 0xa1, 0x8d, 0x23, 0xd7, 0x0b, 0x0e, 0x28,
+ 0xaf, 0x59, 0xf2, 0xe5, 0x4f, 0xf4, 0x21, 0x94, 0x99, 0x90, 0xc0, 0xf2, 0x4e, 0x49, 0xd0, 0x98,
+ 0x67, 0x52, 0xee, 0xbe, 0x42, 0x4a, 0x97, 0x31, 0x9b, 0x0c, 0x9e, 0xff, 0x46, 0x18, 0x2a, 0x3e,
+ 0xf1, 0x6c, 0x6b, 0x60, 0x7f, 0x61, 0x9d, 0x0c, 0x48, 0xa3, 0xb0, 0x66, 0xac, 0x17, 0x4d, 0x8d,
+ 0x46, 0xe7, 0x7f, 0x4e, 0x2e, 0xfd, 0x63, 0xd7, 0x19, 0x5c, 0x36, 0x8a, 0x8c, 0xa1, 0x48, 0x09,
+ 0x07, 0xce, 0xe0, 0x92, 0x2d, 0x9a, 0x3b, 0x76, 0x02, 0xde, 0x5b, 0x62, 0xbd, 0x25, 0x46, 0x61,
+ 0xdd, 0xeb, 0x50, 0x1f, 0xda, 0xce, 0xf1, 0xd0, 0xed, 0x1f, 0x87, 0x06, 0x01, 0x66, 0x90, 0xda,
+ 0xd0, 0x76, 0x9e, 0xba, 0x7d, 0x53, 0x9a, 0x85, 0x72, 0x5a, 0x17, 0x3a, 0x67, 0x59, 0x70, 0x5a,
+ 0x17, 0x2a, 0xe7, 0x06, 0x2c, 0x51, 0x99, 0x3d, 0x8f, 0x58, 0x01, 0x89, 0x98, 0x2b, 0x8c, 0x79,
+ 0x71, 0x68, 0x3b, 0x5b, 0xac, 0x47, 0xe3, 0xb7, 0x2e, 0x12, 0xfc, 0x55, 0xc1, 0x6f, 0x5d, 0xe8,
+ 0xfc, 0x78, 0x03, 0x4a, 0xa1, 0xcd, 0x51, 0x11, 0x66, 0xf7, 0x0f, 0xf6, 0x3b, 0xf5, 0x19, 0x04,
+ 0x30, 0xdf, 0x3e, 0xda, 0xea, 0xec, 0x6f, 0xd7, 0x0d, 0x54, 0x86, 0xc2, 0x76, 0x87, 0x37, 0x72,
+ 0xf8, 0x11, 0x40, 0x64, 0x5d, 0x54, 0x80, 0xfc, 0x6e, 0xe7, 0xb3, 0xfa, 0x0c, 0xe5, 0x79, 0xde,
+ 0x31, 0x8f, 0x76, 0x0e, 0xf6, 0xeb, 0x06, 0x1d, 0xbc, 0x65, 0x76, 0xda, 0xdd, 0x4e, 0x3d, 0x47,
+ 0x39, 0x9e, 0x1e, 0x6c, 0xd7, 0xf3, 0xa8, 0x04, 0x73, 0xcf, 0xdb, 0x7b, 0xcf, 0x3a, 0xf5, 0x59,
+ 0xfc, 0x0b, 0x03, 0xaa, 0x62, 0xbd, 0xf8, 0x99, 0x40, 0xdf, 0x81, 0xf9, 0x33, 0x76, 0x2e, 0xd8,
+ 0x56, 0x2c, 0x6f, 0xde, 0x8c, 0x2d, 0xae, 0x76, 0x76, 0x4c, 0xc1, 0x8b, 0x30, 0xe4, 0xcf, 0x27,
+ 0x7e, 0x23, 0xb7, 0x96, 0x5f, 0x2f, 0x6f, 0xd6, 0x37, 0xf8, 0x79, 0xdd, 0xd8, 0x25, 0x97, 0xcf,
+ 0xad, 0xc1, 0x98, 0x98, 0xb4, 0x13, 0x21, 0x98, 0x1d, 0xba, 0x1e, 0x61, 0x3b, 0xb6, 0x68, 0xb2,
+ 0xdf, 0x74, 0x1b, 0xb3, 0x45, 0x13, 0xbb, 0x95, 0x37, 0xf0, 0xaf, 0x0c, 0x80, 0xc3, 0x71, 0x90,
+ 0x7d, 0x34, 0x96, 0x61, 0x6e, 0x42, 0x05, 0x8b, 0x63, 0xc1, 0x1b, 0xec, 0x4c, 0x10, 0xcb, 0x27,
+ 0xe1, 0x99, 0xa0, 0x0d, 0x74, 0x1d, 0x0a, 0x23, 0x8f, 0x4c, 0x8e, 0xcf, 0x27, 0x0c, 0xa4, 0x68,
+ 0xce, 0xd3, 0xe6, 0xee, 0x04, 0xbd, 0x09, 0x15, 0xfb, 0xd4, 0x71, 0x3d, 0x72, 0xcc, 0x65, 0xcd,
+ 0xb1, 0xde, 0x32, 0xa7, 0x31, 0xbd, 0x15, 0x16, 0x2e, 0x78, 0x5e, 0x65, 0xd9, 0xa3, 0x24, 0xec,
+ 0x40, 0x99, 0xa9, 0x3a, 0x95, 0xf9, 0xde, 0x89, 0x74, 0xcc, 0xb1, 0x61, 0x49, 0x13, 0x0a, 0xad,
+ 0xf1, 0x0f, 0x00, 0x6d, 0x93, 0x01, 0x09, 0xc8, 0x34, 0xde, 0x43, 0xb1, 0x49, 0x5e, 0xb5, 0x09,
+ 0xfe, 0xb9, 0x01, 0x4b, 0x9a, 0xf8, 0xa9, 0xa6, 0xd5, 0x80, 0x42, 0x9f, 0x09, 0xe3, 0x1a, 0xe4,
+ 0x4d, 0xd9, 0x44, 0x0f, 0xa0, 0x28, 0x14, 0xf0, 0x1b, 0xf9, 0x8c, 0x4d, 0x53, 0xe0, 0x3a, 0xf9,
+ 0xf8, 0x57, 0x39, 0x28, 0x89, 0x89, 0x1e, 0x8c, 0x50, 0x1b, 0xaa, 0x1e, 0x6f, 0x1c, 0xb3, 0xf9,
+ 0x08, 0x8d, 0x9a, 0xd9, 0x4e, 0xe8, 0xc9, 0x8c, 0x59, 0x11, 0x43, 0x18, 0x19, 0xfd, 0x21, 0x94,
+ 0xa5, 0x88, 0xd1, 0x38, 0x10, 0x26, 0x6f, 0xe8, 0x02, 0xa2, 0xfd, 0xf7, 0x64, 0xc6, 0x04, 0xc1,
+ 0x7e, 0x38, 0x0e, 0x50, 0x17, 0x96, 0xe5, 0x60, 0x3e, 0x1b, 0xa1, 0x46, 0x9e, 0x49, 0x59, 0xd3,
+ 0xa5, 0x24, 0x97, 0xea, 0xc9, 0x8c, 0x89, 0xc4, 0x78, 0xa5, 0x53, 0x55, 0x29, 0xb8, 0xe0, 0xce,
+ 0x3b, 0xa1, 0x52, 0xf7, 0xc2, 0x49, 0xaa, 0xd4, 0xbd, 0x70, 0x1e, 0x95, 0xa0, 0x20, 0x5a, 0xf8,
+ 0x5f, 0x73, 0x00, 0x72, 0x35, 0x0e, 0x46, 0x68, 0x1b, 0x6a, 0x9e, 0x68, 0x69, 0xd6, 0x7a, 0x23,
+ 0xd5, 0x5a, 0x62, 0x11, 0x67, 0xcc, 0xaa, 0x1c, 0xc4, 0x95, 0xfb, 0x1e, 0x54, 0x42, 0x29, 0x91,
+ 0xc1, 0x6e, 0xa4, 0x18, 0x2c, 0x94, 0x50, 0x96, 0x03, 0xa8, 0xc9, 0x3e, 0x81, 0x6b, 0xe1, 0xf8,
+ 0x14, 0x9b, 0xbd, 0x79, 0x85, 0xcd, 0x42, 0x81, 0x4b, 0x52, 0x82, 0x6a, 0x35, 0x55, 0xb1, 0xc8,
+ 0x6c, 0x37, 0x52, 0xcc, 0x96, 0x54, 0x8c, 0x1a, 0x0e, 0x68, 0xbc, 0xe4, 0x4d, 0xfc, 0x7f, 0x79,
+ 0x28, 0x6c, 0xb9, 0xc3, 0x91, 0xe5, 0xd1, 0xd5, 0x98, 0xf7, 0x88, 0x3f, 0x1e, 0x04, 0xcc, 0x5c,
+ 0xb5, 0xcd, 0x3b, 0xba, 0x44, 0xc1, 0x26, 0xff, 0x9a, 0x8c, 0xd5, 0x14, 0x43, 0xe8, 0x60, 0x11,
+ 0x1e, 0x73, 0xaf, 0x31, 0x58, 0x04, 0x47, 0x31, 0x44, 0x1e, 0xe4, 0x7c, 0x74, 0x90, 0x9b, 0x50,
+ 0x98, 0x10, 0x2f, 0x0a, 0xe9, 0x4f, 0x66, 0x4c, 0x49, 0x40, 0xef, 0xc0, 0x42, 0x3c, 0xbc, 0xcc,
+ 0x09, 0x9e, 0x5a, 0x4f, 0x8f, 0x46, 0x77, 0xa0, 0xa2, 0xc5, 0xb8, 0x79, 0xc1, 0x57, 0x1e, 0x2a,
+ 0x21, 0x6e, 0x45, 0xfa, 0x55, 0x1a, 0x8f, 0x2b, 0x4f, 0x66, 0xa4, 0x67, 0x5d, 0x91, 0x9e, 0xb5,
+ 0x28, 0x46, 0x09, 0xdf, 0xaa, 0x39, 0x99, 0xef, 0xeb, 0x4e, 0x06, 0x7f, 0x1f, 0xaa, 0x9a, 0x81,
+ 0x68, 0xdc, 0xe9, 0x7c, 0xfc, 0xac, 0xbd, 0xc7, 0x83, 0xd4, 0x63, 0x16, 0x97, 0xcc, 0xba, 0x41,
+ 0x63, 0xdd, 0x5e, 0xe7, 0xe8, 0xa8, 0x9e, 0x43, 0x55, 0x28, 0xed, 0x1f, 0x74, 0x8f, 0x39, 0x57,
+ 0x1e, 0x3f, 0x0e, 0x25, 0x88, 0x20, 0xa7, 0xc4, 0xb6, 0x19, 0x25, 0xb6, 0x19, 0x32, 0xb6, 0xe5,
+ 0xa2, 0xd8, 0xc6, 0xc2, 0xdc, 0x5e, 0xa7, 0x7d, 0xd4, 0xa9, 0xcf, 0x3e, 0xaa, 0x41, 0x85, 0xdb,
+ 0xf7, 0x78, 0xec, 0xd0, 0x50, 0xfb, 0xcf, 0x06, 0x40, 0x74, 0x9a, 0x50, 0x0b, 0x0a, 0x3d, 0x8e,
+ 0xd3, 0x30, 0x98, 0x33, 0xba, 0x96, 0xba, 0x64, 0xa6, 0xe4, 0x42, 0xdf, 0x82, 0x82, 0x3f, 0xee,
+ 0xf5, 0x88, 0x2f, 0x43, 0xde, 0xf5, 0xb8, 0x3f, 0x14, 0xde, 0xca, 0x94, 0x7c, 0x74, 0xc8, 0x0b,
+ 0xcb, 0x1e, 0x8c, 0x59, 0x00, 0xbc, 0x7a, 0x88, 0xe0, 0xc3, 0xff, 0x60, 0x40, 0x59, 0xd9, 0xbc,
+ 0xbf, 0xa7, 0x13, 0xbe, 0x09, 0x25, 0xa6, 0x03, 0xe9, 0x0b, 0x37, 0x5c, 0x34, 0x23, 0x02, 0xfa,
+ 0x03, 0x28, 0xc9, 0x13, 0x20, 0x3d, 0x71, 0x23, 0x5d, 0xec, 0xc1, 0xc8, 0x8c, 0x58, 0xf1, 0x2e,
+ 0x2c, 0x32, 0xab, 0xf4, 0x68, 0x72, 0x2d, 0xed, 0xa8, 0xa6, 0x9f, 0x46, 0x2c, 0xfd, 0x6c, 0x42,
+ 0x71, 0x74, 0x76, 0xe9, 0xdb, 0x3d, 0x6b, 0x20, 0xb4, 0x08, 0xdb, 0xf8, 0x23, 0x40, 0xaa, 0xb0,
+ 0x69, 0xa6, 0x8b, 0xab, 0x50, 0x7e, 0x62, 0xf9, 0x67, 0x42, 0x25, 0xfc, 0x00, 0xaa, 0xb4, 0xb9,
+ 0xfb, 0xfc, 0x35, 0x74, 0x64, 0x97, 0x03, 0xc9, 0x3d, 0x95, 0xcd, 0x11, 0xcc, 0x9e, 0x59, 0xfe,
+ 0x19, 0x9b, 0x68, 0xd5, 0x64, 0xbf, 0xd1, 0x3b, 0x50, 0xef, 0xf1, 0x49, 0x1e, 0xc7, 0xae, 0x0c,
+ 0x0b, 0x82, 0x1e, 0x66, 0x82, 0x9f, 0x42, 0x85, 0xcf, 0xe1, 0xab, 0x56, 0x02, 0x2f, 0xc2, 0xc2,
+ 0x91, 0x63, 0x8d, 0xfc, 0x33, 0x57, 0x46, 0x37, 0x3a, 0xe9, 0x7a, 0x44, 0x9b, 0x0a, 0xf1, 0x6d,
+ 0x58, 0xf0, 0xc8, 0xd0, 0xb2, 0x1d, 0xdb, 0x39, 0x3d, 0x3e, 0xb9, 0x0c, 0x88, 0x2f, 0x2e, 0x4c,
+ 0xb5, 0x90, 0xfc, 0x88, 0x52, 0xa9, 0x6a, 0x27, 0x03, 0xf7, 0x44, 0xb8, 0x39, 0xf6, 0x1b, 0xff,
+ 0x2c, 0x07, 0x95, 0x4f, 0xac, 0xa0, 0x27, 0x97, 0x0e, 0xed, 0x40, 0x2d, 0x74, 0x6e, 0x8c, 0x22,
+ 0x74, 0x89, 0x85, 0x58, 0x36, 0x46, 0xa6, 0xd2, 0x32, 0x3a, 0x56, 0x7b, 0x2a, 0x81, 0x89, 0xb2,
+ 0x9c, 0x1e, 0x19, 0x84, 0xa2, 0x72, 0xd9, 0xa2, 0x18, 0xa3, 0x2a, 0x4a, 0x25, 0xa0, 0x03, 0xa8,
+ 0x8f, 0x3c, 0xf7, 0xd4, 0x23, 0xbe, 0x1f, 0x0a, 0xe3, 0x61, 0x0c, 0xa7, 0x08, 0x3b, 0x14, 0xac,
+ 0x91, 0xb8, 0x85, 0x91, 0x4e, 0x7a, 0xb4, 0x10, 0xe5, 0x33, 0xdc, 0x39, 0xfd, 0x57, 0x0e, 0x50,
+ 0x72, 0x52, 0xbf, 0x6b, 0x8a, 0x77, 0x17, 0x6a, 0x7e, 0x60, 0x79, 0x89, 0xcd, 0x56, 0x65, 0xd4,
+ 0xd0, 0xe3, 0xbf, 0x0d, 0xa1, 0x42, 0xc7, 0x8e, 0x1b, 0xd8, 0x2f, 0x2e, 0x45, 0x96, 0x5c, 0x93,
+ 0xe4, 0x7d, 0x46, 0x45, 0x1d, 0x28, 0xbc, 0xb0, 0x07, 0x01, 0xf1, 0xfc, 0xc6, 0xdc, 0x5a, 0x7e,
+ 0xbd, 0xb6, 0xf9, 0xe0, 0x55, 0xcb, 0xb0, 0xf1, 0x21, 0xe3, 0xef, 0x5e, 0x8e, 0x88, 0x29, 0xc7,
+ 0xaa, 0x99, 0xe7, 0xbc, 0x96, 0x8d, 0xdf, 0x80, 0xe2, 0x4b, 0x2a, 0x82, 0xde, 0xb2, 0x0b, 0x3c,
+ 0x59, 0x64, 0x6d, 0x7e, 0xc9, 0x7e, 0xe1, 0x59, 0xa7, 0x43, 0xe2, 0x04, 0xf2, 0x1e, 0x28, 0xdb,
+ 0xf8, 0x2e, 0x40, 0x04, 0x43, 0x5d, 0xfe, 0xfe, 0xc1, 0xe1, 0xb3, 0x6e, 0x7d, 0x06, 0x55, 0xa0,
+ 0xb8, 0x7f, 0xb0, 0xdd, 0xd9, 0xeb, 0xd0, 0xf8, 0x80, 0x5b, 0xd2, 0xa4, 0xda, 0x5a, 0xaa, 0x98,
+ 0x86, 0x86, 0x89, 0x57, 0x60, 0x39, 0x6d, 0x01, 0x69, 0x2e, 0x5a, 0x15, 0xbb, 0x74, 0xaa, 0xa3,
+ 0xa2, 0x42, 0xe7, 0xf4, 0xe9, 0x36, 0xa0, 0xc0, 0x77, 0x6f, 0x5f, 0x24, 0xe7, 0xb2, 0x49, 0x0d,
+ 0xc1, 0x37, 0x23, 0xe9, 0x8b, 0x55, 0x0a, 0xdb, 0xa9, 0xee, 0x65, 0x2e, 0xd5, 0xbd, 0xa0, 0x3b,
+ 0x50, 0x0d, 0x4f, 0x83, 0xe5, 0x8b, 0x5c, 0xa0, 0x64, 0x56, 0xe4, 0x46, 0xa7, 0x34, 0xcd, 0xe8,
+ 0x05, 0xdd, 0xe8, 0xe8, 0x2e, 0xcc, 0x93, 0x09, 0x71, 0x02, 0xbf, 0x51, 0x66, 0x11, 0xa3, 0x2a,
+ 0x73, 0xf7, 0x0e, 0xa5, 0x9a, 0xa2, 0x13, 0x7f, 0x17, 0x16, 0xd9, 0x1d, 0xe9, 0xb1, 0x67, 0x39,
+ 0xea, 0x65, 0xae, 0xdb, 0xdd, 0x13, 0xe6, 0xa6, 0x3f, 0x51, 0x0d, 0x72, 0x3b, 0xdb, 0xc2, 0x08,
+ 0xb9, 0x9d, 0x6d, 0xfc, 0x13, 0x03, 0x90, 0x3a, 0x6e, 0x2a, 0x3b, 0xc7, 0x84, 0x4b, 0xf8, 0x7c,
+ 0x04, 0xbf, 0x0c, 0x73, 0xc4, 0xf3, 0x5c, 0x8f, 0x59, 0xb4, 0x64, 0xf2, 0x06, 0x7e, 0x4b, 0xe8,
+ 0x60, 0x92, 0x89, 0x7b, 0x1e, 0x9e, 0x41, 0x2e, 0xcd, 0x08, 0x55, 0xdd, 0x85, 0x25, 0x8d, 0x6b,
+ 0xaa, 0xc8, 0xf5, 0x21, 0x2c, 0x30, 0x61, 0x5b, 0x67, 0xa4, 0x77, 0x3e, 0x72, 0x6d, 0x27, 0x81,
+ 0x47, 0x57, 0x2e, 0x72, 0xb0, 0x74, 0x1e, 0x7c, 0x62, 0x95, 0x90, 0xd8, 0xed, 0xee, 0xe1, 0xcf,
+ 0x60, 0x25, 0x26, 0x47, 0xaa, 0xff, 0x27, 0x50, 0xee, 0x85, 0x44, 0x5f, 0xe4, 0x3a, 0xb7, 0x74,
+ 0xe5, 0xe2, 0x43, 0xd5, 0x11, 0xf8, 0x00, 0xae, 0x27, 0x44, 0x4f, 0x35, 0xe7, 0xb7, 0xe1, 0x1a,
+ 0x13, 0xb8, 0x4b, 0xc8, 0xa8, 0x3d, 0xb0, 0x27, 0x99, 0x96, 0x1e, 0x89, 0x49, 0x29, 0x8c, 0x5f,
+ 0xef, 0xbe, 0xc0, 0x7f, 0x24, 0x10, 0xbb, 0xf6, 0x90, 0x74, 0xdd, 0xbd, 0x6c, 0xdd, 0x68, 0x34,
+ 0x3b, 0x27, 0x97, 0xbe, 0x48, 0x6b, 0xd8, 0x6f, 0xfc, 0x2f, 0x86, 0x30, 0x95, 0x3a, 0xfc, 0x6b,
+ 0xde, 0xc9, 0xab, 0x00, 0xa7, 0xf4, 0xc8, 0x90, 0x3e, 0xed, 0xe0, 0x15, 0x15, 0x85, 0x12, 0xea,
+ 0x49, 0xfd, 0x77, 0x45, 0xe8, 0xb9, 0x2c, 0xf6, 0x39, 0xfb, 0x27, 0xf4, 0x72, 0xb7, 0xa0, 0xcc,
+ 0x08, 0x47, 0x81, 0x15, 0x8c, 0xfd, 0xc4, 0x62, 0xfc, 0x95, 0xd8, 0xf6, 0x72, 0xd0, 0x54, 0xf3,
+ 0xfa, 0x16, 0xcc, 0xb3, 0xcb, 0x84, 0x4c, 0xa5, 0x6f, 0xa4, 0xec, 0x47, 0xae, 0x87, 0x29, 0x18,
+ 0xf1, 0xcf, 0x0c, 0x98, 0x7f, 0xca, 0x4a, 0xb0, 0x8a, 0x6a, 0xb3, 0x72, 0x2d, 0x1c, 0x6b, 0xc8,
+ 0x0b, 0x43, 0x25, 0x93, 0xfd, 0x66, 0xa9, 0x27, 0x21, 0xde, 0x33, 0x73, 0x8f, 0xa7, 0xb8, 0x25,
+ 0x33, 0x6c, 0x53, 0x9b, 0xf5, 0x06, 0x36, 0x71, 0x02, 0xd6, 0x3b, 0xcb, 0x7a, 0x15, 0x0a, 0xcd,
+ 0x9e, 0x6d, 0x7f, 0x8f, 0x58, 0x9e, 0x23, 0x8a, 0xa6, 0x45, 0x33, 0x22, 0xe0, 0x3d, 0xa8, 0x73,
+ 0x3d, 0xda, 0xfd, 0xbe, 0x92, 0x60, 0x86, 0x68, 0x46, 0x0c, 0x4d, 0x93, 0x96, 0x8b, 0x4b, 0xfb,
+ 0xa5, 0x01, 0x8b, 0x8a, 0xb8, 0xa9, 0xac, 0xfa, 0x2e, 0xcc, 0xf3, 0x22, 0xb5, 0xc8, 0x74, 0x96,
+ 0xf5, 0x51, 0x1c, 0xc6, 0x14, 0x3c, 0x68, 0x03, 0x0a, 0xfc, 0x97, 0xbc, 0x03, 0xa4, 0xb3, 0x4b,
+ 0x26, 0x7c, 0x17, 0x96, 0x04, 0x89, 0x0c, 0xdd, 0xb4, 0x83, 0xc1, 0x16, 0x03, 0xff, 0x05, 0x2c,
+ 0xeb, 0x6c, 0x53, 0x4d, 0x49, 0x51, 0x32, 0xf7, 0x3a, 0x4a, 0xb6, 0xa5, 0x92, 0xcf, 0x46, 0x7d,
+ 0x25, 0x8f, 0x8a, 0xef, 0x18, 0x75, 0xbd, 0x72, 0xfa, 0x7a, 0x45, 0x13, 0x90, 0x22, 0xbe, 0xd1,
+ 0x09, 0x7c, 0x20, 0xb7, 0xc3, 0x9e, 0xed, 0x87, 0x3e, 0x1c, 0x43, 0x65, 0x60, 0x3b, 0xc4, 0xf2,
+ 0x44, 0xe5, 0xdc, 0xe0, 0x95, 0x73, 0x95, 0x86, 0xbf, 0x00, 0xa4, 0x0e, 0xfc, 0x46, 0x95, 0xbe,
+ 0x27, 0x4d, 0x76, 0xe8, 0xb9, 0x43, 0x37, 0xd3, 0xec, 0xf8, 0x2f, 0xe1, 0x5a, 0x8c, 0xef, 0x1b,
+ 0x55, 0x73, 0x09, 0x16, 0xb7, 0x89, 0x4c, 0x68, 0xa4, 0xdb, 0xfb, 0x08, 0x90, 0x4a, 0x9c, 0x2a,
+ 0xb2, 0xb5, 0x60, 0xf1, 0xa9, 0x3b, 0xa1, 0x2e, 0x92, 0x52, 0x23, 0xdf, 0xc0, 0xeb, 0x10, 0xa1,
+ 0x29, 0xc2, 0x36, 0x05, 0x57, 0x07, 0x4c, 0x05, 0xfe, 0x1f, 0x06, 0x54, 0xda, 0x03, 0xcb, 0x1b,
+ 0x4a, 0xe0, 0xef, 0xc1, 0x3c, 0xbf, 0x5d, 0x8b, 0x82, 0xd6, 0x3d, 0x5d, 0x8c, 0xca, 0xcb, 0x1b,
+ 0x6d, 0x7e, 0x17, 0x17, 0xa3, 0xa8, 0xe2, 0xe2, 0xcd, 0x6b, 0x3b, 0xf6, 0x06, 0xb6, 0x8d, 0xde,
+ 0x83, 0x39, 0x8b, 0x0e, 0x61, 0xa1, 0xa8, 0x16, 0xaf, 0x6b, 0x30, 0x69, 0xec, 0x0e, 0xc0, 0xb9,
+ 0xf0, 0x77, 0xa0, 0xac, 0x20, 0xa0, 0x02, 0xe4, 0x1f, 0x77, 0x44, 0xc2, 0xde, 0xde, 0xea, 0xee,
+ 0x3c, 0xe7, 0x05, 0x9d, 0x1a, 0xc0, 0x76, 0x27, 0x6c, 0xe7, 0xf0, 0xa7, 0x62, 0x94, 0x70, 0xfb,
+ 0xaa, 0x3e, 0x46, 0x96, 0x3e, 0xb9, 0xd7, 0xd2, 0xe7, 0x02, 0xaa, 0x62, 0xfa, 0xd3, 0x86, 0x31,
+ 0x26, 0x2f, 0x23, 0x8c, 0x29, 0xca, 0x9b, 0x82, 0x11, 0xff, 0xda, 0x80, 0xfa, 0xb6, 0xfb, 0xd2,
+ 0x39, 0xf5, 0xac, 0x7e, 0x78, 0x4e, 0x3e, 0x8c, 0xad, 0xd4, 0x46, 0xac, 0x38, 0x1a, 0xe3, 0x8f,
+ 0x08, 0xb1, 0x15, 0x6b, 0x44, 0x65, 0x43, 0x1e, 0x0b, 0x65, 0x13, 0x7f, 0x00, 0x0b, 0xb1, 0x41,
+ 0xd4, 0xf6, 0xcf, 0xdb, 0x7b, 0x3b, 0xdb, 0xd4, 0xd6, 0xac, 0xb0, 0xd6, 0xd9, 0x6f, 0x3f, 0xda,
+ 0xeb, 0x88, 0x07, 0xa4, 0xf6, 0xfe, 0x56, 0x67, 0xaf, 0x9e, 0xc3, 0x3d, 0x58, 0x54, 0xe0, 0xa7,
+ 0x7d, 0x19, 0xc8, 0xd0, 0x6e, 0x01, 0xaa, 0x22, 0xda, 0x8b, 0x43, 0xf9, 0xef, 0x39, 0xa8, 0x49,
+ 0xca, 0xd7, 0x83, 0x89, 0x56, 0x60, 0xbe, 0x7f, 0x72, 0x64, 0x7f, 0x21, 0x5f, 0x8e, 0x44, 0x8b,
+ 0xd2, 0x07, 0x1c, 0x87, 0x3f, 0xdf, 0x8a, 0x16, 0x0d, 0xe3, 0x9e, 0xf5, 0x22, 0xd8, 0x71, 0xfa,
+ 0xe4, 0x82, 0x25, 0x05, 0xb3, 0x66, 0x44, 0x60, 0x15, 0x26, 0xf1, 0xcc, 0xcb, 0x6e, 0x56, 0xca,
+ 0xb3, 0x2f, 0xba, 0x0f, 0x75, 0xfa, 0xbb, 0x3d, 0x1a, 0x0d, 0x6c, 0xd2, 0xe7, 0x02, 0x0a, 0x8c,
+ 0x27, 0x41, 0xa7, 0xe8, 0xec, 0x2e, 0xe2, 0x37, 0x8a, 0x2c, 0x2c, 0x89, 0x16, 0x5a, 0x83, 0x32,
+ 0xd7, 0x6f, 0xc7, 0x79, 0xe6, 0x13, 0xf6, 0xf6, 0x99, 0x37, 0x55, 0x92, 0x9e, 0x66, 0x40, 0x3c,
+ 0xcd, 0x58, 0x82, 0xc5, 0xf6, 0x38, 0x38, 0xeb, 0x38, 0x34, 0x56, 0x48, 0x2b, 0x2f, 0x03, 0xa2,
+ 0xc4, 0x6d, 0xdb, 0x57, 0xa9, 0x82, 0x55, 0x5f, 0x90, 0x0e, 0x2c, 0x51, 0x22, 0x71, 0x02, 0xbb,
+ 0xa7, 0xc4, 0x55, 0x99, 0x79, 0x19, 0xb1, 0xcc, 0xcb, 0xf2, 0xfd, 0x97, 0xae, 0xd7, 0x17, 0x36,
+ 0x0f, 0xdb, 0xf8, 0x9f, 0x0c, 0x0e, 0xf9, 0xcc, 0xd7, 0xd2, 0xa7, 0xdf, 0x51, 0x0c, 0x7a, 0x1f,
+ 0x0a, 0xee, 0x88, 0xbd, 0xf0, 0x8b, 0x32, 0xcc, 0xca, 0x06, 0xff, 0x26, 0x60, 0x43, 0x08, 0x3e,
+ 0xe0, 0xbd, 0xa6, 0x64, 0x43, 0xf7, 0xa0, 0x76, 0x66, 0xf9, 0x67, 0xa4, 0x7f, 0x28, 0x65, 0xf2,
+ 0x9b, 0x5f, 0x8c, 0x8a, 0xd7, 0x23, 0xfd, 0x1e, 0x93, 0xe0, 0x0a, 0xfd, 0xf0, 0x03, 0xb8, 0x26,
+ 0x39, 0xc5, 0xeb, 0xc4, 0x15, 0xcc, 0x2f, 0xe1, 0x96, 0x64, 0xde, 0x3a, 0xb3, 0x9c, 0x53, 0x22,
+ 0x01, 0x7f, 0x5f, 0x0b, 0x24, 0xe7, 0x93, 0x4f, 0x9d, 0xcf, 0x23, 0x68, 0x84, 0xf3, 0x61, 0x37,
+ 0x6b, 0x77, 0xa0, 0x2a, 0x3a, 0xf6, 0xc5, 0x79, 0x2a, 0x99, 0xec, 0x37, 0xa5, 0x79, 0xee, 0x20,
+ 0x4c, 0xa5, 0xe9, 0x6f, 0xbc, 0x05, 0x37, 0xa4, 0x0c, 0x71, 0xe7, 0xd5, 0x85, 0x24, 0x14, 0x4f,
+ 0x13, 0x22, 0x0c, 0x4b, 0x87, 0x5e, 0xbd, 0xf0, 0x2a, 0xa7, 0xbe, 0x04, 0x4c, 0xa6, 0xa1, 0xc8,
+ 0xbc, 0xc6, 0x37, 0x25, 0x55, 0x4c, 0xc9, 0x96, 0x24, 0x99, 0x0a, 0x50, 0xc9, 0x62, 0xc1, 0x28,
+ 0x39, 0xb1, 0x60, 0x09, 0xd1, 0x3f, 0x80, 0xd5, 0x50, 0x09, 0x6a, 0xb7, 0x43, 0xe2, 0x0d, 0x6d,
+ 0xdf, 0x57, 0xea, 0xde, 0x69, 0x13, 0xbf, 0x07, 0xb3, 0x23, 0x22, 0x82, 0x50, 0x79, 0x13, 0xc9,
+ 0x4d, 0xa9, 0x0c, 0x66, 0xfd, 0xb8, 0x0f, 0xb7, 0xa5, 0x74, 0x6e, 0xd1, 0x54, 0xf1, 0x71, 0xa5,
+ 0x64, 0x35, 0x30, 0x97, 0x51, 0x0d, 0xcc, 0xc7, 0xde, 0x62, 0x3e, 0xe2, 0x86, 0x94, 0x67, 0x7e,
+ 0xaa, 0xe4, 0x62, 0x97, 0xdb, 0x34, 0x74, 0x15, 0x53, 0x09, 0xfb, 0x1b, 0xe1, 0x05, 0xbe, 0x2a,
+ 0x0f, 0x4f, 0xd8, 0x0c, 0xe5, 0x43, 0x87, 0x6c, 0xd2, 0xac, 0x99, 0x2e, 0x80, 0xa9, 0xd6, 0x42,
+ 0x67, 0x4d, 0x8d, 0x86, 0x4f, 0x60, 0x59, 0xf7, 0x6b, 0x53, 0xe9, 0xb2, 0x0c, 0x73, 0x81, 0x7b,
+ 0x4e, 0x64, 0xac, 0xe1, 0x0d, 0x69, 0xbb, 0xd0, 0xe7, 0x4d, 0x65, 0x3b, 0x2b, 0x12, 0xc6, 0x4e,
+ 0xc7, 0xb4, 0xfa, 0xd2, 0x8d, 0x25, 0xef, 0x40, 0xbc, 0x81, 0xf7, 0x61, 0x25, 0xee, 0xd9, 0xa6,
+ 0x52, 0xf9, 0x39, 0x3f, 0x4b, 0x69, 0xce, 0x6f, 0x2a, 0xb9, 0x1f, 0x47, 0x7e, 0x49, 0xf1, 0x6d,
+ 0x53, 0x89, 0x34, 0xa1, 0x99, 0xe6, 0xea, 0xbe, 0x8a, 0xa3, 0x13, 0x7a, 0xbe, 0xa9, 0x84, 0xf9,
+ 0x91, 0xb0, 0xe9, 0x97, 0x3f, 0x72, 0x57, 0xf9, 0x2b, 0xdd, 0x95, 0x38, 0x24, 0x91, 0x43, 0xfd,
+ 0x1a, 0x36, 0x9d, 0xc0, 0x88, 0x7c, 0xf9, 0xb4, 0x18, 0x34, 0x9c, 0x85, 0x18, 0xac, 0x21, 0x37,
+ 0xb6, 0x1a, 0x01, 0xa6, 0x5a, 0x8c, 0x4f, 0x22, 0x37, 0x9e, 0x08, 0x12, 0x53, 0x09, 0xfe, 0x14,
+ 0xd6, 0xb2, 0xe3, 0xc3, 0x34, 0x92, 0xef, 0xb7, 0xa0, 0x14, 0x5e, 0x86, 0x94, 0xef, 0xcd, 0xca,
+ 0x50, 0xd8, 0x3f, 0x38, 0x3a, 0x6c, 0x6f, 0x75, 0xf8, 0x07, 0x67, 0x5b, 0x07, 0xa6, 0xf9, 0xec,
+ 0xb0, 0x5b, 0xcf, 0x6d, 0xfe, 0x26, 0x0f, 0xb9, 0xdd, 0xe7, 0xe8, 0x33, 0x98, 0xe3, 0x5f, 0x5f,
+ 0x5c, 0xf1, 0xc9, 0x4d, 0xf3, 0xaa, 0x0f, 0x4c, 0xf0, 0xf5, 0x9f, 0xfc, 0xf7, 0x6f, 0x7e, 0x91,
+ 0x5b, 0xc4, 0x95, 0xd6, 0xe4, 0xdb, 0xad, 0xf3, 0x49, 0x8b, 0x85, 0xa9, 0x87, 0xc6, 0x7d, 0xf4,
+ 0x31, 0xe4, 0x0f, 0xc7, 0x01, 0xca, 0xfc, 0x14, 0xa7, 0x99, 0xfd, 0xcd, 0x09, 0xbe, 0xc6, 0x84,
+ 0x2e, 0x60, 0x10, 0x42, 0x47, 0xe3, 0x80, 0x8a, 0xfc, 0x21, 0x94, 0xd5, 0x2f, 0x46, 0x5e, 0xf9,
+ 0x7d, 0x4e, 0xf3, 0xd5, 0x5f, 0xa3, 0xe0, 0x5b, 0x0c, 0xea, 0x3a, 0x46, 0x02, 0x8a, 0x7f, 0xd3,
+ 0xa2, 0xce, 0xa2, 0x7b, 0xe1, 0xa0, 0xcc, 0xaf, 0x77, 0x9a, 0xd9, 0x1f, 0xa8, 0x24, 0x66, 0x11,
+ 0x5c, 0x38, 0x54, 0xe4, 0x9f, 0x89, 0x6f, 0x53, 0x7a, 0x01, 0xba, 0x9d, 0xf2, 0x6d, 0x82, 0xfa,
+ 0x0a, 0xdf, 0x5c, 0xcb, 0x66, 0x10, 0x20, 0x37, 0x19, 0xc8, 0x0a, 0x5e, 0x14, 0x20, 0xbd, 0x90,
+ 0xe5, 0xa1, 0x71, 0x7f, 0xb3, 0x07, 0x73, 0xec, 0x85, 0x0b, 0x7d, 0x2e, 0x7f, 0x34, 0x53, 0x9e,
+ 0xfa, 0x32, 0x16, 0x5a, 0x7b, 0x1b, 0xc3, 0xcb, 0x0c, 0xa8, 0x86, 0x4b, 0x14, 0x88, 0xbd, 0x6f,
+ 0x3d, 0x34, 0xee, 0xaf, 0x1b, 0xef, 0x1b, 0x9b, 0xbf, 0x9e, 0x83, 0x39, 0x56, 0xda, 0x45, 0xe7,
+ 0x00, 0xd1, 0x6b, 0x4f, 0x7c, 0x76, 0x89, 0xf7, 0xa3, 0xf8, 0xec, 0x92, 0x0f, 0x45, 0xb8, 0xc9,
+ 0x40, 0x97, 0xf1, 0x02, 0x05, 0x65, 0x15, 0xe3, 0x16, 0x2b, 0x82, 0x53, 0x3b, 0xfe, 0xad, 0x21,
+ 0x2a, 0xdb, 0xfc, 0x2c, 0xa1, 0x34, 0x69, 0xda, 0x93, 0x4f, 0x7c, 0x3b, 0xa4, 0x3c, 0xf7, 0xe0,
+ 0xef, 0x32, 0xc0, 0x16, 0xae, 0x47, 0x80, 0x1e, 0xe3, 0x78, 0x68, 0xdc, 0xff, 0xbc, 0x81, 0x97,
+ 0x84, 0x95, 0x63, 0x3d, 0xe8, 0x47, 0x50, 0xd3, 0x9f, 0x34, 0xd0, 0x9d, 0x14, 0xac, 0xf8, 0xcb,
+ 0x48, 0xf3, 0xad, 0xab, 0x99, 0x84, 0x4e, 0xab, 0x4c, 0x27, 0x01, 0xce, 0x91, 0xcf, 0x09, 0x19,
+ 0x59, 0x94, 0x49, 0xac, 0x01, 0xfa, 0x47, 0x43, 0xbc, 0x38, 0x45, 0x6f, 0x14, 0x28, 0x4d, 0x7a,
+ 0xe2, 0x05, 0xa4, 0x79, 0xf7, 0x15, 0x5c, 0x42, 0x89, 0x3f, 0x66, 0x4a, 0x7c, 0x80, 0x97, 0x23,
+ 0x25, 0x02, 0x7b, 0x48, 0x02, 0x57, 0x68, 0xf1, 0xf9, 0x4d, 0x7c, 0x5d, 0x33, 0x8e, 0xd6, 0x1b,
+ 0x2d, 0x16, 0x7f, 0x67, 0x48, 0x5d, 0x2c, 0xed, 0xdd, 0x22, 0x75, 0xb1, 0xf4, 0x47, 0x8a, 0xb4,
+ 0xc5, 0xe2, 0xaf, 0x0a, 0x69, 0x8b, 0x15, 0xf6, 0x6c, 0xfe, 0xff, 0x2c, 0x14, 0xb6, 0xf8, 0x37,
+ 0xe1, 0xc8, 0x85, 0x52, 0x58, 0xa6, 0x47, 0xab, 0x69, 0x75, 0xc6, 0xe8, 0x5a, 0xd3, 0xbc, 0x9d,
+ 0xd9, 0x2f, 0x14, 0x7a, 0x93, 0x29, 0xf4, 0x06, 0x5e, 0xa1, 0xc8, 0xe2, 0xb3, 0xf3, 0x16, 0x2f,
+ 0x66, 0xb5, 0xac, 0x7e, 0x9f, 0x1a, 0xe2, 0xcf, 0xa1, 0xa2, 0xd6, 0xd1, 0xd1, 0x9b, 0xa9, 0xb5,
+ 0x4d, 0xb5, 0x14, 0xdf, 0xc4, 0x57, 0xb1, 0x08, 0xe4, 0xb7, 0x18, 0xf2, 0x2a, 0xbe, 0x91, 0x82,
+ 0xec, 0x31, 0x56, 0x0d, 0x9c, 0xd7, 0xc0, 0xd3, 0xc1, 0xb5, 0x12, 0x7b, 0x3a, 0xb8, 0x5e, 0x42,
+ 0xbf, 0x12, 0x7c, 0xcc, 0x58, 0x29, 0xb8, 0x0f, 0x10, 0x55, 0xb2, 0x51, 0xaa, 0x2d, 0x95, 0x7b,
+ 0x5d, 0xdc, 0x39, 0x24, 0x8b, 0xe0, 0x18, 0x33, 0x58, 0xb1, 0xef, 0x62, 0xb0, 0x03, 0xdb, 0x0f,
+ 0xf8, 0xc1, 0xac, 0x6a, 0xa5, 0x69, 0x94, 0x3a, 0x1f, 0xbd, 0xbe, 0xdd, 0xbc, 0x73, 0x25, 0x8f,
+ 0x40, 0xbf, 0xcb, 0xd0, 0x6f, 0xe3, 0x66, 0x0a, 0xfa, 0x88, 0xf3, 0xd2, 0xcd, 0xf6, 0xe3, 0x02,
+ 0x94, 0x9f, 0x5a, 0xb6, 0x13, 0x10, 0xc7, 0x72, 0x7a, 0x04, 0x9d, 0xc0, 0x1c, 0x8b, 0xd4, 0x71,
+ 0x47, 0xac, 0x96, 0x6d, 0xe3, 0x8e, 0x58, 0xab, 0x69, 0xe2, 0x35, 0x06, 0xdc, 0xc4, 0xd7, 0x28,
+ 0xf0, 0x30, 0x12, 0xdd, 0x62, 0xa5, 0x48, 0x3a, 0xe9, 0x17, 0x30, 0x2f, 0x5e, 0xfb, 0x62, 0x82,
+ 0xb4, 0xe2, 0x4f, 0xf3, 0x66, 0x7a, 0x67, 0xda, 0x5e, 0x56, 0x61, 0x7c, 0xc6, 0x47, 0x71, 0x26,
+ 0x00, 0x51, 0x8d, 0x3d, 0xbe, 0xa2, 0x89, 0x92, 0x7c, 0x73, 0x2d, 0x9b, 0x21, 0xcd, 0xa6, 0x2a,
+ 0x66, 0x3f, 0xe4, 0xa5, 0xb8, 0x7f, 0x0a, 0xb3, 0x4f, 0x2c, 0xff, 0x0c, 0xc5, 0x62, 0xaf, 0xf2,
+ 0xad, 0x58, 0xb3, 0x99, 0xd6, 0x25, 0x50, 0x6e, 0x33, 0x94, 0x1b, 0xdc, 0x95, 0xa9, 0x28, 0x67,
+ 0x96, 0x7f, 0x26, 0xec, 0xc7, 0x3f, 0x1d, 0x8b, 0xdb, 0x4f, 0xfb, 0xfc, 0x2c, 0x6e, 0x3f, 0xfd,
+ 0x6b, 0xb3, 0x6c, 0xfb, 0x51, 0x94, 0xf3, 0x09, 0xc5, 0x19, 0x41, 0x51, 0x7e, 0xad, 0x85, 0x62,
+ 0x4f, 0xf7, 0xb1, 0x2f, 0xbb, 0x9a, 0xab, 0x59, 0xdd, 0x02, 0xed, 0x0e, 0x43, 0xbb, 0x85, 0x1b,
+ 0x89, 0xd5, 0x12, 0x9c, 0x0f, 0x8d, 0xfb, 0xef, 0x1b, 0xe8, 0x47, 0x00, 0xd1, 0xc3, 0x44, 0xe2,
+ 0x0c, 0xc6, 0xdf, 0x38, 0x12, 0x67, 0x30, 0xf1, 0xa6, 0x81, 0x37, 0x18, 0xee, 0x3a, 0xbe, 0x13,
+ 0xc7, 0x0d, 0x3c, 0xcb, 0xf1, 0x5f, 0x10, 0xef, 0x3d, 0x5e, 0x67, 0xf5, 0xcf, 0xec, 0x11, 0x9d,
+ 0xb2, 0x07, 0xa5, 0xb0, 0xee, 0x1c, 0xf7, 0xb7, 0xf1, 0x7a, 0x78, 0xdc, 0xdf, 0x26, 0x0a, 0xd6,
+ 0xba, 0xe3, 0xd1, 0xf6, 0x8b, 0x64, 0xa5, 0x47, 0xf0, 0x97, 0x75, 0x98, 0xa5, 0x79, 0x37, 0x4d,
+ 0x4f, 0xa2, 0xca, 0x49, 0x7c, 0xf6, 0x89, 0x3a, 0x6a, 0x7c, 0xf6, 0xc9, 0xa2, 0x8b, 0x9e, 0x9e,
+ 0xd0, 0x6b, 0x56, 0x8b, 0x17, 0x29, 0xe8, 0x4c, 0x5d, 0x28, 0x2b, 0xa5, 0x15, 0x94, 0x22, 0x4c,
+ 0x2f, 0xd0, 0xc6, 0x03, 0x5e, 0x4a, 0x5d, 0x06, 0xbf, 0xc1, 0xf0, 0xae, 0xf1, 0x80, 0xc7, 0xf0,
+ 0xfa, 0x9c, 0x83, 0x02, 0x8a, 0xd9, 0x89, 0x93, 0x9f, 0x32, 0x3b, 0xfd, 0xf4, 0xaf, 0x65, 0x33,
+ 0x64, 0xce, 0x2e, 0x3a, 0xfa, 0x2f, 0xa1, 0xa2, 0x16, 0x58, 0x50, 0x8a, 0xf2, 0xb1, 0xa2, 0x72,
+ 0x3c, 0x92, 0xa4, 0xd5, 0x67, 0x74, 0xdf, 0xc6, 0x20, 0x2d, 0x85, 0x8d, 0x02, 0x0f, 0xa0, 0x20,
+ 0x2a, 0x2e, 0x69, 0x26, 0xd5, 0x0b, 0xd0, 0x69, 0x26, 0x8d, 0x95, 0x6b, 0xf4, 0xfc, 0x99, 0x21,
+ 0xd2, 0x4b, 0xa5, 0x8c, 0xd6, 0x02, 0xed, 0x31, 0x09, 0xb2, 0xd0, 0xa2, 0x5a, 0x66, 0x16, 0x9a,
+ 0x72, 0xa1, 0xcf, 0x42, 0x3b, 0x25, 0x81, 0xf0, 0x07, 0xf2, 0xa2, 0x8c, 0x32, 0x84, 0xa9, 0x11,
+ 0x12, 0x5f, 0xc5, 0x92, 0x76, 0xbd, 0x89, 0x00, 0x65, 0x78, 0xbc, 0x00, 0x88, 0xea, 0x41, 0xf1,
+ 0x9c, 0x35, 0xb5, 0x0e, 0x1e, 0xcf, 0x59, 0xd3, 0x4b, 0x4a, 0xba, 0x8f, 0x8d, 0x70, 0xf9, 0xed,
+ 0x8a, 0x22, 0xff, 0xdc, 0x00, 0x94, 0x2c, 0x1d, 0xa1, 0x07, 0xe9, 0xd2, 0x53, 0xab, 0xeb, 0xcd,
+ 0x77, 0x5f, 0x8f, 0x39, 0xcd, 0x21, 0x47, 0x2a, 0xf5, 0x18, 0xf7, 0xe8, 0x25, 0x55, 0xea, 0xc7,
+ 0x06, 0x54, 0xb5, 0xba, 0x13, 0xba, 0x97, 0xb1, 0xa6, 0xb1, 0xa2, 0x7b, 0xf3, 0xed, 0x57, 0xf2,
+ 0xa5, 0x25, 0xf3, 0xca, 0x0e, 0x90, 0xb7, 0x9a, 0x9f, 0x1a, 0x50, 0xd3, 0xeb, 0x54, 0x28, 0x43,
+ 0x76, 0xa2, 0x68, 0xdf, 0x5c, 0x7f, 0x35, 0xe3, 0xd5, 0xcb, 0x13, 0x5d, 0x68, 0x06, 0x50, 0x10,
+ 0x95, 0xad, 0xb4, 0x8d, 0xaf, 0x97, 0xfb, 0xd3, 0x36, 0x7e, 0xac, 0x2c, 0x96, 0xb2, 0xf1, 0x3d,
+ 0x77, 0x40, 0x94, 0x63, 0x26, 0x4a, 0x5f, 0x59, 0x68, 0x57, 0x1f, 0xb3, 0x58, 0xdd, 0x2c, 0x0b,
+ 0x2d, 0x3a, 0x66, 0xb2, 0xe6, 0x85, 0x32, 0x84, 0xbd, 0xe2, 0x98, 0xc5, 0x4b, 0x66, 0x29, 0xc7,
+ 0x8c, 0x01, 0x2a, 0xc7, 0x2c, 0xaa, 0x4e, 0xa5, 0x1d, 0xb3, 0xc4, 0xeb, 0x45, 0xda, 0x31, 0x4b,
+ 0x16, 0xb8, 0x52, 0xd6, 0x91, 0xe1, 0x6a, 0xc7, 0x6c, 0x29, 0xa5, 0x90, 0x85, 0xde, 0xcd, 0x30,
+ 0x62, 0xea, 0xa3, 0x48, 0xf3, 0xbd, 0xd7, 0xe4, 0xce, 0xdc, 0xe3, 0xdc, 0xfc, 0x72, 0x8f, 0xff,
+ 0x9d, 0x01, 0xcb, 0x69, 0x45, 0x30, 0x94, 0x81, 0x93, 0xf1, 0x98, 0xd2, 0xdc, 0x78, 0x5d, 0xf6,
+ 0xab, 0xad, 0x15, 0xee, 0xfa, 0x47, 0xf5, 0x7f, 0xfb, 0x72, 0xd5, 0xf8, 0xcf, 0x2f, 0x57, 0x8d,
+ 0xff, 0xf9, 0x72, 0xd5, 0xf8, 0xfb, 0xff, 0x5d, 0x9d, 0x39, 0x99, 0x67, 0xff, 0xd5, 0xf8, 0xdb,
+ 0xbf, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x54, 0x11, 0xdf, 0xef, 0x3c, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
diff --git a/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto b/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto
index 14391378ad..4ccc234744 100644
--- a/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto
+++ b/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto
@@ -217,7 +217,7 @@ service Maintenance {
// It only iterates "key" bucket in backend storage.
rpc HashKV(HashKVRequest) returns (HashKVResponse) {
option (google.api.http) = {
- post: "/v3/maintenance/hash"
+ post: "/v3/maintenance/hashkv"
body: "*"
};
}
diff --git a/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go b/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go
index ae112ae131..23201302e8 100644
--- a/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go
+++ b/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go
@@ -45,6 +45,7 @@ var (
ErrGRPCMemberNotLearner = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member").Err()
ErrGRPCLearnerNotReady = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member which is in sync with leader").Err()
ErrGRPCTooManyLearners = status.New(codes.FailedPrecondition, "etcdserver: too many learner members in cluster").Err()
+ ErrGRPCClusterIdMismatch = status.New(codes.FailedPrecondition, "etcdserver: cluster ID mismatch").Err()
ErrGRPCRequestTooLarge = status.New(codes.InvalidArgument, "etcdserver: request is too large").Err()
ErrGRPCRequestTooManyRequests = status.New(codes.ResourceExhausted, "etcdserver: too many requests").Err()
@@ -114,6 +115,7 @@ var (
ErrorDesc(ErrGRPCMemberNotLearner): ErrGRPCMemberNotLearner,
ErrorDesc(ErrGRPCLearnerNotReady): ErrGRPCLearnerNotReady,
ErrorDesc(ErrGRPCTooManyLearners): ErrGRPCTooManyLearners,
+ ErrorDesc(ErrGRPCClusterIdMismatch): ErrGRPCClusterIdMismatch,
ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge,
ErrorDesc(ErrGRPCRequestTooManyRequests): ErrGRPCRequestTooManyRequests,
@@ -200,6 +202,7 @@ var (
ErrInvalidAuthToken = Error(ErrGRPCInvalidAuthToken)
ErrAuthOldRevision = Error(ErrGRPCAuthOldRevision)
ErrInvalidAuthMgmt = Error(ErrGRPCInvalidAuthMgmt)
+ ErrClusterIdMismatch = Error(ErrGRPCClusterIdMismatch)
ErrNoLeader = Error(ErrGRPCNoLeader)
ErrNotLeader = Error(ErrGRPCNotLeader)
diff --git a/vendor/go.etcd.io/etcd/api/v3/version/version.go b/vendor/go.etcd.io/etcd/api/v3/version/version.go
index d62f6474d9..1819ead729 100644
--- a/vendor/go.etcd.io/etcd/api/v3/version/version.go
+++ b/vendor/go.etcd.io/etcd/api/v3/version/version.go
@@ -26,7 +26,7 @@ import (
var (
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
MinClusterVersion = "3.0.0"
- Version = "3.5.9"
+ Version = "3.5.10"
APIVersion = "unknown"
// Git SHA Value will be set during build
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/pathutil/path.go b/vendor/go.etcd.io/etcd/client/pkg/v3/pathutil/path.go
new file mode 100644
index 0000000000..f26254ba93
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/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/go.etcd.io/etcd/client/pkg/v3/srv/srv.go b/vendor/go.etcd.io/etcd/client/pkg/v3/srv/srv.go
new file mode 100644
index 0000000000..948c683490
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/srv/srv.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 srv looks up DNS SRV records.
+package srv
+
+import (
+ "fmt"
+ "net"
+ "net/url"
+ "strings"
+
+ "go.etcd.io/etcd/client/pkg/v3/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(serviceScheme, 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
+ }
+
+ err := updateNodeMap(service, serviceScheme)
+ if err != nil {
+ return nil, fmt.Errorf("error querying DNS SRV records for _%s %s", service, err)
+ }
+ 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, serviceName 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(GetSRVService(service, serviceName, "https"), "https")
+ errHTTP := updateURLs(GetSRVService(service, serviceName, "http"), "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
+}
+
+// GetSRVService generates a SRV service including an optional suffix.
+func GetSRVService(service, serviceName string, scheme string) (SRVService string) {
+ if scheme == "https" {
+ service = fmt.Sprintf("%s-ssl", service)
+ }
+
+ if serviceName != "" {
+ return fmt.Sprintf("%s-%s", service, serviceName)
+ }
+ return service
+}
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/assert.go b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/assert.go
new file mode 100644
index 0000000000..e8e042021e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/assert.go
@@ -0,0 +1,67 @@
+// 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 testutil
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+)
+
+func AssertEqual(t *testing.T, e, a interface{}, msg ...string) {
+ t.Helper()
+ if (e == nil || a == nil) && (isNil(e) && isNil(a)) {
+ return
+ }
+ if reflect.DeepEqual(e, a) {
+ return
+ }
+ s := ""
+ if len(msg) > 1 {
+ s = msg[0] + ": "
+ }
+ s = fmt.Sprintf("%sexpected %+v, got %+v", s, e, a)
+ FatalStack(t, s)
+}
+
+func AssertNil(t *testing.T, v interface{}) {
+ t.Helper()
+ AssertEqual(t, nil, v)
+}
+
+func AssertNotNil(t *testing.T, v interface{}) {
+ t.Helper()
+ if v == nil {
+ t.Fatalf("expected non-nil, got %+v", v)
+ }
+}
+
+func AssertTrue(t *testing.T, v bool, msg ...string) {
+ t.Helper()
+ AssertEqual(t, true, v, msg...)
+}
+
+func AssertFalse(t *testing.T, v bool, msg ...string) {
+ t.Helper()
+ AssertEqual(t, false, v, msg...)
+}
+
+func isNil(v interface{}) bool {
+ if v == nil {
+ return true
+ }
+ rv := reflect.ValueOf(v)
+ return rv.Kind() != reflect.Struct && rv.IsNil()
+}
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/leak.go b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/leak.go
new file mode 100644
index 0000000000..e9ffbd0ffe
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/leak.go
@@ -0,0 +1,181 @@
+// Copyright 2013 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 testutil
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+ "regexp"
+ "runtime"
+ "sort"
+ "strings"
+ "testing"
+ "time"
+)
+
+// TODO: Replace with https://github.com/uber-go/goleak.
+
+/*
+CheckLeakedGoroutine verifies tests do not leave any leaky
+goroutines. It returns true when there are goroutines still
+running(leaking) after all tests.
+
+ import "go.etcd.io/etcd/client/pkg/v3/testutil"
+
+ func TestMain(m *testing.M) {
+ testutil.MustTestMainWithLeakDetection(m)
+ }
+
+ func TestSample(t *testing.T) {
+ RegisterLeakDetection(t)
+ ...
+ }
+*/
+func CheckLeakedGoroutine() bool {
+ gs := interestingGoroutines()
+ if len(gs) == 0 {
+ return false
+ }
+
+ stackCount := make(map[string]int)
+ re := regexp.MustCompile(`\(0[0-9a-fx, ]*\)`)
+ for _, g := range gs {
+ // strip out pointer arguments in first function of stack dump
+ normalized := string(re.ReplaceAll([]byte(g), []byte("(...)")))
+ stackCount[normalized]++
+ }
+
+ fmt.Fprintf(os.Stderr, "Unexpected goroutines running after all test(s).\n")
+ for stack, count := range stackCount {
+ fmt.Fprintf(os.Stderr, "%d instances of:\n%s\n", count, stack)
+ }
+ return true
+}
+
+// CheckAfterTest returns an error if AfterTest would fail with an error.
+// Waits for go-routines shutdown for 'd'.
+func CheckAfterTest(d time.Duration) error {
+ http.DefaultTransport.(*http.Transport).CloseIdleConnections()
+ var bad string
+ // Presence of these goroutines causes immediate test failure.
+ badSubstring := map[string]string{
+ ").writeLoop(": "a Transport",
+ "created by net/http/httptest.(*Server).Start": "an httptest.Server",
+ "timeoutHandler": "a TimeoutHandler",
+ "net.(*netFD).connect(": "a timing out dial",
+ ").noteClientGone(": "a closenotifier sender",
+ ").readLoop(": "a Transport",
+ ".grpc": "a gRPC resource",
+ ").sendCloseSubstream(": "a stream closing routine",
+ }
+
+ var stacks string
+ begin := time.Now()
+ for time.Since(begin) < d {
+ bad = ""
+ goroutines := interestingGoroutines()
+ if len(goroutines) == 0 {
+ return nil
+ }
+ stacks = strings.Join(goroutines, "\n\n")
+
+ for substr, what := range badSubstring {
+ if strings.Contains(stacks, substr) {
+ bad = what
+ }
+ }
+ // Undesired goroutines found, but goroutines might just still be
+ // shutting down, so give it some time.
+ runtime.Gosched()
+ time.Sleep(50 * time.Millisecond)
+ }
+ return fmt.Errorf("appears to have leaked %s:\n%s", bad, stacks)
+}
+
+// RegisterLeakDetection is a convenient way to register before-and-after code to a test.
+// If you execute RegisterLeakDetection, you don't need to explicitly register AfterTest.
+func RegisterLeakDetection(t TB) {
+ if err := CheckAfterTest(10 * time.Millisecond); err != nil {
+ t.Skip("Found leaked goroutined BEFORE test", err)
+ return
+ }
+ t.Cleanup(func() {
+ afterTest(t)
+ })
+}
+
+// afterTest is meant to run in a defer that executes after a test completes.
+// It will detect common goroutine leaks, retrying in case there are goroutines
+// not synchronously torn down, and fail the test if any goroutines are stuck.
+func afterTest(t TB) {
+ // If test-failed the leaked goroutines list is hidding the real
+ // source of problem.
+ if !t.Failed() {
+ if err := CheckAfterTest(1 * time.Second); err != nil {
+ t.Errorf("Test %v", err)
+ }
+ }
+}
+
+func interestingGoroutines() (gs []string) {
+ buf := make([]byte, 2<<20)
+ buf = buf[:runtime.Stack(buf, true)]
+ for _, g := range strings.Split(string(buf), "\n\n") {
+ sl := strings.SplitN(g, "\n", 2)
+ if len(sl) != 2 {
+ continue
+ }
+ stack := strings.TrimSpace(sl[1])
+ if stack == "" ||
+ strings.Contains(stack, "sync.(*WaitGroup).Done") ||
+ strings.Contains(stack, "os.(*file).close") ||
+ strings.Contains(stack, "os.(*Process).Release") ||
+ strings.Contains(stack, "created by os/signal.init") ||
+ strings.Contains(stack, "runtime/panic.go") ||
+ strings.Contains(stack, "created by testing.RunTests") ||
+ strings.Contains(stack, "created by testing.runTests") ||
+ strings.Contains(stack, "created by testing.(*T).Run") ||
+ strings.Contains(stack, "testing.Main(") ||
+ strings.Contains(stack, "runtime.goexit") ||
+ strings.Contains(stack, "go.etcd.io/etcd/client/pkg/v3/testutil.interestingGoroutines") ||
+ strings.Contains(stack, "go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop") ||
+ strings.Contains(stack, "github.com/golang/glog.(*loggingT).flushDaemon") ||
+ strings.Contains(stack, "created by runtime.gc") ||
+ strings.Contains(stack, "created by text/template/parse.lex") ||
+ strings.Contains(stack, "runtime.MHeap_Scavenger") ||
+ strings.Contains(stack, "rcrypto/internal/boring.(*PublicKeyRSA).finalize") ||
+ strings.Contains(stack, "net.(*netFD).Close(") ||
+ strings.Contains(stack, "testing.(*T).Run") {
+ continue
+ }
+ gs = append(gs, stack)
+ }
+ sort.Strings(gs)
+ return gs
+}
+
+func MustCheckLeakedGoroutine() {
+ http.DefaultTransport.(*http.Transport).CloseIdleConnections()
+
+ CheckAfterTest(5 * time.Second)
+
+ // Let the other goroutines finalize.
+ runtime.Gosched()
+
+ if CheckLeakedGoroutine() {
+ os.Exit(1)
+ }
+}
+
+// MustTestMainWithLeakDetection expands standard m.Run with leaked
+// goroutines detection.
+func MustTestMainWithLeakDetection(m *testing.M) {
+ v := m.Run()
+ if v == 0 {
+ MustCheckLeakedGoroutine()
+ }
+ os.Exit(v)
+}
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/pauseable_handler.go b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/pauseable_handler.go
new file mode 100644
index 0000000000..e0d6aca26d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/pauseable_handler.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 testutil
+
+import (
+ "net/http"
+ "sync"
+)
+
+type PauseableHandler struct {
+ Next http.Handler
+ mu sync.Mutex
+ paused bool
+}
+
+func (ph *PauseableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ ph.mu.Lock()
+ paused := ph.paused
+ ph.mu.Unlock()
+ if !paused {
+ ph.Next.ServeHTTP(w, r)
+ } else {
+ hj, ok := w.(http.Hijacker)
+ if !ok {
+ panic("webserver doesn't support hijacking")
+ }
+ conn, _, err := hj.Hijack()
+ if err != nil {
+ panic(err.Error())
+ }
+ conn.Close()
+ }
+}
+
+func (ph *PauseableHandler) Pause() {
+ ph.mu.Lock()
+ defer ph.mu.Unlock()
+ ph.paused = true
+}
+
+func (ph *PauseableHandler) Resume() {
+ ph.mu.Lock()
+ defer ph.mu.Unlock()
+ ph.paused = false
+}
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/recorder.go b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/recorder.go
new file mode 100644
index 0000000000..41349fec52
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/recorder.go
@@ -0,0 +1,139 @@
+// 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 testutil
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+)
+
+type Action struct {
+ Name string
+ Params []interface{}
+}
+
+type Recorder interface {
+ // Record publishes an Action (e.g., function call) which will
+ // be reflected by Wait() or Chan()
+ Record(a Action)
+ // Wait waits until at least n Actions are available or returns with error
+ Wait(n int) ([]Action, error)
+ // Action returns immediately available Actions
+ Action() []Action
+ // Chan returns the channel for actions published by Record
+ Chan() <-chan Action
+}
+
+// RecorderBuffered appends all Actions to a slice
+type RecorderBuffered struct {
+ sync.Mutex
+ actions []Action
+}
+
+func (r *RecorderBuffered) Record(a Action) {
+ r.Lock()
+ r.actions = append(r.actions, a)
+ r.Unlock()
+}
+
+func (r *RecorderBuffered) Action() []Action {
+ r.Lock()
+ cpy := make([]Action, len(r.actions))
+ copy(cpy, r.actions)
+ r.Unlock()
+ return cpy
+}
+
+func (r *RecorderBuffered) Wait(n int) (acts []Action, err error) {
+ // legacy racey behavior
+ WaitSchedule()
+ acts = r.Action()
+ if len(acts) < n {
+ err = newLenErr(n, len(acts))
+ }
+ return acts, err
+}
+
+func (r *RecorderBuffered) Chan() <-chan Action {
+ ch := make(chan Action)
+ go func() {
+ acts := r.Action()
+ for i := range acts {
+ ch <- acts[i]
+ }
+ close(ch)
+ }()
+ return ch
+}
+
+// RecorderStream writes all Actions to an unbuffered channel
+type recorderStream struct {
+ ch chan Action
+ waitTimeout time.Duration
+}
+
+func NewRecorderStream() Recorder {
+ return NewRecorderStreamWithWaitTimout(time.Duration(5 * time.Second))
+}
+
+func NewRecorderStreamWithWaitTimout(waitTimeout time.Duration) Recorder {
+ return &recorderStream{ch: make(chan Action), waitTimeout: waitTimeout}
+}
+
+func (r *recorderStream) Record(a Action) {
+ r.ch <- a
+}
+
+func (r *recorderStream) Action() (acts []Action) {
+ for {
+ select {
+ case act := <-r.ch:
+ acts = append(acts, act)
+ default:
+ return acts
+ }
+ }
+}
+
+func (r *recorderStream) Chan() <-chan Action {
+ return r.ch
+}
+
+func (r *recorderStream) Wait(n int) ([]Action, error) {
+ acts := make([]Action, n)
+ timeoutC := time.After(r.waitTimeout)
+ for i := 0; i < n; i++ {
+ select {
+ case acts[i] = <-r.ch:
+ case <-timeoutC:
+ acts = acts[:i]
+ return acts, newLenErr(n, i)
+ }
+ }
+ // extra wait to catch any Action spew
+ select {
+ case act := <-r.ch:
+ acts = append(acts, act)
+ case <-time.After(10 * time.Millisecond):
+ }
+ return acts, nil
+}
+
+func newLenErr(expected int, actual int) error {
+ s := fmt.Sprintf("len(actions) = %d, expected >= %d", actual, expected)
+ return errors.New(s)
+}
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testingtb.go b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testingtb.go
new file mode 100644
index 0000000000..970542c040
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testingtb.go
@@ -0,0 +1,130 @@
+// Copyright 2021 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 testutil
+
+import (
+ "io/ioutil"
+ "log"
+ "os"
+)
+
+// TB is a subset of methods of testing.TB interface.
+// We cannot implement testing.TB due to protection, so we expose this simplified interface.
+type TB interface {
+ Cleanup(func())
+ Error(args ...interface{})
+ Errorf(format string, args ...interface{})
+ Fail()
+ FailNow()
+ Failed() bool
+ Fatal(args ...interface{})
+ Fatalf(format string, args ...interface{})
+ Logf(format string, args ...interface{})
+ Name() string
+ TempDir() string
+ Helper()
+ Skip(args ...interface{})
+}
+
+// NewTestingTBProthesis creates a fake variant of testing.TB implementation.
+// It's supposed to be used in contexts were real testing.T is not provided,
+// e.g. in 'examples'.
+//
+// The `closef` goroutine should get executed when tb will not be needed any longer.
+//
+// The provided implementation is NOT thread safe (Cleanup() method).
+func NewTestingTBProthesis(name string) (tb TB, closef func()) {
+ testtb := &testingTBProthesis{name: name}
+ return testtb, testtb.close
+}
+
+type testingTBProthesis struct {
+ name string
+ failed bool
+ cleanups []func()
+}
+
+func (t *testingTBProthesis) Helper() {
+ // Ignored
+}
+
+func (t *testingTBProthesis) Skip(args ...interface{}) {
+ t.Log(append([]interface{}{"Skipping due to: "}, args...))
+}
+
+func (t *testingTBProthesis) Cleanup(f func()) {
+ t.cleanups = append(t.cleanups, f)
+}
+
+func (t *testingTBProthesis) Error(args ...interface{}) {
+ log.Println(args...)
+ t.Fail()
+}
+
+func (t *testingTBProthesis) Errorf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+ t.Fail()
+}
+
+func (t *testingTBProthesis) Fail() {
+ t.failed = true
+}
+
+func (t *testingTBProthesis) FailNow() {
+ t.failed = true
+ panic("FailNow() called")
+}
+
+func (t *testingTBProthesis) Failed() bool {
+ return t.failed
+}
+
+func (t *testingTBProthesis) Fatal(args ...interface{}) {
+ log.Fatalln(args...)
+}
+
+func (t *testingTBProthesis) Fatalf(format string, args ...interface{}) {
+ log.Fatalf(format, args...)
+}
+
+func (t *testingTBProthesis) Logf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+}
+
+func (t *testingTBProthesis) Log(args ...interface{}) {
+ log.Println(args...)
+}
+
+func (t *testingTBProthesis) Name() string {
+ return t.name
+}
+
+func (t *testingTBProthesis) TempDir() string {
+ dir, err := ioutil.TempDir("", t.name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.cleanups = append([]func(){func() {
+ t.Logf("Cleaning UP: %v", dir)
+ os.RemoveAll(dir)
+ }}, t.cleanups...)
+ return dir
+}
+
+func (t *testingTBProthesis) close() {
+ for i := len(t.cleanups) - 1; i >= 0; i-- {
+ t.cleanups[i]()
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testutil.go b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testutil.go
new file mode 100644
index 0000000000..6dc55d0dfa
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/testutil.go
@@ -0,0 +1,106 @@
+// 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 testutil provides test utility functions.
+package testutil
+
+import (
+ "net/url"
+ "os"
+ "runtime"
+ "testing"
+ "time"
+)
+
+// WaitSchedule briefly sleeps in order to invoke the go scheduler.
+// TODO: improve this when we are able to know the schedule or status of target go-routine.
+func WaitSchedule() {
+ time.Sleep(10 * time.Millisecond)
+}
+
+func MustNewURLs(t *testing.T, urls []string) []url.URL {
+ if urls == nil {
+ return nil
+ }
+ var us []url.URL
+ for _, url := range urls {
+ u := MustNewURL(t, url)
+ us = append(us, *u)
+ }
+ return us
+}
+
+func MustNewURL(t *testing.T, s string) *url.URL {
+ u, err := url.Parse(s)
+ if err != nil {
+ t.Fatalf("parse %v error: %v", s, err)
+ }
+ return u
+}
+
+// FatalStack helps to fatal the test and print out the stacks of all running goroutines.
+func FatalStack(t *testing.T, s string) {
+ stackTrace := make([]byte, 1024*1024)
+ n := runtime.Stack(stackTrace, true)
+ t.Errorf("---> Test failed: %s", s)
+ t.Error(string(stackTrace[:n]))
+ t.Fatal(s)
+}
+
+// ConditionFunc returns true when a condition is met.
+type ConditionFunc func() (bool, error)
+
+// Poll calls a condition function repeatedly on a polling interval until it returns true, returns an error
+// or the timeout is reached. If the condition function returns true or an error before the timeout, Poll
+// immediately returns with the true value or the error. If the timeout is exceeded, Poll returns false.
+func Poll(interval time.Duration, timeout time.Duration, condition ConditionFunc) (bool, error) {
+ timeoutCh := time.After(timeout)
+ ticker := time.NewTicker(interval)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case <-timeoutCh:
+ return false, nil
+ case <-ticker.C:
+ success, err := condition()
+ if err != nil {
+ return false, err
+ }
+ if success {
+ return true, nil
+ }
+ }
+ }
+}
+
+func SkipTestIfShortMode(t TB, reason string) {
+ if t != nil {
+ t.Helper()
+ if testing.Short() {
+ t.Skip(reason)
+ }
+ }
+}
+
+// ExitInShortMode closes the current process (with 0) if the short test mode detected.
+//
+// To be used in Test-main, where test context (testing.TB) is not available.
+//
+// Requires custom env-variable (GOLANG_TEST_SHORT) apart of `go test --short flag`.
+func ExitInShortMode(reason string) {
+ if os.Getenv("GOLANG_TEST_SHORT") == "true" {
+ os.Exit(0)
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/var.go b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/var.go
new file mode 100644
index 0000000000..0c4c9fc6ee
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/testutil/var.go
@@ -0,0 +1,22 @@
+// 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 testutil
+
+import "time"
+
+var (
+ ApplyTimeout = time.Second
+ RequestTimeout = 3 * time.Second
+)
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go b/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go
index 38548ddd71..fe028c6132 100644
--- a/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go
@@ -21,12 +21,12 @@ type SocketOpts struct {
// in which case lock on data file could result in unexpected
// condition. User should take caution to protect against lock race.
// [1] https://man7.org/linux/man-pages/man7/socket.7.html
- ReusePort bool
+ ReusePort bool `json:"reuse-port"`
// ReuseAddress enables a socket option SO_REUSEADDR which allows
// binding to an address in `TIME_WAIT` state. Useful to improve MTTR
// in cases where etcd slow to restart due to excessive `TIME_WAIT`.
// [1] https://man7.org/linux/man-pages/man7/socket.7.html
- ReuseAddress bool
+ ReuseAddress bool `json:"reuse-address"`
}
func getControls(sopts *SocketOpts) Controls {
diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go b/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go
index 62fe0d3851..8c3a35b140 100644
--- a/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go
+++ b/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go
@@ -15,6 +15,7 @@
package transport
import (
+ "context"
"fmt"
"strings"
"time"
@@ -27,6 +28,8 @@ func ValidateSecureEndpoints(tlsInfo TLSInfo, eps []string) ([]string, error) {
if err != nil {
return nil, err
}
+ defer t.CloseIdleConnections()
+
var errs []string
var endpoints []string
for _, ep := range eps {
@@ -34,7 +37,7 @@ func ValidateSecureEndpoints(tlsInfo TLSInfo, eps []string) ([]string, error) {
errs = append(errs, fmt.Sprintf("%q is insecure", ep))
continue
}
- conn, cerr := t.Dial("tcp", ep[len("https://"):])
+ conn, cerr := t.DialContext(context.Background(), "tcp", ep[len("https://"):])
if cerr != nil {
errs = append(errs, fmt.Sprintf("%q failed to dial (%v)", ep, cerr))
continue
diff --git a/vendor/github.com/mwitkow/go-conntrack/LICENSE b/vendor/go.etcd.io/etcd/client/v2/LICENSE
similarity index 99%
rename from vendor/github.com/mwitkow/go-conntrack/LICENSE
rename to vendor/go.etcd.io/etcd/client/v2/LICENSE
index 8dada3edaf..d645695673 100644
--- a/vendor/github.com/mwitkow/go-conntrack/LICENSE
+++ b/vendor/go.etcd.io/etcd/client/v2/LICENSE
@@ -1,3 +1,4 @@
+
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@@ -178,7 +179,7 @@
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 "{}"
+ 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
@@ -186,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright {yyyy} {name of copyright owner}
+ 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.
diff --git a/vendor/go.etcd.io/etcd/client/v2/README.md b/vendor/go.etcd.io/etcd/client/v2/README.md
new file mode 100644
index 0000000000..5ecb67820f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/README.md
@@ -0,0 +1,112 @@
+# etcd/client
+
+etcd/client is the Go client library for etcd.
+
+[![GoDoc](https://godoc.org/go.etcd.io/etcd/client?status.png)](https://godoc.org/go.etcd.io/etcd/client)
+
+For full compatibility, it is recommended to install released versions of clients using go modules.
+
+## Install
+
+```bash
+go get go.etcd.io/etcd/v3/client
+```
+
+## Usage
+
+```go
+package main
+
+import (
+ "log"
+ "time"
+ "context"
+
+ "go.etcd.io/etcd/v3/client"
+)
+
+func main() {
+ cfg := client.Config{
+ Endpoints: []string{"http://127.0.0.1:2379"},
+ Transport: client.DefaultTransport,
+ // set timeout per request to fail fast when the target endpoint is unavailable
+ HeaderTimeoutPerRequest: time.Second,
+ }
+ c, err := client.New(cfg)
+ if err != nil {
+ log.Fatal(err)
+ }
+ kapi := client.NewKeysAPI(c)
+ // set "/foo" key with "bar" value
+ log.Print("Setting '/foo' key with 'bar' value")
+ resp, err := kapi.Set(context.Background(), "/foo", "bar", nil)
+ if err != nil {
+ log.Fatal(err)
+ } else {
+ // print common key info
+ log.Printf("Set is done. Metadata is %q\n", resp)
+ }
+ // get "/foo" key's value
+ log.Print("Getting '/foo' key value")
+ resp, err = kapi.Get(context.Background(), "/foo", nil)
+ if err != nil {
+ log.Fatal(err)
+ } else {
+ // print common key info
+ log.Printf("Get is done. Metadata is %q\n", resp)
+ // print value
+ log.Printf("%q key has %q value\n", resp.Node.Key, resp.Node.Value)
+ }
+}
+```
+
+## Error Handling
+
+etcd client might return three types of errors.
+
+- context error
+
+Each API call has its first parameter as `context`. A context can be canceled or have an attached deadline. If the context is canceled or reaches its deadline, the responding context error will be returned no matter what internal errors the API call has already encountered.
+
+- cluster error
+
+Each API call tries to send request to the cluster endpoints one by one until it successfully gets a response. If a requests to an endpoint fails, due to exceeding per request timeout or connection issues, the error will be added into a list of errors. If all possible endpoints fail, a cluster error that includes all encountered errors will be returned.
+
+- response error
+
+If the response gets from the cluster is invalid, a plain string error will be returned. For example, it might be a invalid JSON error.
+
+Here is the example code to handle client errors:
+
+```go
+cfg := client.Config{Endpoints: []string{"http://etcd1:2379","http://etcd2:2379","http://etcd3:2379"}}
+c, err := client.New(cfg)
+if err != nil {
+ log.Fatal(err)
+}
+
+kapi := client.NewKeysAPI(c)
+resp, err := kapi.Set(ctx, "test", "bar", nil)
+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 cerr, ok := err.(*client.ClusterError); ok {
+ // process (cerr.Errors)
+ } else {
+ // bad cluster endpoints, which are not etcd servers
+ }
+}
+```
+
+
+## Caveat
+
+1. etcd/client prefers to use the same endpoint as long as the endpoint continues to work well. This saves socket resources, and improves efficiency for both client and server side. This preference doesn't remove consistency from the data consumed by the client because data replicated to each etcd member has already passed through the consensus process.
+
+2. etcd/client does round-robin rotation on other available endpoints if the preferred endpoint isn't functioning properly. For example, if the member that etcd/client connects to is hard killed, etcd/client will fail on the first attempt with the killed member, and succeed on the second attempt with another member. If it fails to talk to all available endpoints, it will return all errors happened.
+
+3. Default etcd/client cannot handle the case that the remote server is SIGSTOPed now. TCP keepalive mechanism doesn't help in this scenario because operating system may still send TCP keep-alive packets. Over time we'd like to improve this functionality, but solving this issue isn't high priority because a real-life case in which a server is stopped, but the connection is kept alive, hasn't been brought to our attention.
+
+4. etcd/client cannot detect whether a member is healthy with watches and non-quorum read requests. If the member is isolated from the cluster, etcd/client may retrieve outdated data. Instead, users can either issue quorum read requests or monitor the /health endpoint for member health information.
diff --git a/vendor/go.etcd.io/etcd/client/v2/auth_role.go b/vendor/go.etcd.io/etcd/client/v2/auth_role.go
new file mode 100644
index 0000000000..b6ba7e150d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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/go.etcd.io/etcd/client/v2/auth_user.go b/vendor/go.etcd.io/etcd/client/v2/auth_user.go
new file mode 100644
index 0000000000..8e7e2efe83
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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/go.etcd.io/etcd/client/v2/cancelreq.go b/vendor/go.etcd.io/etcd/client/v2/cancelreq.go
new file mode 100644
index 0000000000..76d1f04019
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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/go.etcd.io/etcd/client/v2/client.go b/vendor/go.etcd.io/etcd/client/v2/client.go
new file mode 100644
index 0000000000..fda25988f6
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/client.go
@@ -0,0 +1,717 @@
+// 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"
+
+ "go.etcd.io/etcd/api/v3/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,
+ DialContext: (&net.Dialer{
+ Timeout: 30 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }).DialContext,
+ 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
+}
+
+// ErrNoRequest indicates that the HTTPRequest object could not be found
+// or was nil. No processing could continue.
+var ErrNoRequest = errors.New("no HTTPRequest was available")
+
+func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Response, []byte, error) {
+ req := act.HTTPRequest(c.endpoint)
+ if req == nil {
+ return nil, nil, ErrNoRequest
+ }
+
+ if err := printcURL(req); err != nil {
+ return nil, nil, err
+ }
+
+ isWait := false
+ if 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/go.etcd.io/etcd/client/v2/cluster_error.go b/vendor/go.etcd.io/etcd/client/v2/cluster_error.go
new file mode 100644
index 0000000000..34618cdbd9
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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/go.etcd.io/etcd/client/v2/curl.go b/vendor/go.etcd.io/etcd/client/v2/curl.go
new file mode 100644
index 0000000000..c8bc9fba20
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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/go.etcd.io/etcd/client/v2/discover.go b/vendor/go.etcd.io/etcd/client/v2/discover.go
new file mode 100644
index 0000000000..646ba5dada
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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 (
+ "go.etcd.io/etcd/client/pkg/v3/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, serviceName 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, serviceName string) ([]string, error) {
+ srvs, err := srv.GetClient("etcd-client", domain, serviceName)
+ if err != nil {
+ return nil, err
+ }
+ return srvs.Endpoints, nil
+}
diff --git a/vendor/go.etcd.io/etcd/client/v2/doc.go b/vendor/go.etcd.io/etcd/client/v2/doc.go
new file mode 100644
index 0000000000..68284c20a8
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/doc.go
@@ -0,0 +1,72 @@
+// 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"
+
+ "go.etcd.io/etcd/client/v2"
+ )
+
+ 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/go.etcd.io/etcd/client/v2/json.go b/vendor/go.etcd.io/etcd/client/v2/json.go
new file mode 100644
index 0000000000..d5be690a17
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/json.go
@@ -0,0 +1,73 @@
+// Copyright 2019 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 (
+ "strconv"
+ "unsafe"
+
+ "github.com/json-iterator/go"
+ "github.com/modern-go/reflect2"
+)
+
+type customNumberExtension struct {
+ jsoniter.DummyExtension
+}
+
+func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
+ if typ.String() == "interface {}" {
+ return customNumberDecoder{}
+ }
+ return nil
+}
+
+type customNumberDecoder struct {
+}
+
+func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+ switch iter.WhatIsNext() {
+ case jsoniter.NumberValue:
+ var number jsoniter.Number
+ iter.ReadVal(&number)
+ i64, err := strconv.ParseInt(string(number), 10, 64)
+ if err == nil {
+ *(*interface{})(ptr) = i64
+ return
+ }
+ f64, err := strconv.ParseFloat(string(number), 64)
+ if err == nil {
+ *(*interface{})(ptr) = f64
+ return
+ }
+ iter.ReportError("DecodeNumber", err.Error())
+ default:
+ *(*interface{})(ptr) = iter.Read()
+ }
+}
+
+// caseSensitiveJsonIterator returns a jsoniterator API that's configured to be
+// case-sensitive when unmarshalling, and otherwise compatible with
+// the encoding/json standard library.
+func caseSensitiveJsonIterator() jsoniter.API {
+ config := jsoniter.Config{
+ EscapeHTML: true,
+ SortMapKeys: true,
+ ValidateJsonRawMessage: true,
+ CaseSensitive: true,
+ }.Froze()
+ // Force jsoniter to decode number to interface{} via int64/float64, if possible.
+ config.RegisterExtension(&customNumberExtension{})
+ return config
+}
diff --git a/vendor/go.etcd.io/etcd/client/v2/keys.go b/vendor/go.etcd.io/etcd/client/v2/keys.go
new file mode 100644
index 0000000000..e8f1664617
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/keys.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 client
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/pathutil"
+)
+
+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
+}
+
+var jsonIterator = caseSensitiveJsonIterator()
+
+func unmarshalSuccessfulKeysResponse(header http.Header, body []byte) (*Response, error) {
+ var res Response
+ err := jsonIterator.Unmarshal(body, &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/go.etcd.io/etcd/client/v2/members.go b/vendor/go.etcd.io/etcd/client/v2/members.go
new file mode 100644
index 0000000000..5d638487c5
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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"
+
+ "go.etcd.io/etcd/client/pkg/v3/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/go.etcd.io/etcd/client/v2/util.go b/vendor/go.etcd.io/etcd/client/v2/util.go
new file mode 100644
index 0000000000..15a8babff4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v2/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/go.etcd.io/etcd/client/v3/client.go b/vendor/go.etcd.io/etcd/client/v3/client.go
index 4dfae89c61..efa44e8902 100644
--- a/vendor/go.etcd.io/etcd/client/v3/client.go
+++ b/vendor/go.etcd.io/etcd/client/v3/client.go
@@ -264,6 +264,7 @@ func (c *Client) getToken(ctx context.Context) error {
resp, err := c.Auth.Authenticate(ctx, c.Username, c.Password)
if err != nil {
if err == rpctypes.ErrAuthNotEnabled {
+ c.authTokenBundle.UpdateAuthToken("")
return nil
}
return err
@@ -501,7 +502,7 @@ func (c *Client) checkVersion() (err error) {
return
}
}
- if maj < 3 || (maj == 3 && min < 2) {
+ if maj < 3 || (maj == 3 && min < 4) {
rerr = ErrOldCluster
}
errc <- rerr
@@ -509,7 +510,7 @@ func (c *Client) checkVersion() (err error) {
}
// wait for success
for range eps {
- if err = <-errc; err == nil {
+ if err = <-errc; err != nil {
break
}
}
diff --git a/vendor/go.etcd.io/etcd/client/v3/concurrency/doc.go b/vendor/go.etcd.io/etcd/client/v3/concurrency/doc.go
new file mode 100644
index 0000000000..dcdbf511d1
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/concurrency/doc.go
@@ -0,0 +1,17 @@
+// 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 concurrency implements concurrency operations on top of
+// etcd such as distributed locks, barriers, and elections.
+package concurrency
diff --git a/vendor/go.etcd.io/etcd/client/v3/concurrency/election.go b/vendor/go.etcd.io/etcd/client/v3/concurrency/election.go
new file mode 100644
index 0000000000..31e93d2428
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/concurrency/election.go
@@ -0,0 +1,254 @@
+// 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 concurrency
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ v3 "go.etcd.io/etcd/client/v3"
+)
+
+var (
+ ErrElectionNotLeader = errors.New("election: not leader")
+ ErrElectionNoLeader = errors.New("election: no leader")
+)
+
+type Election struct {
+ session *Session
+
+ keyPrefix string
+
+ leaderKey string
+ leaderRev int64
+ leaderSession *Session
+ hdr *pb.ResponseHeader
+}
+
+// NewElection returns a new election on a given key prefix.
+func NewElection(s *Session, pfx string) *Election {
+ return &Election{session: s, keyPrefix: pfx + "/"}
+}
+
+// ResumeElection initializes an election with a known leader.
+func ResumeElection(s *Session, pfx string, leaderKey string, leaderRev int64) *Election {
+ return &Election{
+ keyPrefix: pfx,
+ session: s,
+ leaderKey: leaderKey,
+ leaderRev: leaderRev,
+ leaderSession: s,
+ }
+}
+
+// Campaign puts a value as eligible for the election on the prefix
+// key.
+// Multiple sessions can participate in the election for the
+// same prefix, but only one can be the leader at a time.
+//
+// If the context is 'context.TODO()/context.Background()', the Campaign
+// will continue to be blocked for other keys to be deleted, unless server
+// returns a non-recoverable error (e.g. ErrCompacted).
+// Otherwise, until the context is not cancelled or timed-out, Campaign will
+// continue to be blocked until it becomes the leader.
+func (e *Election) Campaign(ctx context.Context, val string) error {
+ s := e.session
+ client := e.session.Client()
+
+ k := fmt.Sprintf("%s%x", e.keyPrefix, s.Lease())
+ txn := client.Txn(ctx).If(v3.Compare(v3.CreateRevision(k), "=", 0))
+ txn = txn.Then(v3.OpPut(k, val, v3.WithLease(s.Lease())))
+ txn = txn.Else(v3.OpGet(k))
+ resp, err := txn.Commit()
+ if err != nil {
+ return err
+ }
+ e.leaderKey, e.leaderRev, e.leaderSession = k, resp.Header.Revision, s
+ if !resp.Succeeded {
+ kv := resp.Responses[0].GetResponseRange().Kvs[0]
+ e.leaderRev = kv.CreateRevision
+ if string(kv.Value) != val {
+ if err = e.Proclaim(ctx, val); err != nil {
+ e.Resign(ctx)
+ return err
+ }
+ }
+ }
+
+ _, err = waitDeletes(ctx, client, e.keyPrefix, e.leaderRev-1)
+ if err != nil {
+ // clean up in case of context cancel
+ select {
+ case <-ctx.Done():
+ e.Resign(client.Ctx())
+ default:
+ e.leaderSession = nil
+ }
+ return err
+ }
+ e.hdr = resp.Header
+
+ return nil
+}
+
+// Proclaim lets the leader announce a new value without another election.
+func (e *Election) Proclaim(ctx context.Context, val string) error {
+ if e.leaderSession == nil {
+ return ErrElectionNotLeader
+ }
+ client := e.session.Client()
+ cmp := v3.Compare(v3.CreateRevision(e.leaderKey), "=", e.leaderRev)
+ txn := client.Txn(ctx).If(cmp)
+ txn = txn.Then(v3.OpPut(e.leaderKey, val, v3.WithLease(e.leaderSession.Lease())))
+ tresp, terr := txn.Commit()
+ if terr != nil {
+ return terr
+ }
+ if !tresp.Succeeded {
+ e.leaderKey = ""
+ return ErrElectionNotLeader
+ }
+
+ e.hdr = tresp.Header
+ return nil
+}
+
+// Resign lets a leader start a new election.
+func (e *Election) Resign(ctx context.Context) (err error) {
+ if e.leaderSession == nil {
+ return nil
+ }
+ client := e.session.Client()
+ cmp := v3.Compare(v3.CreateRevision(e.leaderKey), "=", e.leaderRev)
+ resp, err := client.Txn(ctx).If(cmp).Then(v3.OpDelete(e.leaderKey)).Commit()
+ if err == nil {
+ e.hdr = resp.Header
+ }
+ e.leaderKey = ""
+ e.leaderSession = nil
+ return err
+}
+
+// Leader returns the leader value for the current election.
+func (e *Election) Leader(ctx context.Context) (*v3.GetResponse, error) {
+ client := e.session.Client()
+ resp, err := client.Get(ctx, e.keyPrefix, v3.WithFirstCreate()...)
+ if err != nil {
+ return nil, err
+ } else if len(resp.Kvs) == 0 {
+ // no leader currently elected
+ return nil, ErrElectionNoLeader
+ }
+ return resp, nil
+}
+
+// Observe returns a channel that reliably observes ordered leader proposals
+// as GetResponse values on every current elected leader key. It will not
+// necessarily fetch all historical leader updates, but will always post the
+// most recent leader value.
+//
+// The channel closes when the context is canceled or the underlying watcher
+// is otherwise disrupted.
+func (e *Election) Observe(ctx context.Context) <-chan v3.GetResponse {
+ retc := make(chan v3.GetResponse)
+ go e.observe(ctx, retc)
+ return retc
+}
+
+func (e *Election) observe(ctx context.Context, ch chan<- v3.GetResponse) {
+ client := e.session.Client()
+
+ defer close(ch)
+ for {
+ resp, err := client.Get(ctx, e.keyPrefix, v3.WithFirstCreate()...)
+ if err != nil {
+ return
+ }
+
+ var kv *mvccpb.KeyValue
+ var hdr *pb.ResponseHeader
+
+ if len(resp.Kvs) == 0 {
+ cctx, cancel := context.WithCancel(ctx)
+ // wait for first key put on prefix
+ opts := []v3.OpOption{v3.WithRev(resp.Header.Revision), v3.WithPrefix()}
+ wch := client.Watch(cctx, e.keyPrefix, opts...)
+ for kv == nil {
+ wr, ok := <-wch
+ if !ok || wr.Err() != nil {
+ cancel()
+ return
+ }
+ // only accept puts; a delete will make observe() spin
+ for _, ev := range wr.Events {
+ if ev.Type == mvccpb.PUT {
+ hdr, kv = &wr.Header, ev.Kv
+ // may have multiple revs; hdr.rev = the last rev
+ // set to kv's rev in case batch has multiple Puts
+ hdr.Revision = kv.ModRevision
+ break
+ }
+ }
+ }
+ cancel()
+ } else {
+ hdr, kv = resp.Header, resp.Kvs[0]
+ }
+
+ select {
+ case ch <- v3.GetResponse{Header: hdr, Kvs: []*mvccpb.KeyValue{kv}}:
+ case <-ctx.Done():
+ return
+ }
+
+ cctx, cancel := context.WithCancel(ctx)
+ wch := client.Watch(cctx, string(kv.Key), v3.WithRev(hdr.Revision+1))
+ keyDeleted := false
+ for !keyDeleted {
+ wr, ok := <-wch
+ if !ok {
+ cancel()
+ return
+ }
+ for _, ev := range wr.Events {
+ if ev.Type == mvccpb.DELETE {
+ keyDeleted = true
+ break
+ }
+ resp.Header = &wr.Header
+ resp.Kvs = []*mvccpb.KeyValue{ev.Kv}
+ select {
+ case ch <- *resp:
+ case <-cctx.Done():
+ cancel()
+ return
+ }
+ }
+ }
+ cancel()
+ }
+}
+
+// Key returns the leader key if elected, empty string otherwise.
+func (e *Election) Key() string { return e.leaderKey }
+
+// Rev returns the leader key's creation revision, if elected.
+func (e *Election) Rev() int64 { return e.leaderRev }
+
+// Header is the response header from the last successful election proposal.
+func (e *Election) Header() *pb.ResponseHeader { return e.hdr }
diff --git a/vendor/go.etcd.io/etcd/client/v3/concurrency/key.go b/vendor/go.etcd.io/etcd/client/v3/concurrency/key.go
new file mode 100644
index 0000000000..20825950f3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/concurrency/key.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.
+
+package concurrency
+
+import (
+ "context"
+ "fmt"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ v3 "go.etcd.io/etcd/client/v3"
+)
+
+func waitDelete(ctx context.Context, client *v3.Client, key string, rev int64) error {
+ cctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+
+ var wr v3.WatchResponse
+ wch := client.Watch(cctx, key, v3.WithRev(rev))
+ for wr = range wch {
+ for _, ev := range wr.Events {
+ if ev.Type == mvccpb.DELETE {
+ return nil
+ }
+ }
+ }
+ if err := wr.Err(); err != nil {
+ return err
+ }
+ if err := ctx.Err(); err != nil {
+ return err
+ }
+ return fmt.Errorf("lost watcher waiting for delete")
+}
+
+// waitDeletes efficiently waits until all keys matching the prefix and no greater
+// than the create revision.
+func waitDeletes(ctx context.Context, client *v3.Client, pfx string, maxCreateRev int64) (*pb.ResponseHeader, error) {
+ getOpts := append(v3.WithLastCreate(), v3.WithMaxCreateRev(maxCreateRev))
+ for {
+ resp, err := client.Get(ctx, pfx, getOpts...)
+ if err != nil {
+ return nil, err
+ }
+ if len(resp.Kvs) == 0 {
+ return resp.Header, nil
+ }
+ lastKey := string(resp.Kvs[0].Key)
+ if err = waitDelete(ctx, client, lastKey, resp.Header.Revision); err != nil {
+ return nil, err
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/concurrency/mutex.go b/vendor/go.etcd.io/etcd/client/v3/concurrency/mutex.go
new file mode 100644
index 0000000000..c3800d6282
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/concurrency/mutex.go
@@ -0,0 +1,167 @@
+// 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 concurrency
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "sync"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ v3 "go.etcd.io/etcd/client/v3"
+)
+
+// ErrLocked is returned by TryLock when Mutex is already locked by another session.
+var ErrLocked = errors.New("mutex: Locked by another session")
+var ErrSessionExpired = errors.New("mutex: session is expired")
+
+// Mutex implements the sync Locker interface with etcd
+type Mutex struct {
+ s *Session
+
+ pfx string
+ myKey string
+ myRev int64
+ hdr *pb.ResponseHeader
+}
+
+func NewMutex(s *Session, pfx string) *Mutex {
+ return &Mutex{s, pfx + "/", "", -1, nil}
+}
+
+// TryLock locks the mutex if not already locked by another session.
+// If lock is held by another session, return immediately after attempting necessary cleanup
+// The ctx argument is used for the sending/receiving Txn RPC.
+func (m *Mutex) TryLock(ctx context.Context) error {
+ resp, err := m.tryAcquire(ctx)
+ if err != nil {
+ return err
+ }
+ // if no key on prefix / the minimum rev is key, already hold the lock
+ ownerKey := resp.Responses[1].GetResponseRange().Kvs
+ if len(ownerKey) == 0 || ownerKey[0].CreateRevision == m.myRev {
+ m.hdr = resp.Header
+ return nil
+ }
+ client := m.s.Client()
+ // Cannot lock, so delete the key
+ if _, err := client.Delete(ctx, m.myKey); err != nil {
+ return err
+ }
+ m.myKey = "\x00"
+ m.myRev = -1
+ return ErrLocked
+}
+
+// Lock locks the mutex with a cancelable context. If the context is canceled
+// while trying to acquire the lock, the mutex tries to clean its stale lock entry.
+func (m *Mutex) Lock(ctx context.Context) error {
+ resp, err := m.tryAcquire(ctx)
+ if err != nil {
+ return err
+ }
+ // if no key on prefix / the minimum rev is key, already hold the lock
+ ownerKey := resp.Responses[1].GetResponseRange().Kvs
+ if len(ownerKey) == 0 || ownerKey[0].CreateRevision == m.myRev {
+ m.hdr = resp.Header
+ return nil
+ }
+ client := m.s.Client()
+ // wait for deletion revisions prior to myKey
+ // TODO: early termination if the session key is deleted before other session keys with smaller revisions.
+ _, werr := waitDeletes(ctx, client, m.pfx, m.myRev-1)
+ // release lock key if wait failed
+ if werr != nil {
+ m.Unlock(client.Ctx())
+ return werr
+ }
+
+ // make sure the session is not expired, and the owner key still exists.
+ gresp, werr := client.Get(ctx, m.myKey)
+ if werr != nil {
+ m.Unlock(client.Ctx())
+ return werr
+ }
+
+ if len(gresp.Kvs) == 0 { // is the session key lost?
+ return ErrSessionExpired
+ }
+ m.hdr = gresp.Header
+
+ return nil
+}
+
+func (m *Mutex) tryAcquire(ctx context.Context) (*v3.TxnResponse, error) {
+ s := m.s
+ client := m.s.Client()
+
+ m.myKey = fmt.Sprintf("%s%x", m.pfx, s.Lease())
+ cmp := v3.Compare(v3.CreateRevision(m.myKey), "=", 0)
+ // put self in lock waiters via myKey; oldest waiter holds lock
+ put := v3.OpPut(m.myKey, "", v3.WithLease(s.Lease()))
+ // reuse key in case this session already holds the lock
+ get := v3.OpGet(m.myKey)
+ // fetch current holder to complete uncontended path with only one RPC
+ getOwner := v3.OpGet(m.pfx, v3.WithFirstCreate()...)
+ resp, err := client.Txn(ctx).If(cmp).Then(put, getOwner).Else(get, getOwner).Commit()
+ if err != nil {
+ return nil, err
+ }
+ m.myRev = resp.Header.Revision
+ if !resp.Succeeded {
+ m.myRev = resp.Responses[0].GetResponseRange().Kvs[0].CreateRevision
+ }
+ return resp, nil
+}
+
+func (m *Mutex) Unlock(ctx context.Context) error {
+ client := m.s.Client()
+ if _, err := client.Delete(ctx, m.myKey); err != nil {
+ return err
+ }
+ m.myKey = "\x00"
+ m.myRev = -1
+ return nil
+}
+
+func (m *Mutex) IsOwner() v3.Cmp {
+ return v3.Compare(v3.CreateRevision(m.myKey), "=", m.myRev)
+}
+
+func (m *Mutex) Key() string { return m.myKey }
+
+// Header is the response header received from etcd on acquiring the lock.
+func (m *Mutex) Header() *pb.ResponseHeader { return m.hdr }
+
+type lockerMutex struct{ *Mutex }
+
+func (lm *lockerMutex) Lock() {
+ client := lm.s.Client()
+ if err := lm.Mutex.Lock(client.Ctx()); err != nil {
+ panic(err)
+ }
+}
+func (lm *lockerMutex) Unlock() {
+ client := lm.s.Client()
+ if err := lm.Mutex.Unlock(client.Ctx()); err != nil {
+ panic(err)
+ }
+}
+
+// NewLocker creates a sync.Locker backed by an etcd mutex.
+func NewLocker(s *Session, pfx string) sync.Locker {
+ return &lockerMutex{NewMutex(s, pfx)}
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/concurrency/session.go b/vendor/go.etcd.io/etcd/client/v3/concurrency/session.go
new file mode 100644
index 0000000000..7143cc4747
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/concurrency/session.go
@@ -0,0 +1,141 @@
+// 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 concurrency
+
+import (
+ "context"
+ "time"
+
+ v3 "go.etcd.io/etcd/client/v3"
+)
+
+const defaultSessionTTL = 60
+
+// Session represents a lease kept alive for the lifetime of a client.
+// Fault-tolerant applications may use sessions to reason about liveness.
+type Session struct {
+ client *v3.Client
+ opts *sessionOptions
+ id v3.LeaseID
+
+ cancel context.CancelFunc
+ donec <-chan struct{}
+}
+
+// NewSession gets the leased session for a client.
+func NewSession(client *v3.Client, opts ...SessionOption) (*Session, error) {
+ ops := &sessionOptions{ttl: defaultSessionTTL, ctx: client.Ctx()}
+ for _, opt := range opts {
+ opt(ops)
+ }
+
+ id := ops.leaseID
+ if id == v3.NoLease {
+ resp, err := client.Grant(ops.ctx, int64(ops.ttl))
+ if err != nil {
+ return nil, err
+ }
+ id = resp.ID
+ }
+
+ ctx, cancel := context.WithCancel(ops.ctx)
+ keepAlive, err := client.KeepAlive(ctx, id)
+ if err != nil || keepAlive == nil {
+ cancel()
+ return nil, err
+ }
+
+ donec := make(chan struct{})
+ s := &Session{client: client, opts: ops, id: id, cancel: cancel, donec: donec}
+
+ // keep the lease alive until client error or cancelled context
+ go func() {
+ defer close(donec)
+ for range keepAlive {
+ // eat messages until keep alive channel closes
+ }
+ }()
+
+ return s, nil
+}
+
+// Client is the etcd client that is attached to the session.
+func (s *Session) Client() *v3.Client {
+ return s.client
+}
+
+// Lease is the lease ID for keys bound to the session.
+func (s *Session) Lease() v3.LeaseID { return s.id }
+
+// Done returns a channel that closes when the lease is orphaned, expires, or
+// is otherwise no longer being refreshed.
+func (s *Session) Done() <-chan struct{} { return s.donec }
+
+// Orphan ends the refresh for the session lease. This is useful
+// in case the state of the client connection is indeterminate (revoke
+// would fail) or when transferring lease ownership.
+func (s *Session) Orphan() {
+ s.cancel()
+ <-s.donec
+}
+
+// Close orphans the session and revokes the session lease.
+func (s *Session) Close() error {
+ s.Orphan()
+ // if revoke takes longer than the ttl, lease is expired anyway
+ ctx, cancel := context.WithTimeout(s.opts.ctx, time.Duration(s.opts.ttl)*time.Second)
+ _, err := s.client.Revoke(ctx, s.id)
+ cancel()
+ return err
+}
+
+type sessionOptions struct {
+ ttl int
+ leaseID v3.LeaseID
+ ctx context.Context
+}
+
+// SessionOption configures Session.
+type SessionOption func(*sessionOptions)
+
+// WithTTL configures the session's TTL in seconds.
+// If TTL is <= 0, the default 60 seconds TTL will be used.
+func WithTTL(ttl int) SessionOption {
+ return func(so *sessionOptions) {
+ if ttl > 0 {
+ so.ttl = ttl
+ }
+ }
+}
+
+// WithLease specifies the existing leaseID to be used for the session.
+// This is useful in process restart scenario, for example, to reclaim
+// leadership from an election prior to restart.
+func WithLease(leaseID v3.LeaseID) SessionOption {
+ return func(so *sessionOptions) {
+ so.leaseID = leaseID
+ }
+}
+
+// WithContext assigns a context to the session instead of defaulting to
+// using the client context. This is useful for canceling NewSession and
+// Close operations immediately without having to close the client. If the
+// context is canceled before Close() completes, the session's lease will be
+// abandoned and left to expire instead of being revoked.
+func WithContext(ctx context.Context) SessionOption {
+ return func(so *sessionOptions) {
+ so.ctx = ctx
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/concurrency/stm.go b/vendor/go.etcd.io/etcd/client/v3/concurrency/stm.go
new file mode 100644
index 0000000000..ba7303d097
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/concurrency/stm.go
@@ -0,0 +1,387 @@
+// 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 concurrency
+
+import (
+ "context"
+ "math"
+
+ v3 "go.etcd.io/etcd/client/v3"
+)
+
+// STM is an interface for software transactional memory.
+type STM interface {
+ // Get returns the value for a key and inserts the key in the txn's read set.
+ // If Get fails, it aborts the transaction with an error, never returning.
+ Get(key ...string) string
+ // Put adds a value for a key to the write set.
+ Put(key, val string, opts ...v3.OpOption)
+ // Rev returns the revision of a key in the read set.
+ Rev(key string) int64
+ // Del deletes a key.
+ Del(key string)
+
+ // commit attempts to apply the txn's changes to the server.
+ commit() *v3.TxnResponse
+ reset()
+}
+
+// Isolation is an enumeration of transactional isolation levels which
+// describes how transactions should interfere and conflict.
+type Isolation int
+
+const (
+ // SerializableSnapshot provides serializable isolation and also checks
+ // for write conflicts.
+ SerializableSnapshot Isolation = iota
+ // Serializable reads within the same transaction attempt return data
+ // from the at the revision of the first read.
+ Serializable
+ // RepeatableReads reads within the same transaction attempt always
+ // return the same data.
+ RepeatableReads
+ // ReadCommitted reads keys from any committed revision.
+ ReadCommitted
+)
+
+// stmError safely passes STM errors through panic to the STM error channel.
+type stmError struct{ err error }
+
+type stmOptions struct {
+ iso Isolation
+ ctx context.Context
+ prefetch []string
+}
+
+type stmOption func(*stmOptions)
+
+// WithIsolation specifies the transaction isolation level.
+func WithIsolation(lvl Isolation) stmOption {
+ return func(so *stmOptions) { so.iso = lvl }
+}
+
+// WithAbortContext specifies the context for permanently aborting the transaction.
+func WithAbortContext(ctx context.Context) stmOption {
+ return func(so *stmOptions) { so.ctx = ctx }
+}
+
+// WithPrefetch is a hint to prefetch a list of keys before trying to apply.
+// If an STM transaction will unconditionally fetch a set of keys, prefetching
+// those keys will save the round-trip cost from requesting each key one by one
+// with Get().
+func WithPrefetch(keys ...string) stmOption {
+ return func(so *stmOptions) { so.prefetch = append(so.prefetch, keys...) }
+}
+
+// NewSTM initiates a new STM instance, using serializable snapshot isolation by default.
+func NewSTM(c *v3.Client, apply func(STM) error, so ...stmOption) (*v3.TxnResponse, error) {
+ opts := &stmOptions{ctx: c.Ctx()}
+ for _, f := range so {
+ f(opts)
+ }
+ if len(opts.prefetch) != 0 {
+ f := apply
+ apply = func(s STM) error {
+ s.Get(opts.prefetch...)
+ return f(s)
+ }
+ }
+ return runSTM(mkSTM(c, opts), apply)
+}
+
+func mkSTM(c *v3.Client, opts *stmOptions) STM {
+ switch opts.iso {
+ case SerializableSnapshot:
+ s := &stmSerializable{
+ stm: stm{client: c, ctx: opts.ctx},
+ prefetch: make(map[string]*v3.GetResponse),
+ }
+ s.conflicts = func() []v3.Cmp {
+ return append(s.rset.cmps(), s.wset.cmps(s.rset.first()+1)...)
+ }
+ return s
+ case Serializable:
+ s := &stmSerializable{
+ stm: stm{client: c, ctx: opts.ctx},
+ prefetch: make(map[string]*v3.GetResponse),
+ }
+ s.conflicts = func() []v3.Cmp { return s.rset.cmps() }
+ return s
+ case RepeatableReads:
+ s := &stm{client: c, ctx: opts.ctx, getOpts: []v3.OpOption{v3.WithSerializable()}}
+ s.conflicts = func() []v3.Cmp { return s.rset.cmps() }
+ return s
+ case ReadCommitted:
+ s := &stm{client: c, ctx: opts.ctx, getOpts: []v3.OpOption{v3.WithSerializable()}}
+ s.conflicts = func() []v3.Cmp { return nil }
+ return s
+ default:
+ panic("unsupported stm")
+ }
+}
+
+type stmResponse struct {
+ resp *v3.TxnResponse
+ err error
+}
+
+func runSTM(s STM, apply func(STM) error) (*v3.TxnResponse, error) {
+ outc := make(chan stmResponse, 1)
+ go func() {
+ defer func() {
+ if r := recover(); r != nil {
+ e, ok := r.(stmError)
+ if !ok {
+ // client apply panicked
+ panic(r)
+ }
+ outc <- stmResponse{nil, e.err}
+ }
+ }()
+ var out stmResponse
+ for {
+ s.reset()
+ if out.err = apply(s); out.err != nil {
+ break
+ }
+ if out.resp = s.commit(); out.resp != nil {
+ break
+ }
+ }
+ outc <- out
+ }()
+ r := <-outc
+ return r.resp, r.err
+}
+
+// stm implements repeatable-read software transactional memory over etcd
+type stm struct {
+ client *v3.Client
+ ctx context.Context
+ // rset holds read key values and revisions
+ rset readSet
+ // wset holds overwritten keys and their values
+ wset writeSet
+ // getOpts are the opts used for gets
+ getOpts []v3.OpOption
+ // conflicts computes the current conflicts on the txn
+ conflicts func() []v3.Cmp
+}
+
+type stmPut struct {
+ val string
+ op v3.Op
+}
+
+type readSet map[string]*v3.GetResponse
+
+func (rs readSet) add(keys []string, txnresp *v3.TxnResponse) {
+ for i, resp := range txnresp.Responses {
+ rs[keys[i]] = (*v3.GetResponse)(resp.GetResponseRange())
+ }
+}
+
+// first returns the store revision from the first fetch
+func (rs readSet) first() int64 {
+ ret := int64(math.MaxInt64 - 1)
+ for _, resp := range rs {
+ if rev := resp.Header.Revision; rev < ret {
+ ret = rev
+ }
+ }
+ return ret
+}
+
+// cmps guards the txn from updates to read set
+func (rs readSet) cmps() []v3.Cmp {
+ cmps := make([]v3.Cmp, 0, len(rs))
+ for k, rk := range rs {
+ cmps = append(cmps, isKeyCurrent(k, rk))
+ }
+ return cmps
+}
+
+type writeSet map[string]stmPut
+
+func (ws writeSet) get(keys ...string) *stmPut {
+ for _, key := range keys {
+ if wv, ok := ws[key]; ok {
+ return &wv
+ }
+ }
+ return nil
+}
+
+// cmps returns a cmp list testing no writes have happened past rev
+func (ws writeSet) cmps(rev int64) []v3.Cmp {
+ cmps := make([]v3.Cmp, 0, len(ws))
+ for key := range ws {
+ cmps = append(cmps, v3.Compare(v3.ModRevision(key), "<", rev))
+ }
+ return cmps
+}
+
+// puts is the list of ops for all pending writes
+func (ws writeSet) puts() []v3.Op {
+ puts := make([]v3.Op, 0, len(ws))
+ for _, v := range ws {
+ puts = append(puts, v.op)
+ }
+ return puts
+}
+
+func (s *stm) Get(keys ...string) string {
+ if wv := s.wset.get(keys...); wv != nil {
+ return wv.val
+ }
+ return respToValue(s.fetch(keys...))
+}
+
+func (s *stm) Put(key, val string, opts ...v3.OpOption) {
+ s.wset[key] = stmPut{val, v3.OpPut(key, val, opts...)}
+}
+
+func (s *stm) Del(key string) { s.wset[key] = stmPut{"", v3.OpDelete(key)} }
+
+func (s *stm) Rev(key string) int64 {
+ if resp := s.fetch(key); resp != nil && len(resp.Kvs) != 0 {
+ return resp.Kvs[0].ModRevision
+ }
+ return 0
+}
+
+func (s *stm) commit() *v3.TxnResponse {
+ txnresp, err := s.client.Txn(s.ctx).If(s.conflicts()...).Then(s.wset.puts()...).Commit()
+ if err != nil {
+ panic(stmError{err})
+ }
+ if txnresp.Succeeded {
+ return txnresp
+ }
+ return nil
+}
+
+func (s *stm) fetch(keys ...string) *v3.GetResponse {
+ if len(keys) == 0 {
+ return nil
+ }
+ ops := make([]v3.Op, len(keys))
+ for i, key := range keys {
+ if resp, ok := s.rset[key]; ok {
+ return resp
+ }
+ ops[i] = v3.OpGet(key, s.getOpts...)
+ }
+ txnresp, err := s.client.Txn(s.ctx).Then(ops...).Commit()
+ if err != nil {
+ panic(stmError{err})
+ }
+ s.rset.add(keys, txnresp)
+ return (*v3.GetResponse)(txnresp.Responses[0].GetResponseRange())
+}
+
+func (s *stm) reset() {
+ s.rset = make(map[string]*v3.GetResponse)
+ s.wset = make(map[string]stmPut)
+}
+
+type stmSerializable struct {
+ stm
+ prefetch map[string]*v3.GetResponse
+}
+
+func (s *stmSerializable) Get(keys ...string) string {
+ if wv := s.wset.get(keys...); wv != nil {
+ return wv.val
+ }
+ firstRead := len(s.rset) == 0
+ for _, key := range keys {
+ if resp, ok := s.prefetch[key]; ok {
+ delete(s.prefetch, key)
+ s.rset[key] = resp
+ }
+ }
+ resp := s.stm.fetch(keys...)
+ if firstRead {
+ // txn's base revision is defined by the first read
+ s.getOpts = []v3.OpOption{
+ v3.WithRev(resp.Header.Revision),
+ v3.WithSerializable(),
+ }
+ }
+ return respToValue(resp)
+}
+
+func (s *stmSerializable) Rev(key string) int64 {
+ s.Get(key)
+ return s.stm.Rev(key)
+}
+
+func (s *stmSerializable) gets() ([]string, []v3.Op) {
+ keys := make([]string, 0, len(s.rset))
+ ops := make([]v3.Op, 0, len(s.rset))
+ for k := range s.rset {
+ keys = append(keys, k)
+ ops = append(ops, v3.OpGet(k))
+ }
+ return keys, ops
+}
+
+func (s *stmSerializable) commit() *v3.TxnResponse {
+ keys, getops := s.gets()
+ txn := s.client.Txn(s.ctx).If(s.conflicts()...).Then(s.wset.puts()...)
+ // use Else to prefetch keys in case of conflict to save a round trip
+ txnresp, err := txn.Else(getops...).Commit()
+ if err != nil {
+ panic(stmError{err})
+ }
+ if txnresp.Succeeded {
+ return txnresp
+ }
+ // load prefetch with Else data
+ s.rset.add(keys, txnresp)
+ s.prefetch = s.rset
+ s.getOpts = nil
+ return nil
+}
+
+func isKeyCurrent(k string, r *v3.GetResponse) v3.Cmp {
+ if len(r.Kvs) != 0 {
+ return v3.Compare(v3.ModRevision(k), "=", r.Kvs[0].ModRevision)
+ }
+ return v3.Compare(v3.ModRevision(k), "=", 0)
+}
+
+func respToValue(resp *v3.GetResponse) string {
+ if resp == nil || len(resp.Kvs) == 0 {
+ return ""
+ }
+ return string(resp.Kvs[0].Value)
+}
+
+// NewSTMRepeatable is deprecated.
+func NewSTMRepeatable(ctx context.Context, c *v3.Client, apply func(STM) error) (*v3.TxnResponse, error) {
+ return NewSTM(c, apply, WithAbortContext(ctx), WithIsolation(RepeatableReads))
+}
+
+// NewSTMSerializable is deprecated.
+func NewSTMSerializable(ctx context.Context, c *v3.Client, apply func(STM) error) (*v3.TxnResponse, error) {
+ return NewSTM(c, apply, WithAbortContext(ctx), WithIsolation(Serializable))
+}
+
+// NewSTMReadCommitted is deprecated.
+func NewSTMReadCommitted(ctx context.Context, c *v3.Client, apply func(STM) error) (*v3.TxnResponse, error) {
+ return NewSTM(c, apply, WithAbortContext(ctx), WithIsolation(ReadCommitted))
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go b/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go
index f6674235cd..35a3fe8c33 100644
--- a/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go
+++ b/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go
@@ -41,10 +41,6 @@ func extractHostFromHostPort(ep string) string {
return host
}
-func extractHostFromPath(pathStr string) string {
- return extractHostFromHostPort(path.Base(pathStr))
-}
-
// mustSplit2 returns the values from strings.SplitN(s, sep, 2).
// If sep is not found, it returns ("", "", false) instead.
func mustSplit2(s, sep string) (string, string) {
@@ -96,29 +92,29 @@ func translateEndpoint(ep string) (addr string, serverName string, requireCreds
if strings.HasPrefix(ep, "unix:///") || strings.HasPrefix(ep, "unixs:///") {
// absolute path case
schema, absolutePath := mustSplit2(ep, "://")
- return "unix://" + absolutePath, extractHostFromPath(absolutePath), schemeToCredsRequirement(schema)
+ return "unix://" + absolutePath, path.Base(absolutePath), schemeToCredsRequirement(schema)
}
if strings.HasPrefix(ep, "unix://") || strings.HasPrefix(ep, "unixs://") {
// legacy etcd local path
schema, localPath := mustSplit2(ep, "://")
- return "unix:" + localPath, extractHostFromPath(localPath), schemeToCredsRequirement(schema)
+ return "unix:" + localPath, path.Base(localPath), schemeToCredsRequirement(schema)
}
schema, localPath := mustSplit2(ep, ":")
- return "unix:" + localPath, extractHostFromPath(localPath), schemeToCredsRequirement(schema)
+ return "unix:" + localPath, path.Base(localPath), schemeToCredsRequirement(schema)
}
if strings.Contains(ep, "://") {
url, err := url.Parse(ep)
if err != nil {
- return ep, extractHostFromHostPort(ep), CREDS_OPTIONAL
+ return ep, ep, CREDS_OPTIONAL
}
if url.Scheme == "http" || url.Scheme == "https" {
- return url.Host, url.Hostname(), schemeToCredsRequirement(url.Scheme)
+ return url.Host, url.Host, schemeToCredsRequirement(url.Scheme)
}
- return ep, url.Hostname(), schemeToCredsRequirement(url.Scheme)
+ return ep, url.Host, schemeToCredsRequirement(url.Scheme)
}
// Handles plain addresses like 10.0.0.44:437.
- return ep, extractHostFromHostPort(ep), CREDS_OPTIONAL
+ return ep, ep, CREDS_OPTIONAL
}
// RequiresCredentials returns whether given endpoint requires
diff --git a/vendor/go.etcd.io/etcd/client/v3/lease.go b/vendor/go.etcd.io/etcd/client/v3/lease.go
index 9e1b704648..19af9c093a 100644
--- a/vendor/go.etcd.io/etcd/client/v3/lease.go
+++ b/vendor/go.etcd.io/etcd/client/v3/lease.go
@@ -294,7 +294,9 @@ func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAl
}
l.mu.Unlock()
- go l.keepAliveCtxCloser(ctx, id, ka.donec)
+ if ctx.Done() != nil {
+ go l.keepAliveCtxCloser(ctx, id, ka.donec)
+ }
l.firstKeepAliveOnce.Do(func() {
go l.recvKeepAliveLoop()
go l.deadlineLoop()
diff --git a/vendor/go.etcd.io/etcd/client/v3/namespace/doc.go b/vendor/go.etcd.io/etcd/client/v3/namespace/doc.go
new file mode 100644
index 0000000000..689e0e0bb3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/namespace/doc.go
@@ -0,0 +1,42 @@
+// 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 namespace is a clientv3 wrapper that translates all keys to begin
+// with a given prefix.
+//
+// First, create a client:
+//
+// cli, err := clientv3.New(clientv3.Config{Endpoints: []string{"localhost:2379"}})
+// if err != nil {
+// // handle error!
+// }
+//
+// Next, override the client interfaces:
+//
+// unprefixedKV := cli.KV
+// cli.KV = namespace.NewKV(cli.KV, "my-prefix/")
+// cli.Watcher = namespace.NewWatcher(cli.Watcher, "my-prefix/")
+// cli.Lease = namespace.NewLease(cli.Lease, "my-prefix/")
+//
+// Now calls using 'cli' will namespace / prefix all keys with "my-prefix/":
+//
+// cli.Put(context.TODO(), "abc", "123")
+// resp, _ := unprefixedKV.Get(context.TODO(), "my-prefix/abc")
+// fmt.Printf("%s\n", resp.Kvs[0].Value)
+// // Output: 123
+// unprefixedKV.Put(context.TODO(), "my-prefix/abc", "456")
+// resp, _ = cli.Get(context.TODO(), "abc")
+// fmt.Printf("%s\n", resp.Kvs[0].Value)
+// // Output: 456
+package namespace
diff --git a/vendor/go.etcd.io/etcd/client/v3/namespace/kv.go b/vendor/go.etcd.io/etcd/client/v3/namespace/kv.go
new file mode 100644
index 0000000000..f745225cac
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/namespace/kv.go
@@ -0,0 +1,206 @@
+// 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 namespace
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/v3"
+)
+
+type kvPrefix struct {
+ clientv3.KV
+ pfx string
+}
+
+// NewKV wraps a KV instance so that all requests
+// are prefixed with a given string.
+func NewKV(kv clientv3.KV, prefix string) clientv3.KV {
+ return &kvPrefix{kv, prefix}
+}
+
+func (kv *kvPrefix) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
+ if len(key) == 0 {
+ return nil, rpctypes.ErrEmptyKey
+ }
+ op := kv.prefixOp(clientv3.OpPut(key, val, opts...))
+ r, err := kv.KV.Do(ctx, op)
+ if err != nil {
+ return nil, err
+ }
+ put := r.Put()
+ kv.unprefixPutResponse(put)
+ return put, nil
+}
+
+func (kv *kvPrefix) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
+ if len(key) == 0 && !(clientv3.IsOptsWithFromKey(opts) || clientv3.IsOptsWithPrefix(opts)) {
+ return nil, rpctypes.ErrEmptyKey
+ }
+ r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpGet(key, opts...)))
+ if err != nil {
+ return nil, err
+ }
+ get := r.Get()
+ kv.unprefixGetResponse(get)
+ return get, nil
+}
+
+func (kv *kvPrefix) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
+ if len(key) == 0 && !(clientv3.IsOptsWithFromKey(opts) || clientv3.IsOptsWithPrefix(opts)) {
+ return nil, rpctypes.ErrEmptyKey
+ }
+ r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpDelete(key, opts...)))
+ if err != nil {
+ return nil, err
+ }
+ del := r.Del()
+ kv.unprefixDeleteResponse(del)
+ return del, nil
+}
+
+func (kv *kvPrefix) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) {
+ if len(op.KeyBytes()) == 0 && !op.IsTxn() {
+ return clientv3.OpResponse{}, rpctypes.ErrEmptyKey
+ }
+ r, err := kv.KV.Do(ctx, kv.prefixOp(op))
+ if err != nil {
+ return r, err
+ }
+ switch {
+ case r.Get() != nil:
+ kv.unprefixGetResponse(r.Get())
+ case r.Put() != nil:
+ kv.unprefixPutResponse(r.Put())
+ case r.Del() != nil:
+ kv.unprefixDeleteResponse(r.Del())
+ case r.Txn() != nil:
+ kv.unprefixTxnResponse(r.Txn())
+ }
+ return r, nil
+}
+
+type txnPrefix struct {
+ clientv3.Txn
+ kv *kvPrefix
+}
+
+func (kv *kvPrefix) Txn(ctx context.Context) clientv3.Txn {
+ return &txnPrefix{kv.KV.Txn(ctx), kv}
+}
+
+func (txn *txnPrefix) If(cs ...clientv3.Cmp) clientv3.Txn {
+ txn.Txn = txn.Txn.If(txn.kv.prefixCmps(cs)...)
+ return txn
+}
+
+func (txn *txnPrefix) Then(ops ...clientv3.Op) clientv3.Txn {
+ txn.Txn = txn.Txn.Then(txn.kv.prefixOps(ops)...)
+ return txn
+}
+
+func (txn *txnPrefix) Else(ops ...clientv3.Op) clientv3.Txn {
+ txn.Txn = txn.Txn.Else(txn.kv.prefixOps(ops)...)
+ return txn
+}
+
+func (txn *txnPrefix) Commit() (*clientv3.TxnResponse, error) {
+ resp, err := txn.Txn.Commit()
+ if err != nil {
+ return nil, err
+ }
+ txn.kv.unprefixTxnResponse(resp)
+ return resp, nil
+}
+
+func (kv *kvPrefix) prefixOp(op clientv3.Op) clientv3.Op {
+ if !op.IsTxn() {
+ begin, end := kv.prefixInterval(op.KeyBytes(), op.RangeBytes())
+ op.WithKeyBytes(begin)
+ op.WithRangeBytes(end)
+ return op
+ }
+ cmps, thenOps, elseOps := op.Txn()
+ return clientv3.OpTxn(kv.prefixCmps(cmps), kv.prefixOps(thenOps), kv.prefixOps(elseOps))
+}
+
+func (kv *kvPrefix) unprefixGetResponse(resp *clientv3.GetResponse) {
+ for i := range resp.Kvs {
+ resp.Kvs[i].Key = resp.Kvs[i].Key[len(kv.pfx):]
+ }
+}
+
+func (kv *kvPrefix) unprefixPutResponse(resp *clientv3.PutResponse) {
+ if resp.PrevKv != nil {
+ resp.PrevKv.Key = resp.PrevKv.Key[len(kv.pfx):]
+ }
+}
+
+func (kv *kvPrefix) unprefixDeleteResponse(resp *clientv3.DeleteResponse) {
+ for i := range resp.PrevKvs {
+ resp.PrevKvs[i].Key = resp.PrevKvs[i].Key[len(kv.pfx):]
+ }
+}
+
+func (kv *kvPrefix) unprefixTxnResponse(resp *clientv3.TxnResponse) {
+ for _, r := range resp.Responses {
+ switch tv := r.Response.(type) {
+ case *pb.ResponseOp_ResponseRange:
+ if tv.ResponseRange != nil {
+ kv.unprefixGetResponse((*clientv3.GetResponse)(tv.ResponseRange))
+ }
+ case *pb.ResponseOp_ResponsePut:
+ if tv.ResponsePut != nil {
+ kv.unprefixPutResponse((*clientv3.PutResponse)(tv.ResponsePut))
+ }
+ case *pb.ResponseOp_ResponseDeleteRange:
+ if tv.ResponseDeleteRange != nil {
+ kv.unprefixDeleteResponse((*clientv3.DeleteResponse)(tv.ResponseDeleteRange))
+ }
+ case *pb.ResponseOp_ResponseTxn:
+ if tv.ResponseTxn != nil {
+ kv.unprefixTxnResponse((*clientv3.TxnResponse)(tv.ResponseTxn))
+ }
+ default:
+ }
+ }
+}
+
+func (kv *kvPrefix) prefixInterval(key, end []byte) (pfxKey []byte, pfxEnd []byte) {
+ return prefixInterval(kv.pfx, key, end)
+}
+
+func (kv *kvPrefix) prefixCmps(cs []clientv3.Cmp) []clientv3.Cmp {
+ newCmps := make([]clientv3.Cmp, len(cs))
+ for i := range cs {
+ newCmps[i] = cs[i]
+ pfxKey, endKey := kv.prefixInterval(cs[i].KeyBytes(), cs[i].RangeEnd)
+ newCmps[i].WithKeyBytes(pfxKey)
+ if len(cs[i].RangeEnd) != 0 {
+ newCmps[i].RangeEnd = endKey
+ }
+ }
+ return newCmps
+}
+
+func (kv *kvPrefix) prefixOps(ops []clientv3.Op) []clientv3.Op {
+ newOps := make([]clientv3.Op, len(ops))
+ for i := range ops {
+ newOps[i] = kv.prefixOp(ops[i])
+ }
+ return newOps
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/namespace/lease.go b/vendor/go.etcd.io/etcd/client/v3/namespace/lease.go
new file mode 100644
index 0000000000..f274de5e99
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/namespace/lease.go
@@ -0,0 +1,57 @@
+// 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 namespace
+
+import (
+ "bytes"
+ "context"
+
+ "go.etcd.io/etcd/client/v3"
+)
+
+type leasePrefix struct {
+ clientv3.Lease
+ pfx []byte
+}
+
+// NewLease wraps a Lease interface to filter for only keys with a prefix
+// and remove that prefix when fetching attached keys through TimeToLive.
+func NewLease(l clientv3.Lease, prefix string) clientv3.Lease {
+ return &leasePrefix{l, []byte(prefix)}
+}
+
+func (l *leasePrefix) TimeToLive(ctx context.Context, id clientv3.LeaseID, opts ...clientv3.LeaseOption) (*clientv3.LeaseTimeToLiveResponse, error) {
+ resp, err := l.Lease.TimeToLive(ctx, id, opts...)
+ if err != nil {
+ return nil, err
+ }
+ if len(resp.Keys) > 0 {
+ var outKeys [][]byte
+ for i := range resp.Keys {
+ if len(resp.Keys[i]) < len(l.pfx) {
+ // too short
+ continue
+ }
+ if !bytes.Equal(resp.Keys[i][:len(l.pfx)], l.pfx) {
+ // doesn't match prefix
+ continue
+ }
+ // strip prefix
+ outKeys = append(outKeys, resp.Keys[i][len(l.pfx):])
+ }
+ resp.Keys = outKeys
+ }
+ return resp, nil
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/namespace/util.go b/vendor/go.etcd.io/etcd/client/v3/namespace/util.go
new file mode 100644
index 0000000000..ecf04046c3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/namespace/util.go
@@ -0,0 +1,42 @@
+// 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 namespace
+
+func prefixInterval(pfx string, key, end []byte) (pfxKey []byte, pfxEnd []byte) {
+ pfxKey = make([]byte, len(pfx)+len(key))
+ copy(pfxKey[copy(pfxKey, pfx):], key)
+
+ if len(end) == 1 && end[0] == 0 {
+ // the edge of the keyspace
+ pfxEnd = make([]byte, len(pfx))
+ copy(pfxEnd, pfx)
+ ok := false
+ for i := len(pfxEnd) - 1; i >= 0; i-- {
+ if pfxEnd[i]++; pfxEnd[i] != 0 {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ // 0xff..ff => 0x00
+ pfxEnd = []byte{0}
+ }
+ } else if len(end) >= 1 {
+ pfxEnd = make([]byte, len(pfx)+len(end))
+ copy(pfxEnd[copy(pfxEnd, pfx):], end)
+ }
+
+ return pfxKey, pfxEnd
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/namespace/watch.go b/vendor/go.etcd.io/etcd/client/v3/namespace/watch.go
new file mode 100644
index 0000000000..12362856d0
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/namespace/watch.go
@@ -0,0 +1,83 @@
+// 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 namespace
+
+import (
+ "context"
+ "sync"
+
+ "go.etcd.io/etcd/client/v3"
+)
+
+type watcherPrefix struct {
+ clientv3.Watcher
+ pfx string
+
+ wg sync.WaitGroup
+ stopc chan struct{}
+ stopOnce sync.Once
+}
+
+// NewWatcher wraps a Watcher instance so that all Watch requests
+// are prefixed with a given string and all Watch responses have
+// the prefix removed.
+func NewWatcher(w clientv3.Watcher, prefix string) clientv3.Watcher {
+ return &watcherPrefix{Watcher: w, pfx: prefix, stopc: make(chan struct{})}
+}
+
+func (w *watcherPrefix) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
+ // since OpOption is opaque, determine range for prefixing through an OpGet
+ op := clientv3.OpGet(key, opts...)
+ end := op.RangeBytes()
+ pfxBegin, pfxEnd := prefixInterval(w.pfx, []byte(key), end)
+ if pfxEnd != nil {
+ opts = append(opts, clientv3.WithRange(string(pfxEnd)))
+ }
+
+ wch := w.Watcher.Watch(ctx, string(pfxBegin), opts...)
+
+ // translate watch events from prefixed to unprefixed
+ pfxWch := make(chan clientv3.WatchResponse)
+ w.wg.Add(1)
+ go func() {
+ defer func() {
+ close(pfxWch)
+ w.wg.Done()
+ }()
+ for wr := range wch {
+ for i := range wr.Events {
+ wr.Events[i].Kv.Key = wr.Events[i].Kv.Key[len(w.pfx):]
+ if wr.Events[i].PrevKv != nil {
+ wr.Events[i].PrevKv.Key = wr.Events[i].Kv.Key
+ }
+ }
+ select {
+ case pfxWch <- wr:
+ case <-ctx.Done():
+ return
+ case <-w.stopc:
+ return
+ }
+ }
+ }()
+ return pfxWch
+}
+
+func (w *watcherPrefix) Close() error {
+ err := w.Watcher.Close()
+ w.stopOnce.Do(func() { close(w.stopc) })
+ w.wg.Wait()
+ return err
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints.go b/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints.go
new file mode 100644
index 0000000000..72bd227874
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints.go
@@ -0,0 +1,82 @@
+package endpoints
+
+import (
+ "context"
+
+ clientv3 "go.etcd.io/etcd/client/v3"
+)
+
+// Endpoint represents a single address the connection can be established with.
+//
+// Inspired by: https://pkg.go.dev/google.golang.org/grpc/resolver#Address.
+// Please document etcd version since which version each field is supported.
+type Endpoint struct {
+ // Addr is the server address on which a connection will be established.
+ // Since etcd 3.1
+ Addr string
+
+ // Metadata is the information associated with Addr, which may be used
+ // to make load balancing decision.
+ // Since etcd 3.1
+ Metadata interface{}
+}
+
+type Operation uint8
+
+const (
+ // Add indicates an Endpoint is added.
+ Add Operation = iota
+ // Delete indicates an existing address is deleted.
+ Delete
+)
+
+// Update describes a single edit action of an Endpoint.
+type Update struct {
+ // Op - action Add or Delete.
+ Op Operation
+ Key string
+ Endpoint Endpoint
+}
+
+// WatchChannel is used to deliver notifications about endpoints updates.
+type WatchChannel <-chan []*Update
+
+// Key2EndpointMap maps etcd key into struct describing the endpoint.
+type Key2EndpointMap map[string]Endpoint
+
+// UpdateWithOpts describes endpoint update (add or delete) together
+// with etcd options (e.g. to attach an endpoint to a lease).
+type UpdateWithOpts struct {
+ Update
+ Opts []clientv3.OpOption
+}
+
+// NewAddUpdateOpts constructs UpdateWithOpts for endpoint registration.
+func NewAddUpdateOpts(key string, endpoint Endpoint, opts ...clientv3.OpOption) *UpdateWithOpts {
+ return &UpdateWithOpts{Update: Update{Op: Add, Key: key, Endpoint: endpoint}, Opts: opts}
+}
+
+// NewDeleteUpdateOpts constructs UpdateWithOpts for endpoint deletion.
+func NewDeleteUpdateOpts(key string, opts ...clientv3.OpOption) *UpdateWithOpts {
+ return &UpdateWithOpts{Update: Update{Op: Delete, Key: key}, Opts: opts}
+}
+
+// Manager can be used to add/remove & inspect endpoints stored in etcd for
+// a particular target.
+type Manager interface {
+ // Update allows to atomically add/remove a few endpoints from etcd.
+ Update(ctx context.Context, updates []*UpdateWithOpts) error
+
+ // AddEndpoint registers a single endpoint in etcd.
+ // For more advanced use-cases use the Update method.
+ AddEndpoint(ctx context.Context, key string, endpoint Endpoint, opts ...clientv3.OpOption) error
+ // DeleteEndpoint deletes a single endpoint stored in etcd.
+ // For more advanced use-cases use the Update method.
+ DeleteEndpoint(ctx context.Context, key string, opts ...clientv3.OpOption) error
+
+ // List returns all the endpoints for the current target as a map.
+ List(ctx context.Context) (Key2EndpointMap, error)
+ // NewWatchChannel creates a channel that populates or endpoint updates.
+ // Cancel the 'ctx' to close the watcher.
+ NewWatchChannel(ctx context.Context) (WatchChannel, error)
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints_impl.go b/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints_impl.go
new file mode 100644
index 0000000000..94cb73188b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/endpoints_impl.go
@@ -0,0 +1,178 @@
+package endpoints
+
+// TODO: The API is not yet implemented.
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "strings"
+
+ clientv3 "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/client/v3/naming/endpoints/internal"
+
+ "go.uber.org/zap"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+type endpointManager struct {
+ // Client is an initialized etcd client.
+ client *clientv3.Client
+ target string
+}
+
+// NewManager creates an endpoint manager which implements the interface of 'Manager'.
+func NewManager(client *clientv3.Client, target string) (Manager, error) {
+ if client == nil {
+ return nil, errors.New("invalid etcd client")
+ }
+
+ if target == "" {
+ return nil, errors.New("invalid target")
+ }
+
+ em := &endpointManager{
+ client: client,
+ target: target,
+ }
+ return em, nil
+}
+
+func (m *endpointManager) Update(ctx context.Context, updates []*UpdateWithOpts) (err error) {
+ ops := make([]clientv3.Op, 0, len(updates))
+ for _, update := range updates {
+ if !strings.HasPrefix(update.Key, m.target+"/") {
+ return status.Errorf(codes.InvalidArgument, "endpoints: endpoint key should be prefixed with '%s/' got: '%s'", m.target, update.Key)
+ }
+
+ switch update.Op {
+ case Add:
+ internalUpdate := &internal.Update{
+ Op: internal.Add,
+ Addr: update.Endpoint.Addr,
+ Metadata: update.Endpoint.Metadata,
+ }
+
+ var v []byte
+ if v, err = json.Marshal(internalUpdate); err != nil {
+ return status.Error(codes.InvalidArgument, err.Error())
+ }
+ ops = append(ops, clientv3.OpPut(update.Key, string(v), update.Opts...))
+ case Delete:
+ ops = append(ops, clientv3.OpDelete(update.Key, update.Opts...))
+ default:
+ return status.Error(codes.InvalidArgument, "endpoints: bad update op")
+ }
+ }
+ _, err = m.client.KV.Txn(ctx).Then(ops...).Commit()
+ return err
+}
+
+func (m *endpointManager) AddEndpoint(ctx context.Context, key string, endpoint Endpoint, opts ...clientv3.OpOption) error {
+ return m.Update(ctx, []*UpdateWithOpts{NewAddUpdateOpts(key, endpoint, opts...)})
+}
+
+func (m *endpointManager) DeleteEndpoint(ctx context.Context, key string, opts ...clientv3.OpOption) error {
+ return m.Update(ctx, []*UpdateWithOpts{NewDeleteUpdateOpts(key, opts...)})
+}
+
+func (m *endpointManager) NewWatchChannel(ctx context.Context) (WatchChannel, error) {
+ key := m.target + "/"
+ resp, err := m.client.Get(ctx, key, clientv3.WithPrefix(), clientv3.WithSerializable())
+ if err != nil {
+ return nil, err
+ }
+
+ lg := m.client.GetLogger()
+ initUpdates := make([]*Update, 0, len(resp.Kvs))
+ for _, kv := range resp.Kvs {
+ var iup internal.Update
+ if err := json.Unmarshal(kv.Value, &iup); err != nil {
+ lg.Warn("unmarshal endpoint update failed", zap.String("key", string(kv.Key)), zap.Error(err))
+ continue
+ }
+ up := &Update{
+ Op: Add,
+ Key: string(kv.Key),
+ Endpoint: Endpoint{Addr: iup.Addr, Metadata: iup.Metadata},
+ }
+ initUpdates = append(initUpdates, up)
+ }
+
+ upch := make(chan []*Update, 1)
+ if len(initUpdates) > 0 {
+ upch <- initUpdates
+ }
+ go m.watch(ctx, resp.Header.Revision+1, upch)
+ return upch, nil
+}
+
+func (m *endpointManager) watch(ctx context.Context, rev int64, upch chan []*Update) {
+ defer close(upch)
+
+ lg := m.client.GetLogger()
+ opts := []clientv3.OpOption{clientv3.WithRev(rev), clientv3.WithPrefix()}
+ key := m.target + "/"
+ wch := m.client.Watch(ctx, key, opts...)
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case wresp, ok := <-wch:
+ if !ok {
+ lg.Warn("watch closed", zap.String("target", m.target))
+ return
+ }
+ if wresp.Err() != nil {
+ lg.Warn("watch failed", zap.String("target", m.target), zap.Error(wresp.Err()))
+ return
+ }
+
+ deltaUps := make([]*Update, 0, len(wresp.Events))
+ for _, e := range wresp.Events {
+ var iup internal.Update
+ var err error
+ var op Operation
+ switch e.Type {
+ case clientv3.EventTypePut:
+ err = json.Unmarshal(e.Kv.Value, &iup)
+ op = Add
+ if err != nil {
+ lg.Warn("unmarshal endpoint update failed", zap.String("key", string(e.Kv.Key)), zap.Error(err))
+ continue
+ }
+ case clientv3.EventTypeDelete:
+ iup = internal.Update{Op: internal.Delete}
+ op = Delete
+ default:
+ continue
+ }
+ up := &Update{Op: op, Key: string(e.Kv.Key), Endpoint: Endpoint{Addr: iup.Addr, Metadata: iup.Metadata}}
+ deltaUps = append(deltaUps, up)
+ }
+ if len(deltaUps) > 0 {
+ upch <- deltaUps
+ }
+ }
+ }
+}
+
+func (m *endpointManager) List(ctx context.Context) (Key2EndpointMap, error) {
+ key := m.target + "/"
+ resp, err := m.client.Get(ctx, key, clientv3.WithPrefix(), clientv3.WithSerializable())
+ if err != nil {
+ return nil, err
+ }
+
+ eps := make(Key2EndpointMap)
+ for _, kv := range resp.Kvs {
+ var iup internal.Update
+ if err := json.Unmarshal(kv.Value, &iup); err != nil {
+ continue
+ }
+
+ eps[string(kv.Key)] = Endpoint{Addr: iup.Addr, Metadata: iup.Metadata}
+ }
+ return eps, nil
+}
diff --git a/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/internal/update.go b/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/internal/update.go
new file mode 100644
index 0000000000..71aa83fed4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/client/v3/naming/endpoints/internal/update.go
@@ -0,0 +1,38 @@
+package internal
+
+// Operation describes action performed on endpoint (addition vs deletion).
+// Must stay JSON-format compatible with:
+// https://pkg.go.dev/google.golang.org/grpc@v1.29.1/naming#Operation
+type Operation uint8
+
+const (
+ // Add indicates a new address is added.
+ Add Operation = iota
+ // Delete indicates an existing address is deleted.
+ Delete
+)
+
+// Update defines a persistent (JSON marshalled) format representing
+// endpoint within the etcd storage.
+//
+// As the format can be persisted by one version of etcd client library and
+// read by other the format must be kept backward compatible and
+// in particular must be superset of the grpc(<=1.29.1) naming.Update structure:
+// https://pkg.go.dev/google.golang.org/grpc@v1.29.1/naming#Update
+//
+// Please document since which version of etcd-client given property is supported.
+// Please keep the naming consistent with e.g. https://pkg.go.dev/google.golang.org/grpc/resolver#Address.
+//
+// Notice that it is not valid having both empty string Addr and nil Metadata in an Update.
+type Update struct {
+ // Op indicates the operation of the update.
+ // Since etcd 3.1.
+ Op Operation
+ // Addr is the updated address. It is empty string if there is no address update.
+ // Since etcd 3.1.
+ Addr string
+ // Metadata is the updated metadata. It is nil if there is no metadata update.
+ // Metadata is not required for a custom naming implementation.
+ // Since etcd 3.1.
+ Metadata interface{}
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/LICENSE b/vendor/go.etcd.io/etcd/pkg/v3/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/adt/README.md b/vendor/go.etcd.io/etcd/pkg/v3/adt/README.md
new file mode 100644
index 0000000000..107c6bcae2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/adt/README.md
@@ -0,0 +1,48 @@
+
+## Red-Black Tree
+
+*"Introduction to Algorithms" (Cormen et al, 3rd ed.), Chapter 13*
+
+1. Every node is either red or black.
+2. The root is black.
+3. Every leaf (NIL) is black.
+4. If a node is red, then both its children are black.
+5. For each node, all simple paths from the node to descendant leaves contain the
+same number of black nodes.
+
+For example,
+
+```go
+import (
+ "fmt"
+
+ "go.etcd.io/etcd/pkg/v3/adt"
+)
+
+func main() {
+ ivt := adt.NewIntervalTree()
+ ivt.Insert(NewInt64Interval(510, 511), 0)
+ ivt.Insert(NewInt64Interval(82, 83), 0)
+ ivt.Insert(NewInt64Interval(830, 831), 0)
+ ...
+```
+
+After inserting the values `510`, `82`, `830`, `11`, `383`, `647`, `899`, `261`, `410`, `514`, `815`, `888`, `972`, `238`, `292`, `953`.
+
+![red-black-tree-01-insertion.png](img/red-black-tree-01-insertion.png)
+
+Deleting the node `514` should not trigger any rebalancing:
+
+![red-black-tree-02-delete-514.png](img/red-black-tree-02-delete-514.png)
+
+Deleting the node `11` triggers multiple rotates for rebalancing:
+
+![red-black-tree-03-delete-11.png](img/red-black-tree-03-delete-11.png)
+![red-black-tree-04-delete-11.png](img/red-black-tree-04-delete-11.png)
+![red-black-tree-05-delete-11.png](img/red-black-tree-05-delete-11.png)
+![red-black-tree-06-delete-11.png](img/red-black-tree-06-delete-11.png)
+![red-black-tree-07-delete-11.png](img/red-black-tree-07-delete-11.png)
+![red-black-tree-08-delete-11.png](img/red-black-tree-08-delete-11.png)
+![red-black-tree-09-delete-11.png](img/red-black-tree-09-delete-11.png)
+
+Try yourself at https://www.cs.usfca.edu/~galles/visualization/RedBlack.html.
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/adt/adt.go b/vendor/go.etcd.io/etcd/pkg/v3/adt/adt.go
new file mode 100644
index 0000000000..1a9559145b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/adt/adt.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/go.etcd.io/etcd/pkg/v3/adt/interval_tree.go b/vendor/go.etcd.io/etcd/pkg/v3/adt/interval_tree.go
new file mode 100644
index 0000000000..271e3d3893
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/adt/interval_tree.go
@@ -0,0 +1,947 @@
+// 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"
+ "fmt"
+ "math"
+ "strings"
+)
+
+// 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
+)
+
+func (c rbcolor) String() string {
+ switch c {
+ case black:
+ return "black"
+ case red:
+ return "red"
+ default:
+ panic(fmt.Errorf("unknown color %d", c))
+ }
+}
+
+// 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(sentinel *intervalNode) rbcolor {
+ if x == sentinel {
+ return black
+ }
+ return x.c
+}
+
+func (x *intervalNode) height(sentinel *intervalNode) int {
+ if x == sentinel {
+ return 0
+ }
+ ld := x.left.height(sentinel)
+ rd := x.right.height(sentinel)
+ if ld < rd {
+ return rd + 1
+ }
+ return ld + 1
+}
+
+func (x *intervalNode) min(sentinel *intervalNode) *intervalNode {
+ for x.left != sentinel {
+ x = x.left
+ }
+ return x
+}
+
+// successor is the next in-order node in the tree
+func (x *intervalNode) successor(sentinel *intervalNode) *intervalNode {
+ if x.right != sentinel {
+ return x.right.min(sentinel)
+ }
+ y := x.parent
+ for y != sentinel && 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(sentinel *intervalNode) {
+ for x != sentinel {
+ oldmax := x.max
+ max := x.iv.Ivl.End
+ if x.left != sentinel && x.left.max.Compare(max) > 0 {
+ max = x.left.max
+ }
+ if x.right != sentinel && 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, sentinel *intervalNode, nv nodeVisitor) bool {
+ if x == sentinel {
+ return true
+ }
+ v := iv.Compare(&x.iv.Ivl)
+ switch {
+ case v < 0:
+ if !x.left.visit(iv, sentinel, nv) {
+ return false
+ }
+ case v > 0:
+ maxiv := Interval{x.iv.Ivl.Begin, x.max}
+ if maxiv.Compare(iv) == 0 {
+ if !x.left.visit(iv, sentinel, nv) || !x.right.visit(iv, sentinel, nv) {
+ return false
+ }
+ }
+ default:
+ if !x.left.visit(iv, sentinel, nv) || !nv(x) || !x.right.visit(iv, sentinel, nv) {
+ return false
+ }
+ }
+ return true
+}
+
+// IntervalValue represents a range tree node that contains a range and a value.
+type IntervalValue struct {
+ Ivl Interval
+ Val interface{}
+}
+
+// IntervalTree represents a (mostly) textbook implementation of the
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.) chapter 13 red-black tree
+// and chapter 14.3 interval tree with search supporting "stabbing queries".
+type IntervalTree interface {
+ // Insert adds a node with the given interval into the tree.
+ Insert(ivl Interval, val interface{})
+ // Delete removes the node with the given interval from the tree, returning
+ // true if a node is in fact removed.
+ Delete(ivl Interval) bool
+ // Len gives the number of elements in the tree.
+ Len() int
+ // Height is the number of levels in the tree; one node has height 1.
+ Height() int
+ // MaxHeight is the expected maximum tree height given the number of nodes.
+ MaxHeight() int
+ // 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.
+ Visit(ivl Interval, ivv IntervalVisitor)
+ // Find gets the IntervalValue for the node matching the given interval
+ Find(ivl Interval) *IntervalValue
+ // Intersects returns true if there is some tree node intersecting the given interval.
+ Intersects(iv Interval) bool
+ // Contains returns true if the interval tree's keys cover the entire given interval.
+ Contains(ivl Interval) bool
+ // Stab returns a slice with all elements in the tree intersecting the interval.
+ Stab(iv Interval) []*IntervalValue
+ // Union merges a given interval tree into the receiver.
+ Union(inIvt IntervalTree, ivl Interval)
+}
+
+// NewIntervalTree returns a new interval tree.
+func NewIntervalTree() IntervalTree {
+ sentinel := &intervalNode{
+ iv: IntervalValue{},
+ max: nil,
+ left: nil,
+ right: nil,
+ parent: nil,
+ c: black,
+ }
+ return &intervalTree{
+ root: sentinel,
+ count: 0,
+ sentinel: sentinel,
+ }
+}
+
+type intervalTree struct {
+ root *intervalNode
+ count int
+
+ // red-black NIL node
+ // use 'sentinel' as a dummy object to simplify boundary conditions
+ // use the sentinel to treat a nil child of a node x as an ordinary node whose parent is x
+ // use one shared sentinel to represent all nil leaves and the root's parent
+ sentinel *intervalNode
+}
+
+// TODO: make this consistent with textbook implementation
+//
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.4, p324
+//
+// RB-DELETE(T, z)
+//
+// y = z
+// y-original-color = y.color
+//
+// if z.left == T.nil
+// x = z.right
+// RB-TRANSPLANT(T, z, z.right)
+// else if z.right == T.nil
+// x = z.left
+// RB-TRANSPLANT(T, z, z.left)
+// else
+// y = TREE-MINIMUM(z.right)
+// y-original-color = y.color
+// x = y.right
+// if y.p == z
+// x.p = y
+// else
+// RB-TRANSPLANT(T, y, y.right)
+// y.right = z.right
+// y.right.p = y
+// RB-TRANSPLANT(T, z, y)
+// y.left = z.left
+// y.left.p = y
+// y.color = z.color
+//
+// if y-original-color == BLACK
+// RB-DELETE-FIXUP(T, x)
+
+// 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 == ivt.sentinel {
+ return false
+ }
+
+ y := z
+ if z.left != ivt.sentinel && z.right != ivt.sentinel {
+ y = z.successor(ivt.sentinel)
+ }
+
+ x := ivt.sentinel
+ if y.left != ivt.sentinel {
+ x = y.left
+ } else if y.right != ivt.sentinel {
+ x = y.right
+ }
+
+ x.parent = y.parent
+
+ if y.parent == ivt.sentinel {
+ ivt.root = x
+ } else {
+ if y == y.parent.left {
+ y.parent.left = x
+ } else {
+ y.parent.right = x
+ }
+ y.parent.updateMax(ivt.sentinel)
+ }
+ if y != z {
+ z.iv = y.iv
+ z.updateMax(ivt.sentinel)
+ }
+
+ if y.color(ivt.sentinel) == black {
+ ivt.deleteFixup(x)
+ }
+
+ ivt.count--
+ return true
+}
+
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.4, p326
+//
+// RB-DELETE-FIXUP(T, z)
+//
+// while x ≠ T.root and x.color == BLACK
+// if x == x.p.left
+// w = x.p.right
+// if w.color == RED
+// w.color = BLACK
+// x.p.color = RED
+// LEFT-ROTATE(T, x, p)
+// if w.left.color == BLACK and w.right.color == BLACK
+// w.color = RED
+// x = x.p
+// else if w.right.color == BLACK
+// w.left.color = BLACK
+// w.color = RED
+// RIGHT-ROTATE(T, w)
+// w = w.p.right
+// w.color = x.p.color
+// x.p.color = BLACK
+// LEFT-ROTATE(T, w.p)
+// x = T.root
+// else
+// w = x.p.left
+// if w.color == RED
+// w.color = BLACK
+// x.p.color = RED
+// RIGHT-ROTATE(T, x, p)
+// if w.right.color == BLACK and w.left.color == BLACK
+// w.color = RED
+// x = x.p
+// else if w.left.color == BLACK
+// w.right.color = BLACK
+// w.color = RED
+// LEFT-ROTATE(T, w)
+// w = w.p.left
+// w.color = x.p.color
+// x.p.color = BLACK
+// RIGHT-ROTATE(T, w.p)
+// x = T.root
+//
+// x.color = BLACK
+func (ivt *intervalTree) deleteFixup(x *intervalNode) {
+ for x != ivt.root && x.color(ivt.sentinel) == black {
+ if x == x.parent.left { // line 3-20
+ w := x.parent.right
+ if w.color(ivt.sentinel) == red {
+ w.c = black
+ x.parent.c = red
+ ivt.rotateLeft(x.parent)
+ w = x.parent.right
+ }
+ if w == nil {
+ break
+ }
+ if w.left.color(ivt.sentinel) == black && w.right.color(ivt.sentinel) == black {
+ w.c = red
+ x = x.parent
+ } else {
+ if w.right.color(ivt.sentinel) == black {
+ w.left.c = black
+ w.c = red
+ ivt.rotateRight(w)
+ w = x.parent.right
+ }
+ w.c = x.parent.color(ivt.sentinel)
+ x.parent.c = black
+ w.right.c = black
+ ivt.rotateLeft(x.parent)
+ x = ivt.root
+ }
+ } else { // line 22-38
+ // same as above but with left and right exchanged
+ w := x.parent.left
+ if w.color(ivt.sentinel) == red {
+ w.c = black
+ x.parent.c = red
+ ivt.rotateRight(x.parent)
+ w = x.parent.left
+ }
+ if w == nil {
+ break
+ }
+ if w.left.color(ivt.sentinel) == black && w.right.color(ivt.sentinel) == black {
+ w.c = red
+ x = x.parent
+ } else {
+ if w.left.color(ivt.sentinel) == black {
+ w.right.c = black
+ w.c = red
+ ivt.rotateLeft(w)
+ w = x.parent.left
+ }
+ w.c = x.parent.color(ivt.sentinel)
+ x.parent.c = black
+ w.left.c = black
+ ivt.rotateRight(x.parent)
+ x = ivt.root
+ }
+ }
+ }
+
+ if x != nil {
+ x.c = black
+ }
+}
+
+func (ivt *intervalTree) createIntervalNode(ivl Interval, val interface{}) *intervalNode {
+ return &intervalNode{
+ iv: IntervalValue{ivl, val},
+ max: ivl.End,
+ c: red,
+ left: ivt.sentinel,
+ right: ivt.sentinel,
+ parent: ivt.sentinel,
+ }
+}
+
+// TODO: make this consistent with textbook implementation
+//
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.3, p315
+//
+// RB-INSERT(T, z)
+//
+// y = T.nil
+// x = T.root
+//
+// while x ≠ T.nil
+// y = x
+// if z.key < x.key
+// x = x.left
+// else
+// x = x.right
+//
+// z.p = y
+//
+// if y == T.nil
+// T.root = z
+// else if z.key < y.key
+// y.left = z
+// else
+// y.right = z
+//
+// z.left = T.nil
+// z.right = T.nil
+// z.color = RED
+//
+// RB-INSERT-FIXUP(T, z)
+
+// Insert adds a node with the given interval into the tree.
+func (ivt *intervalTree) Insert(ivl Interval, val interface{}) {
+ y := ivt.sentinel
+ z := ivt.createIntervalNode(ivl, val)
+ x := ivt.root
+ for x != ivt.sentinel {
+ 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 == ivt.sentinel {
+ ivt.root = z
+ } else {
+ if z.iv.Ivl.Begin.Compare(y.iv.Ivl.Begin) < 0 {
+ y.left = z
+ } else {
+ y.right = z
+ }
+ y.updateMax(ivt.sentinel)
+ }
+ z.c = red
+
+ ivt.insertFixup(z)
+ ivt.count++
+}
+
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.3, p316
+//
+// RB-INSERT-FIXUP(T, z)
+//
+// while z.p.color == RED
+// if z.p == z.p.p.left
+// y = z.p.p.right
+// if y.color == RED
+// z.p.color = BLACK
+// y.color = BLACK
+// z.p.p.color = RED
+// z = z.p.p
+// else if z == z.p.right
+// z = z.p
+// LEFT-ROTATE(T, z)
+// z.p.color = BLACK
+// z.p.p.color = RED
+// RIGHT-ROTATE(T, z.p.p)
+// else
+// y = z.p.p.left
+// if y.color == RED
+// z.p.color = BLACK
+// y.color = BLACK
+// z.p.p.color = RED
+// z = z.p.p
+// else if z == z.p.right
+// z = z.p
+// RIGHT-ROTATE(T, z)
+// z.p.color = BLACK
+// z.p.p.color = RED
+// LEFT-ROTATE(T, z.p.p)
+//
+// T.root.color = BLACK
+func (ivt *intervalTree) insertFixup(z *intervalNode) {
+ for z.parent.color(ivt.sentinel) == red {
+ if z.parent == z.parent.parent.left { // line 3-15
+
+ y := z.parent.parent.right
+ if y.color(ivt.sentinel) == 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 { // line 16-28
+ // same as then with left/right exchanged
+ y := z.parent.parent.left
+ if y.color(ivt.sentinel) == 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)
+ }
+ }
+ }
+
+ // line 30
+ ivt.root.c = black
+}
+
+// rotateLeft moves x so it is left of its right child
+//
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.2, p313
+//
+// LEFT-ROTATE(T, x)
+//
+// y = x.right
+// x.right = y.left
+//
+// if y.left ≠ T.nil
+// y.left.p = x
+//
+// y.p = x.p
+//
+// if x.p == T.nil
+// T.root = y
+// else if x == x.p.left
+// x.p.left = y
+// else
+// x.p.right = y
+//
+// y.left = x
+// x.p = y
+func (ivt *intervalTree) rotateLeft(x *intervalNode) {
+ // rotateLeft x must have right child
+ if x.right == ivt.sentinel {
+ return
+ }
+
+ // line 2-3
+ y := x.right
+ x.right = y.left
+
+ // line 5-6
+ if y.left != ivt.sentinel {
+ y.left.parent = x
+ }
+ x.updateMax(ivt.sentinel)
+
+ // line 10-15, 18
+ ivt.replaceParent(x, y)
+
+ // line 17
+ y.left = x
+ y.updateMax(ivt.sentinel)
+}
+
+// rotateRight moves x so it is right of its left child
+//
+// RIGHT-ROTATE(T, x)
+//
+// y = x.left
+// x.left = y.right
+//
+// if y.right ≠ T.nil
+// y.right.p = x
+//
+// y.p = x.p
+//
+// if x.p == T.nil
+// T.root = y
+// else if x == x.p.right
+// x.p.right = y
+// else
+// x.p.left = y
+//
+// y.right = x
+// x.p = y
+func (ivt *intervalTree) rotateRight(x *intervalNode) {
+ // rotateRight x must have left child
+ if x.left == ivt.sentinel {
+ return
+ }
+
+ // line 2-3
+ y := x.left
+ x.left = y.right
+
+ // line 5-6
+ if y.right != ivt.sentinel {
+ y.right.parent = x
+ }
+ x.updateMax(ivt.sentinel)
+
+ // line 10-15, 18
+ ivt.replaceParent(x, y)
+
+ // line 17
+ y.right = x
+ y.updateMax(ivt.sentinel)
+}
+
+// replaceParent replaces x's parent with y
+func (ivt *intervalTree) replaceParent(x *intervalNode, y *intervalNode) {
+ y.parent = x.parent
+ if x.parent == ivt.sentinel {
+ ivt.root = y
+ } else {
+ if x == x.parent.left {
+ x.parent.left = y
+ } else {
+ x.parent.right = y
+ }
+ x.parent.updateMax(ivt.sentinel)
+ }
+ 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(ivt.sentinel) }
+
+// 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, ivt.sentinel, func(n *intervalNode) bool { return ivv(&n.iv) })
+}
+
+// find the exact node for a given interval
+func (ivt *intervalTree) find(ivl Interval) *intervalNode {
+ ret := ivt.sentinel
+ f := func(n *intervalNode) bool {
+ if n.iv.Ivl != ivl {
+ return true
+ }
+ ret = n
+ return false
+ }
+ ivt.root.visit(&ivl, ivt.sentinel, 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 == ivt.sentinel {
+ 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 != ivt.sentinel && iv.Compare(&x.iv.Ivl) != 0 {
+ if x.left != ivt.sentinel && x.left.max.Compare(iv.Begin) > 0 {
+ x = x.left
+ } else {
+ x = x.right
+ }
+ }
+ return x != ivt.sentinel
+}
+
+// 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 visitedInterval struct {
+ root Interval
+ left Interval
+ right Interval
+ color rbcolor
+ depth int
+}
+
+func (vi visitedInterval) String() string {
+ bd := new(strings.Builder)
+ bd.WriteString(fmt.Sprintf("root [%v,%v,%v], left [%v,%v], right [%v,%v], depth %d",
+ vi.root.Begin, vi.root.End, vi.color,
+ vi.left.Begin, vi.left.End,
+ vi.right.Begin, vi.right.End,
+ vi.depth,
+ ))
+ return bd.String()
+}
+
+// visitLevel traverses tree in level order.
+// used for testing
+func (ivt *intervalTree) visitLevel() []visitedInterval {
+ if ivt.root == ivt.sentinel {
+ return nil
+ }
+
+ rs := make([]visitedInterval, 0, ivt.Len())
+
+ type pair struct {
+ node *intervalNode
+ depth int
+ }
+ queue := []pair{{ivt.root, 0}}
+ for len(queue) > 0 {
+ f := queue[0]
+ queue = queue[1:]
+
+ vi := visitedInterval{
+ root: f.node.iv.Ivl,
+ color: f.node.color(ivt.sentinel),
+ depth: f.depth,
+ }
+ if f.node.left != ivt.sentinel {
+ vi.left = f.node.left.iv.Ivl
+ queue = append(queue, pair{f.node.left, f.depth + 1})
+ }
+ if f.node.right != ivt.sentinel {
+ vi.right = f.node.right.iv.Ivl
+ queue = append(queue, pair{f.node.right, f.depth + 1})
+ }
+
+ rs = append(rs, vi)
+ }
+
+ return rs
+}
+
+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 newInt64EmptyInterval() Interval {
+ return Interval{Begin: nil, End: nil}
+}
+
+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/go.etcd.io/etcd/pkg/v3/contention/contention.go b/vendor/go.etcd.io/etcd/pkg/v3/contention/contention.go
new file mode 100644
index 0000000000..26ce9a2f34
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/contention/doc.go b/vendor/go.etcd.io/etcd/pkg/v3/contention/doc.go
new file mode 100644
index 0000000000..daf452219e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/cpuutil/doc.go b/vendor/go.etcd.io/etcd/pkg/v3/cpuutil/doc.go
new file mode 100644
index 0000000000..0323b2d34c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/cpuutil/endian.go b/vendor/go.etcd.io/etcd/pkg/v3/cpuutil/endian.go
new file mode 100644
index 0000000000..06c06cd4a5
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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() {
+ i := int(0x1)
+ if v := (*[intWidth]byte)(unsafe.Pointer(&i)); v[0] == 0 {
+ byteOrder = binary.BigEndian
+ } else {
+ byteOrder = binary.LittleEndian
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/crc/crc.go b/vendor/go.etcd.io/etcd/pkg/v3/crc/crc.go
new file mode 100644
index 0000000000..4b998a4845
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/debugutil/doc.go b/vendor/go.etcd.io/etcd/pkg/v3/debugutil/doc.go
new file mode 100644
index 0000000000..74499eb273
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/debugutil/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 debugutil includes utility functions for debugging.
+package debugutil
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/debugutil/pprof.go b/vendor/go.etcd.io/etcd/pkg/v3/debugutil/pprof.go
new file mode 100644
index 0000000000..22c2e1ee5d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/debugutil/pprof.go
@@ -0,0 +1,47 @@
+// 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 debugutil
+
+import (
+ "net/http"
+ "net/http/pprof"
+ "runtime"
+)
+
+const HTTPPrefixPProf = "/debug/pprof"
+
+// PProfHandlers returns a map of pprof handlers keyed by the HTTP path.
+func PProfHandlers() map[string]http.Handler {
+ // set only when there's no existing setting
+ if runtime.SetMutexProfileFraction(-1) == 0 {
+ // 1 out of 5 mutex events are reported, on average
+ runtime.SetMutexProfileFraction(5)
+ }
+
+ m := make(map[string]http.Handler)
+
+ m[HTTPPrefixPProf+"/"] = http.HandlerFunc(pprof.Index)
+ m[HTTPPrefixPProf+"/profile"] = http.HandlerFunc(pprof.Profile)
+ m[HTTPPrefixPProf+"/symbol"] = http.HandlerFunc(pprof.Symbol)
+ m[HTTPPrefixPProf+"/cmdline"] = http.HandlerFunc(pprof.Cmdline)
+ m[HTTPPrefixPProf+"/trace"] = http.HandlerFunc(pprof.Trace)
+ m[HTTPPrefixPProf+"/heap"] = pprof.Handler("heap")
+ m[HTTPPrefixPProf+"/goroutine"] = pprof.Handler("goroutine")
+ m[HTTPPrefixPProf+"/threadcreate"] = pprof.Handler("threadcreate")
+ m[HTTPPrefixPProf+"/block"] = pprof.Handler("block")
+ m[HTTPPrefixPProf+"/mutex"] = pprof.Handler("mutex")
+
+ return m
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/flag.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/flag.go
new file mode 100644
index 0000000000..76a51a8901
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/flag.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 flags implements command-line flag parsing.
+package flags
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/spf13/pflag"
+ "go.uber.org/zap"
+)
+
+// SetFlagsFromEnv parses all registered flags in the given flagset,
+// and if they are not already set it attempts to set their values from
+// environment variables. Environment variables take the name of the flag but
+// are UPPERCASE, have the given prefix and any dashes are replaced by
+// underscores - for example: some-flag => ETCD_SOME_FLAG
+func SetFlagsFromEnv(lg *zap.Logger, prefix string, fs *flag.FlagSet) error {
+ var err error
+ alreadySet := make(map[string]bool)
+ fs.Visit(func(f *flag.Flag) {
+ alreadySet[FlagToEnv(prefix, f.Name)] = true
+ })
+ usedEnvKey := make(map[string]bool)
+ fs.VisitAll(func(f *flag.Flag) {
+ if serr := setFlagFromEnv(lg, fs, prefix, f.Name, usedEnvKey, alreadySet, true); serr != nil {
+ err = serr
+ }
+ })
+ verifyEnv(lg, prefix, usedEnvKey, alreadySet)
+ return err
+}
+
+// SetPflagsFromEnv is similar to SetFlagsFromEnv. However, the accepted flagset type is pflag.FlagSet
+// and it does not do any logging.
+func SetPflagsFromEnv(lg *zap.Logger, prefix string, fs *pflag.FlagSet) error {
+ var err error
+ alreadySet := make(map[string]bool)
+ usedEnvKey := make(map[string]bool)
+ fs.VisitAll(func(f *pflag.Flag) {
+ if f.Changed {
+ alreadySet[FlagToEnv(prefix, f.Name)] = true
+ }
+ if serr := setFlagFromEnv(lg, fs, prefix, f.Name, usedEnvKey, alreadySet, false); serr != nil {
+ err = serr
+ }
+ })
+ verifyEnv(lg, prefix, usedEnvKey, alreadySet)
+ return err
+}
+
+// FlagToEnv converts flag string to upper-case environment variable key string.
+func FlagToEnv(prefix, name string) string {
+ return prefix + "_" + strings.ToUpper(strings.Replace(name, "-", "_", -1))
+}
+
+func verifyEnv(lg *zap.Logger, prefix string, usedEnvKey, alreadySet map[string]bool) {
+ for _, env := range os.Environ() {
+ kv := strings.SplitN(env, "=", 2)
+ if len(kv) != 2 {
+ if lg != nil {
+ lg.Warn("found invalid environment variable", zap.String("environment-variable", env))
+ }
+ }
+ if usedEnvKey[kv[0]] {
+ continue
+ }
+ if alreadySet[kv[0]] {
+ if lg != nil {
+ lg.Fatal(
+ "conflicting environment variable is shadowed by corresponding command-line flag (either unset environment variable or disable flag))",
+ zap.String("environment-variable", kv[0]),
+ )
+ }
+ }
+ if strings.HasPrefix(env, prefix+"_") {
+ if lg != nil {
+ lg.Warn("unrecognized environment variable", zap.String("environment-variable", env))
+ }
+ }
+ }
+}
+
+type flagSetter interface {
+ Set(fk string, fv string) error
+}
+
+func setFlagFromEnv(lg *zap.Logger, fs flagSetter, prefix, fname string, usedEnvKey, alreadySet map[string]bool, log bool) error {
+ key := FlagToEnv(prefix, fname)
+ if !alreadySet[key] {
+ val := os.Getenv(key)
+ if val != "" {
+ usedEnvKey[key] = true
+ if serr := fs.Set(fname, val); serr != nil {
+ return fmt.Errorf("invalid value %q for %s: %v", val, key, serr)
+ }
+ if log && lg != nil {
+ lg.Info(
+ "recognized and used environment variable",
+ zap.String("variable-name", key),
+ zap.String("variable-value", val),
+ )
+ }
+ }
+ }
+ return nil
+}
+
+func IsSet(fs *flag.FlagSet, name string) bool {
+ set := false
+ fs.Visit(func(f *flag.Flag) {
+ if f.Name == name {
+ set = true
+ }
+ })
+ return set
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/ignored.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/ignored.go
new file mode 100644
index 0000000000..9443935354
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/ignored.go
@@ -0,0 +1,41 @@
+// 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 flags
+
+import "go.uber.org/zap"
+
+// IgnoredFlag encapsulates a flag that may have been previously valid but is
+// now ignored. If an IgnoredFlag is set, a warning is printed and
+// operation continues.
+type IgnoredFlag struct {
+ lg *zap.Logger
+ Name string
+}
+
+// IsBoolFlag is defined to allow the flag to be defined without an argument
+func (f *IgnoredFlag) IsBoolFlag() bool {
+ return true
+}
+
+func (f *IgnoredFlag) Set(s string) error {
+ if f.lg != nil {
+ f.lg.Warn("flag is no longer supported - ignoring", zap.String("flag-name", f.Name))
+ }
+ return nil
+}
+
+func (f *IgnoredFlag) String() string {
+ return ""
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/selective_string.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/selective_string.go
new file mode 100644
index 0000000000..4b90fbf4b4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/selective_string.go
@@ -0,0 +1,114 @@
+// 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 flags
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// SelectiveStringValue implements the flag.Value interface.
+type SelectiveStringValue struct {
+ v string
+ valids map[string]struct{}
+}
+
+// Set verifies the argument to be a valid member of the allowed values
+// before setting the underlying flag value.
+func (ss *SelectiveStringValue) Set(s string) error {
+ if _, ok := ss.valids[s]; ok {
+ ss.v = s
+ return nil
+ }
+ return errors.New("invalid value")
+}
+
+// String returns the set value (if any) of the SelectiveStringValue
+func (ss *SelectiveStringValue) String() string {
+ return ss.v
+}
+
+// Valids returns the list of valid strings.
+func (ss *SelectiveStringValue) Valids() []string {
+ s := make([]string, 0, len(ss.valids))
+ for k := range ss.valids {
+ s = append(s, k)
+ }
+ sort.Strings(s)
+ return s
+}
+
+// NewSelectiveStringValue creates a new string flag
+// for which any one of the given strings is a valid value,
+// and any other value is an error.
+//
+// valids[0] will be default value. Caller must be sure
+// len(valids) != 0 or it will panic.
+func NewSelectiveStringValue(valids ...string) *SelectiveStringValue {
+ vm := make(map[string]struct{})
+ for _, v := range valids {
+ vm[v] = struct{}{}
+ }
+ return &SelectiveStringValue{valids: vm, v: valids[0]}
+}
+
+// SelectiveStringsValue implements the flag.Value interface.
+type SelectiveStringsValue struct {
+ vs []string
+ valids map[string]struct{}
+}
+
+// Set verifies the argument to be a valid member of the allowed values
+// before setting the underlying flag value.
+func (ss *SelectiveStringsValue) Set(s string) error {
+ vs := strings.Split(s, ",")
+ for i := range vs {
+ if _, ok := ss.valids[vs[i]]; ok {
+ ss.vs = append(ss.vs, vs[i])
+ } else {
+ return fmt.Errorf("invalid value %q", vs[i])
+ }
+ }
+ sort.Strings(ss.vs)
+ return nil
+}
+
+// String returns the set value (if any) of the SelectiveStringsValue.
+func (ss *SelectiveStringsValue) String() string {
+ return strings.Join(ss.vs, ",")
+}
+
+// Valids returns the list of valid strings.
+func (ss *SelectiveStringsValue) Valids() []string {
+ s := make([]string, 0, len(ss.valids))
+ for k := range ss.valids {
+ s = append(s, k)
+ }
+ sort.Strings(s)
+ return s
+}
+
+// NewSelectiveStringsValue creates a new string slice flag
+// for which any one of the given strings is a valid value,
+// and any other value is an error.
+func NewSelectiveStringsValue(valids ...string) *SelectiveStringsValue {
+ vm := make(map[string]struct{})
+ for _, v := range valids {
+ vm[v] = struct{}{}
+ }
+ return &SelectiveStringsValue{valids: vm, vs: []string{}}
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/strings.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/strings.go
new file mode 100644
index 0000000000..a80190658e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/strings.go
@@ -0,0 +1,53 @@
+// 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 flags
+
+import (
+ "flag"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// StringsValue wraps "sort.StringSlice".
+type StringsValue sort.StringSlice
+
+// Set parses a command line set of strings, separated by comma.
+// Implements "flag.Value" interface.
+func (ss *StringsValue) Set(s string) error {
+ *ss = strings.Split(s, ",")
+ return nil
+}
+
+// String implements "flag.Value" interface.
+func (ss *StringsValue) String() string { return strings.Join(*ss, ",") }
+
+// NewStringsValue implements string slice as "flag.Value" interface.
+// Given value is to be separated by comma.
+func NewStringsValue(s string) (ss *StringsValue) {
+ if s == "" {
+ return &StringsValue{}
+ }
+ ss = new(StringsValue)
+ if err := ss.Set(s); err != nil {
+ panic(fmt.Sprintf("new StringsValue should never fail: %v", err))
+ }
+ return ss
+}
+
+// StringsFromFlag returns a string slice from the flag.
+func StringsFromFlag(fs *flag.FlagSet, flagName string) []string {
+ return []string(*fs.Lookup(flagName).Value.(*StringsValue))
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/uint32.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/uint32.go
new file mode 100644
index 0000000000..496730a454
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/uint32.go
@@ -0,0 +1,45 @@
+// Copyright 2022 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 flags
+
+import (
+ "flag"
+ "strconv"
+)
+
+type uint32Value uint32
+
+// NewUint32Value creates an uint32 instance with the provided value.
+func NewUint32Value(v uint32) *uint32Value {
+ val := new(uint32Value)
+ *val = uint32Value(v)
+ return val
+}
+
+// Set parses a command line uint32 value.
+// Implements "flag.Value" interface.
+func (i *uint32Value) Set(s string) error {
+ v, err := strconv.ParseUint(s, 0, 32)
+ *i = uint32Value(v)
+ return err
+}
+
+func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
+
+// Uint32FromFlag return the uint32 value of a flag with the given name
+func Uint32FromFlag(fs *flag.FlagSet, name string) uint32 {
+ val := *fs.Lookup(name).Value.(*uint32Value)
+ return uint32(val)
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_strings.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_strings.go
new file mode 100644
index 0000000000..e67af1f9b5
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_strings.go
@@ -0,0 +1,77 @@
+// 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 flags
+
+import (
+ "flag"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// UniqueStringsValue wraps a list of unique strings.
+// The values are set in order.
+type UniqueStringsValue struct {
+ Values map[string]struct{}
+}
+
+// Set parses a command line set of strings, separated by comma.
+// Implements "flag.Value" interface.
+// The values are set in order.
+func (us *UniqueStringsValue) Set(s string) error {
+ us.Values = make(map[string]struct{})
+ for _, v := range strings.Split(s, ",") {
+ us.Values[v] = struct{}{}
+ }
+ return nil
+}
+
+// String implements "flag.Value" interface.
+func (us *UniqueStringsValue) String() string {
+ return strings.Join(us.stringSlice(), ",")
+}
+
+func (us *UniqueStringsValue) stringSlice() []string {
+ ss := make([]string, 0, len(us.Values))
+ for v := range us.Values {
+ ss = append(ss, v)
+ }
+ sort.Strings(ss)
+ return ss
+}
+
+// NewUniqueStringsValue implements string slice as "flag.Value" interface.
+// Given value is to be separated by comma.
+// The values are set in order.
+func NewUniqueStringsValue(s string) (us *UniqueStringsValue) {
+ us = &UniqueStringsValue{Values: make(map[string]struct{})}
+ if s == "" {
+ return us
+ }
+ if err := us.Set(s); err != nil {
+ panic(fmt.Sprintf("new UniqueStringsValue should never fail: %v", err))
+ }
+ return us
+}
+
+// UniqueStringsFromFlag returns a string slice from the flag.
+func UniqueStringsFromFlag(fs *flag.FlagSet, flagName string) []string {
+ return (*fs.Lookup(flagName).Value.(*UniqueStringsValue)).stringSlice()
+}
+
+// UniqueStringsMapFromFlag returns a map of strings from the flag.
+func UniqueStringsMapFromFlag(fs *flag.FlagSet, flagName string) map[string]struct{} {
+ return (*fs.Lookup(flagName).Value.(*UniqueStringsValue)).Values
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_urls.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_urls.go
new file mode 100644
index 0000000000..cc9b13294b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_urls.go
@@ -0,0 +1,97 @@
+// 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 flags
+
+import (
+ "flag"
+ "fmt"
+ "net/url"
+ "sort"
+ "strings"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+)
+
+// UniqueURLs contains unique URLs
+// with non-URL exceptions.
+type UniqueURLs struct {
+ Values map[string]struct{}
+ uss []url.URL
+ Allowed map[string]struct{}
+}
+
+// Set parses a command line set of URLs formatted like:
+// http://127.0.0.1:2380,http://10.1.1.2:80
+// Implements "flag.Value" interface.
+func (us *UniqueURLs) Set(s string) error {
+ if _, ok := us.Values[s]; ok {
+ return nil
+ }
+ if _, ok := us.Allowed[s]; ok {
+ us.Values[s] = struct{}{}
+ return nil
+ }
+ ss, err := types.NewURLs(strings.Split(s, ","))
+ if err != nil {
+ return err
+ }
+ us.Values = make(map[string]struct{})
+ us.uss = make([]url.URL, 0)
+ for _, v := range ss {
+ x := v.String()
+ if _, exists := us.Values[x]; exists {
+ continue
+ }
+ us.Values[x] = struct{}{}
+ us.uss = append(us.uss, v)
+ }
+ return nil
+}
+
+// String implements "flag.Value" interface.
+func (us *UniqueURLs) String() string {
+ all := make([]string, 0, len(us.Values))
+ for u := range us.Values {
+ all = append(all, u)
+ }
+ sort.Strings(all)
+ return strings.Join(all, ",")
+}
+
+// NewUniqueURLsWithExceptions implements "url.URL" slice as flag.Value interface.
+// Given value is to be separated by comma.
+func NewUniqueURLsWithExceptions(s string, exceptions ...string) *UniqueURLs {
+ us := &UniqueURLs{Values: make(map[string]struct{}), Allowed: make(map[string]struct{})}
+ for _, v := range exceptions {
+ us.Allowed[v] = struct{}{}
+ }
+ if s == "" {
+ return us
+ }
+ if err := us.Set(s); err != nil {
+ panic(fmt.Sprintf("new UniqueURLs should never fail: %v", err))
+ }
+ return us
+}
+
+// UniqueURLsFromFlag returns a slice from urls got from the flag.
+func UniqueURLsFromFlag(fs *flag.FlagSet, urlsFlagName string) []url.URL {
+ return (*fs.Lookup(urlsFlagName).Value.(*UniqueURLs)).uss
+}
+
+// UniqueURLsMapFromFlag returns a map from url strings got from the flag.
+func UniqueURLsMapFromFlag(fs *flag.FlagSet, urlsFlagName string) map[string]struct{} {
+ return (*fs.Lookup(urlsFlagName).Value.(*UniqueURLs)).Values
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/flags/urls.go b/vendor/go.etcd.io/etcd/pkg/v3/flags/urls.go
new file mode 100644
index 0000000000..885d32f457
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/flags/urls.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 flags
+
+import (
+ "flag"
+ "fmt"
+ "net/url"
+ "strings"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+)
+
+// URLsValue wraps "types.URLs".
+type URLsValue types.URLs
+
+// Set parses a command line set of URLs formatted like:
+// http://127.0.0.1:2380,http://10.1.1.2:80
+// Implements "flag.Value" interface.
+func (us *URLsValue) Set(s string) error {
+ ss, err := types.NewURLs(strings.Split(s, ","))
+ if err != nil {
+ return err
+ }
+ *us = URLsValue(ss)
+ return nil
+}
+
+// String implements "flag.Value" interface.
+func (us *URLsValue) String() string {
+ all := make([]string, len(*us))
+ for i, u := range *us {
+ all[i] = u.String()
+ }
+ return strings.Join(all, ",")
+}
+
+// NewURLsValue implements "url.URL" slice as flag.Value interface.
+// Given value is to be separated by comma.
+func NewURLsValue(s string) *URLsValue {
+ if s == "" {
+ return &URLsValue{}
+ }
+ v := &URLsValue{}
+ if err := v.Set(s); err != nil {
+ panic(fmt.Sprintf("new URLsValue should never fail: %v", err))
+ }
+ return v
+}
+
+// URLsFromFlag returns a slices from url got from the flag.
+func URLsFromFlag(fs *flag.FlagSet, urlsFlagName string) []url.URL {
+ return []url.URL(*fs.Lookup(urlsFlagName).Value.(*URLsValue))
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/grpc_testing/recorder.go b/vendor/go.etcd.io/etcd/pkg/v3/grpc_testing/recorder.go
new file mode 100644
index 0000000000..d6b6d2aac2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/grpc_testing/recorder.go
@@ -0,0 +1,69 @@
+// Copyright 2021 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 grpc_testing
+
+import (
+ "context"
+ "sync"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/metadata"
+)
+
+type GrpcRecorder struct {
+ mux sync.RWMutex
+ requests []RequestInfo
+}
+
+type RequestInfo struct {
+ FullMethod string
+ Authority string
+}
+
+func (ri *GrpcRecorder) UnaryInterceptor() grpc.UnaryServerInterceptor {
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ ri.record(toRequestInfo(ctx, info))
+ resp, err := handler(ctx, req)
+ return resp, err
+ }
+}
+
+func (ri *GrpcRecorder) RecordedRequests() []RequestInfo {
+ ri.mux.RLock()
+ defer ri.mux.RUnlock()
+ reqs := make([]RequestInfo, len(ri.requests))
+ copy(reqs, ri.requests)
+ return reqs
+}
+
+func toRequestInfo(ctx context.Context, info *grpc.UnaryServerInfo) RequestInfo {
+ req := RequestInfo{
+ FullMethod: info.FullMethod,
+ }
+ md, ok := metadata.FromIncomingContext(ctx)
+ if ok {
+ as := md.Get(":authority")
+ if len(as) != 0 {
+ req.Authority = as[0]
+ }
+ }
+ return req
+}
+
+func (ri *GrpcRecorder) record(r RequestInfo) {
+ ri.mux.Lock()
+ defer ri.mux.Unlock()
+ ri.requests = append(ri.requests, r)
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/grpc_testing/stub_server.go b/vendor/go.etcd.io/etcd/pkg/v3/grpc_testing/stub_server.go
new file mode 100644
index 0000000000..92e0788a09
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/grpc_testing/stub_server.go
@@ -0,0 +1,90 @@
+package grpc_testing
+
+import (
+ "context"
+ "fmt"
+ "net"
+
+ "google.golang.org/grpc"
+ testpb "google.golang.org/grpc/interop/grpc_testing"
+)
+
+// StubServer is borrowed from the interal package of grpc-go.
+// See https://github.com/grpc/grpc-go/blob/master/internal/stubserver/stubserver.go
+// Since it cannot be imported directly, we have to copy and paste it here,
+// and useless code for our testing is removed.
+
+// StubServer is a server that is easy to customize within individual test
+// cases.
+type StubServer struct {
+ testService testpb.TestServiceServer
+
+ // Network and Address are parameters for Listen. Defaults will be used if these are empty before Start.
+ Network string
+ Address string
+
+ s *grpc.Server
+
+ cleanups []func() // Lambdas executed in Stop(); populated by Start().
+}
+
+func New(testService testpb.TestServiceServer) *StubServer {
+ return &StubServer{testService: testService}
+}
+
+// Start starts the server and creates a client connected to it.
+func (ss *StubServer) Start(sopts []grpc.ServerOption, dopts ...grpc.DialOption) error {
+ if ss.Network == "" {
+ ss.Network = "tcp"
+ }
+ if ss.Address == "" {
+ ss.Address = "localhost:0"
+ }
+
+ lis, err := net.Listen(ss.Network, ss.Address)
+ if err != nil {
+ return fmt.Errorf("net.Listen(%q, %q) = %v", ss.Network, ss.Address, err)
+ }
+ ss.Address = lis.Addr().String()
+ ss.cleanups = append(ss.cleanups, func() { lis.Close() })
+
+ s := grpc.NewServer(sopts...)
+ testpb.RegisterTestServiceServer(s, ss.testService)
+ go s.Serve(lis)
+ ss.cleanups = append(ss.cleanups, s.Stop)
+ ss.s = s
+
+ return nil
+}
+
+// Stop stops ss and cleans up all resources it consumed.
+func (ss *StubServer) Stop() {
+ for i := len(ss.cleanups) - 1; i >= 0; i-- {
+ ss.cleanups[i]()
+ }
+}
+
+// Addr gets the address the server listening on.
+func (ss *StubServer) Addr() string {
+ return ss.Address
+}
+
+type dummyStubServer struct {
+ testpb.UnimplementedTestServiceServer
+ body []byte
+}
+
+func (d dummyStubServer) UnaryCall(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
+ return &testpb.SimpleResponse{
+ Payload: &testpb.Payload{
+ Type: testpb.PayloadType_COMPRESSABLE,
+ Body: d.body,
+ },
+ }, nil
+}
+
+// NewDummyStubServer creates a simple test server that serves Unary calls with
+// responses with the given payload.
+func NewDummyStubServer(body []byte) *StubServer {
+ return New(dummyStubServer{body: body})
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/httputil/httputil.go b/vendor/go.etcd.io/etcd/pkg/v3/httputil/httputil.go
new file mode 100644
index 0000000000..3bf58a3a1d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/httputil/httputil.go
@@ -0,0 +1,50 @@
+// 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.
+
+// 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.
+
+// Package httputil provides HTTP utility functions.
+package httputil
+
+import (
+ "io"
+ "io/ioutil"
+ "net"
+ "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.
+// Borrowed from golang/net/context/ctxhttp/cancelreq.go.
+func GracefulClose(resp *http.Response) {
+ io.Copy(ioutil.Discard, resp.Body)
+ resp.Body.Close()
+}
+
+// GetHostname returns the hostname from request Host field.
+// It returns empty string, if Host field contains invalid
+// value (e.g. "localhost:::" with too many colons).
+func GetHostname(req *http.Request) string {
+ if req == nil {
+ return ""
+ }
+ h, _, err := net.SplitHostPort(req.Host)
+ if err != nil {
+ return req.Host
+ }
+ return h
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/idutil/id.go b/vendor/go.etcd.io/etcd/pkg/v3/idutil/id.go
new file mode 100644
index 0000000000..63a02cd734
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/idutil/id.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 idutil implements utility functions for generating unique,
+// randomized ids.
+package idutil
+
+import (
+ "math"
+ "sync/atomic"
+ "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 {
+ // 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 {
+ suffix := atomic.AddUint64(&g.suffix, 1)
+ id := g.prefix | lowbit(suffix, suffixLen)
+ return id
+}
+
+func lowbit(x uint64, n uint) uint64 {
+ return x & (math.MaxUint64 >> (64 - n))
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/ioutil/pagewriter.go b/vendor/go.etcd.io/etcd/pkg/v3/ioutil/pagewriter.go
new file mode 100644
index 0000000000..62eb5cd43e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/ioutil/pagewriter.go
@@ -0,0 +1,121 @@
+// 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 (
+ "fmt"
+ "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 {
+ if pageBytes <= 0 {
+ panic(fmt.Sprintf("assertion failed: invalid pageBytes (%d) value, it must be greater than 0", pageBytes))
+ }
+ 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
+}
+
+// Flush flushes buffered data.
+func (pw *PageWriter) Flush() error {
+ _, err := pw.flush()
+ return err
+}
+
+// FlushN flushes buffered data and returns the number of written bytes.
+func (pw *PageWriter) FlushN() (int, error) {
+ return pw.flush()
+}
+
+func (pw *PageWriter) flush() (int, error) {
+ if pw.bufferedBytes == 0 {
+ return 0, nil
+ }
+ n, err := pw.w.Write(pw.buf[:pw.bufferedBytes])
+ pw.pageOffset = (pw.pageOffset + pw.bufferedBytes) % pw.pageBytes
+ pw.bufferedBytes = 0
+ return n, err
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/ioutil/readcloser.go b/vendor/go.etcd.io/etcd/pkg/v3/ioutil/readcloser.go
new file mode 100644
index 0000000000..d3efcfe3d5
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/ioutil/reader.go b/vendor/go.etcd.io/etcd/pkg/v3/ioutil/reader.go
new file mode 100644
index 0000000000..0703ed476d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/ioutil/util.go b/vendor/go.etcd.io/etcd/pkg/v3/ioutil/util.go
new file mode 100644
index 0000000000..dc36e183c2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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"
+
+ "go.etcd.io/etcd/client/pkg/v3/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/go.etcd.io/etcd/pkg/v3/netutil/doc.go b/vendor/go.etcd.io/etcd/pkg/v3/netutil/doc.go
new file mode 100644
index 0000000000..5d92d03a6f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/netutil/doc.go
@@ -0,0 +1,16 @@
+// 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 netutil implements network-related utility functions.
+package netutil
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/netutil/netutil.go b/vendor/go.etcd.io/etcd/pkg/v3/netutil/netutil.go
new file mode 100644
index 0000000000..689927b4c6
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/netutil/netutil.go
@@ -0,0 +1,222 @@
+// 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 (
+ "context"
+ "fmt"
+ "net"
+ "net/url"
+ "reflect"
+ "sort"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+
+ "go.uber.org/zap"
+)
+
+// indirection for testing
+var 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, lg *zap.Logger, 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, lg, 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, lg *zap.Logger, 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 {
+ lg.Warn(
+ "failed to parse URL Host while resolving URL",
+ zap.String("url", u.String()),
+ zap.String("host", u.Host),
+ zap.Error(err),
+ )
+ return "", err
+ }
+ if host == "localhost" {
+ return "", nil
+ }
+ for ctx.Err() == nil {
+ tcpAddr, err := resolveTCPAddr(ctx, u.Host)
+ if err == nil {
+ lg.Info(
+ "resolved URL Host",
+ zap.String("url", u.String()),
+ zap.String("host", u.Host),
+ zap.String("resolved-addr", tcpAddr.String()),
+ )
+ return tcpAddr.String(), nil
+ }
+
+ lg.Warn(
+ "failed to resolve URL Host",
+ zap.String("url", u.String()),
+ zap.String("host", u.Host),
+ zap.Duration("retry-interval", retryInterval),
+ zap.Error(err),
+ )
+
+ select {
+ case <-ctx.Done():
+ lg.Warn(
+ "failed to resolve URL Host; returning",
+ zap.String("url", u.String()),
+ zap.String("host", u.Host),
+ zap.Duration("retry-interval", retryInterval),
+ zap.Error(err),
+ )
+ 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, lg *zap.Logger, 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))
+ }
+
+ sort.Sort(types.URLs(a))
+ sort.Sort(types.URLs(b))
+ var needResolve bool
+ for i := range a {
+ if !reflect.DeepEqual(a[i], b[i]) {
+ needResolve = true
+ break
+ }
+ }
+ if !needResolve {
+ return true, nil
+ }
+
+ // If URLs are not equal, try to resolve it and compare again.
+ urls, err := resolveTCPAddrs(ctx, lg, [][]url.URL{a, b})
+ if err != nil {
+ return false, err
+ }
+ 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("resolved urls: %q != %q", a[i].String(), b[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, lg *zap.Logger, a []string, b []string) (bool, error) {
+ if len(a) != len(b) {
+ return false, fmt.Errorf("len(%q) != len(%q)", a, b)
+ }
+ urlsA, err := stringsToURLs(a)
+ if err != nil {
+ return false, err
+ }
+ urlsB, err := stringsToURLs(b)
+ if err != nil {
+ return false, err
+ }
+ return urlsEqual(ctx, lg, 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 stringsToURLs(us []string) ([]url.URL, error) {
+ urls := make([]url.URL, 0, len(us))
+ for _, str := range us {
+ u, err := url.Parse(str)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse string to URL: %q", str)
+ }
+ urls = append(urls, *u)
+ }
+ return urls, nil
+}
+
+func IsNetworkTimeoutError(err error) bool {
+ nerr, ok := err.(net.Error)
+ return ok && nerr.Timeout()
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes.go b/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes.go
new file mode 100644
index 0000000000..f66719ea16
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes.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.
+
+//go:build !linux
+// +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/go.etcd.io/etcd/pkg/v3/netutil/routes_linux.go b/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes_linux.go
new file mode 100644
index 0000000000..5f8bd0c488
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes_linux.go
@@ -0,0 +1,251 @@
+// 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.
+
+//go:build linux
+// +build linux
+
+package netutil
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "net"
+ "sort"
+ "syscall"
+
+ "go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/pbutil/pbutil.go b/vendor/go.etcd.io/etcd/pkg/v3/pbutil/pbutil.go
new file mode 100644
index 0000000000..821f59703a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/pbutil/pbutil.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 pbutil defines interfaces for handling Protocol Buffer objects.
+package pbutil
+
+import "fmt"
+
+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 {
+ panic(fmt.Sprintf("marshal should never fail (%v)", err))
+ }
+ return d
+}
+
+func MustUnmarshal(um Unmarshaler, data []byte) {
+ if err := um.Unmarshal(data); err != nil {
+ panic(fmt.Sprintf("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/go.etcd.io/etcd/pkg/v3/runtime/fds_linux.go b/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_linux.go
new file mode 100644
index 0000000000..b5f6a7823a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_linux.go
@@ -0,0 +1,47 @@
+// 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 (
+ "os"
+ "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) {
+ return countFiles("/proc/self/fd")
+}
+
+// countFiles reads the directory named by dirname and returns the count.
+func countFiles(dirname string) (uint64, error) {
+ f, err := os.Open(dirname)
+ if err != nil {
+ return 0, err
+ }
+ list, err := f.Readdirnames(-1)
+ f.Close()
+ if err != nil {
+ return 0, err
+ }
+ return uint64(len(list)), nil
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_other.go b/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_other.go
new file mode 100644
index 0000000000..034f3d4264
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_other.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.
+
+//go:build !linux
+// +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/go.etcd.io/etcd/pkg/v3/schedule/doc.go b/vendor/go.etcd.io/etcd/pkg/v3/schedule/doc.go
new file mode 100644
index 0000000000..cca2c75fb6
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/schedule/schedule.go b/vendor/go.etcd.io/etcd/pkg/v3/schedule/schedule.go
new file mode 100644
index 0000000000..234d01989d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/pkg/v3/traceutil/trace.go b/vendor/go.etcd.io/etcd/pkg/v3/traceutil/trace.go
new file mode 100644
index 0000000000..bdd8e9b66a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/traceutil/trace.go
@@ -0,0 +1,240 @@
+// Copyright 2019 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 traceutil implements tracing utilities using "context".
+package traceutil
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "math/rand"
+ "time"
+
+ "go.uber.org/zap"
+)
+
+const (
+ TraceKey = "trace"
+ StartTimeKey = "startTime"
+)
+
+// Field is a kv pair to record additional details of the trace.
+type Field struct {
+ Key string
+ Value interface{}
+}
+
+func (f *Field) format() string {
+ return fmt.Sprintf("%s:%v; ", f.Key, f.Value)
+}
+
+func writeFields(fields []Field) string {
+ if len(fields) == 0 {
+ return ""
+ }
+ var buf bytes.Buffer
+ buf.WriteString("{")
+ for _, f := range fields {
+ buf.WriteString(f.format())
+ }
+ buf.WriteString("}")
+ return buf.String()
+}
+
+type Trace struct {
+ operation string
+ lg *zap.Logger
+ fields []Field
+ startTime time.Time
+ steps []step
+ stepDisabled bool
+ isEmpty bool
+}
+
+type step struct {
+ time time.Time
+ msg string
+ fields []Field
+ isSubTraceStart bool
+ isSubTraceEnd bool
+}
+
+func New(op string, lg *zap.Logger, fields ...Field) *Trace {
+ return &Trace{operation: op, lg: lg, startTime: time.Now(), fields: fields}
+}
+
+// TODO returns a non-nil, empty Trace
+func TODO() *Trace {
+ return &Trace{isEmpty: true}
+}
+
+func Get(ctx context.Context) *Trace {
+ if trace, ok := ctx.Value(TraceKey).(*Trace); ok && trace != nil {
+ return trace
+ }
+ return TODO()
+}
+
+func (t *Trace) GetStartTime() time.Time {
+ return t.startTime
+}
+
+func (t *Trace) SetStartTime(time time.Time) {
+ t.startTime = time
+}
+
+func (t *Trace) InsertStep(at int, time time.Time, msg string, fields ...Field) {
+ newStep := step{time: time, msg: msg, fields: fields}
+ if at < len(t.steps) {
+ t.steps = append(t.steps[:at+1], t.steps[at:]...)
+ t.steps[at] = newStep
+ } else {
+ t.steps = append(t.steps, newStep)
+ }
+}
+
+// StartSubTrace adds step to trace as a start sign of sublevel trace
+// All steps in the subtrace will log out the input fields of this function
+func (t *Trace) StartSubTrace(fields ...Field) {
+ t.steps = append(t.steps, step{fields: fields, isSubTraceStart: true})
+}
+
+// StopSubTrace adds step to trace as a end sign of sublevel trace
+// All steps in the subtrace will log out the input fields of this function
+func (t *Trace) StopSubTrace(fields ...Field) {
+ t.steps = append(t.steps, step{fields: fields, isSubTraceEnd: true})
+}
+
+// Step adds step to trace
+func (t *Trace) Step(msg string, fields ...Field) {
+ if !t.stepDisabled {
+ t.steps = append(t.steps, step{time: time.Now(), msg: msg, fields: fields})
+ }
+}
+
+// StepWithFunction will measure the input function as a single step
+func (t *Trace) StepWithFunction(f func(), msg string, fields ...Field) {
+ t.disableStep()
+ f()
+ t.enableStep()
+ t.Step(msg, fields...)
+}
+
+func (t *Trace) AddField(fields ...Field) {
+ for _, f := range fields {
+ if !t.updateFieldIfExist(f) {
+ t.fields = append(t.fields, f)
+ }
+ }
+}
+
+func (t *Trace) IsEmpty() bool {
+ return t.isEmpty
+}
+
+// Log dumps all steps in the Trace
+func (t *Trace) Log() {
+ t.LogWithStepThreshold(0)
+}
+
+// LogIfLong dumps logs if the duration is longer than threshold
+func (t *Trace) LogIfLong(threshold time.Duration) {
+ if time.Since(t.startTime) > threshold {
+ stepThreshold := threshold / time.Duration(len(t.steps)+1)
+ t.LogWithStepThreshold(stepThreshold)
+ }
+}
+
+// LogAllStepsIfLong dumps all logs if the duration is longer than threshold
+func (t *Trace) LogAllStepsIfLong(threshold time.Duration) {
+ if time.Since(t.startTime) > threshold {
+ t.LogWithStepThreshold(0)
+ }
+}
+
+// LogWithStepThreshold only dumps step whose duration is longer than step threshold
+func (t *Trace) LogWithStepThreshold(threshold time.Duration) {
+ msg, fs := t.logInfo(threshold)
+ if t.lg != nil {
+ t.lg.Info(msg, fs...)
+ }
+}
+
+func (t *Trace) logInfo(threshold time.Duration) (string, []zap.Field) {
+ endTime := time.Now()
+ totalDuration := endTime.Sub(t.startTime)
+ traceNum := rand.Int31()
+ msg := fmt.Sprintf("trace[%d] %s", traceNum, t.operation)
+
+ var steps []string
+ lastStepTime := t.startTime
+ for i := 0; i < len(t.steps); i++ {
+ step := t.steps[i]
+ // add subtrace common fields which defined at the beginning to each sub-steps
+ if step.isSubTraceStart {
+ for j := i + 1; j < len(t.steps) && !t.steps[j].isSubTraceEnd; j++ {
+ t.steps[j].fields = append(step.fields, t.steps[j].fields...)
+ }
+ continue
+ }
+ // add subtrace common fields which defined at the end to each sub-steps
+ if step.isSubTraceEnd {
+ for j := i - 1; j >= 0 && !t.steps[j].isSubTraceStart; j-- {
+ t.steps[j].fields = append(step.fields, t.steps[j].fields...)
+ }
+ continue
+ }
+ }
+ for i := 0; i < len(t.steps); i++ {
+ step := t.steps[i]
+ if step.isSubTraceStart || step.isSubTraceEnd {
+ continue
+ }
+ stepDuration := step.time.Sub(lastStepTime)
+ if stepDuration > threshold {
+ steps = append(steps, fmt.Sprintf("trace[%d] '%v' %s (duration: %v)",
+ traceNum, step.msg, writeFields(step.fields), stepDuration))
+ }
+ lastStepTime = step.time
+ }
+
+ fs := []zap.Field{zap.String("detail", writeFields(t.fields)),
+ zap.Duration("duration", totalDuration),
+ zap.Time("start", t.startTime),
+ zap.Time("end", endTime),
+ zap.Strings("steps", steps),
+ zap.Int("step_count", len(steps))}
+ return msg, fs
+}
+
+func (t *Trace) updateFieldIfExist(f Field) bool {
+ for i, v := range t.fields {
+ if v.Key == f.Key {
+ t.fields[i].Value = f.Value
+ return true
+ }
+ }
+ return false
+}
+
+// disableStep sets the flag to prevent the trace from adding steps
+func (t *Trace) disableStep() {
+ t.stepDisabled = true
+}
+
+// enableStep re-enable the trace to add steps
+func (t *Trace) enableStep() {
+ t.stepDisabled = false
+}
diff --git a/vendor/go.etcd.io/etcd/pkg/v3/wait/wait.go b/vendor/go.etcd.io/etcd/pkg/v3/wait/wait.go
new file mode 100644
index 0000000000..a3e2aec7cb
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/wait/wait.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 wait provides utility functions for polling, listening using Go
+// channel.
+package wait
+
+import (
+ "log"
+ "sync"
+)
+
+const (
+ // To avoid lock contention we use an array of list struct (rw mutex & map)
+ // for the id argument, we apply mod operation and uses its remainder to
+ // index into the array and find the corresponding element.
+ defaultListElementLength = 64
+)
+
+// 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 {
+ e []listElement
+}
+
+type listElement struct {
+ l sync.RWMutex
+ m map[uint64]chan interface{}
+}
+
+// New creates a Wait.
+func New() Wait {
+ res := list{
+ e: make([]listElement, defaultListElementLength),
+ }
+ for i := 0; i < len(res.e); i++ {
+ res.e[i].m = make(map[uint64]chan interface{})
+ }
+ return &res
+}
+
+func (w *list) Register(id uint64) <-chan interface{} {
+ idx := id % defaultListElementLength
+ newCh := make(chan interface{}, 1)
+ w.e[idx].l.Lock()
+ defer w.e[idx].l.Unlock()
+ if _, ok := w.e[idx].m[id]; !ok {
+ w.e[idx].m[id] = newCh
+ } else {
+ log.Panicf("dup id %x", id)
+ }
+ return newCh
+}
+
+func (w *list) Trigger(id uint64, x interface{}) {
+ idx := id % defaultListElementLength
+ w.e[idx].l.Lock()
+ ch := w.e[idx].m[id]
+ delete(w.e[idx].m, id)
+ w.e[idx].l.Unlock()
+ if ch != nil {
+ ch <- x
+ close(ch)
+ }
+}
+
+func (w *list) IsRegistered(id uint64) bool {
+ idx := id % defaultListElementLength
+ w.e[idx].l.RLock()
+ defer w.e[idx].l.RUnlock()
+ _, ok := w.e[idx].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/go.etcd.io/etcd/pkg/v3/wait/wait_time.go b/vendor/go.etcd.io/etcd/pkg/v3/wait/wait_time.go
new file mode 100644
index 0000000000..297e48a47d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/pkg/v3/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/go.etcd.io/etcd/raft/v3/LICENSE b/vendor/go.etcd.io/etcd/raft/v3/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/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/go.etcd.io/etcd/raft/v3/OWNERS b/vendor/go.etcd.io/etcd/raft/v3/OWNERS
new file mode 100644
index 0000000000..ab781066e2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/OWNERS
@@ -0,0 +1,19 @@
+approvers:
+- heyitsanthony
+- philips
+- fanminshi
+- gyuho
+- mitake
+- jpbetz
+- xiang90
+- bdarnell
+reviewers:
+- heyitsanthony
+- philips
+- fanminshi
+- gyuho
+- mitake
+- jpbetz
+- xiang90
+- bdarnell
+- tschottdorf
diff --git a/vendor/go.etcd.io/etcd/raft/v3/README.md b/vendor/go.etcd.io/etcd/raft/v3/README.md
new file mode 100644
index 0000000000..fbd8b4d49b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/README.md
@@ -0,0 +1,201 @@
+# Raft library
+
+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://raft.github.io/raft.pdf) by Diego Ongaro and John Ousterhout.
+
+This Raft library is stable and feature complete. As of 2016, it is **the most widely used** Raft library in production, serving tens of thousands clusters each day. It powers distributed systems such as etcd, Kubernetes, Docker Swarm, Cloud Foundry Diego, CockroachDB, TiDB, Project Calico, Flannel, Hyperledger and more.
+
+Most Raft implementations have a monolithic design, including storage handling, messaging serialization, and network transport. This library instead follows a minimalistic design philosophy by only implementing the core raft algorithm. This minimalism buys flexibility, determinism, and performance.
+
+To keep the codebase small as well as provide flexibility, the library only implements the Raft algorithm; both network and disk IO are left to the user. Library users must implement their own transportation layer for message passing between Raft peers over the wire. Similarly, users must implement their own storage layer to persist the Raft log and state.
+
+In order to easily test the Raft library, its behavior should be deterministic. To achieve this determinism, the library models Raft as a state machine. The state machine takes a `Message` as input. A message can either be a local timer update or a network message sent from a remote peer. The state machine's output is a 3-tuple `{[]Messages, []LogEntries, NextState}` consisting of an array of `Messages`, `log entries`, and `Raft state changes`. For state machines with the same state, the same state machine input should always generate the same state machine output.
+
+A simple example application, _raftexample_, is also available to help illustrate how to use this package in practice: https://github.com/etcd-io/etcd/tree/main/contrib/raftexample
+
+# Features
+
+This raft implementation is a full feature implementation of Raft protocol. Features includes:
+
+- Leader election
+- Log replication
+- Log compaction
+- Membership changes
+- Leadership transfer extension
+- Efficient linearizable read-only queries served by both the leader and followers
+ - leader checks with quorum and bypasses Raft log before processing read-only queries
+ - followers asks leader to get a safe read index before processing read-only queries
+- More efficient lease-based linearizable read-only queries served by both the leader and followers
+ - leader bypasses Raft log and processing read-only queries locally
+ - followers asks leader to get a safe read index before processing read-only queries
+ - this approach relies on the clock of the all the machines in raft group
+
+This raft implementation also includes a few optional enhancements:
+
+- Optimistic pipelining to reduce log replication latency
+- Flow control for log replication
+- Batching Raft messages to reduce synchronized network I/O calls
+- Batching log entries to reduce disk synchronized I/O
+- Writing to leader's disk in parallel
+- Internal proposal redirection from followers to leader
+- Automatic stepping down when the leader loses quorum
+- Protection against unbounded log growth when quorum is lost
+
+## Notable Users
+
+- [cockroachdb](https://github.com/cockroachdb/cockroach) A Scalable, Survivable, Strongly-Consistent SQL Database
+- [dgraph](https://github.com/dgraph-io/dgraph) A Scalable, Distributed, Low Latency, High Throughput Graph Database
+- [etcd](https://github.com/etcd-io/etcd) A distributed reliable key-value store
+- [tikv](https://github.com/pingcap/tikv) A Distributed transactional key value database powered by Rust and Raft
+- [swarmkit](https://github.com/docker/swarmkit) A toolkit for orchestrating distributed systems at any scale.
+- [chain core](https://github.com/chain/chain) Software for operating permissioned, multi-asset blockchain networks
+
+## Usage
+
+The primary object in raft is a Node. Either start a Node from scratch using raft.StartNode or start a Node from some initial state using raft.RestartNode.
+
+To start a three-node cluster
+```go
+ storage := raft.NewMemoryStorage()
+ c := &raft.Config{
+ ID: 0x01,
+ ElectionTick: 10,
+ HeartbeatTick: 1,
+ Storage: storage,
+ MaxSizePerMsg: 4096,
+ MaxInflightMsgs: 256,
+ }
+ // Set peer list to the other nodes in the cluster.
+ // Note that they need to be started separately as well.
+ n := raft.StartNode(c, []raft.Peer{{ID: 0x02}, {ID: 0x03}})
+```
+
+Start a single node cluster, like so:
+```go
+ // Create storage and config as shown above.
+ // Set peer list to itself, so this node can become the leader of this single-node cluster.
+ peers := []raft.Peer{{ID: 0x01}}
+ n := raft.StartNode(c, peers)
+```
+
+To allow a new node to join this cluster, do not pass in any peers. First, add the node to the existing cluster by calling `ProposeConfChange` on any existing node inside the cluster. Then, start the node with an empty peer list, like so:
+```go
+ // Create storage and config as shown above.
+ n := raft.StartNode(c, nil)
+```
+
+To restart a node from previous state:
+```go
+ storage := raft.NewMemoryStorage()
+
+ // Recover the in-memory storage from persistent snapshot, state and entries.
+ storage.ApplySnapshot(snapshot)
+ storage.SetHardState(state)
+ storage.Append(entries)
+
+ c := &raft.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)
+```
+
+After creating a Node, the user has a few responsibilities:
+
+First, 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 Entries, HardState and Snapshot to persistent storage in order, i.e. Entries first, then HardState and Snapshot if they are not empty. If persistent storage supports atomic writes then all of them can be written together. 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 to make sure that no new entries are persisted while marshalling. The easiest way to achieve this is to serialise the messages directly inside the 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 repopulating its state upon a restart), or a custom disk-backed implementation can be supplied.
+
+Third, after receiving a message from another node, pass it to Node.Step:
+
+```go
+ func recvRaftRPC(ctx context.Context, m raftpb.Message) {
+ n.Step(ctx, m)
+ }
+```
+
+Finally, 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:
+
+```go
+ for {
+ select {
+ case <-s.Ticker:
+ n.Tick()
+ case rd := <-s.Node.Ready():
+ saveToStorage(rd.HardState, 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 the node to take application data, serialize it into a byte slice and call:
+
+```go
+ 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; the command may have to be reproposed after a timeout.
+
+To add or remove node in a cluster, build ConfChange struct 'cc' and call:
+
+```go
+ n.ProposeConfChange(ctx, cc)
+```
+
+After config change is committed, some committed entry with type raftpb.EntryConfChange will be returned. This must be applied to node through:
+
+```go
+ 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://github.com/ongardie/dissertation/blob/master/stanford.pdf), although this 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 there is no attempt to commit two membership changes at once by matching log positions (which would be unsafe since they should have different quorum requirements), any proposed membership change is simply disallowed while any uncommitted change appears in the leader's log.
+
+This approach introduces a problem when removing 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.
+
+## Go docs
+
+More detailed development documentation can be found in go docs: https://pkg.go.dev/go.etcd.io/etcd/raft/v3.
\ No newline at end of file
diff --git a/vendor/go.etcd.io/etcd/raft/v3/bootstrap.go b/vendor/go.etcd.io/etcd/raft/v3/bootstrap.go
new file mode 100644
index 0000000000..824bd5f51b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/bootstrap.go
@@ -0,0 +1,80 @@
+// 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 "go.etcd.io/etcd/raft/v3/raftpb"
+)
+
+// Bootstrap initializes the RawNode for first use by appending configuration
+// changes for the supplied peers. This method returns an error if the Storage
+// is nonempty.
+//
+// It is recommended that instead of calling this method, applications bootstrap
+// their state manually by setting up a Storage that has a first index > 1 and
+// which stores the desired ConfState as its InitialState.
+func (rn *RawNode) Bootstrap(peers []Peer) error {
+ if len(peers) == 0 {
+ return errors.New("must provide at least one peer to Bootstrap")
+ }
+ lastIndex, err := rn.raft.raftLog.storage.LastIndex()
+ if err != nil {
+ return err
+ }
+
+ if lastIndex != 0 {
+ return errors.New("can't bootstrap a nonempty Storage")
+ }
+
+ // We've faked out initial entries above, but nothing has been
+ // persisted. Start with an empty HardState (thus the first Ready will
+ // emit a HardState update for the app to persist).
+ rn.prevHardSt = emptyState
+
+ // TODO(tbg): remove StartNode and give the application the right tools to
+ // bootstrap the initial membership in a cleaner way.
+ rn.raft.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 {
+ return err
+ }
+
+ ents[i] = pb.Entry{Type: pb.EntryConfChange, Term: 1, Index: uint64(i + 1), Data: data}
+ }
+ rn.raft.raftLog.append(ents...)
+
+ // 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.
+ //
+ // TODO(bdarnell): These entries are still unstable; do we need to preserve
+ // the invariant that committed < unstable?
+ rn.raft.raftLog.committed = uint64(len(ents))
+ for _, peer := range peers {
+ rn.raft.applyConfChange(pb.ConfChange{NodeID: peer.ID, Type: pb.ConfChangeAddNode}.AsV2())
+ }
+ return nil
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/confchange/confchange.go b/vendor/go.etcd.io/etcd/raft/v3/confchange/confchange.go
new file mode 100644
index 0000000000..dddbcc9d9b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/confchange/confchange.go
@@ -0,0 +1,423 @@
+// Copyright 2019 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 confchange
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+
+ "go.etcd.io/etcd/raft/v3/quorum"
+ pb "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/raft/v3/tracker"
+)
+
+// Changer facilitates configuration changes. It exposes methods to handle
+// simple and joint consensus while performing the proper validation that allows
+// refusing invalid configuration changes before they affect the active
+// configuration.
+type Changer struct {
+ Tracker tracker.ProgressTracker
+ LastIndex uint64
+}
+
+// EnterJoint verifies that the outgoing (=right) majority config of the joint
+// config is empty and initializes it with a copy of the incoming (=left)
+// majority config. That is, it transitions from
+//
+// (1 2 3)&&()
+//
+// to
+//
+// (1 2 3)&&(1 2 3).
+//
+// The supplied changes are then applied to the incoming majority config,
+// resulting in a joint configuration that in terms of the Raft thesis[1]
+// (Section 4.3) corresponds to `C_{new,old}`.
+//
+// [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf
+func (c Changer) EnterJoint(autoLeave bool, ccs ...pb.ConfChangeSingle) (tracker.Config, tracker.ProgressMap, error) {
+ cfg, prs, err := c.checkAndCopy()
+ if err != nil {
+ return c.err(err)
+ }
+ if joint(cfg) {
+ err := errors.New("config is already joint")
+ return c.err(err)
+ }
+ if len(incoming(cfg.Voters)) == 0 {
+ // We allow adding nodes to an empty config for convenience (testing and
+ // bootstrap), but you can't enter a joint state.
+ err := errors.New("can't make a zero-voter config joint")
+ return c.err(err)
+ }
+ // Clear the outgoing config.
+ *outgoingPtr(&cfg.Voters) = quorum.MajorityConfig{}
+ // Copy incoming to outgoing.
+ for id := range incoming(cfg.Voters) {
+ outgoing(cfg.Voters)[id] = struct{}{}
+ }
+
+ if err := c.apply(&cfg, prs, ccs...); err != nil {
+ return c.err(err)
+ }
+ cfg.AutoLeave = autoLeave
+ return checkAndReturn(cfg, prs)
+}
+
+// LeaveJoint transitions out of a joint configuration. It is an error to call
+// this method if the configuration is not joint, i.e. if the outgoing majority
+// config Voters[1] is empty.
+//
+// The outgoing majority config of the joint configuration will be removed,
+// that is, the incoming config is promoted as the sole decision maker. In the
+// notation of the Raft thesis[1] (Section 4.3), this method transitions from
+// `C_{new,old}` into `C_new`.
+//
+// At the same time, any staged learners (LearnersNext) the addition of which
+// was held back by an overlapping voter in the former outgoing config will be
+// inserted into Learners.
+//
+// [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf
+func (c Changer) LeaveJoint() (tracker.Config, tracker.ProgressMap, error) {
+ cfg, prs, err := c.checkAndCopy()
+ if err != nil {
+ return c.err(err)
+ }
+ if !joint(cfg) {
+ err := errors.New("can't leave a non-joint config")
+ return c.err(err)
+ }
+ if len(outgoing(cfg.Voters)) == 0 {
+ err := fmt.Errorf("configuration is not joint: %v", cfg)
+ return c.err(err)
+ }
+ for id := range cfg.LearnersNext {
+ nilAwareAdd(&cfg.Learners, id)
+ prs[id].IsLearner = true
+ }
+ cfg.LearnersNext = nil
+
+ for id := range outgoing(cfg.Voters) {
+ _, isVoter := incoming(cfg.Voters)[id]
+ _, isLearner := cfg.Learners[id]
+
+ if !isVoter && !isLearner {
+ delete(prs, id)
+ }
+ }
+ *outgoingPtr(&cfg.Voters) = nil
+ cfg.AutoLeave = false
+
+ return checkAndReturn(cfg, prs)
+}
+
+// Simple carries out a series of configuration changes that (in aggregate)
+// mutates the incoming majority config Voters[0] by at most one. This method
+// will return an error if that is not the case, if the resulting quorum is
+// zero, or if the configuration is in a joint state (i.e. if there is an
+// outgoing configuration).
+func (c Changer) Simple(ccs ...pb.ConfChangeSingle) (tracker.Config, tracker.ProgressMap, error) {
+ cfg, prs, err := c.checkAndCopy()
+ if err != nil {
+ return c.err(err)
+ }
+ if joint(cfg) {
+ err := errors.New("can't apply simple config change in joint config")
+ return c.err(err)
+ }
+ if err := c.apply(&cfg, prs, ccs...); err != nil {
+ return c.err(err)
+ }
+ if n := symdiff(incoming(c.Tracker.Voters), incoming(cfg.Voters)); n > 1 {
+ return tracker.Config{}, nil, errors.New("more than one voter changed without entering joint config")
+ }
+
+ return checkAndReturn(cfg, prs)
+}
+
+// apply a change to the configuration. By convention, changes to voters are
+// always made to the incoming majority config Voters[0]. Voters[1] is either
+// empty or preserves the outgoing majority configuration while in a joint state.
+func (c Changer) apply(cfg *tracker.Config, prs tracker.ProgressMap, ccs ...pb.ConfChangeSingle) error {
+ for _, cc := range ccs {
+ if cc.NodeID == 0 {
+ // etcd replaces the NodeID with zero if it decides (downstream of
+ // raft) to not apply a change, so we have to have explicit code
+ // here to ignore these.
+ continue
+ }
+ switch cc.Type {
+ case pb.ConfChangeAddNode:
+ c.makeVoter(cfg, prs, cc.NodeID)
+ case pb.ConfChangeAddLearnerNode:
+ c.makeLearner(cfg, prs, cc.NodeID)
+ case pb.ConfChangeRemoveNode:
+ c.remove(cfg, prs, cc.NodeID)
+ case pb.ConfChangeUpdateNode:
+ default:
+ return fmt.Errorf("unexpected conf type %d", cc.Type)
+ }
+ }
+ if len(incoming(cfg.Voters)) == 0 {
+ return errors.New("removed all voters")
+ }
+ return nil
+}
+
+// makeVoter adds or promotes the given ID to be a voter in the incoming
+// majority config.
+func (c Changer) makeVoter(cfg *tracker.Config, prs tracker.ProgressMap, id uint64) {
+ pr := prs[id]
+ if pr == nil {
+ c.initProgress(cfg, prs, id, false /* isLearner */)
+ return
+ }
+
+ pr.IsLearner = false
+ nilAwareDelete(&cfg.Learners, id)
+ nilAwareDelete(&cfg.LearnersNext, id)
+ incoming(cfg.Voters)[id] = struct{}{}
+}
+
+// makeLearner makes the given ID a learner or stages it to be a learner once
+// an active joint configuration is exited.
+//
+// The former happens when the peer is not a part of the outgoing config, in
+// which case we either add a new learner or demote a voter in the incoming
+// config.
+//
+// The latter case occurs when the configuration is joint and the peer is a
+// voter in the outgoing config. In that case, we do not want to add the peer
+// as a learner because then we'd have to track a peer as a voter and learner
+// simultaneously. Instead, we add the learner to LearnersNext, so that it will
+// be added to Learners the moment the outgoing config is removed by
+// LeaveJoint().
+func (c Changer) makeLearner(cfg *tracker.Config, prs tracker.ProgressMap, id uint64) {
+ pr := prs[id]
+ if pr == nil {
+ c.initProgress(cfg, prs, id, true /* isLearner */)
+ return
+ }
+ if pr.IsLearner {
+ return
+ }
+ // Remove any existing voter in the incoming config...
+ c.remove(cfg, prs, id)
+ // ... but save the Progress.
+ prs[id] = pr
+ // Use LearnersNext if we can't add the learner to Learners directly, i.e.
+ // if the peer is still tracked as a voter in the outgoing config. It will
+ // be turned into a learner in LeaveJoint().
+ //
+ // Otherwise, add a regular learner right away.
+ if _, onRight := outgoing(cfg.Voters)[id]; onRight {
+ nilAwareAdd(&cfg.LearnersNext, id)
+ } else {
+ pr.IsLearner = true
+ nilAwareAdd(&cfg.Learners, id)
+ }
+}
+
+// remove this peer as a voter or learner from the incoming config.
+func (c Changer) remove(cfg *tracker.Config, prs tracker.ProgressMap, id uint64) {
+ if _, ok := prs[id]; !ok {
+ return
+ }
+
+ delete(incoming(cfg.Voters), id)
+ nilAwareDelete(&cfg.Learners, id)
+ nilAwareDelete(&cfg.LearnersNext, id)
+
+ // If the peer is still a voter in the outgoing config, keep the Progress.
+ if _, onRight := outgoing(cfg.Voters)[id]; !onRight {
+ delete(prs, id)
+ }
+}
+
+// initProgress initializes a new progress for the given node or learner.
+func (c Changer) initProgress(cfg *tracker.Config, prs tracker.ProgressMap, id uint64, isLearner bool) {
+ if !isLearner {
+ incoming(cfg.Voters)[id] = struct{}{}
+ } else {
+ nilAwareAdd(&cfg.Learners, id)
+ }
+ prs[id] = &tracker.Progress{
+ // Initializing the Progress with the last index means that the follower
+ // can be probed (with the last index).
+ //
+ // TODO(tbg): seems awfully optimistic. Using the first index would be
+ // better. The general expectation here is that the follower has no log
+ // at all (and will thus likely need a snapshot), though the app may
+ // have applied a snapshot out of band before adding the replica (thus
+ // making the first index the better choice).
+ Next: c.LastIndex,
+ Match: 0,
+ Inflights: tracker.NewInflights(c.Tracker.MaxInflight),
+ 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 had a chance to communicate with us.
+ RecentActive: true,
+ }
+}
+
+// checkInvariants makes sure that the config and progress are compatible with
+// each other. This is used to check both what the Changer is initialized with,
+// as well as what it returns.
+func checkInvariants(cfg tracker.Config, prs tracker.ProgressMap) error {
+ // NB: intentionally allow the empty config. In production we'll never see a
+ // non-empty config (we prevent it from being created) but we will need to
+ // be able to *create* an initial config, for example during bootstrap (or
+ // during tests). Instead of having to hand-code this, we allow
+ // transitioning from an empty config into any other legal and non-empty
+ // config.
+ for _, ids := range []map[uint64]struct{}{
+ cfg.Voters.IDs(),
+ cfg.Learners,
+ cfg.LearnersNext,
+ } {
+ for id := range ids {
+ if _, ok := prs[id]; !ok {
+ return fmt.Errorf("no progress for %d", id)
+ }
+ }
+ }
+
+ // Any staged learner was staged because it could not be directly added due
+ // to a conflicting voter in the outgoing config.
+ for id := range cfg.LearnersNext {
+ if _, ok := outgoing(cfg.Voters)[id]; !ok {
+ return fmt.Errorf("%d is in LearnersNext, but not Voters[1]", id)
+ }
+ if prs[id].IsLearner {
+ return fmt.Errorf("%d is in LearnersNext, but is already marked as learner", id)
+ }
+ }
+ // Conversely Learners and Voters doesn't intersect at all.
+ for id := range cfg.Learners {
+ if _, ok := outgoing(cfg.Voters)[id]; ok {
+ return fmt.Errorf("%d is in Learners and Voters[1]", id)
+ }
+ if _, ok := incoming(cfg.Voters)[id]; ok {
+ return fmt.Errorf("%d is in Learners and Voters[0]", id)
+ }
+ if !prs[id].IsLearner {
+ return fmt.Errorf("%d is in Learners, but is not marked as learner", id)
+ }
+ }
+
+ if !joint(cfg) {
+ // We enforce that empty maps are nil instead of zero.
+ if outgoing(cfg.Voters) != nil {
+ return fmt.Errorf("cfg.Voters[1] must be nil when not joint")
+ }
+ if cfg.LearnersNext != nil {
+ return fmt.Errorf("cfg.LearnersNext must be nil when not joint")
+ }
+ if cfg.AutoLeave {
+ return fmt.Errorf("AutoLeave must be false when not joint")
+ }
+ }
+
+ return nil
+}
+
+// checkAndCopy copies the tracker's config and progress map (deeply enough for
+// the purposes of the Changer) and returns those copies. It returns an error
+// if checkInvariants does.
+func (c Changer) checkAndCopy() (tracker.Config, tracker.ProgressMap, error) {
+ cfg := c.Tracker.Config.Clone()
+ prs := tracker.ProgressMap{}
+
+ for id, pr := range c.Tracker.Progress {
+ // A shallow copy is enough because we only mutate the Learner field.
+ ppr := *pr
+ prs[id] = &ppr
+ }
+ return checkAndReturn(cfg, prs)
+}
+
+// checkAndReturn calls checkInvariants on the input and returns either the
+// resulting error or the input.
+func checkAndReturn(cfg tracker.Config, prs tracker.ProgressMap) (tracker.Config, tracker.ProgressMap, error) {
+ if err := checkInvariants(cfg, prs); err != nil {
+ return tracker.Config{}, tracker.ProgressMap{}, err
+ }
+ return cfg, prs, nil
+}
+
+// err returns zero values and an error.
+func (c Changer) err(err error) (tracker.Config, tracker.ProgressMap, error) {
+ return tracker.Config{}, nil, err
+}
+
+// nilAwareAdd populates a map entry, creating the map if necessary.
+func nilAwareAdd(m *map[uint64]struct{}, id uint64) {
+ if *m == nil {
+ *m = map[uint64]struct{}{}
+ }
+ (*m)[id] = struct{}{}
+}
+
+// nilAwareDelete deletes from a map, nil'ing the map itself if it is empty after.
+func nilAwareDelete(m *map[uint64]struct{}, id uint64) {
+ if *m == nil {
+ return
+ }
+ delete(*m, id)
+ if len(*m) == 0 {
+ *m = nil
+ }
+}
+
+// symdiff returns the count of the symmetric difference between the sets of
+// uint64s, i.e. len( (l - r) \union (r - l)).
+func symdiff(l, r map[uint64]struct{}) int {
+ var n int
+ pairs := [][2]quorum.MajorityConfig{
+ {l, r}, // count elems in l but not in r
+ {r, l}, // count elems in r but not in l
+ }
+ for _, p := range pairs {
+ for id := range p[0] {
+ if _, ok := p[1][id]; !ok {
+ n++
+ }
+ }
+ }
+ return n
+}
+
+func joint(cfg tracker.Config) bool {
+ return len(outgoing(cfg.Voters)) > 0
+}
+
+func incoming(voters quorum.JointConfig) quorum.MajorityConfig { return voters[0] }
+func outgoing(voters quorum.JointConfig) quorum.MajorityConfig { return voters[1] }
+func outgoingPtr(voters *quorum.JointConfig) *quorum.MajorityConfig { return &voters[1] }
+
+// Describe prints the type and NodeID of the configuration changes as a
+// space-delimited string.
+func Describe(ccs ...pb.ConfChangeSingle) string {
+ var buf strings.Builder
+ for _, cc := range ccs {
+ if buf.Len() > 0 {
+ buf.WriteByte(' ')
+ }
+ fmt.Fprintf(&buf, "%s(%d)", cc.Type, cc.NodeID)
+ }
+ return buf.String()
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/confchange/restore.go b/vendor/go.etcd.io/etcd/raft/v3/confchange/restore.go
new file mode 100644
index 0000000000..ea317fc289
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/confchange/restore.go
@@ -0,0 +1,155 @@
+// Copyright 2019 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 confchange
+
+import (
+ pb "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/raft/v3/tracker"
+)
+
+// toConfChangeSingle translates a conf state into 1) a slice of operations creating
+// first the config that will become the outgoing one, and then the incoming one, and
+// b) another slice that, when applied to the config resulted from 1), represents the
+// ConfState.
+func toConfChangeSingle(cs pb.ConfState) (out []pb.ConfChangeSingle, in []pb.ConfChangeSingle) {
+ // Example to follow along this code:
+ // voters=(1 2 3) learners=(5) outgoing=(1 2 4 6) learners_next=(4)
+ //
+ // This means that before entering the joint config, the configuration
+ // had voters (1 2 4 6) and perhaps some learners that are already gone.
+ // The new set of voters is (1 2 3), i.e. (1 2) were kept around, and (4 6)
+ // are no longer voters; however 4 is poised to become a learner upon leaving
+ // the joint state.
+ // We can't tell whether 5 was a learner before entering the joint config,
+ // but it doesn't matter (we'll pretend that it wasn't).
+ //
+ // The code below will construct
+ // outgoing = add 1; add 2; add 4; add 6
+ // incoming = remove 1; remove 2; remove 4; remove 6
+ // add 1; add 2; add 3;
+ // add-learner 5;
+ // add-learner 4;
+ //
+ // So, when starting with an empty config, after applying 'outgoing' we have
+ //
+ // quorum=(1 2 4 6)
+ //
+ // From which we enter a joint state via 'incoming'
+ //
+ // quorum=(1 2 3)&&(1 2 4 6) learners=(5) learners_next=(4)
+ //
+ // as desired.
+
+ for _, id := range cs.VotersOutgoing {
+ // If there are outgoing voters, first add them one by one so that the
+ // (non-joint) config has them all.
+ out = append(out, pb.ConfChangeSingle{
+ Type: pb.ConfChangeAddNode,
+ NodeID: id,
+ })
+
+ }
+
+ // We're done constructing the outgoing slice, now on to the incoming one
+ // (which will apply on top of the config created by the outgoing slice).
+
+ // First, we'll remove all of the outgoing voters.
+ for _, id := range cs.VotersOutgoing {
+ in = append(in, pb.ConfChangeSingle{
+ Type: pb.ConfChangeRemoveNode,
+ NodeID: id,
+ })
+ }
+ // Then we'll add the incoming voters and learners.
+ for _, id := range cs.Voters {
+ in = append(in, pb.ConfChangeSingle{
+ Type: pb.ConfChangeAddNode,
+ NodeID: id,
+ })
+ }
+ for _, id := range cs.Learners {
+ in = append(in, pb.ConfChangeSingle{
+ Type: pb.ConfChangeAddLearnerNode,
+ NodeID: id,
+ })
+ }
+ // Same for LearnersNext; these are nodes we want to be learners but which
+ // are currently voters in the outgoing config.
+ for _, id := range cs.LearnersNext {
+ in = append(in, pb.ConfChangeSingle{
+ Type: pb.ConfChangeAddLearnerNode,
+ NodeID: id,
+ })
+ }
+ return out, in
+}
+
+func chain(chg Changer, ops ...func(Changer) (tracker.Config, tracker.ProgressMap, error)) (tracker.Config, tracker.ProgressMap, error) {
+ for _, op := range ops {
+ cfg, prs, err := op(chg)
+ if err != nil {
+ return tracker.Config{}, nil, err
+ }
+ chg.Tracker.Config = cfg
+ chg.Tracker.Progress = prs
+ }
+ return chg.Tracker.Config, chg.Tracker.Progress, nil
+}
+
+// Restore takes a Changer (which must represent an empty configuration), and
+// runs a sequence of changes enacting the configuration described in the
+// ConfState.
+//
+// TODO(tbg) it's silly that this takes a Changer. Unravel this by making sure
+// the Changer only needs a ProgressMap (not a whole Tracker) at which point
+// this can just take LastIndex and MaxInflight directly instead and cook up
+// the results from that alone.
+func Restore(chg Changer, cs pb.ConfState) (tracker.Config, tracker.ProgressMap, error) {
+ outgoing, incoming := toConfChangeSingle(cs)
+
+ var ops []func(Changer) (tracker.Config, tracker.ProgressMap, error)
+
+ if len(outgoing) == 0 {
+ // No outgoing config, so just apply the incoming changes one by one.
+ for _, cc := range incoming {
+ cc := cc // loop-local copy
+ ops = append(ops, func(chg Changer) (tracker.Config, tracker.ProgressMap, error) {
+ return chg.Simple(cc)
+ })
+ }
+ } else {
+ // The ConfState describes a joint configuration.
+ //
+ // First, apply all of the changes of the outgoing config one by one, so
+ // that it temporarily becomes the incoming active config. For example,
+ // if the config is (1 2 3)&(2 3 4), this will establish (2 3 4)&().
+ for _, cc := range outgoing {
+ cc := cc // loop-local copy
+ ops = append(ops, func(chg Changer) (tracker.Config, tracker.ProgressMap, error) {
+ return chg.Simple(cc)
+ })
+ }
+ // Now enter the joint state, which rotates the above additions into the
+ // outgoing config, and adds the incoming config in. Continuing the
+ // example above, we'd get (1 2 3)&(2 3 4), i.e. the incoming operations
+ // would be removing 2,3,4 and then adding in 1,2,3 while transitioning
+ // into a joint state.
+ ops = append(ops, func(chg Changer) (tracker.Config, tracker.ProgressMap, error) {
+ return chg.EnterJoint(cs.AutoLeave, incoming...)
+ })
+ }
+
+ return chain(chg, ops...)
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/design.md b/vendor/go.etcd.io/etcd/raft/v3/design.md
new file mode 100644
index 0000000000..7bc0531dce
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/design.md
@@ -0,0 +1,57 @@
+## Progress
+
+Progress represents a follower’s progress in the view of the leader. Leader maintains progresses of all followers, and sends `replication message` to the follower based on its progress.
+
+`replication message` is a `msgApp` with log entries.
+
+A progress has two attribute: `match` and `next`. `match` is the index of the highest known matched entry. If leader knows nothing about follower’s replication status, `match` is set to zero. `next` is the index of the first entry that will be replicated to the follower. Leader puts entries from `next` to its latest one in next `replication message`.
+
+A progress is in one of the three state: `probe`, `replicate`, `snapshot`.
+
+```
+ +--------------------------------------------------------+
+ | send snapshot |
+ | |
+ +---------+----------+ +----------v---------+
+ +---> probe | | snapshot |
+ | | max inflight = 1 <----------------------------------+ max inflight = 0 |
+ | +---------+----------+ +--------------------+
+ | | 1. snapshot success
+ | | (next=snapshot.index + 1)
+ | | 2. snapshot failure
+ | | (no change)
+ | | 3. receives msgAppResp(rej=false&&index>lastsnap.index)
+ | | (match=m.index,next=match+1)
+receives msgAppResp(rej=true)
+(next=match+1)| |
+ | |
+ | |
+ | | receives msgAppResp(rej=false&&index>match)
+ | | (match=m.index,next=match+1)
+ | |
+ | |
+ | |
+ | +---------v----------+
+ | | replicate |
+ +---+ max inflight = n |
+ +--------------------+
+```
+
+When the progress of a follower is in `probe` state, leader sends at most one `replication message` per heartbeat interval. The leader sends `replication message` slowly and probing the actual progress of the follower. A `msgHeartbeatResp` or a `msgAppResp` with reject might trigger the sending of the next `replication message`.
+
+When the progress of a follower is in `replicate` state, leader sends `replication message`, then optimistically increases `next` to the latest entry sent. This is an optimized state for fast replicating log entries to the follower.
+
+When the progress of a follower is in `snapshot` state, leader stops sending any `replication message`.
+
+A newly elected leader sets the progresses of all the followers to `probe` state with `match` = 0 and `next` = last index. The leader slowly (at most once per heartbeat) sends `replication message` to the follower and probes its progress.
+
+A progress changes to `replicate` when the follower replies with a non-rejection `msgAppResp`, which implies that it has matched the index sent. At this point, leader starts to stream log entries to the follower fast. The progress will fall back to `probe` when the follower replies a rejection `msgAppResp` or the link layer reports the follower is unreachable. We aggressively reset `next` to `match`+1 since if we receive any `msgAppResp` soon, both `match` and `next` will increase directly to the `index` in `msgAppResp`. (We might end up with sending some duplicate entries when aggressively reset `next` too low. see open question)
+
+A progress changes from `probe` to `snapshot` when the follower falls very far behind and requires a snapshot. After sending `msgSnap`, the leader waits until the success, failure or abortion of the previous snapshot sent. The progress will go back to `probe` after the sending result is applied.
+
+### Flow Control
+
+1. limit the max size of message sent per message. Max should be configurable.
+Lower the cost at probing state as we limit the size per message; lower the penalty when aggressively decreased to a too low `next`
+
+2. limit the # of in flight messages < N when in `replicate` state. N should be configurable. Most implementation will have a sending buffer on top of its actual network transport layer (not blocking raft node). We want to make sure raft does not overflow that buffer, which can cause message dropping and triggering a bunch of unnecessary resending repeatedly.
diff --git a/vendor/go.etcd.io/etcd/raft/v3/doc.go b/vendor/go.etcd.io/etcd/raft/v3/doc.go
new file mode 100644
index 0000000000..4febfe6084
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/doc.go
@@ -0,0 +1,299 @@
+// 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://raft.github.io/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/etcd-io/etcd/tree/main/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 serialize 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 a 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://github.com/ongardie/dissertation/blob/master/stanford.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 campaigning 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/go.etcd.io/etcd/raft/v3/log.go b/vendor/go.etcd.io/etcd/raft/v3/log.go
new file mode 100644
index 0000000000..c94c41f778
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/log.go
@@ -0,0 +1,406 @@
+// 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 "go.etcd.io/etcd/raft/v3/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
+
+ // maxNextEntsSize is the maximum number aggregate byte size of the messages
+ // returned from calls to nextEnts.
+ maxNextEntsSize uint64
+}
+
+// newLog returns log using the given storage and default options. It
+// recovers the log to the state that it just commits and applies the
+// latest snapshot.
+func newLog(storage Storage, logger Logger) *raftLog {
+ return newLogWithSize(storage, logger, noLimit)
+}
+
+// newLogWithSize returns a log using the given storage and max
+// message size.
+func newLogWithSize(storage Storage, logger Logger, maxNextEntsSize uint64) *raftLog {
+ if storage == nil {
+ log.Panic("storage must not be nil")
+ }
+ log := &raftLog{
+ storage: storage,
+ logger: logger,
+ maxNextEntsSize: maxNextEntsSize,
+ }
+ 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 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
+}
+
+// findConflictByTerm takes an (index, term) pair (indicating a conflicting log
+// entry on a leader/follower during an append) and finds the largest index in
+// log l with a term <= `term` and an index <= `index`. If no such index exists
+// in the log, the log's first index is returned.
+//
+// The index provided MUST be equal to or less than l.lastIndex(). Invalid
+// inputs log a warning and the input index is returned.
+func (l *raftLog) findConflictByTerm(index uint64, term uint64) uint64 {
+ if li := l.lastIndex(); index > li {
+ // NB: such calls should not exist, but since there is a straightfoward
+ // way to recover, do it.
+ //
+ // It is tempting to also check something about the first index, but
+ // there is odd behavior with peers that have no log, in which case
+ // lastIndex will return zero and firstIndex will return one, which
+ // leads to calls with an index of zero into this method.
+ l.logger.Warningf("index(%d) is out of range [0, lastIndex(%d)] in findConflictByTerm",
+ index, li)
+ return index
+ }
+ for {
+ logTerm, err := l.term(index)
+ if logTerm <= term || err != nil {
+ break
+ }
+ index--
+ }
+ return index
+}
+
+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, l.maxNextEntsSize)
+ 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
+}
+
+// hasPendingSnapshot returns if there is pending snapshot waiting for applying.
+func (l *raftLog) hasPendingSnapshot() bool {
+ return l.unstable.snapshot != nil && !IsEmptySnap(*l.unstable.snapshot)
+}
+
+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 {
+ combined := make([]pb.Entry, len(ents)+len(unstable))
+ n := copy(combined, ents)
+ copy(combined[n:], unstable)
+ ents = combined
+ } 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 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/go.etcd.io/etcd/raft/v3/log_unstable.go b/vendor/go.etcd.io/etcd/raft/v3/log_unstable.go
new file mode 100644
index 0000000000..230fd21f99
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/log_unstable.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 raft
+
+import pb "go.etcd.io/etcd/raft/v3/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 && 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.entries)
+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/go.etcd.io/etcd/raft/v3/logger.go b/vendor/go.etcd.io/etcd/raft/v3/logger.go
new file mode 100644
index 0000000000..dc73b1f210
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/logger.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 raft
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "sync"
+)
+
+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) {
+ raftLoggerMu.Lock()
+ raftLogger = l
+ raftLoggerMu.Unlock()
+}
+
+func ResetDefaultLogger() {
+ SetLogger(defaultLogger)
+}
+
+func getLogger() Logger {
+ raftLoggerMu.Lock()
+ defer raftLoggerMu.Unlock()
+ return raftLogger
+}
+
+var (
+ defaultLogger = &DefaultLogger{Logger: log.New(os.Stderr, "raft", log.LstdFlags)}
+ discardLogger = &DefaultLogger{Logger: log.New(ioutil.Discard, "", 0)}
+ raftLoggerMu sync.Mutex
+ 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/go.etcd.io/etcd/raft/v3/node.go b/vendor/go.etcd.io/etcd/raft/v3/node.go
new file mode 100644
index 0000000000..dca5954f7a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/node.go
@@ -0,0 +1,590 @@
+// 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 "go.etcd.io/etcd/raft/v3/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
+}
+
+// appliedCursor extracts from the Ready the highest index the client has
+// applied (once the Ready is confirmed via Advance). If no information is
+// contained in the Ready, returns zero.
+func (rd Ready) appliedCursor() uint64 {
+ if n := len(rd.CommittedEntries); n > 0 {
+ return rd.CommittedEntries[n-1].Index
+ }
+ if index := rd.Snapshot.Metadata.Index; index > 0 {
+ return index
+ }
+ return 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. Note that proposals can be lost without
+ // notice, therefore it is user's job to ensure proposal retries.
+ Propose(ctx context.Context, data []byte) error
+ // ProposeConfChange proposes a configuration change. Like any proposal, the
+ // configuration change may be dropped with or without an error being
+ // returned. In particular, configuration changes are dropped unless the
+ // leader has certainty that there is no prior unapplied configuration
+ // change in its log.
+ //
+ // The method accepts either a pb.ConfChange (deprecated) or pb.ConfChangeV2
+ // message. The latter allows arbitrary configuration changes via joint
+ // consensus, notably including replacing a voter. Passing a ConfChangeV2
+ // message is only allowed if all Nodes participating in the cluster run a
+ // version of this library aware of the V2 API. See pb.ConfChangeV2 for
+ // usage details and semantics.
+ ProposeConfChange(ctx context.Context, cc pb.ConfChangeI) 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 a config change (previously passed to
+ // ProposeConfChange) to the node. This must be called whenever a config
+ // change is observed in Ready.CommittedEntries, except when the app decides
+ // to reject the configuration change (i.e. treats it as a noop instead), in
+ // which case it must not be called.
+ //
+ // Returns an opaque non-nil ConfState protobuf which must be recorded in
+ // snapshots.
+ ApplyConfChange(cc pb.ConfChangeI) *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.
+ // Note that request can be lost without notice, therefore it is user's job
+ // to ensure read index retries.
+ 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. The id is the raft ID of the follower
+ // who is meant to receive the snapshot, and the status is SnapshotFinish or SnapshotFailure.
+ // Calling ReportSnapshot with SnapshotFinish is a no-op. But, any failure in applying a
+ // snapshot (for e.g., while streaming it from leader to follower), should be reported to the
+ // leader with SnapshotFailure. When leader sends a snapshot to a follower, it pauses any raft
+ // log probes until the follower can apply the snapshot and advance its state. If the follower
+ // can't do that, for e.g., due to a crash, it could end up in a limbo, never getting any
+ // updates from the leader. Therefore, it is crucial that the application ensures that any
+ // failure in snapshot sending is caught and reported back to the leader; so it can resume raft
+ // log probing in the follower.
+ 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.
+//
+// Peers must not be zero length; call RestartNode in that case.
+func StartNode(c *Config, peers []Peer) Node {
+ if len(peers) == 0 {
+ panic("no peers given; use RestartNode instead")
+ }
+ rn, err := NewRawNode(c)
+ if err != nil {
+ panic(err)
+ }
+ rn.Bootstrap(peers)
+
+ n := newNode(rn)
+
+ go n.run()
+ 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 {
+ rn, err := NewRawNode(c)
+ if err != nil {
+ panic(err)
+ }
+ n := newNode(rn)
+ go n.run()
+ return &n
+}
+
+type msgWithResult struct {
+ m pb.Message
+ result chan error
+}
+
+// node is the canonical implementation of the Node interface
+type node struct {
+ propc chan msgWithResult
+ recvc chan pb.Message
+ confc chan pb.ConfChangeV2
+ confstatec chan pb.ConfState
+ readyc chan Ready
+ advancec chan struct{}
+ tickc chan struct{}
+ done chan struct{}
+ stop chan struct{}
+ status chan chan Status
+
+ rn *RawNode
+}
+
+func newNode(rn *RawNode) node {
+ return node{
+ propc: make(chan msgWithResult),
+ recvc: make(chan pb.Message),
+ confc: make(chan pb.ConfChangeV2),
+ 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),
+ rn: rn,
+ }
+}
+
+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() {
+ var propc chan msgWithResult
+ var readyc chan Ready
+ var advancec chan struct{}
+ var rd Ready
+
+ r := n.rn.raft
+
+ lead := None
+
+ for {
+ if advancec != nil {
+ readyc = nil
+ } else if n.rn.HasReady() {
+ // Populate a Ready. Note that this Ready is not guaranteed to
+ // actually be handled. We will arm readyc, but there's no guarantee
+ // that we will actually send on it. It's possible that we will
+ // service another channel instead, loop around, and then populate
+ // the Ready again. We could instead force the previous Ready to be
+ // handled first, but it's generally good to emit larger Readys plus
+ // it simplifies testing (by emitting less frequently and more
+ // predictably).
+ rd = n.rn.readyWithoutAccept()
+ readyc = n.readyc
+ }
+
+ 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 pm := <-propc:
+ m := pm.m
+ m.From = r.id
+ err := r.Step(m)
+ if pm.result != nil {
+ pm.result <- err
+ close(pm.result)
+ }
+ case m := <-n.recvc:
+ // filter out response message from unknown From.
+ if pr := r.prs.Progress[m.From]; pr != nil || !IsResponseMsg(m.Type) {
+ r.Step(m)
+ }
+ case cc := <-n.confc:
+ _, okBefore := r.prs.Progress[r.id]
+ cs := r.applyConfChange(cc)
+ // If the node was removed, block incoming proposals. Note that we
+ // only do this if the node was in the config before. Nodes may be
+ // a member of the group without knowing this (when they're catching
+ // up on the log and don't have the latest config) and we don't want
+ // to block the proposal channel in that case.
+ //
+ // NB: propc is reset when the leader changes, which, if we learn
+ // about it, sort of implies that we got readded, maybe? This isn't
+ // very sound and likely has bugs.
+ if _, okAfter := r.prs.Progress[r.id]; okBefore && !okAfter {
+ var found bool
+ outer:
+ for _, sl := range [][]uint64{cs.Voters, cs.VotersOutgoing} {
+ for _, id := range sl {
+ if id == r.id {
+ found = true
+ break outer
+ }
+ }
+ }
+ if !found {
+ propc = nil
+ }
+ }
+ select {
+ case n.confstatec <- cs:
+ case <-n.done:
+ }
+ case <-n.tickc:
+ n.rn.Tick()
+ case readyc <- rd:
+ n.rn.acceptReady(rd)
+ advancec = n.advancec
+ case <-advancec:
+ n.rn.Advance(rd)
+ rd = Ready{}
+ 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.rn.raft.logger.Warningf("%x A tick missed to fire. Node blocks too long!", n.rn.raft.id)
+ }
+}
+
+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.stepWait(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 confChangeToMsg(c pb.ConfChangeI) (pb.Message, error) {
+ typ, data, err := pb.MarshalConfChange(c)
+ if err != nil {
+ return pb.Message{}, err
+ }
+ return pb.Message{Type: pb.MsgProp, Entries: []pb.Entry{{Type: typ, Data: data}}}, nil
+}
+
+func (n *node) ProposeConfChange(ctx context.Context, cc pb.ConfChangeI) error {
+ msg, err := confChangeToMsg(cc)
+ if err != nil {
+ return err
+ }
+ return n.Step(ctx, msg)
+}
+
+func (n *node) step(ctx context.Context, m pb.Message) error {
+ return n.stepWithWaitOption(ctx, m, false)
+}
+
+func (n *node) stepWait(ctx context.Context, m pb.Message) error {
+ return n.stepWithWaitOption(ctx, m, true)
+}
+
+// Step advances the state machine using msgs. The ctx.Err() will be returned,
+// if any.
+func (n *node) stepWithWaitOption(ctx context.Context, m pb.Message, wait bool) error {
+ if m.Type != pb.MsgProp {
+ select {
+ case n.recvc <- m:
+ return nil
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-n.done:
+ return ErrStopped
+ }
+ }
+ ch := n.propc
+ pm := msgWithResult{m: m}
+ if wait {
+ pm.result = make(chan error, 1)
+ }
+ select {
+ case ch <- pm:
+ if !wait {
+ return nil
+ }
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-n.done:
+ return ErrStopped
+ }
+ select {
+ case err := <-pm.result:
+ if err != nil {
+ return err
+ }
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-n.done:
+ return ErrStopped
+ }
+ return nil
+}
+
+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.ConfChangeI) *pb.ConfState {
+ var cs pb.ConfState
+ select {
+ case n.confc <- cc.AsV2():
+ 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(r.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/go.etcd.io/etcd/raft/v3/quorum/joint.go b/vendor/go.etcd.io/etcd/raft/v3/quorum/joint.go
new file mode 100644
index 0000000000..e3741e0b0a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/quorum/joint.go
@@ -0,0 +1,75 @@
+// Copyright 2019 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 quorum
+
+// JointConfig is a configuration of two groups of (possibly overlapping)
+// majority configurations. Decisions require the support of both majorities.
+type JointConfig [2]MajorityConfig
+
+func (c JointConfig) String() string {
+ if len(c[1]) > 0 {
+ return c[0].String() + "&&" + c[1].String()
+ }
+ return c[0].String()
+}
+
+// IDs returns a newly initialized map representing the set of voters present
+// in the joint configuration.
+func (c JointConfig) IDs() map[uint64]struct{} {
+ m := map[uint64]struct{}{}
+ for _, cc := range c {
+ for id := range cc {
+ m[id] = struct{}{}
+ }
+ }
+ return m
+}
+
+// Describe returns a (multi-line) representation of the commit indexes for the
+// given lookuper.
+func (c JointConfig) Describe(l AckedIndexer) string {
+ return MajorityConfig(c.IDs()).Describe(l)
+}
+
+// CommittedIndex returns the largest committed index for the given joint
+// quorum. An index is jointly committed if it is committed in both constituent
+// majorities.
+func (c JointConfig) CommittedIndex(l AckedIndexer) Index {
+ idx0 := c[0].CommittedIndex(l)
+ idx1 := c[1].CommittedIndex(l)
+ if idx0 < idx1 {
+ return idx0
+ }
+ return idx1
+}
+
+// VoteResult takes a mapping of voters to yes/no (true/false) votes and returns
+// a result indicating whether the vote is pending, lost, or won. A joint quorum
+// requires both majority quorums to vote in favor.
+func (c JointConfig) VoteResult(votes map[uint64]bool) VoteResult {
+ r1 := c[0].VoteResult(votes)
+ r2 := c[1].VoteResult(votes)
+
+ if r1 == r2 {
+ // If they agree, return the agreed state.
+ return r1
+ }
+ if r1 == VoteLost || r2 == VoteLost {
+ // If either config has lost, loss is the only possible outcome.
+ return VoteLost
+ }
+ // One side won, the other one is pending, so the whole outcome is.
+ return VotePending
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/quorum/majority.go b/vendor/go.etcd.io/etcd/raft/v3/quorum/majority.go
new file mode 100644
index 0000000000..8858a36b63
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/quorum/majority.go
@@ -0,0 +1,210 @@
+// Copyright 2019 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 quorum
+
+import (
+ "fmt"
+ "math"
+ "sort"
+ "strings"
+)
+
+// MajorityConfig is a set of IDs that uses majority quorums to make decisions.
+type MajorityConfig map[uint64]struct{}
+
+func (c MajorityConfig) String() string {
+ sl := make([]uint64, 0, len(c))
+ for id := range c {
+ sl = append(sl, id)
+ }
+ sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] })
+ var buf strings.Builder
+ buf.WriteByte('(')
+ for i := range sl {
+ if i > 0 {
+ buf.WriteByte(' ')
+ }
+ fmt.Fprint(&buf, sl[i])
+ }
+ buf.WriteByte(')')
+ return buf.String()
+}
+
+// Describe returns a (multi-line) representation of the commit indexes for the
+// given lookuper.
+func (c MajorityConfig) Describe(l AckedIndexer) string {
+ if len(c) == 0 {
+ return ""
+ }
+ type tup struct {
+ id uint64
+ idx Index
+ ok bool // idx found?
+ bar int // length of bar displayed for this tup
+ }
+
+ // Below, populate .bar so that the i-th largest commit index has bar i (we
+ // plot this as sort of a progress bar). The actual code is a bit more
+ // complicated and also makes sure that equal index => equal bar.
+
+ n := len(c)
+ info := make([]tup, 0, n)
+ for id := range c {
+ idx, ok := l.AckedIndex(id)
+ info = append(info, tup{id: id, idx: idx, ok: ok})
+ }
+
+ // Sort by index
+ sort.Slice(info, func(i, j int) bool {
+ if info[i].idx == info[j].idx {
+ return info[i].id < info[j].id
+ }
+ return info[i].idx < info[j].idx
+ })
+
+ // Populate .bar.
+ for i := range info {
+ if i > 0 && info[i-1].idx < info[i].idx {
+ info[i].bar = i
+ }
+ }
+
+ // Sort by ID.
+ sort.Slice(info, func(i, j int) bool {
+ return info[i].id < info[j].id
+ })
+
+ var buf strings.Builder
+
+ // Print.
+ fmt.Fprint(&buf, strings.Repeat(" ", n)+" idx\n")
+ for i := range info {
+ bar := info[i].bar
+ if !info[i].ok {
+ fmt.Fprint(&buf, "?"+strings.Repeat(" ", n))
+ } else {
+ fmt.Fprint(&buf, strings.Repeat("x", bar)+">"+strings.Repeat(" ", n-bar))
+ }
+ fmt.Fprintf(&buf, " %5d (id=%d)\n", info[i].idx, info[i].id)
+ }
+ return buf.String()
+}
+
+// Slice returns the MajorityConfig as a sorted slice.
+func (c MajorityConfig) Slice() []uint64 {
+ var sl []uint64
+ for id := range c {
+ sl = append(sl, id)
+ }
+ sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] })
+ return sl
+}
+
+func insertionSort(sl []uint64) {
+ a, b := 0, len(sl)
+ for i := a + 1; i < b; i++ {
+ for j := i; j > a && sl[j] < sl[j-1]; j-- {
+ sl[j], sl[j-1] = sl[j-1], sl[j]
+ }
+ }
+}
+
+// CommittedIndex computes the committed index from those supplied via the
+// provided AckedIndexer (for the active config).
+func (c MajorityConfig) CommittedIndex(l AckedIndexer) Index {
+ n := len(c)
+ if n == 0 {
+ // This plays well with joint quorums which, when one half is the zero
+ // MajorityConfig, should behave like the other half.
+ return math.MaxUint64
+ }
+
+ // Use an on-stack slice to collect the committed indexes when n <= 7
+ // (otherwise we alloc). The alternative is to stash a slice on
+ // MajorityConfig, but this impairs usability (as is, MajorityConfig is just
+ // a map, and that's nice). The assumption is that running with a
+ // replication factor of >7 is rare, and in cases in which it happens
+ // performance is a lesser concern (additionally the performance
+ // implications of an allocation here are far from drastic).
+ var stk [7]uint64
+ var srt []uint64
+ if len(stk) >= n {
+ srt = stk[:n]
+ } else {
+ srt = make([]uint64, n)
+ }
+
+ {
+ // Fill the slice with the indexes observed. Any unused slots will be
+ // left as zero; these correspond to voters that may report in, but
+ // haven't yet. We fill from the right (since the zeroes will end up on
+ // the left after sorting below anyway).
+ i := n - 1
+ for id := range c {
+ if idx, ok := l.AckedIndex(id); ok {
+ srt[i] = uint64(idx)
+ i--
+ }
+ }
+ }
+
+ // Sort by index. Use a bespoke algorithm (copied from the stdlib's sort
+ // package) to keep srt on the stack.
+ insertionSort(srt)
+
+ // The smallest index into the array for which the value is acked by a
+ // quorum. In other words, from the end of the slice, move n/2+1 to the
+ // left (accounting for zero-indexing).
+ pos := n - (n/2 + 1)
+ return Index(srt[pos])
+}
+
+// VoteResult takes a mapping of voters to yes/no (true/false) votes and returns
+// a result indicating whether the vote is pending (i.e. neither a quorum of
+// yes/no has been reached), won (a quorum of yes has been reached), or lost (a
+// quorum of no has been reached).
+func (c MajorityConfig) VoteResult(votes map[uint64]bool) VoteResult {
+ if len(c) == 0 {
+ // By convention, the elections on an empty config win. This comes in
+ // handy with joint quorums because it'll make a half-populated joint
+ // quorum behave like a majority quorum.
+ return VoteWon
+ }
+
+ ny := [2]int{} // vote counts for no and yes, respectively
+
+ var missing int
+ for id := range c {
+ v, ok := votes[id]
+ if !ok {
+ missing++
+ continue
+ }
+ if v {
+ ny[1]++
+ } else {
+ ny[0]++
+ }
+ }
+
+ q := len(c)/2 + 1
+ if ny[1] >= q {
+ return VoteWon
+ }
+ if ny[1]+missing >= q {
+ return VotePending
+ }
+ return VoteLost
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/quorum/quorum.go b/vendor/go.etcd.io/etcd/raft/v3/quorum/quorum.go
new file mode 100644
index 0000000000..2899e46c96
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/quorum/quorum.go
@@ -0,0 +1,58 @@
+// Copyright 2019 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 quorum
+
+import (
+ "math"
+ "strconv"
+)
+
+// Index is a Raft log position.
+type Index uint64
+
+func (i Index) String() string {
+ if i == math.MaxUint64 {
+ return "∞"
+ }
+ return strconv.FormatUint(uint64(i), 10)
+}
+
+// AckedIndexer allows looking up a commit index for a given ID of a voter
+// from a corresponding MajorityConfig.
+type AckedIndexer interface {
+ AckedIndex(voterID uint64) (idx Index, found bool)
+}
+
+type mapAckIndexer map[uint64]Index
+
+func (m mapAckIndexer) AckedIndex(id uint64) (Index, bool) {
+ idx, ok := m[id]
+ return idx, ok
+}
+
+// VoteResult indicates the outcome of a vote.
+//
+//go:generate stringer -type=VoteResult
+type VoteResult uint8
+
+const (
+ // VotePending indicates that the decision of the vote depends on future
+ // votes, i.e. neither "yes" or "no" has reached quorum yet.
+ VotePending VoteResult = 1 + iota
+ // VoteLost indicates that the quorum has voted "no".
+ VoteLost
+ // VoteWon indicates that the quorum has voted "yes".
+ VoteWon
+)
diff --git a/vendor/go.etcd.io/etcd/raft/v3/quorum/voteresult_string.go b/vendor/go.etcd.io/etcd/raft/v3/quorum/voteresult_string.go
new file mode 100644
index 0000000000..9eca8fd0c9
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/quorum/voteresult_string.go
@@ -0,0 +1,26 @@
+// Code generated by "stringer -type=VoteResult"; DO NOT EDIT.
+
+package quorum
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[VotePending-1]
+ _ = x[VoteLost-2]
+ _ = x[VoteWon-3]
+}
+
+const _VoteResult_name = "VotePendingVoteLostVoteWon"
+
+var _VoteResult_index = [...]uint8{0, 11, 19, 26}
+
+func (i VoteResult) String() string {
+ i -= 1
+ if i >= VoteResult(len(_VoteResult_index)-1) {
+ return "VoteResult(" + strconv.FormatInt(int64(i+1), 10) + ")"
+ }
+ return _VoteResult_name[_VoteResult_index[i]:_VoteResult_index[i+1]]
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/raft.go b/vendor/go.etcd.io/etcd/raft/v3/raft.go
new file mode 100644
index 0000000000..c80262ebaf
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/raft.go
@@ -0,0 +1,1837 @@
+// 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"
+
+ "go.etcd.io/etcd/raft/v3/confchange"
+ "go.etcd.io/etcd/raft/v3/quorum"
+ pb "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/raft/v3/tracker"
+)
+
+// 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"
+)
+
+// ErrProposalDropped is returned when the proposal is ignored by some cases,
+// so that the proposer can be notified and fail fast.
+var ErrProposalDropped = errors.New("raft proposal dropped")
+
+// lockedRand is a small wrapper around rand.Rand to provide
+// synchronization among multiple raft groups. 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
+
+ // 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 byte 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
+ // MaxCommittedSizePerReady limits the size of the committed entries which
+ // can be applied.
+ MaxCommittedSizePerReady uint64
+ // MaxUncommittedEntriesSize limits the aggregate byte size of the
+ // uncommitted entries that may be appended to a leader's log. Once this
+ // limit is exceeded, proposals will begin to return ErrProposalDropped
+ // errors. Note: 0 for no limit.
+ MaxUncommittedEntriesSize 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 inaccurate 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.MaxUncommittedEntriesSize == 0 {
+ c.MaxUncommittedEntriesSize = noLimit
+ }
+
+ // default MaxCommittedSizePerReady to MaxSizePerMsg because they were
+ // previously the same parameter.
+ if c.MaxCommittedSizePerReady == 0 {
+ c.MaxCommittedSizePerReady = c.MaxSizePerMsg
+ }
+
+ if c.MaxInflightMsgs <= 0 {
+ return errors.New("max inflight messages must be greater than 0")
+ }
+
+ if c.Logger == nil {
+ c.Logger = getLogger()
+ }
+
+ 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
+
+ maxMsgSize uint64
+ maxUncommittedSize uint64
+ // TODO(tbg): rename to trk.
+ prs tracker.ProgressTracker
+
+ state StateType
+
+ // isLearner is true if the local raft node is a learner.
+ isLearner 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
+ // Only one conf change may be pending (in the log, but not yet
+ // applied) at a time. This is enforced via pendingConfIndex, which
+ // is set to a value >= the log index of the latest pending
+ // configuration change (if any). Config changes are only allowed to
+ // be proposed if the leader's applied index is greater than this
+ // value.
+ pendingConfIndex uint64
+ // an estimate of the size of the uncommitted tail of the Raft log. Used to
+ // prevent unbounded log growth. Only maintained by the leader. Reset on
+ // term changes.
+ uncommittedSize uint64
+
+ 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
+
+ // pendingReadIndexMessages is used to store messages of type MsgReadIndex
+ // that can't be answered as new leader didn't committed any log in
+ // current term. Those will be handled as fast as first log is committed in
+ // current term.
+ pendingReadIndexMessages []pb.Message
+}
+
+func newRaft(c *Config) *raft {
+ if err := c.validate(); err != nil {
+ panic(err.Error())
+ }
+ raftlog := newLogWithSize(c.Storage, c.Logger, c.MaxCommittedSizePerReady)
+ hs, cs, err := c.Storage.InitialState()
+ if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+
+ r := &raft{
+ id: c.ID,
+ lead: None,
+ isLearner: false,
+ raftLog: raftlog,
+ maxMsgSize: c.MaxSizePerMsg,
+ maxUncommittedSize: c.MaxUncommittedEntriesSize,
+ prs: tracker.MakeProgressTracker(c.MaxInflightMsgs),
+ electionTimeout: c.ElectionTick,
+ heartbeatTimeout: c.HeartbeatTick,
+ logger: c.Logger,
+ checkQuorum: c.CheckQuorum,
+ preVote: c.PreVote,
+ readOnly: newReadOnly(c.ReadOnlyOption),
+ disableProposalForwarding: c.DisableProposalForwarding,
+ }
+
+ cfg, prs, err := confchange.Restore(confchange.Changer{
+ Tracker: r.prs,
+ LastIndex: raftlog.lastIndex(),
+ }, cs)
+ if err != nil {
+ panic(err)
+ }
+ assertConfStatesEquivalent(r.logger, cs, r.switchToConfig(cfg, prs))
+
+ if !IsEmptyHardState(hs) {
+ r.loadState(hs)
+ }
+ if c.Applied > 0 {
+ raftlog.appliedTo(c.Applied)
+ }
+ r.becomeFollower(r.Term, None)
+
+ var nodesStrs []string
+ for _, n := range r.prs.VoterNodes() {
+ 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,
+ }
+}
+
+// send schedules persisting state to a stable storage and AFTER that
+// sending the message (as part of next Ready message processing).
+func (r *raft) send(m pb.Message) {
+ if m.From == None {
+ 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)
+}
+
+// sendAppend sends an append RPC with new entries (if any) and the
+// current commit index to the given peer.
+func (r *raft) sendAppend(to uint64) {
+ r.maybeSendAppend(to, true)
+}
+
+// maybeSendAppend sends an append RPC with new entries to the given peer,
+// if necessary. Returns true if a message was sent. The sendIfEmpty
+// argument controls whether messages with no entries will be sent
+// ("empty" messages are useful to convey updated Commit indexes, but
+// are undesirable when we're sending multiple messages in a batch).
+func (r *raft) maybeSendAppend(to uint64, sendIfEmpty bool) bool {
+ pr := r.prs.Progress[to]
+ if pr.IsPaused() {
+ return false
+ }
+ m := pb.Message{}
+ m.To = to
+
+ term, errt := r.raftLog.term(pr.Next - 1)
+ ents, erre := r.raftLog.entries(pr.Next, r.maxMsgSize)
+ if len(ents) == 0 && !sendIfEmpty {
+ return false
+ }
+
+ 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 false
+ }
+
+ 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 false
+ }
+ 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 StateReplicate
+ case tracker.StateReplicate:
+ last := m.Entries[n-1].Index
+ pr.OptimisticUpdate(last)
+ pr.Inflights.Add(last)
+ case tracker.StateProbe:
+ pr.ProbeSent = true
+ default:
+ r.logger.Panicf("%x is sending append in unhandled state %s", r.id, pr.State)
+ }
+ }
+ }
+ r.send(m)
+ return true
+}
+
+// sendHeartbeat sends a heartbeat RPC to the given peer.
+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.prs.Progress[to].Match, r.raftLog.committed)
+ m := pb.Message{
+ To: to,
+ Type: pb.MsgHeartbeat,
+ Commit: commit,
+ Context: ctx,
+ }
+
+ r.send(m)
+}
+
+// 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.prs.Visit(func(id uint64, _ *tracker.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.prs.Visit(func(id uint64, _ *tracker.Progress) {
+ if id == r.id {
+ return
+ }
+ r.sendHeartbeat(id, ctx)
+ })
+}
+
+func (r *raft) advance(rd Ready) {
+ r.reduceUncommittedSize(rd.CommittedEntries)
+
+ // If entries were applied (or a snapshot), update our cursor for
+ // the next Ready. Note that if the current HardState contains a
+ // new Commit index, this does not mean that we're also applying
+ // all of the new entries due to commit pagination by size.
+ if newApplied := rd.appliedCursor(); newApplied > 0 {
+ oldApplied := r.raftLog.applied
+ r.raftLog.appliedTo(newApplied)
+
+ if r.prs.Config.AutoLeave && oldApplied <= r.pendingConfIndex && newApplied >= r.pendingConfIndex && r.state == StateLeader {
+ // If the current (and most recent, at least for this leader's term)
+ // configuration should be auto-left, initiate that now. We use a
+ // nil Data which unmarshals into an empty ConfChangeV2 and has the
+ // benefit that appendEntry can never refuse it based on its size
+ // (which registers as zero).
+ ent := pb.Entry{
+ Type: pb.EntryConfChangeV2,
+ Data: nil,
+ }
+ // There's no way in which this proposal should be able to be rejected.
+ if !r.appendEntry(ent) {
+ panic("refused un-refusable auto-leaving ConfChangeV2")
+ }
+ r.pendingConfIndex = r.raftLog.lastIndex()
+ r.logger.Infof("initiating automatic transition out of joint configuration %s", r.prs.Config)
+ }
+ }
+
+ if len(rd.Entries) > 0 {
+ e := rd.Entries[len(rd.Entries)-1]
+ r.raftLog.stableTo(e.Index, e.Term)
+ }
+ if !IsEmptySnap(rd.Snapshot) {
+ r.raftLog.stableSnapTo(rd.Snapshot.Metadata.Index)
+ }
+}
+
+// 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 {
+ mci := r.prs.Committed()
+ 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.prs.ResetVotes()
+ r.prs.Visit(func(id uint64, pr *tracker.Progress) {
+ *pr = tracker.Progress{
+ Match: 0,
+ Next: r.raftLog.lastIndex() + 1,
+ Inflights: tracker.NewInflights(r.prs.MaxInflight),
+ IsLearner: pr.IsLearner,
+ }
+ if id == r.id {
+ pr.Match = r.raftLog.lastIndex()
+ }
+ })
+
+ r.pendingConfIndex = 0
+ r.uncommittedSize = 0
+ r.readOnly = newReadOnly(r.readOnly.option)
+}
+
+func (r *raft) appendEntry(es ...pb.Entry) (accepted bool) {
+ li := r.raftLog.lastIndex()
+ for i := range es {
+ es[i].Term = r.Term
+ es[i].Index = li + 1 + uint64(i)
+ }
+ // Track the size of this uncommitted proposal.
+ if !r.increaseUncommittedSize(es) {
+ r.logger.Debugf(
+ "%x appending new entries to log would exceed uncommitted entry size limit; dropping proposal",
+ r.id,
+ )
+ // Drop the proposal.
+ return false
+ }
+ // use latest "last" index after truncate/append
+ li = r.raftLog.append(es...)
+ r.prs.Progress[r.id].MaybeUpdate(li)
+ // Regardless of maybeCommit's return, our caller will call bcastAppend.
+ r.maybeCommit()
+ return true
+}
+
+// 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.prs.ResetVotes()
+ r.tick = r.tickElection
+ r.lead = None
+ 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
+ // Followers enter replicate mode when they've been successfully probed
+ // (perhaps after having received a snapshot as a result). The leader is
+ // trivially in this state. Note that r.reset() has initialized this
+ // progress with the last index already.
+ r.prs.Progress[r.id].BecomeReplicate()
+
+ // Conservatively set the pendingConfIndex to the last index in the
+ // log. There may or may not be a pending config change, but it's
+ // safe to delay any future proposals until we commit all our
+ // pending log entries, and scanning the entire tail of the log
+ // could be expensive.
+ r.pendingConfIndex = r.raftLog.lastIndex()
+
+ emptyEnt := pb.Entry{Data: nil}
+ if !r.appendEntry(emptyEnt) {
+ // This won't happen because we just called reset() above.
+ r.logger.Panic("empty entry was dropped")
+ }
+ // As a special case, don't count the initial empty entry towards the
+ // uncommitted log quota. This is because we want to preserve the
+ // behavior of allowing one entry larger than quota if the current
+ // usage is zero.
+ r.reduceUncommittedSize([]pb.Entry{emptyEnt})
+ r.logger.Infof("%x became leader at term %d", r.id, r.Term)
+}
+
+func (r *raft) hup(t CampaignType) {
+ if r.state == StateLeader {
+ r.logger.Debugf("%x ignoring MsgHup because already leader", r.id)
+ return
+ }
+
+ if !r.promotable() {
+ r.logger.Warningf("%x is unpromotable and can not campaign", r.id)
+ return
+ }
+ 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
+ }
+
+ r.logger.Infof("%x is starting a new election at term %d", r.id, r.Term)
+ r.campaign(t)
+}
+
+// campaign transitions the raft instance to candidate state. This must only be
+// called after verifying that this is a legitimate transition.
+func (r *raft) campaign(t CampaignType) {
+ if !r.promotable() {
+ // This path should not be hit (callers are supposed to check), but
+ // better safe than sorry.
+ r.logger.Warningf("%x is unpromotable; campaign() should have been called", r.id)
+ }
+ 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 _, _, res := r.poll(r.id, voteRespMsgType(voteMsg), true); res == quorum.VoteWon {
+ // 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
+ }
+ var ids []uint64
+ {
+ idMap := r.prs.Voters.IDs()
+ ids = make([]uint64, 0, len(idMap))
+ for id := range idMap {
+ ids = append(ids, id)
+ }
+ sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
+ }
+ for _, id := range ids {
+ 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, rejected int, result quorum.VoteResult) {
+ 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)
+ }
+ r.prs.RecordVote(id, v)
+ return r.prs.TallyVotes()
+}
+
+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 || r.preVote) && (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, by notifying leader of this node's activeness.
+ // The above comments also true for Pre-Vote
+ //
+ // When follower gets isolated, it soon starts an election ending
+ // up with a higher term than leader, although it won't receive enough
+ // votes to win the election. When it regains connectivity, this response
+ // with "pb.MsgAppResp" of higher term would force leader to step down.
+ // However, this disruption is inevitable to free this stuck node with
+ // fresh election. This can be prevented with Pre-Vote phase.
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp})
+ } else if m.Type == pb.MsgPreVote {
+ // Before Pre-Vote enable, there may have candidate with higher term,
+ // but less log. After update to Pre-Vote, the cluster may deadlock if
+ // we drop messages with a lower term.
+ 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: pb.MsgPreVoteResp, Reject: true})
+ } 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.preVote {
+ r.hup(campaignPreElection)
+ } else {
+ r.hup(campaignElection)
+ }
+
+ case pb.MsgVote, pb.MsgPreVote:
+ // We can vote if this is a repeat of a vote we've already cast...
+ canVote := r.Vote == m.From ||
+ // ...we haven't voted and we don't think there's a leader yet in this term...
+ (r.Vote == None && r.lead == None) ||
+ // ...or this is a PreVote for a future term...
+ (m.Type == pb.MsgPreVote && m.Term > r.Term)
+ // ...and we believe the candidate is up to date.
+ if canVote && r.raftLog.isUpToDate(m.Index, m.LogTerm) {
+ // Note: it turns out that that learners must be allowed to cast votes.
+ // This seems counter- intuitive but is necessary in the situation in which
+ // a learner has been promoted (i.e. is now a voter) but has not learned
+ // about this yet.
+ // For example, consider a group in which id=1 is a learner and id=2 and
+ // id=3 are voters. A configuration change promoting 1 can be committed on
+ // the quorum `{2,3}` without the config change being appended to the
+ // learner's log. If the leader (say 2) fails, there are de facto two
+ // voters remaining. Only 3 can win an election (due to its log containing
+ // all committed entries), but to do so it will need 1 to vote. But 1
+ // considers itself a learner and will continue to do so until 3 has
+ // stepped up as leader, replicates the conf change to 1, and 1 applies it.
+ // Ultimately, by receiving a request to vote, the learner realizes that
+ // the candidate believes it to be a voter, and that it should act
+ // accordingly. The candidate's config may be stale, too; but in that case
+ // it won't win the election, at least in the absence of the bug discussed
+ // in:
+ // https://github.com/etcd-io/etcd/issues/7625#issuecomment-488798263.
+ 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 out 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:
+ err := r.step(r, m)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type stepFunc func(r *raft, m pb.Message) error
+
+func stepLeader(r *raft, m pb.Message) error {
+ // These message types do not require any progress for m.From.
+ switch m.Type {
+ case pb.MsgBeat:
+ r.bcastHeartbeat()
+ return nil
+ case pb.MsgCheckQuorum:
+ // The leader should always see itself as active. As a precaution, handle
+ // the case in which the leader isn't in the configuration any more (for
+ // example if it just removed itself).
+ //
+ // TODO(tbg): I added a TODO in removeNode, it doesn't seem that the
+ // leader steps down when removing itself. I might be missing something.
+ if pr := r.prs.Progress[r.id]; pr != nil {
+ pr.RecentActive = true
+ }
+ if !r.prs.QuorumActive() {
+ r.logger.Warningf("%x stepped down to follower since quorum is not active", r.id)
+ r.becomeFollower(r.Term, None)
+ }
+ // Mark everyone (but ourselves) as inactive in preparation for the next
+ // CheckQuorum.
+ r.prs.Visit(func(id uint64, pr *tracker.Progress) {
+ if id != r.id {
+ pr.RecentActive = false
+ }
+ })
+ return nil
+ case pb.MsgProp:
+ if len(m.Entries) == 0 {
+ r.logger.Panicf("%x stepped empty MsgProp", r.id)
+ }
+ if r.prs.Progress[r.id] == nil {
+ // 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 ErrProposalDropped
+ }
+ 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 ErrProposalDropped
+ }
+
+ for i := range m.Entries {
+ e := &m.Entries[i]
+ var cc pb.ConfChangeI
+ if e.Type == pb.EntryConfChange {
+ var ccc pb.ConfChange
+ if err := ccc.Unmarshal(e.Data); err != nil {
+ panic(err)
+ }
+ cc = ccc
+ } else if e.Type == pb.EntryConfChangeV2 {
+ var ccc pb.ConfChangeV2
+ if err := ccc.Unmarshal(e.Data); err != nil {
+ panic(err)
+ }
+ cc = ccc
+ }
+ if cc != nil {
+ alreadyPending := r.pendingConfIndex > r.raftLog.applied
+ alreadyJoint := len(r.prs.Config.Voters[1]) > 0
+ wantsLeaveJoint := len(cc.AsV2().Changes) == 0
+
+ var refused string
+ if alreadyPending {
+ refused = fmt.Sprintf("possible unapplied conf change at index %d (applied to %d)", r.pendingConfIndex, r.raftLog.applied)
+ } else if alreadyJoint && !wantsLeaveJoint {
+ refused = "must transition out of joint config first"
+ } else if !alreadyJoint && wantsLeaveJoint {
+ refused = "not in joint state; refusing empty conf change"
+ }
+
+ if refused != "" {
+ r.logger.Infof("%x ignoring conf change %v at config %s: %s", r.id, cc, r.prs.Config, refused)
+ m.Entries[i] = pb.Entry{Type: pb.EntryNormal}
+ } else {
+ r.pendingConfIndex = r.raftLog.lastIndex() + uint64(i) + 1
+ }
+ }
+ }
+
+ if !r.appendEntry(m.Entries...) {
+ return ErrProposalDropped
+ }
+ r.bcastAppend()
+ return nil
+ case pb.MsgReadIndex:
+ // only one voting member (the leader) in the cluster
+ if r.prs.IsSingleton() {
+ if resp := r.responseToReadIndexReq(m, r.raftLog.committed); resp.To != None {
+ r.send(resp)
+ }
+ return nil
+ }
+
+ // Postpone read only request when this leader has not committed
+ // any log entry at its term.
+ if !r.committedEntryInCurrentTerm() {
+ r.pendingReadIndexMessages = append(r.pendingReadIndexMessages, m)
+ return nil
+ }
+
+ sendMsgReadIndexResponse(r, m)
+
+ return nil
+ }
+
+ // All other message types require a progress for m.From (pr).
+ pr := r.prs.Progress[m.From]
+ if pr == nil {
+ r.logger.Debugf("%x no progress available for %x", r.id, m.From)
+ return nil
+ }
+ switch m.Type {
+ case pb.MsgAppResp:
+ pr.RecentActive = true
+
+ if m.Reject {
+ // RejectHint is the suggested next base entry for appending (i.e.
+ // we try to append entry RejectHint+1 next), and LogTerm is the
+ // term that the follower has at index RejectHint. Older versions
+ // of this library did not populate LogTerm for rejections and it
+ // is zero for followers with an empty log.
+ //
+ // Under normal circumstances, the leader's log is longer than the
+ // follower's and the follower's log is a prefix of the leader's
+ // (i.e. there is no divergent uncommitted suffix of the log on the
+ // follower). In that case, the first probe reveals where the
+ // follower's log ends (RejectHint=follower's last index) and the
+ // subsequent probe succeeds.
+ //
+ // However, when networks are partitioned or systems overloaded,
+ // large divergent log tails can occur. The naive attempt, probing
+ // entry by entry in decreasing order, will be the product of the
+ // length of the diverging tails and the network round-trip latency,
+ // which can easily result in hours of time spent probing and can
+ // even cause outright outages. The probes are thus optimized as
+ // described below.
+ r.logger.Debugf("%x received MsgAppResp(rejected, hint: (index %d, term %d)) from %x for index %d",
+ r.id, m.RejectHint, m.LogTerm, m.From, m.Index)
+ nextProbeIdx := m.RejectHint
+ if m.LogTerm > 0 {
+ // If the follower has an uncommitted log tail, we would end up
+ // probing one by one until we hit the common prefix.
+ //
+ // For example, if the leader has:
+ //
+ // idx 1 2 3 4 5 6 7 8 9
+ // -----------------
+ // term (L) 1 3 3 3 5 5 5 5 5
+ // term (F) 1 1 1 1 2 2
+ //
+ // Then, after sending an append anchored at (idx=9,term=5) we
+ // would receive a RejectHint of 6 and LogTerm of 2. Without the
+ // code below, we would try an append at index 6, which would
+ // fail again.
+ //
+ // However, looking only at what the leader knows about its own
+ // log and the rejection hint, it is clear that a probe at index
+ // 6, 5, 4, 3, and 2 must fail as well:
+ //
+ // For all of these indexes, the leader's log term is larger than
+ // the rejection's log term. If a probe at one of these indexes
+ // succeeded, its log term at that index would match the leader's,
+ // i.e. 3 or 5 in this example. But the follower already told the
+ // leader that it is still at term 2 at index 9, and since the
+ // log term only ever goes up (within a log), this is a contradiction.
+ //
+ // At index 1, however, the leader can draw no such conclusion,
+ // as its term 1 is not larger than the term 2 from the
+ // follower's rejection. We thus probe at 1, which will succeed
+ // in this example. In general, with this approach we probe at
+ // most once per term found in the leader's log.
+ //
+ // There is a similar mechanism on the follower (implemented in
+ // handleAppendEntries via a call to findConflictByTerm) that is
+ // useful if the follower has a large divergent uncommitted log
+ // tail[1], as in this example:
+ //
+ // idx 1 2 3 4 5 6 7 8 9
+ // -----------------
+ // term (L) 1 3 3 3 3 3 3 3 7
+ // term (F) 1 3 3 4 4 5 5 5 6
+ //
+ // Naively, the leader would probe at idx=9, receive a rejection
+ // revealing the log term of 6 at the follower. Since the leader's
+ // term at the previous index is already smaller than 6, the leader-
+ // side optimization discussed above is ineffective. The leader thus
+ // probes at index 8 and, naively, receives a rejection for the same
+ // index and log term 5. Again, the leader optimization does not improve
+ // over linear probing as term 5 is above the leader's term 3 for that
+ // and many preceding indexes; the leader would have to probe linearly
+ // until it would finally hit index 3, where the probe would succeed.
+ //
+ // Instead, we apply a similar optimization on the follower. When the
+ // follower receives the probe at index 8 (log term 3), it concludes
+ // that all of the leader's log preceding that index has log terms of
+ // 3 or below. The largest index in the follower's log with a log term
+ // of 3 or below is index 3. The follower will thus return a rejection
+ // for index=3, log term=3 instead. The leader's next probe will then
+ // succeed at that index.
+ //
+ // [1]: more precisely, if the log terms in the large uncommitted
+ // tail on the follower are larger than the leader's. At first,
+ // it may seem unintuitive that a follower could even have such
+ // a large tail, but it can happen:
+ //
+ // 1. Leader appends (but does not commit) entries 2 and 3, crashes.
+ // idx 1 2 3 4 5 6 7 8 9
+ // -----------------
+ // term (L) 1 2 2 [crashes]
+ // term (F) 1
+ // term (F) 1
+ //
+ // 2. a follower becomes leader and appends entries at term 3.
+ // -----------------
+ // term (x) 1 2 2 [down]
+ // term (F) 1 3 3 3 3
+ // term (F) 1
+ //
+ // 3. term 3 leader goes down, term 2 leader returns as term 4
+ // leader. It commits the log & entries at term 4.
+ //
+ // -----------------
+ // term (L) 1 2 2 2
+ // term (x) 1 3 3 3 3 [down]
+ // term (F) 1
+ // -----------------
+ // term (L) 1 2 2 2 4 4 4
+ // term (F) 1 3 3 3 3 [gets probed]
+ // term (F) 1 2 2 2 4 4 4
+ //
+ // 4. the leader will now probe the returning follower at index
+ // 7, the rejection points it at the end of the follower's log
+ // which is at a higher log term than the actually committed
+ // log.
+ nextProbeIdx = r.raftLog.findConflictByTerm(m.RejectHint, m.LogTerm)
+ }
+ if pr.MaybeDecrTo(m.Index, nextProbeIdx) {
+ r.logger.Debugf("%x decreased progress of %x to [%s]", r.id, m.From, pr)
+ if pr.State == tracker.StateReplicate {
+ pr.BecomeProbe()
+ }
+ r.sendAppend(m.From)
+ }
+ } else {
+ oldPaused := pr.IsPaused()
+ if pr.MaybeUpdate(m.Index) {
+ switch {
+ case pr.State == tracker.StateProbe:
+ pr.BecomeReplicate()
+ case pr.State == tracker.StateSnapshot && pr.Match >= pr.PendingSnapshot:
+ // TODO(tbg): we should also enter this branch if a snapshot is
+ // received that is below pr.PendingSnapshot but which makes it
+ // possible to use the log again.
+ r.logger.Debugf("%x recovered from needing snapshot, resumed sending replication messages to %x [%s]", r.id, m.From, pr)
+ // Transition back to replicating state via probing state
+ // (which takes the snapshot into account). If we didn't
+ // move to replicating state, that would only happen with
+ // the next round of appends (but there may not be a next
+ // round for a while, exposing an inconsistent RaftStatus).
+ pr.BecomeProbe()
+ pr.BecomeReplicate()
+ case pr.State == tracker.StateReplicate:
+ pr.Inflights.FreeLE(m.Index)
+ }
+
+ if r.maybeCommit() {
+ // committed index has progressed for the term, so it is safe
+ // to respond to pending read index requests
+ releasePendingReadIndexMessages(r)
+ r.bcastAppend()
+ } else if oldPaused {
+ // If we were paused before, this node may be missing the
+ // latest commit index, so send it.
+ r.sendAppend(m.From)
+ }
+ // We've updated flow control information above, which may
+ // allow us to send multiple (size-limited) in-flight messages
+ // at once (such as when transitioning from probe to
+ // replicate, or when freeTo() covers multiple messages). If
+ // we have more entries to send, send as many messages as we
+ // can (without sending empty messages for the commit index)
+ for r.maybeSendAppend(m.From, false) {
+ }
+ // 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.ProbeSent = false
+
+ // free one slot for the full inflights window to allow progress.
+ if pr.State == tracker.StateReplicate && pr.Inflights.Full() {
+ pr.Inflights.FreeFirstOne()
+ }
+ if pr.Match < r.raftLog.lastIndex() {
+ r.sendAppend(m.From)
+ }
+
+ if r.readOnly.option != ReadOnlySafe || len(m.Context) == 0 {
+ return nil
+ }
+
+ if r.prs.Voters.VoteResult(r.readOnly.recvAck(m.From, m.Context)) != quorum.VoteWon {
+ return nil
+ }
+
+ rss := r.readOnly.advance(m)
+ for _, rs := range rss {
+ if resp := r.responseToReadIndexReq(rs.req, rs.index); resp.To != None {
+ r.send(resp)
+ }
+ }
+ case pb.MsgSnapStatus:
+ if pr.State != tracker.StateSnapshot {
+ return nil
+ }
+ // TODO(tbg): this code is very similar to the snapshot handling in
+ // MsgAppResp above. In fact, the code there is more correct than the
+ // code here and should likely be updated to match (or even better, the
+ // logic pulled into a newly created Progress state machine handler).
+ if !m.Reject {
+ pr.BecomeProbe()
+ r.logger.Debugf("%x snapshot succeeded, resumed sending replication messages to %x [%s]", r.id, m.From, pr)
+ } else {
+ // NB: the order here matters or we'll be probing erroneously from
+ // the snapshot index, but the snapshot never applied.
+ pr.PendingSnapshot = 0
+ 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.ProbeSent = true
+ case pb.MsgUnreachable:
+ // During optimistic replication, if the remote becomes unreachable,
+ // there is huge probability that a MsgApp is lost.
+ if pr.State == tracker.StateReplicate {
+ 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 nil
+ }
+ 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 nil
+ }
+ 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 nil
+ }
+ // 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)
+ }
+ }
+ return nil
+}
+
+// stepCandidate is shared by StateCandidate and StatePreCandidate; the difference is
+// whether they respond to MsgVoteResp or MsgPreVoteResp.
+func stepCandidate(r *raft, m pb.Message) error {
+ // 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 ErrProposalDropped
+ case pb.MsgApp:
+ r.becomeFollower(m.Term, m.From) // always m.Term == r.Term
+ r.handleAppendEntries(m)
+ case pb.MsgHeartbeat:
+ r.becomeFollower(m.Term, m.From) // always m.Term == r.Term
+ r.handleHeartbeat(m)
+ case pb.MsgSnap:
+ r.becomeFollower(m.Term, m.From) // always m.Term == r.Term
+ r.handleSnapshot(m)
+ case myVoteRespType:
+ gr, rj, res := r.poll(m.From, m.Type, !m.Reject)
+ r.logger.Infof("%x has received %d %s votes and %d vote rejections", r.id, gr, m.Type, rj)
+ switch res {
+ case quorum.VoteWon:
+ if r.state == StatePreCandidate {
+ r.campaign(campaignElection)
+ } else {
+ r.becomeLeader()
+ r.bcastAppend()
+ }
+ case quorum.VoteLost:
+ // pb.MsgPreVoteResp contains future term of pre-candidate
+ // m.Term > r.Term; reuse r.Term
+ 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)
+ }
+ return nil
+}
+
+func stepFollower(r *raft, m pb.Message) error {
+ 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 ErrProposalDropped
+ } 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 ErrProposalDropped
+ }
+ 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 nil
+ }
+ m.To = r.lead
+ r.send(m)
+ case pb.MsgTimeoutNow:
+ 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.hup(campaignTransfer)
+ 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 nil
+ }
+ 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 nil
+ }
+ r.readStates = append(r.readStates, ReadState{Index: m.Index, RequestCtx: m.Entries[0].Data})
+ }
+ return nil
+}
+
+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)
+
+ // Return a hint to the leader about the maximum index and term that the
+ // two logs could be divergent at. Do this by searching through the
+ // follower's log for the maximum (index, term) pair with a term <= the
+ // MsgApp's LogTerm and an index <= the MsgApp's Index. This can help
+ // skip all indexes in the follower's uncommitted tail with terms
+ // greater than the MsgApp's LogTerm.
+ //
+ // See the other caller for findConflictByTerm (in stepLeader) for a much
+ // more detailed explanation of this mechanism.
+ hintIndex := min(m.Index, r.raftLog.lastIndex())
+ hintIndex = r.raftLog.findConflictByTerm(hintIndex, m.LogTerm)
+ hintTerm, err := r.raftLog.term(hintIndex)
+ if err != nil {
+ panic(fmt.Sprintf("term(%d) must be valid, but got %v", hintIndex, err))
+ }
+ r.send(pb.Message{
+ To: m.From,
+ Type: pb.MsgAppResp,
+ Index: m.Index,
+ Reject: true,
+ RejectHint: hintIndex,
+ LogTerm: hintTerm,
+ })
+ }
+}
+
+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. If this method returns false, the snapshot was
+// ignored, either because it was obsolete or because of an error.
+func (r *raft) restore(s pb.Snapshot) bool {
+ if s.Metadata.Index <= r.raftLog.committed {
+ return false
+ }
+ if r.state != StateFollower {
+ // This is defense-in-depth: if the leader somehow ended up applying a
+ // snapshot, it could move into a new term without moving into a
+ // follower state. This should never fire, but if it did, we'd have
+ // prevented damage by returning early, so log only a loud warning.
+ //
+ // At the time of writing, the instance is guaranteed to be in follower
+ // state when this method is called.
+ r.logger.Warningf("%x attempted to restore snapshot as leader; should never happen", r.id)
+ r.becomeFollower(r.Term+1, None)
+ return false
+ }
+
+ // More defense-in-depth: throw away snapshot if recipient is not in the
+ // config. This shouldn't ever happen (at the time of writing) but lots of
+ // code here and there assumes that r.id is in the progress tracker.
+ found := false
+ cs := s.Metadata.ConfState
+
+ for _, set := range [][]uint64{
+ cs.Voters,
+ cs.Learners,
+ cs.VotersOutgoing,
+ // `LearnersNext` doesn't need to be checked. According to the rules, if a peer in
+ // `LearnersNext`, it has to be in `VotersOutgoing`.
+ } {
+ for _, id := range set {
+ if id == r.id {
+ found = true
+ break
+ }
+ }
+ if found {
+ break
+ }
+ }
+ if !found {
+ r.logger.Warningf(
+ "%x attempted to restore snapshot but it is not in the ConfState %v; should never happen",
+ r.id, cs,
+ )
+ return false
+ }
+
+ // Now go ahead and actually restore.
+
+ 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
+ }
+
+ r.raftLog.restore(s)
+
+ // Reset the configuration and add the (potentially updated) peers in anew.
+ r.prs = tracker.MakeProgressTracker(r.prs.MaxInflight)
+ cfg, prs, err := confchange.Restore(confchange.Changer{
+ Tracker: r.prs,
+ LastIndex: r.raftLog.lastIndex(),
+ }, cs)
+
+ if err != nil {
+ // This should never happen. Either there's a bug in our config change
+ // handling or the client corrupted the conf change.
+ panic(fmt.Sprintf("unable to restore config %+v: %s", cs, err))
+ }
+
+ assertConfStatesEquivalent(r.logger, cs, r.switchToConfig(cfg, prs))
+
+ pr := r.prs.Progress[r.id]
+ pr.MaybeUpdate(pr.Next - 1) // TODO(tbg): this is untested and likely unneeded
+
+ r.logger.Infof("%x [commit: %d, lastindex: %d, lastterm: %d] restored snapshot [index: %d, term: %d]",
+ r.id, r.raftLog.committed, r.raftLog.lastIndex(), r.raftLog.lastTerm(), s.Metadata.Index, s.Metadata.Term)
+ return true
+}
+
+// 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 {
+ pr := r.prs.Progress[r.id]
+ return pr != nil && !pr.IsLearner && !r.raftLog.hasPendingSnapshot()
+}
+
+func (r *raft) applyConfChange(cc pb.ConfChangeV2) pb.ConfState {
+ cfg, prs, err := func() (tracker.Config, tracker.ProgressMap, error) {
+ changer := confchange.Changer{
+ Tracker: r.prs,
+ LastIndex: r.raftLog.lastIndex(),
+ }
+ if cc.LeaveJoint() {
+ return changer.LeaveJoint()
+ } else if autoLeave, ok := cc.EnterJoint(); ok {
+ return changer.EnterJoint(autoLeave, cc.Changes...)
+ }
+ return changer.Simple(cc.Changes...)
+ }()
+
+ if err != nil {
+ // TODO(tbg): return the error to the caller.
+ panic(err)
+ }
+
+ return r.switchToConfig(cfg, prs)
+}
+
+// switchToConfig reconfigures this node to use the provided configuration. It
+// updates the in-memory state and, when necessary, carries out additional
+// actions such as reacting to the removal of nodes or changed quorum
+// requirements.
+//
+// The inputs usually result from restoring a ConfState or applying a ConfChange.
+func (r *raft) switchToConfig(cfg tracker.Config, prs tracker.ProgressMap) pb.ConfState {
+ r.prs.Config = cfg
+ r.prs.Progress = prs
+
+ r.logger.Infof("%x switched to configuration %s", r.id, r.prs.Config)
+ cs := r.prs.ConfState()
+ pr, ok := r.prs.Progress[r.id]
+
+ // Update whether the node itself is a learner, resetting to false when the
+ // node is removed.
+ r.isLearner = ok && pr.IsLearner
+
+ if (!ok || r.isLearner) && r.state == StateLeader {
+ // This node is leader and was removed or demoted. We prevent demotions
+ // at the time writing but hypothetically we handle them the same way as
+ // removing the leader: stepping down into the next Term.
+ //
+ // TODO(tbg): step down (for sanity) and ask follower with largest Match
+ // to TimeoutNow (to avoid interruption). This might still drop some
+ // proposals but it's better than nothing.
+ //
+ // TODO(tbg): test this branch. It is untested at the time of writing.
+ return cs
+ }
+
+ // The remaining steps only make sense if this node is the leader and there
+ // are other nodes.
+ if r.state != StateLeader || len(cs.Voters) == 0 {
+ return cs
+ }
+
+ if r.maybeCommit() {
+ // If the configuration change means that more entries are committed now,
+ // broadcast/append to everyone in the updated config.
+ r.bcastAppend()
+ } else {
+ // Otherwise, still probe the newly added replicas; there's no reason to
+ // let them wait out a heartbeat interval (or the next incoming
+ // proposal).
+ r.prs.Visit(func(id uint64, pr *tracker.Progress) {
+ r.maybeSendAppend(id, false /* sendIfEmpty */)
+ })
+ }
+ // If the the leadTransferee was removed or demoted, abort the leadership transfer.
+ if _, tOK := r.prs.Config.Voters.IDs()[r.leadTransferee]; !tOK && r.leadTransferee != 0 {
+ r.abortLeaderTransfer()
+ }
+
+ return cs
+}
+
+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)
+}
+
+func (r *raft) sendTimeoutNow(to uint64) {
+ r.send(pb.Message{To: to, Type: pb.MsgTimeoutNow})
+}
+
+func (r *raft) abortLeaderTransfer() {
+ r.leadTransferee = None
+}
+
+// committedEntryInCurrentTerm return true if the peer has committed an entry in its term.
+func (r *raft) committedEntryInCurrentTerm() bool {
+ return r.raftLog.zeroTermOnErrCompacted(r.raftLog.term(r.raftLog.committed)) == r.Term
+}
+
+// responseToReadIndexReq constructs a response for `req`. If `req` comes from the peer
+// itself, a blank value will be returned.
+func (r *raft) responseToReadIndexReq(req pb.Message, readIndex uint64) pb.Message {
+ if req.From == None || req.From == r.id {
+ r.readStates = append(r.readStates, ReadState{
+ Index: readIndex,
+ RequestCtx: req.Entries[0].Data,
+ })
+ return pb.Message{}
+ }
+ return pb.Message{
+ Type: pb.MsgReadIndexResp,
+ To: req.From,
+ Index: readIndex,
+ Entries: req.Entries,
+ }
+}
+
+// increaseUncommittedSize computes the size of the proposed entries and
+// determines whether they would push leader over its maxUncommittedSize limit.
+// If the new entries would exceed the limit, the method returns false. If not,
+// the increase in uncommitted entry size is recorded and the method returns
+// true.
+//
+// Empty payloads are never refused. This is used both for appending an empty
+// entry at a new leader's term, as well as leaving a joint configuration.
+func (r *raft) increaseUncommittedSize(ents []pb.Entry) bool {
+ var s uint64
+ for _, e := range ents {
+ s += uint64(PayloadSize(e))
+ }
+
+ if r.uncommittedSize > 0 && s > 0 && r.uncommittedSize+s > r.maxUncommittedSize {
+ // If the uncommitted tail of the Raft log is empty, allow any size
+ // proposal. Otherwise, limit the size of the uncommitted tail of the
+ // log and drop any proposal that would push the size over the limit.
+ // Note the added requirement s>0 which is used to make sure that
+ // appending single empty entries to the log always succeeds, used both
+ // for replicating a new leader's initial empty entry, and for
+ // auto-leaving joint configurations.
+ return false
+ }
+ r.uncommittedSize += s
+ return true
+}
+
+// reduceUncommittedSize accounts for the newly committed entries by decreasing
+// the uncommitted entry size limit.
+func (r *raft) reduceUncommittedSize(ents []pb.Entry) {
+ if r.uncommittedSize == 0 {
+ // Fast-path for followers, who do not track or enforce the limit.
+ return
+ }
+
+ var s uint64
+ for _, e := range ents {
+ s += uint64(PayloadSize(e))
+ }
+ if s > r.uncommittedSize {
+ // uncommittedSize may underestimate the size of the uncommitted Raft
+ // log tail but will never overestimate it. Saturate at 0 instead of
+ // allowing overflow.
+ r.uncommittedSize = 0
+ } else {
+ r.uncommittedSize -= s
+ }
+}
+
+func numOfPendingConf(ents []pb.Entry) int {
+ n := 0
+ for i := range ents {
+ if ents[i].Type == pb.EntryConfChange || ents[i].Type == pb.EntryConfChangeV2 {
+ n++
+ }
+ }
+ return n
+}
+
+func releasePendingReadIndexMessages(r *raft) {
+ if !r.committedEntryInCurrentTerm() {
+ r.logger.Error("pending MsgReadIndex should be released only after first commit in current term")
+ return
+ }
+
+ msgs := r.pendingReadIndexMessages
+ r.pendingReadIndexMessages = nil
+
+ for _, m := range msgs {
+ sendMsgReadIndexResponse(r, m)
+ }
+}
+
+func sendMsgReadIndexResponse(r *raft, m pb.Message) {
+ // thinking: use an internally 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 {
+ // If more than the local vote is needed, go through a full broadcast.
+ case ReadOnlySafe:
+ r.readOnly.addRequest(r.raftLog.committed, m)
+ // The local node automatically acks the request.
+ r.readOnly.recvAck(r.id, m.Entries[0].Data)
+ r.bcastHeartbeatWithCtx(m.Entries[0].Data)
+ case ReadOnlyLeaseBased:
+ if resp := r.responseToReadIndexReq(m, r.raftLog.committed); resp.To != None {
+ r.send(resp)
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/raftpb/confchange.go b/vendor/go.etcd.io/etcd/raft/v3/raftpb/confchange.go
new file mode 100644
index 0000000000..47fae65dfe
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/raftpb/confchange.go
@@ -0,0 +1,170 @@
+// Copyright 2019 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 raftpb
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/gogo/protobuf/proto"
+)
+
+// ConfChangeI abstracts over ConfChangeV2 and (legacy) ConfChange to allow
+// treating them in a unified manner.
+type ConfChangeI interface {
+ AsV2() ConfChangeV2
+ AsV1() (ConfChange, bool)
+}
+
+// MarshalConfChange calls Marshal on the underlying ConfChange or ConfChangeV2
+// and returns the result along with the corresponding EntryType.
+func MarshalConfChange(c ConfChangeI) (EntryType, []byte, error) {
+ var typ EntryType
+ var ccdata []byte
+ var err error
+ if ccv1, ok := c.AsV1(); ok {
+ typ = EntryConfChange
+ ccdata, err = ccv1.Marshal()
+ } else {
+ ccv2 := c.AsV2()
+ typ = EntryConfChangeV2
+ ccdata, err = ccv2.Marshal()
+ }
+ return typ, ccdata, err
+}
+
+// AsV2 returns a V2 configuration change carrying out the same operation.
+func (c ConfChange) AsV2() ConfChangeV2 {
+ return ConfChangeV2{
+ Changes: []ConfChangeSingle{{
+ Type: c.Type,
+ NodeID: c.NodeID,
+ }},
+ Context: c.Context,
+ }
+}
+
+// AsV1 returns the ConfChange and true.
+func (c ConfChange) AsV1() (ConfChange, bool) {
+ return c, true
+}
+
+// AsV2 is the identity.
+func (c ConfChangeV2) AsV2() ConfChangeV2 { return c }
+
+// AsV1 returns ConfChange{} and false.
+func (c ConfChangeV2) AsV1() (ConfChange, bool) { return ConfChange{}, false }
+
+// EnterJoint returns two bools. The second bool is true if and only if this
+// config change will use Joint Consensus, which is the case if it contains more
+// than one change or if the use of Joint Consensus was requested explicitly.
+// The first bool can only be true if second one is, and indicates whether the
+// Joint State will be left automatically.
+func (c ConfChangeV2) EnterJoint() (autoLeave bool, ok bool) {
+ // NB: in theory, more config changes could qualify for the "simple"
+ // protocol but it depends on the config on top of which the changes apply.
+ // For example, adding two learners is not OK if both nodes are part of the
+ // base config (i.e. two voters are turned into learners in the process of
+ // applying the conf change). In practice, these distinctions should not
+ // matter, so we keep it simple and use Joint Consensus liberally.
+ if c.Transition != ConfChangeTransitionAuto || len(c.Changes) > 1 {
+ // Use Joint Consensus.
+ var autoLeave bool
+ switch c.Transition {
+ case ConfChangeTransitionAuto:
+ autoLeave = true
+ case ConfChangeTransitionJointImplicit:
+ autoLeave = true
+ case ConfChangeTransitionJointExplicit:
+ default:
+ panic(fmt.Sprintf("unknown transition: %+v", c))
+ }
+ return autoLeave, true
+ }
+ return false, false
+}
+
+// LeaveJoint is true if the configuration change leaves a joint configuration.
+// This is the case if the ConfChangeV2 is zero, with the possible exception of
+// the Context field.
+func (c ConfChangeV2) LeaveJoint() bool {
+ // NB: c is already a copy.
+ c.Context = nil
+ return proto.Equal(&c, &ConfChangeV2{})
+}
+
+// ConfChangesFromString parses a Space-delimited sequence of operations into a
+// slice of ConfChangeSingle. The supported operations are:
+// - vn: make n a voter,
+// - ln: make n a learner,
+// - rn: remove n, and
+// - un: update n.
+func ConfChangesFromString(s string) ([]ConfChangeSingle, error) {
+ var ccs []ConfChangeSingle
+ toks := strings.Split(strings.TrimSpace(s), " ")
+ if toks[0] == "" {
+ toks = nil
+ }
+ for _, tok := range toks {
+ if len(tok) < 2 {
+ return nil, fmt.Errorf("unknown token %s", tok)
+ }
+ var cc ConfChangeSingle
+ switch tok[0] {
+ case 'v':
+ cc.Type = ConfChangeAddNode
+ case 'l':
+ cc.Type = ConfChangeAddLearnerNode
+ case 'r':
+ cc.Type = ConfChangeRemoveNode
+ case 'u':
+ cc.Type = ConfChangeUpdateNode
+ default:
+ return nil, fmt.Errorf("unknown input: %s", tok)
+ }
+ id, err := strconv.ParseUint(tok[1:], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ cc.NodeID = id
+ ccs = append(ccs, cc)
+ }
+ return ccs, nil
+}
+
+// ConfChangesToString is the inverse to ConfChangesFromString.
+func ConfChangesToString(ccs []ConfChangeSingle) string {
+ var buf strings.Builder
+ for i, cc := range ccs {
+ if i > 0 {
+ buf.WriteByte(' ')
+ }
+ switch cc.Type {
+ case ConfChangeAddNode:
+ buf.WriteByte('v')
+ case ConfChangeAddLearnerNode:
+ buf.WriteByte('l')
+ case ConfChangeRemoveNode:
+ buf.WriteByte('r')
+ case ConfChangeUpdateNode:
+ buf.WriteByte('u')
+ default:
+ buf.WriteString("unknown")
+ }
+ fmt.Fprintf(&buf, "%d", cc.NodeID)
+ }
+ return buf.String()
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/raftpb/confstate.go b/vendor/go.etcd.io/etcd/raft/v3/raftpb/confstate.go
new file mode 100644
index 0000000000..39b9dd7000
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/raftpb/confstate.go
@@ -0,0 +1,44 @@
+// Copyright 2019 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 raftpb
+
+import (
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// Equivalent returns a nil error if the inputs describe the same configuration.
+// On mismatch, returns a descriptive error showing the differences.
+func (cs ConfState) Equivalent(cs2 ConfState) error {
+ cs1 := cs
+ orig1, orig2 := cs1, cs2
+ s := func(sl *[]uint64) {
+ *sl = append([]uint64(nil), *sl...)
+ sort.Slice(*sl, func(i, j int) bool { return (*sl)[i] < (*sl)[j] })
+ }
+
+ for _, cs := range []*ConfState{&cs1, &cs2} {
+ s(&cs.Voters)
+ s(&cs.Learners)
+ s(&cs.VotersOutgoing)
+ s(&cs.LearnersNext)
+ }
+
+ if !reflect.DeepEqual(cs1, cs2) {
+ return fmt.Errorf("ConfStates not equivalent after sorting:\n%+#v\n%+#v\nInputs were:\n%+#v\n%+#v", cs1, cs2, orig1, orig2)
+ }
+ return nil
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.pb.go b/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.pb.go
new file mode 100644
index 0000000000..1ee77a9a45
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.pb.go
@@ -0,0 +1,2988 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: raft.proto
+
+package raftpb
+
+import (
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+ proto "github.com/golang/protobuf/proto"
+)
+
+// 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.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type EntryType int32
+
+const (
+ EntryNormal EntryType = 0
+ EntryConfChange EntryType = 1
+ EntryConfChangeV2 EntryType = 2
+)
+
+var EntryType_name = map[int32]string{
+ 0: "EntryNormal",
+ 1: "EntryConfChange",
+ 2: "EntryConfChangeV2",
+}
+
+var EntryType_value = map[string]int32{
+ "EntryNormal": 0,
+ "EntryConfChange": 1,
+ "EntryConfChangeV2": 2,
+}
+
+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 fileDescriptor_b042552c306ae59b, []int{0}
+}
+
+// For description of different message types, see:
+// https://pkg.go.dev/go.etcd.io/etcd/raft/v3#hdr-MessageType
+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 fileDescriptor_b042552c306ae59b, []int{1}
+}
+
+// ConfChangeTransition specifies the behavior of a configuration change with
+// respect to joint consensus.
+type ConfChangeTransition int32
+
+const (
+ // Automatically use the simple protocol if possible, otherwise fall back
+ // to ConfChangeJointImplicit. Most applications will want to use this.
+ ConfChangeTransitionAuto ConfChangeTransition = 0
+ // Use joint consensus unconditionally, and transition out of them
+ // automatically (by proposing a zero configuration change).
+ //
+ // This option is suitable for applications that want to minimize the time
+ // spent in the joint configuration and do not store the joint configuration
+ // in the state machine (outside of InitialState).
+ ConfChangeTransitionJointImplicit ConfChangeTransition = 1
+ // Use joint consensus and remain in the joint configuration until the
+ // application proposes a no-op configuration change. This is suitable for
+ // applications that want to explicitly control the transitions, for example
+ // to use a custom payload (via the Context field).
+ ConfChangeTransitionJointExplicit ConfChangeTransition = 2
+)
+
+var ConfChangeTransition_name = map[int32]string{
+ 0: "ConfChangeTransitionAuto",
+ 1: "ConfChangeTransitionJointImplicit",
+ 2: "ConfChangeTransitionJointExplicit",
+}
+
+var ConfChangeTransition_value = map[string]int32{
+ "ConfChangeTransitionAuto": 0,
+ "ConfChangeTransitionJointImplicit": 1,
+ "ConfChangeTransitionJointExplicit": 2,
+}
+
+func (x ConfChangeTransition) Enum() *ConfChangeTransition {
+ p := new(ConfChangeTransition)
+ *p = x
+ return p
+}
+
+func (x ConfChangeTransition) String() string {
+ return proto.EnumName(ConfChangeTransition_name, int32(x))
+}
+
+func (x *ConfChangeTransition) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(ConfChangeTransition_value, data, "ConfChangeTransition")
+ if err != nil {
+ return err
+ }
+ *x = ConfChangeTransition(value)
+ return nil
+}
+
+func (ConfChangeTransition) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{2}
+}
+
+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 fileDescriptor_b042552c306ae59b, []int{3}
+}
+
+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"`
+}
+
+func (m *Entry) Reset() { *m = Entry{} }
+func (m *Entry) String() string { return proto.CompactTextString(m) }
+func (*Entry) ProtoMessage() {}
+func (*Entry) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{0}
+}
+func (m *Entry) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Entry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Entry.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Entry) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Entry.Merge(m, src)
+}
+func (m *Entry) XXX_Size() int {
+ return m.Size()
+}
+func (m *Entry) XXX_DiscardUnknown() {
+ xxx_messageInfo_Entry.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Entry proto.InternalMessageInfo
+
+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"`
+}
+
+func (m *SnapshotMetadata) Reset() { *m = SnapshotMetadata{} }
+func (m *SnapshotMetadata) String() string { return proto.CompactTextString(m) }
+func (*SnapshotMetadata) ProtoMessage() {}
+func (*SnapshotMetadata) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{1}
+}
+func (m *SnapshotMetadata) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *SnapshotMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_SnapshotMetadata.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *SnapshotMetadata) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SnapshotMetadata.Merge(m, src)
+}
+func (m *SnapshotMetadata) XXX_Size() int {
+ return m.Size()
+}
+func (m *SnapshotMetadata) XXX_DiscardUnknown() {
+ xxx_messageInfo_SnapshotMetadata.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SnapshotMetadata proto.InternalMessageInfo
+
+type Snapshot struct {
+ Data []byte `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
+ Metadata SnapshotMetadata `protobuf:"bytes,2,opt,name=metadata" json:"metadata"`
+}
+
+func (m *Snapshot) Reset() { *m = Snapshot{} }
+func (m *Snapshot) String() string { return proto.CompactTextString(m) }
+func (*Snapshot) ProtoMessage() {}
+func (*Snapshot) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{2}
+}
+func (m *Snapshot) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Snapshot.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Snapshot) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Snapshot.Merge(m, src)
+}
+func (m *Snapshot) XXX_Size() int {
+ return m.Size()
+}
+func (m *Snapshot) XXX_DiscardUnknown() {
+ xxx_messageInfo_Snapshot.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Snapshot proto.InternalMessageInfo
+
+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 is generally used for appending Raft logs to followers. For example,
+ // (type=MsgApp,index=100,logTerm=5) means leader appends entries starting at
+ // index=101, and the term of entry at index 100 is 5.
+ // (type=MsgAppResp,reject=true,index=100,logTerm=5) means follower rejects some
+ // entries from its leader as it already has an entry with term 5 at index 100.
+ 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"`
+}
+
+func (m *Message) Reset() { *m = Message{} }
+func (m *Message) String() string { return proto.CompactTextString(m) }
+func (*Message) ProtoMessage() {}
+func (*Message) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{3}
+}
+func (m *Message) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Message.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Message) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Message.Merge(m, src)
+}
+func (m *Message) XXX_Size() int {
+ return m.Size()
+}
+func (m *Message) XXX_DiscardUnknown() {
+ xxx_messageInfo_Message.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message proto.InternalMessageInfo
+
+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"`
+}
+
+func (m *HardState) Reset() { *m = HardState{} }
+func (m *HardState) String() string { return proto.CompactTextString(m) }
+func (*HardState) ProtoMessage() {}
+func (*HardState) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{4}
+}
+func (m *HardState) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *HardState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_HardState.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *HardState) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_HardState.Merge(m, src)
+}
+func (m *HardState) XXX_Size() int {
+ return m.Size()
+}
+func (m *HardState) XXX_DiscardUnknown() {
+ xxx_messageInfo_HardState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HardState proto.InternalMessageInfo
+
+type ConfState struct {
+ // The voters in the incoming config. (If the configuration is not joint,
+ // then the outgoing config is empty).
+ Voters []uint64 `protobuf:"varint,1,rep,name=voters" json:"voters,omitempty"`
+ // The learners in the incoming config.
+ Learners []uint64 `protobuf:"varint,2,rep,name=learners" json:"learners,omitempty"`
+ // The voters in the outgoing config.
+ VotersOutgoing []uint64 `protobuf:"varint,3,rep,name=voters_outgoing,json=votersOutgoing" json:"voters_outgoing,omitempty"`
+ // The nodes that will become learners when the outgoing config is removed.
+ // These nodes are necessarily currently in nodes_joint (or they would have
+ // been added to the incoming config right away).
+ LearnersNext []uint64 `protobuf:"varint,4,rep,name=learners_next,json=learnersNext" json:"learners_next,omitempty"`
+ // If set, the config is joint and Raft will automatically transition into
+ // the final config (i.e. remove the outgoing config) when this is safe.
+ AutoLeave bool `protobuf:"varint,5,opt,name=auto_leave,json=autoLeave" json:"auto_leave"`
+}
+
+func (m *ConfState) Reset() { *m = ConfState{} }
+func (m *ConfState) String() string { return proto.CompactTextString(m) }
+func (*ConfState) ProtoMessage() {}
+func (*ConfState) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{5}
+}
+func (m *ConfState) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ConfState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ConfState.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ConfState) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ConfState.Merge(m, src)
+}
+func (m *ConfState) XXX_Size() int {
+ return m.Size()
+}
+func (m *ConfState) XXX_DiscardUnknown() {
+ xxx_messageInfo_ConfState.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConfState proto.InternalMessageInfo
+
+type ConfChange struct {
+ Type ConfChangeType `protobuf:"varint,2,opt,name=type,enum=raftpb.ConfChangeType" json:"type"`
+ NodeID uint64 `protobuf:"varint,3,opt,name=node_id,json=nodeId" json:"node_id"`
+ Context []byte `protobuf:"bytes,4,opt,name=context" json:"context,omitempty"`
+ // NB: this is used only by etcd to thread through a unique identifier.
+ // Ideally it should really use the Context instead. No counterpart to
+ // this field exists in ConfChangeV2.
+ ID uint64 `protobuf:"varint,1,opt,name=id" json:"id"`
+}
+
+func (m *ConfChange) Reset() { *m = ConfChange{} }
+func (m *ConfChange) String() string { return proto.CompactTextString(m) }
+func (*ConfChange) ProtoMessage() {}
+func (*ConfChange) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{6}
+}
+func (m *ConfChange) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ConfChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ConfChange.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ConfChange) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ConfChange.Merge(m, src)
+}
+func (m *ConfChange) XXX_Size() int {
+ return m.Size()
+}
+func (m *ConfChange) XXX_DiscardUnknown() {
+ xxx_messageInfo_ConfChange.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConfChange proto.InternalMessageInfo
+
+// ConfChangeSingle is an individual configuration change operation. Multiple
+// such operations can be carried out atomically via a ConfChangeV2.
+type ConfChangeSingle struct {
+ Type ConfChangeType `protobuf:"varint,1,opt,name=type,enum=raftpb.ConfChangeType" json:"type"`
+ NodeID uint64 `protobuf:"varint,2,opt,name=node_id,json=nodeId" json:"node_id"`
+}
+
+func (m *ConfChangeSingle) Reset() { *m = ConfChangeSingle{} }
+func (m *ConfChangeSingle) String() string { return proto.CompactTextString(m) }
+func (*ConfChangeSingle) ProtoMessage() {}
+func (*ConfChangeSingle) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{7}
+}
+func (m *ConfChangeSingle) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ConfChangeSingle) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ConfChangeSingle.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ConfChangeSingle) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ConfChangeSingle.Merge(m, src)
+}
+func (m *ConfChangeSingle) XXX_Size() int {
+ return m.Size()
+}
+func (m *ConfChangeSingle) XXX_DiscardUnknown() {
+ xxx_messageInfo_ConfChangeSingle.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConfChangeSingle proto.InternalMessageInfo
+
+// ConfChangeV2 messages initiate configuration changes. They support both the
+// simple "one at a time" membership change protocol and full Joint Consensus
+// allowing for arbitrary changes in membership.
+//
+// The supplied context is treated as an opaque payload and can be used to
+// attach an action on the state machine to the application of the config change
+// proposal. Note that contrary to Joint Consensus as outlined in the Raft
+// paper[1], configuration changes become active when they are *applied* to the
+// state machine (not when they are appended to the log).
+//
+// The simple protocol can be used whenever only a single change is made.
+//
+// Non-simple changes require the use of Joint Consensus, for which two
+// configuration changes are run. The first configuration change specifies the
+// desired changes and transitions the Raft group into the joint configuration,
+// in which quorum requires a majority of both the pre-changes and post-changes
+// configuration. Joint Consensus avoids entering fragile intermediate
+// configurations that could compromise survivability. For example, without the
+// use of Joint Consensus and running across three availability zones with a
+// replication factor of three, it is not possible to replace a voter without
+// entering an intermediate configuration that does not survive the outage of
+// one availability zone.
+//
+// The provided ConfChangeTransition specifies how (and whether) Joint Consensus
+// is used, and assigns the task of leaving the joint configuration either to
+// Raft or the application. Leaving the joint configuration is accomplished by
+// proposing a ConfChangeV2 with only and optionally the Context field
+// populated.
+//
+// For details on Raft membership changes, see:
+//
+// [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf
+type ConfChangeV2 struct {
+ Transition ConfChangeTransition `protobuf:"varint,1,opt,name=transition,enum=raftpb.ConfChangeTransition" json:"transition"`
+ Changes []ConfChangeSingle `protobuf:"bytes,2,rep,name=changes" json:"changes"`
+ Context []byte `protobuf:"bytes,3,opt,name=context" json:"context,omitempty"`
+}
+
+func (m *ConfChangeV2) Reset() { *m = ConfChangeV2{} }
+func (m *ConfChangeV2) String() string { return proto.CompactTextString(m) }
+func (*ConfChangeV2) ProtoMessage() {}
+func (*ConfChangeV2) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b042552c306ae59b, []int{8}
+}
+func (m *ConfChangeV2) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ConfChangeV2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ConfChangeV2.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ConfChangeV2) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ConfChangeV2.Merge(m, src)
+}
+func (m *ConfChangeV2) XXX_Size() int {
+ return m.Size()
+}
+func (m *ConfChangeV2) XXX_DiscardUnknown() {
+ xxx_messageInfo_ConfChangeV2.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConfChangeV2 proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterEnum("raftpb.EntryType", EntryType_name, EntryType_value)
+ proto.RegisterEnum("raftpb.MessageType", MessageType_name, MessageType_value)
+ proto.RegisterEnum("raftpb.ConfChangeTransition", ConfChangeTransition_name, ConfChangeTransition_value)
+ proto.RegisterEnum("raftpb.ConfChangeType", ConfChangeType_name, ConfChangeType_value)
+ 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.RegisterType((*ConfChangeSingle)(nil), "raftpb.ConfChangeSingle")
+ proto.RegisterType((*ConfChangeV2)(nil), "raftpb.ConfChangeV2")
+}
+
+func init() { proto.RegisterFile("raft.proto", fileDescriptor_b042552c306ae59b) }
+
+var fileDescriptor_b042552c306ae59b = []byte{
+ // 1026 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x6e, 0xdb, 0x46,
+ 0x17, 0x25, 0x29, 0x5a, 0x3f, 0x57, 0xb2, 0x3c, 0xbe, 0xf1, 0x17, 0x10, 0x86, 0xc1, 0xe8, 0x53,
+ 0x52, 0x44, 0x70, 0x11, 0xb7, 0xd0, 0xa2, 0x28, 0xba, 0xf3, 0x4f, 0x00, 0xab, 0xb0, 0xdc, 0x54,
+ 0x76, 0xbc, 0x28, 0x50, 0x08, 0x63, 0x71, 0x44, 0xb3, 0x15, 0x39, 0x04, 0x39, 0x72, 0xed, 0x4d,
+ 0x51, 0xf4, 0x09, 0xba, 0xec, 0x26, 0xdb, 0x3e, 0x40, 0x9f, 0xc2, 0x4b, 0x03, 0xdd, 0x74, 0x15,
+ 0x34, 0xf6, 0x8b, 0x14, 0x33, 0x1c, 0x4a, 0x94, 0x6c, 0x64, 0xd1, 0xdd, 0xcc, 0xb9, 0x67, 0xee,
+ 0x9c, 0x73, 0xef, 0xe5, 0x10, 0x20, 0xa1, 0x63, 0xb1, 0x13, 0x27, 0x5c, 0x70, 0x2c, 0xcb, 0x75,
+ 0x7c, 0xbe, 0xb9, 0xe1, 0x73, 0x9f, 0x2b, 0xe8, 0x33, 0xb9, 0xca, 0xa2, 0xed, 0x9f, 0x61, 0xe5,
+ 0x75, 0x24, 0x92, 0x6b, 0x74, 0xc0, 0x3e, 0x65, 0x49, 0xe8, 0x58, 0x2d, 0xb3, 0x63, 0xef, 0xd9,
+ 0x37, 0xef, 0x9f, 0x19, 0x03, 0x85, 0xe0, 0x26, 0xac, 0xf4, 0x22, 0x8f, 0x5d, 0x39, 0xa5, 0x42,
+ 0x28, 0x83, 0xf0, 0x53, 0xb0, 0x4f, 0xaf, 0x63, 0xe6, 0x98, 0x2d, 0xb3, 0xd3, 0xec, 0xae, 0xef,
+ 0x64, 0x77, 0xed, 0xa8, 0x94, 0x32, 0x30, 0x4b, 0x74, 0x1d, 0x33, 0x44, 0xb0, 0x0f, 0xa8, 0xa0,
+ 0x8e, 0xdd, 0x32, 0x3b, 0x8d, 0x81, 0x5a, 0xb7, 0x7f, 0x31, 0x81, 0x9c, 0x44, 0x34, 0x4e, 0x2f,
+ 0xb8, 0xe8, 0x33, 0x41, 0x3d, 0x2a, 0x28, 0x7e, 0x01, 0x30, 0xe2, 0xd1, 0x78, 0x98, 0x0a, 0x2a,
+ 0xb2, 0xdc, 0xf5, 0x79, 0xee, 0x7d, 0x1e, 0x8d, 0x4f, 0x64, 0x40, 0xe7, 0xae, 0x8d, 0x72, 0x40,
+ 0x2a, 0x0d, 0x94, 0xd2, 0xa2, 0x89, 0x0c, 0x92, 0xfe, 0x84, 0xf4, 0x57, 0x34, 0xa1, 0x90, 0xf6,
+ 0x77, 0x50, 0xcd, 0x15, 0x48, 0x89, 0x52, 0x81, 0xba, 0xb3, 0x31, 0x50, 0x6b, 0xfc, 0x0a, 0xaa,
+ 0xa1, 0x56, 0xa6, 0x12, 0xd7, 0xbb, 0x4e, 0xae, 0x65, 0x59, 0xb9, 0xce, 0x3b, 0xe3, 0xb7, 0xdf,
+ 0x95, 0xa0, 0xd2, 0x67, 0x69, 0x4a, 0x7d, 0x86, 0xaf, 0xc0, 0x16, 0xf3, 0x5a, 0x3d, 0xc9, 0x73,
+ 0xe8, 0x70, 0xb1, 0x5a, 0x92, 0x86, 0x1b, 0x60, 0x09, 0xbe, 0xe0, 0xc4, 0x12, 0x5c, 0xda, 0x18,
+ 0x27, 0x7c, 0xc9, 0x86, 0x44, 0x66, 0x06, 0xed, 0x65, 0x83, 0xe8, 0x42, 0x65, 0xc2, 0x7d, 0xd5,
+ 0xdd, 0x95, 0x42, 0x30, 0x07, 0xe7, 0x65, 0x2b, 0x3f, 0x2c, 0xdb, 0x2b, 0xa8, 0xb0, 0x48, 0x24,
+ 0x01, 0x4b, 0x9d, 0x4a, 0xab, 0xd4, 0xa9, 0x77, 0x57, 0x17, 0x7a, 0x9c, 0xa7, 0xd2, 0x1c, 0xdc,
+ 0x82, 0xf2, 0x88, 0x87, 0x61, 0x20, 0x9c, 0x6a, 0x21, 0x97, 0xc6, 0xb0, 0x0b, 0xd5, 0x54, 0x57,
+ 0xcc, 0xa9, 0xa9, 0x4a, 0x92, 0xe5, 0x4a, 0xe6, 0x15, 0xcc, 0x79, 0x32, 0x63, 0xc2, 0x7e, 0x60,
+ 0x23, 0xe1, 0x40, 0xcb, 0xec, 0x54, 0xf3, 0x8c, 0x19, 0x86, 0x2f, 0x00, 0xb2, 0xd5, 0x61, 0x10,
+ 0x09, 0xa7, 0x5e, 0xb8, 0xb3, 0x80, 0xa3, 0x03, 0x95, 0x11, 0x8f, 0x04, 0xbb, 0x12, 0x4e, 0x43,
+ 0x35, 0x36, 0xdf, 0xb6, 0xbf, 0x87, 0xda, 0x21, 0x4d, 0xbc, 0x6c, 0x7c, 0xf2, 0x0a, 0x9a, 0x0f,
+ 0x2a, 0xe8, 0x80, 0x7d, 0xc9, 0x05, 0x5b, 0xfc, 0x38, 0x24, 0x52, 0x30, 0x5c, 0x7a, 0x68, 0xb8,
+ 0xfd, 0xa7, 0x09, 0xb5, 0xd9, 0xbc, 0xe2, 0x53, 0x28, 0xcb, 0x33, 0x49, 0xea, 0x98, 0xad, 0x52,
+ 0xc7, 0x1e, 0xe8, 0x1d, 0x6e, 0x42, 0x75, 0xc2, 0x68, 0x12, 0xc9, 0x88, 0xa5, 0x22, 0xb3, 0x3d,
+ 0xbe, 0x84, 0xb5, 0x8c, 0x35, 0xe4, 0x53, 0xe1, 0xf3, 0x20, 0xf2, 0x9d, 0x92, 0xa2, 0x34, 0x33,
+ 0xf8, 0x1b, 0x8d, 0xe2, 0x73, 0x58, 0xcd, 0x0f, 0x0d, 0x23, 0xe9, 0xd4, 0x56, 0xb4, 0x46, 0x0e,
+ 0x1e, 0xb3, 0x2b, 0x81, 0xcf, 0x01, 0xe8, 0x54, 0xf0, 0xe1, 0x84, 0xd1, 0x4b, 0xa6, 0x86, 0x21,
+ 0x2f, 0x68, 0x4d, 0xe2, 0x47, 0x12, 0x6e, 0xbf, 0x33, 0x01, 0xa4, 0xe8, 0xfd, 0x0b, 0x1a, 0xf9,
+ 0x0c, 0x3f, 0xd7, 0x63, 0x6b, 0xa9, 0xb1, 0x7d, 0x5a, 0xfc, 0x0c, 0x33, 0xc6, 0x83, 0xc9, 0x7d,
+ 0x09, 0x95, 0x88, 0x7b, 0x6c, 0x18, 0x78, 0xba, 0x28, 0x4d, 0x19, 0xbc, 0x7b, 0xff, 0xac, 0x7c,
+ 0xcc, 0x3d, 0xd6, 0x3b, 0x18, 0x94, 0x65, 0xb8, 0xe7, 0x15, 0xfb, 0x62, 0x2f, 0xf4, 0x05, 0x37,
+ 0xc1, 0x0a, 0x3c, 0xdd, 0x08, 0xd0, 0xa7, 0xad, 0xde, 0xc1, 0xc0, 0x0a, 0xbc, 0x76, 0x08, 0x64,
+ 0x7e, 0xf9, 0x49, 0x10, 0xf9, 0x93, 0xb9, 0x48, 0xf3, 0xbf, 0x88, 0xb4, 0x3e, 0x26, 0xb2, 0xfd,
+ 0x87, 0x09, 0x8d, 0x79, 0x9e, 0xb3, 0x2e, 0xee, 0x01, 0x88, 0x84, 0x46, 0x69, 0x20, 0x02, 0x1e,
+ 0xe9, 0x1b, 0xb7, 0x1e, 0xb9, 0x71, 0xc6, 0xc9, 0x27, 0x72, 0x7e, 0x0a, 0xbf, 0x84, 0xca, 0x48,
+ 0xb1, 0xb2, 0x8e, 0x17, 0x9e, 0x94, 0x65, 0x6b, 0xf9, 0x17, 0xa6, 0xe9, 0xc5, 0x9a, 0x95, 0x16,
+ 0x6a, 0xb6, 0x7d, 0x08, 0xb5, 0xd9, 0xbb, 0x8b, 0x6b, 0x50, 0x57, 0x9b, 0x63, 0x9e, 0x84, 0x74,
+ 0x42, 0x0c, 0x7c, 0x02, 0x6b, 0x0a, 0x98, 0xe7, 0x27, 0x26, 0xfe, 0x0f, 0xd6, 0x97, 0xc0, 0xb3,
+ 0x2e, 0xb1, 0xb6, 0xff, 0xb2, 0xa0, 0x5e, 0x78, 0x96, 0x10, 0xa0, 0xdc, 0x4f, 0xfd, 0xc3, 0x69,
+ 0x4c, 0x0c, 0xac, 0x43, 0xa5, 0x9f, 0xfa, 0x7b, 0x8c, 0x0a, 0x62, 0xea, 0xcd, 0x9b, 0x84, 0xc7,
+ 0xc4, 0xd2, 0xac, 0xdd, 0x38, 0x26, 0x25, 0x6c, 0x02, 0x64, 0xeb, 0x01, 0x4b, 0x63, 0x62, 0x6b,
+ 0xe2, 0x19, 0x17, 0x8c, 0xac, 0x48, 0x6d, 0x7a, 0xa3, 0xa2, 0x65, 0x1d, 0x95, 0x4f, 0x00, 0xa9,
+ 0x20, 0x81, 0x86, 0xbc, 0x8c, 0xd1, 0x44, 0x9c, 0xcb, 0x5b, 0xaa, 0xb8, 0x01, 0xa4, 0x88, 0xa8,
+ 0x43, 0x35, 0x44, 0x68, 0xf6, 0x53, 0xff, 0x6d, 0x94, 0x30, 0x3a, 0xba, 0xa0, 0xe7, 0x13, 0x46,
+ 0x00, 0xd7, 0x61, 0x55, 0x27, 0x92, 0x5f, 0xdc, 0x34, 0x25, 0x75, 0x4d, 0xdb, 0xbf, 0x60, 0xa3,
+ 0x1f, 0xbf, 0x9d, 0xf2, 0x64, 0x1a, 0x92, 0x86, 0xb4, 0xdd, 0x4f, 0x7d, 0xd5, 0xa0, 0x31, 0x4b,
+ 0x8e, 0x18, 0xf5, 0x58, 0x42, 0x56, 0xf5, 0xe9, 0xd3, 0x20, 0x64, 0x7c, 0x2a, 0x8e, 0xf9, 0x4f,
+ 0xa4, 0xa9, 0xc5, 0x0c, 0x18, 0xf5, 0xd4, 0xff, 0x8e, 0xac, 0x69, 0x31, 0x33, 0x44, 0x89, 0x21,
+ 0xda, 0xef, 0x9b, 0x84, 0x29, 0x8b, 0xeb, 0xfa, 0x56, 0xbd, 0x57, 0x1c, 0xdc, 0xfe, 0xd5, 0x84,
+ 0x8d, 0xc7, 0xc6, 0x03, 0xb7, 0xc0, 0x79, 0x0c, 0xdf, 0x9d, 0x0a, 0x4e, 0x0c, 0xfc, 0x04, 0xfe,
+ 0xff, 0x58, 0xf4, 0x6b, 0x1e, 0x44, 0xa2, 0x17, 0xc6, 0x93, 0x60, 0x14, 0xc8, 0x56, 0x7c, 0x8c,
+ 0xf6, 0xfa, 0x4a, 0xd3, 0xac, 0xed, 0x6b, 0x68, 0x2e, 0x7e, 0x14, 0xb2, 0x18, 0x73, 0x64, 0xd7,
+ 0xf3, 0xe4, 0xf8, 0x13, 0x03, 0x9d, 0xa2, 0xd8, 0x01, 0x0b, 0xf9, 0x25, 0x53, 0x11, 0x73, 0x31,
+ 0xf2, 0x36, 0xf6, 0xa8, 0xc8, 0x22, 0xd6, 0xa2, 0x91, 0x5d, 0xcf, 0x3b, 0xca, 0xde, 0x1e, 0x15,
+ 0x2d, 0xed, 0xbd, 0xb8, 0xf9, 0xe0, 0x1a, 0xb7, 0x1f, 0x5c, 0xe3, 0xe6, 0xce, 0x35, 0x6f, 0xef,
+ 0x5c, 0xf3, 0x9f, 0x3b, 0xd7, 0xfc, 0xed, 0xde, 0x35, 0x7e, 0xbf, 0x77, 0x8d, 0xdb, 0x7b, 0xd7,
+ 0xf8, 0xfb, 0xde, 0x35, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xee, 0xe3, 0x39, 0x8b, 0xbb, 0x08,
+ 0x00, 0x00,
+}
+
+func (m *Entry) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Entry) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Entry) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Data != nil {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x22
+ }
+ i = encodeVarintRaft(dAtA, i, uint64(m.Index))
+ i--
+ dAtA[i] = 0x18
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ i--
+ dAtA[i] = 0x10
+ i = encodeVarintRaft(dAtA, i, uint64(m.Type))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func (m *SnapshotMetadata) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *SnapshotMetadata) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *SnapshotMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ i--
+ dAtA[i] = 0x18
+ i = encodeVarintRaft(dAtA, i, uint64(m.Index))
+ i--
+ dAtA[i] = 0x10
+ {
+ size, err := m.ConfState.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintRaft(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ return len(dAtA) - i, nil
+}
+
+func (m *Snapshot) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Snapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ {
+ size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintRaft(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ if m.Data != nil {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *Message) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Message) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Context != nil {
+ i -= len(m.Context)
+ copy(dAtA[i:], m.Context)
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Context)))
+ i--
+ dAtA[i] = 0x62
+ }
+ i = encodeVarintRaft(dAtA, i, uint64(m.RejectHint))
+ i--
+ dAtA[i] = 0x58
+ i--
+ if m.Reject {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x50
+ {
+ size, err := m.Snapshot.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintRaft(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x4a
+ i = encodeVarintRaft(dAtA, i, uint64(m.Commit))
+ i--
+ dAtA[i] = 0x40
+ if len(m.Entries) > 0 {
+ for iNdEx := len(m.Entries) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Entries[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintRaft(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x3a
+ }
+ }
+ i = encodeVarintRaft(dAtA, i, uint64(m.Index))
+ i--
+ dAtA[i] = 0x30
+ i = encodeVarintRaft(dAtA, i, uint64(m.LogTerm))
+ i--
+ dAtA[i] = 0x28
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ i--
+ dAtA[i] = 0x20
+ i = encodeVarintRaft(dAtA, i, uint64(m.From))
+ i--
+ dAtA[i] = 0x18
+ i = encodeVarintRaft(dAtA, i, uint64(m.To))
+ i--
+ dAtA[i] = 0x10
+ i = encodeVarintRaft(dAtA, i, uint64(m.Type))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func (m *HardState) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *HardState) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *HardState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ i = encodeVarintRaft(dAtA, i, uint64(m.Commit))
+ i--
+ dAtA[i] = 0x18
+ i = encodeVarintRaft(dAtA, i, uint64(m.Vote))
+ i--
+ dAtA[i] = 0x10
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func (m *ConfState) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ConfState) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ConfState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ i--
+ if m.AutoLeave {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x28
+ if len(m.LearnersNext) > 0 {
+ for iNdEx := len(m.LearnersNext) - 1; iNdEx >= 0; iNdEx-- {
+ i = encodeVarintRaft(dAtA, i, uint64(m.LearnersNext[iNdEx]))
+ i--
+ dAtA[i] = 0x20
+ }
+ }
+ if len(m.VotersOutgoing) > 0 {
+ for iNdEx := len(m.VotersOutgoing) - 1; iNdEx >= 0; iNdEx-- {
+ i = encodeVarintRaft(dAtA, i, uint64(m.VotersOutgoing[iNdEx]))
+ i--
+ dAtA[i] = 0x18
+ }
+ }
+ if len(m.Learners) > 0 {
+ for iNdEx := len(m.Learners) - 1; iNdEx >= 0; iNdEx-- {
+ i = encodeVarintRaft(dAtA, i, uint64(m.Learners[iNdEx]))
+ i--
+ dAtA[i] = 0x10
+ }
+ }
+ if len(m.Voters) > 0 {
+ for iNdEx := len(m.Voters) - 1; iNdEx >= 0; iNdEx-- {
+ i = encodeVarintRaft(dAtA, i, uint64(m.Voters[iNdEx]))
+ i--
+ dAtA[i] = 0x8
+ }
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ConfChange) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ConfChange) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ConfChange) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Context != nil {
+ i -= len(m.Context)
+ copy(dAtA[i:], m.Context)
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Context)))
+ i--
+ dAtA[i] = 0x22
+ }
+ i = encodeVarintRaft(dAtA, i, uint64(m.NodeID))
+ i--
+ dAtA[i] = 0x18
+ i = encodeVarintRaft(dAtA, i, uint64(m.Type))
+ i--
+ dAtA[i] = 0x10
+ i = encodeVarintRaft(dAtA, i, uint64(m.ID))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func (m *ConfChangeSingle) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ConfChangeSingle) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ConfChangeSingle) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ i = encodeVarintRaft(dAtA, i, uint64(m.NodeID))
+ i--
+ dAtA[i] = 0x10
+ i = encodeVarintRaft(dAtA, i, uint64(m.Type))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func (m *ConfChangeV2) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ConfChangeV2) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ConfChangeV2) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.Context != nil {
+ i -= len(m.Context)
+ copy(dAtA[i:], m.Context)
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Context)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Changes) > 0 {
+ for iNdEx := len(m.Changes) - 1; iNdEx >= 0; iNdEx-- {
+ {
+ size, err := m.Changes[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintRaft(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ }
+ i = encodeVarintRaft(dAtA, i, uint64(m.Transition))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintRaft(dAtA []byte, offset int, v uint64) int {
+ offset -= sovRaft(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *Entry) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ 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))
+ }
+ return n
+}
+
+func (m *SnapshotMetadata) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ 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))
+ return n
+}
+
+func (m *Snapshot) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ 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))
+ return n
+}
+
+func (m *Message) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ 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))
+ }
+ return n
+}
+
+func (m *HardState) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ n += 1 + sovRaft(uint64(m.Term))
+ n += 1 + sovRaft(uint64(m.Vote))
+ n += 1 + sovRaft(uint64(m.Commit))
+ return n
+}
+
+func (m *ConfState) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if len(m.Voters) > 0 {
+ for _, e := range m.Voters {
+ n += 1 + sovRaft(uint64(e))
+ }
+ }
+ if len(m.Learners) > 0 {
+ for _, e := range m.Learners {
+ n += 1 + sovRaft(uint64(e))
+ }
+ }
+ if len(m.VotersOutgoing) > 0 {
+ for _, e := range m.VotersOutgoing {
+ n += 1 + sovRaft(uint64(e))
+ }
+ }
+ if len(m.LearnersNext) > 0 {
+ for _, e := range m.LearnersNext {
+ n += 1 + sovRaft(uint64(e))
+ }
+ }
+ n += 2
+ return n
+}
+
+func (m *ConfChange) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ 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))
+ }
+ return n
+}
+
+func (m *ConfChangeSingle) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ n += 1 + sovRaft(uint64(m.Type))
+ n += 1 + sovRaft(uint64(m.NodeID))
+ return n
+}
+
+func (m *ConfChangeV2) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ n += 1 + sovRaft(uint64(m.Transition))
+ if len(m.Changes) > 0 {
+ for _, e := range m.Changes {
+ l = e.Size()
+ n += 1 + l + sovRaft(uint64(l))
+ }
+ }
+ if m.Context != nil {
+ l = len(m.Context)
+ n += 1 + l + sovRaft(uint64(l))
+ }
+ return n
+}
+
+func sovRaft(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ 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.Voters = append(m.Voters, 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var elementCount int
+ var count int
+ for _, integer := range dAtA[iNdEx:postIndex] {
+ if integer < 128 {
+ count++
+ }
+ }
+ elementCount = count
+ if elementCount != 0 && len(m.Voters) == 0 {
+ m.Voters = make([]uint64, 0, elementCount)
+ }
+ 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.Voters = append(m.Voters, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field Voters", 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var elementCount int
+ var count int
+ for _, integer := range dAtA[iNdEx:postIndex] {
+ if integer < 128 {
+ count++
+ }
+ }
+ elementCount = count
+ if elementCount != 0 && len(m.Learners) == 0 {
+ m.Learners = make([]uint64, 0, elementCount)
+ }
+ 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)
+ }
+ case 3:
+ 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.VotersOutgoing = append(m.VotersOutgoing, 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var elementCount int
+ var count int
+ for _, integer := range dAtA[iNdEx:postIndex] {
+ if integer < 128 {
+ count++
+ }
+ }
+ elementCount = count
+ if elementCount != 0 && len(m.VotersOutgoing) == 0 {
+ m.VotersOutgoing = make([]uint64, 0, elementCount)
+ }
+ 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.VotersOutgoing = append(m.VotersOutgoing, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field VotersOutgoing", wireType)
+ }
+ case 4:
+ 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.LearnersNext = append(m.LearnersNext, 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var elementCount int
+ var count int
+ for _, integer := range dAtA[iNdEx:postIndex] {
+ if integer < 128 {
+ count++
+ }
+ }
+ elementCount = count
+ if elementCount != 0 && len(m.LearnersNext) == 0 {
+ m.LearnersNext = make([]uint64, 0, elementCount)
+ }
+ 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.LearnersNext = append(m.LearnersNext, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field LearnersNext", wireType)
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AutoLeave", 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.AutoLeave = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ConfChangeSingle) 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: ConfChangeSingle: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ConfChangeSingle: 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 |= ConfChangeType(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ 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
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ConfChangeV2) 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: ConfChangeV2: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ConfChangeV2: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Transition", wireType)
+ }
+ m.Transition = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Transition |= ConfChangeTransition(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Changes", 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Changes = append(m.Changes, ConfChangeSingle{})
+ if err := m.Changes[len(m.Changes)-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 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 < 0 {
+ return ErrInvalidLengthRaft
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipRaft(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 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
+ }
+ }
+ case 1:
+ iNdEx += 8
+ 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
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthRaft
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupRaft
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthRaft
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthRaft = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowRaft = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupRaft = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.proto b/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.proto
new file mode 100644
index 0000000000..f46a54c948
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.proto
@@ -0,0 +1,187 @@
+syntax = "proto2";
+package raftpb;
+
+import "gogoproto/gogo.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.goproto_getters_all) = false;
+option (gogoproto.goproto_enum_prefix_all) = false;
+option (gogoproto.goproto_unkeyed_all) = false;
+option (gogoproto.goproto_unrecognized_all) = false;
+option (gogoproto.goproto_sizecache_all) = false;
+
+enum EntryType {
+ EntryNormal = 0;
+ EntryConfChange = 1; // corresponds to pb.ConfChange
+ EntryConfChangeV2 = 2; // corresponds to pb.ConfChangeV2
+}
+
+message Entry {
+ optional uint64 Term = 2 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
+ optional uint64 Index = 3 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
+ optional EntryType Type = 1 [(gogoproto.nullable) = false];
+ optional bytes Data = 4;
+}
+
+message SnapshotMetadata {
+ optional ConfState conf_state = 1 [(gogoproto.nullable) = false];
+ optional uint64 index = 2 [(gogoproto.nullable) = false];
+ optional uint64 term = 3 [(gogoproto.nullable) = false];
+}
+
+message Snapshot {
+ optional bytes data = 1;
+ optional SnapshotMetadata metadata = 2 [(gogoproto.nullable) = false];
+}
+
+// For description of different message types, see:
+// https://pkg.go.dev/go.etcd.io/etcd/raft/v3#hdr-MessageType
+enum MessageType {
+ 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;
+}
+
+message Message {
+ optional MessageType type = 1 [(gogoproto.nullable) = false];
+ optional uint64 to = 2 [(gogoproto.nullable) = false];
+ optional uint64 from = 3 [(gogoproto.nullable) = false];
+ optional uint64 term = 4 [(gogoproto.nullable) = false];
+ // logTerm is generally used for appending Raft logs to followers. For example,
+ // (type=MsgApp,index=100,logTerm=5) means leader appends entries starting at
+ // index=101, and the term of entry at index 100 is 5.
+ // (type=MsgAppResp,reject=true,index=100,logTerm=5) means follower rejects some
+ // entries from its leader as it already has an entry with term 5 at index 100.
+ optional uint64 logTerm = 5 [(gogoproto.nullable) = false];
+ optional uint64 index = 6 [(gogoproto.nullable) = false];
+ repeated Entry entries = 7 [(gogoproto.nullable) = false];
+ optional uint64 commit = 8 [(gogoproto.nullable) = false];
+ optional Snapshot snapshot = 9 [(gogoproto.nullable) = false];
+ optional bool reject = 10 [(gogoproto.nullable) = false];
+ optional uint64 rejectHint = 11 [(gogoproto.nullable) = false];
+ optional bytes context = 12;
+}
+
+message HardState {
+ optional uint64 term = 1 [(gogoproto.nullable) = false];
+ optional uint64 vote = 2 [(gogoproto.nullable) = false];
+ optional uint64 commit = 3 [(gogoproto.nullable) = false];
+}
+
+// ConfChangeTransition specifies the behavior of a configuration change with
+// respect to joint consensus.
+enum ConfChangeTransition {
+ // Automatically use the simple protocol if possible, otherwise fall back
+ // to ConfChangeJointImplicit. Most applications will want to use this.
+ ConfChangeTransitionAuto = 0;
+ // Use joint consensus unconditionally, and transition out of them
+ // automatically (by proposing a zero configuration change).
+ //
+ // This option is suitable for applications that want to minimize the time
+ // spent in the joint configuration and do not store the joint configuration
+ // in the state machine (outside of InitialState).
+ ConfChangeTransitionJointImplicit = 1;
+ // Use joint consensus and remain in the joint configuration until the
+ // application proposes a no-op configuration change. This is suitable for
+ // applications that want to explicitly control the transitions, for example
+ // to use a custom payload (via the Context field).
+ ConfChangeTransitionJointExplicit = 2;
+}
+
+message ConfState {
+ // The voters in the incoming config. (If the configuration is not joint,
+ // then the outgoing config is empty).
+ repeated uint64 voters = 1;
+ // The learners in the incoming config.
+ repeated uint64 learners = 2;
+ // The voters in the outgoing config.
+ repeated uint64 voters_outgoing = 3;
+ // The nodes that will become learners when the outgoing config is removed.
+ // These nodes are necessarily currently in nodes_joint (or they would have
+ // been added to the incoming config right away).
+ repeated uint64 learners_next = 4;
+ // If set, the config is joint and Raft will automatically transition into
+ // the final config (i.e. remove the outgoing config) when this is safe.
+ optional bool auto_leave = 5 [(gogoproto.nullable) = false];
+}
+
+enum ConfChangeType {
+ ConfChangeAddNode = 0;
+ ConfChangeRemoveNode = 1;
+ ConfChangeUpdateNode = 2;
+ ConfChangeAddLearnerNode = 3;
+}
+
+message ConfChange {
+ optional ConfChangeType type = 2 [(gogoproto.nullable) = false];
+ optional uint64 node_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "NodeID" ];
+ optional bytes context = 4;
+
+ // NB: this is used only by etcd to thread through a unique identifier.
+ // Ideally it should really use the Context instead. No counterpart to
+ // this field exists in ConfChangeV2.
+ optional uint64 id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ID" ];
+}
+
+// ConfChangeSingle is an individual configuration change operation. Multiple
+// such operations can be carried out atomically via a ConfChangeV2.
+message ConfChangeSingle {
+ optional ConfChangeType type = 1 [(gogoproto.nullable) = false];
+ optional uint64 node_id = 2 [(gogoproto.nullable) = false, (gogoproto.customname) = "NodeID"];
+}
+
+// ConfChangeV2 messages initiate configuration changes. They support both the
+// simple "one at a time" membership change protocol and full Joint Consensus
+// allowing for arbitrary changes in membership.
+//
+// The supplied context is treated as an opaque payload and can be used to
+// attach an action on the state machine to the application of the config change
+// proposal. Note that contrary to Joint Consensus as outlined in the Raft
+// paper[1], configuration changes become active when they are *applied* to the
+// state machine (not when they are appended to the log).
+//
+// The simple protocol can be used whenever only a single change is made.
+//
+// Non-simple changes require the use of Joint Consensus, for which two
+// configuration changes are run. The first configuration change specifies the
+// desired changes and transitions the Raft group into the joint configuration,
+// in which quorum requires a majority of both the pre-changes and post-changes
+// configuration. Joint Consensus avoids entering fragile intermediate
+// configurations that could compromise survivability. For example, without the
+// use of Joint Consensus and running across three availability zones with a
+// replication factor of three, it is not possible to replace a voter without
+// entering an intermediate configuration that does not survive the outage of
+// one availability zone.
+//
+// The provided ConfChangeTransition specifies how (and whether) Joint Consensus
+// is used, and assigns the task of leaving the joint configuration either to
+// Raft or the application. Leaving the joint configuration is accomplished by
+// proposing a ConfChangeV2 with only and optionally the Context field
+// populated.
+//
+// For details on Raft membership changes, see:
+//
+// [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf
+message ConfChangeV2 {
+ optional ConfChangeTransition transition = 1 [(gogoproto.nullable) = false];
+ repeated ConfChangeSingle changes = 2 [(gogoproto.nullable) = false];
+ optional bytes context = 3;
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/rawnode.go b/vendor/go.etcd.io/etcd/raft/v3/rawnode.go
new file mode 100644
index 0000000000..4111d029dd
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/rawnode.go
@@ -0,0 +1,241 @@
+// 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 "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/raft/v3/tracker"
+)
+
+// 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
+}
+
+// NewRawNode instantiates a RawNode from the given configuration.
+//
+// See Bootstrap() for bootstrapping an initial state; this replaces the former
+// 'peers' argument to this method (with identical behavior). However, It is
+// recommended that instead of calling Bootstrap, applications bootstrap their
+// state manually by setting up a Storage that has a first index > 1 and which
+// stores the desired ConfState as its InitialState.
+func NewRawNode(config *Config) (*RawNode, error) {
+ r := newRaft(config)
+ rn := &RawNode{
+ raft: r,
+ }
+ rn.prevSoftSt = r.softState()
+ 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. See (Node).ProposeConfChange for
+// details.
+func (rn *RawNode) ProposeConfChange(cc pb.ConfChangeI) error {
+ m, err := confChangeToMsg(cc)
+ if err != nil {
+ return err
+ }
+ return rn.raft.Step(m)
+}
+
+// ApplyConfChange applies a config change to the local node. The app must call
+// this when it applies a configuration change, except when it decides to reject
+// the configuration change, in which case no call must take place.
+func (rn *RawNode) ApplyConfChange(cc pb.ConfChangeI) *pb.ConfState {
+ cs := rn.raft.applyConfChange(cc.AsV2())
+ return &cs
+}
+
+// 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.prs.Progress[m.From]; pr != nil || !IsResponseMsg(m.Type) {
+ return rn.raft.Step(m)
+ }
+ return ErrStepPeerNotFound
+}
+
+// Ready returns the outstanding work that the application needs to handle. This
+// includes appending and applying entries or a snapshot, updating the HardState,
+// and sending messages. The returned Ready() *must* be handled and subsequently
+// passed back via Advance().
+func (rn *RawNode) Ready() Ready {
+ rd := rn.readyWithoutAccept()
+ rn.acceptReady(rd)
+ return rd
+}
+
+// readyWithoutAccept returns a Ready. This is a read-only operation, i.e. there
+// is no obligation that the Ready must be handled.
+func (rn *RawNode) readyWithoutAccept() Ready {
+ return newReady(rn.raft, rn.prevSoftSt, rn.prevHardSt)
+}
+
+// acceptReady is called when the consumer of the RawNode has decided to go
+// ahead and handle a Ready. Nothing must alter the state of the RawNode between
+// this call and the prior call to Ready().
+func (rn *RawNode) acceptReady(rd Ready) {
+ if rd.SoftState != nil {
+ rn.prevSoftSt = rd.SoftState
+ }
+ if len(rd.ReadStates) != 0 {
+ rn.raft.readStates = nil
+ }
+ rn.raft.msgs = nil
+}
+
+// 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.hasPendingSnapshot() {
+ 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) {
+ if !IsEmptyHardState(rd.HardState) {
+ rn.prevHardSt = rd.HardState
+ }
+ rn.raft.advance(rd)
+}
+
+// Status returns the current status of the given group. This allocates, see
+// BasicStatus and WithProgress for allocation-friendlier choices.
+func (rn *RawNode) Status() Status {
+ status := getStatus(rn.raft)
+ return status
+}
+
+// BasicStatus returns a BasicStatus. Notably this does not contain the
+// Progress map; see WithProgress for an allocation-free way to inspect it.
+func (rn *RawNode) BasicStatus() BasicStatus {
+ return getBasicStatus(rn.raft)
+}
+
+// ProgressType indicates the type of replica a Progress corresponds to.
+type ProgressType byte
+
+const (
+ // ProgressTypePeer accompanies a Progress for a regular peer replica.
+ ProgressTypePeer ProgressType = iota
+ // ProgressTypeLearner accompanies a Progress for a learner replica.
+ ProgressTypeLearner
+)
+
+// WithProgress is a helper to introspect the Progress for this node and its
+// peers.
+func (rn *RawNode) WithProgress(visitor func(id uint64, typ ProgressType, pr tracker.Progress)) {
+ rn.raft.prs.Visit(func(id uint64, pr *tracker.Progress) {
+ typ := ProgressTypePeer
+ if pr.IsLearner {
+ typ = ProgressTypeLearner
+ }
+ p := *pr
+ p.Inflights = nil
+ visitor(id, typ, p)
+ })
+}
+
+// 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/go.etcd.io/etcd/raft/v3/read_only.go b/vendor/go.etcd.io/etcd/raft/v3/read_only.go
new file mode 100644
index 0000000000..ad0688522d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/read_only.go
@@ -0,0 +1,121 @@
+// 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 "go.etcd.io/etcd/raft/v3/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
+ // NB: this never records 'false', but it's more convenient to use this
+ // instead of a map[uint64]struct{} due to the API of quorum.VoteResult. If
+ // this becomes performance sensitive enough (doubtful), quorum.VoteResult
+ // can change to an API that is closer to that of CommittedIndex.
+ acks map[uint64]bool
+}
+
+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 request 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) {
+ s := string(m.Entries[0].Data)
+ if _, ok := ro.pendingReadIndex[s]; ok {
+ return
+ }
+ ro.pendingReadIndex[s] = &readIndexStatus{index: index, req: m, acks: make(map[uint64]bool)}
+ ro.readIndexQueue = append(ro.readIndexQueue, s)
+}
+
+// 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(id uint64, context []byte) map[uint64]bool {
+ rs, ok := ro.pendingReadIndex[string(context)]
+ if !ok {
+ return nil
+ }
+
+ rs.acks[id] = true
+ return rs.acks
+}
+
+// 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/go.etcd.io/etcd/raft/v3/status.go b/vendor/go.etcd.io/etcd/raft/v3/status.go
new file mode 100644
index 0000000000..acfb56c391
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/status.go
@@ -0,0 +1,105 @@
+// 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 "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/raft/v3/tracker"
+)
+
+// Status contains information about this Raft peer and its view of the system.
+// The Progress is only populated on the leader.
+type Status struct {
+ BasicStatus
+ Config tracker.Config
+ Progress map[uint64]tracker.Progress
+}
+
+// BasicStatus contains basic information about the Raft peer. It does not allocate.
+type BasicStatus struct {
+ ID uint64
+
+ pb.HardState
+ SoftState
+
+ Applied uint64
+
+ LeadTransferee uint64
+}
+
+func getProgressCopy(r *raft) map[uint64]tracker.Progress {
+ m := make(map[uint64]tracker.Progress)
+ r.prs.Visit(func(id uint64, pr *tracker.Progress) {
+ p := *pr
+ p.Inflights = pr.Inflights.Clone()
+ pr = nil
+
+ m[id] = p
+ })
+ return m
+}
+
+func getBasicStatus(r *raft) BasicStatus {
+ s := BasicStatus{
+ ID: r.id,
+ LeadTransferee: r.leadTransferee,
+ }
+ s.HardState = r.hardState()
+ s.SoftState = *r.softState()
+ s.Applied = r.raftLog.applied
+ return s
+}
+
+// getStatus gets a copy of the current raft status.
+func getStatus(r *raft) Status {
+ var s Status
+ s.BasicStatus = getBasicStatus(r)
+ if s.RaftState == StateLeader {
+ s.Progress = getProgressCopy(r)
+ }
+ s.Config = r.prs.Config.Clone()
+ 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 {
+ getLogger().Panicf("unexpected error: %v", err)
+ }
+ return string(b)
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/storage.go b/vendor/go.etcd.io/etcd/raft/v3/storage.go
new file mode 100644
index 0000000000..8b16d4fa24
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/storage.go
@@ -0,0 +1,273 @@
+// 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 "go.etcd.io/etcd/raft/v3/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 {
+ // TODO(tbg): split this into two interfaces, LogStorage and StateStorage.
+
+ // 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 {
+ getLogger().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() {
+ getLogger().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() {
+ getLogger().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:
+ getLogger().Panicf("missing log entry [last: %d, append at: %d]",
+ ms.lastIndex(), entries[0].Index)
+ }
+ return nil
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/tracker/inflights.go b/vendor/go.etcd.io/etcd/raft/v3/tracker/inflights.go
new file mode 100644
index 0000000000..1a056341ab
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/tracker/inflights.go
@@ -0,0 +1,132 @@
+// Copyright 2019 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 tracker
+
+// Inflights limits the number of MsgApp (represented by the largest index
+// contained within) sent to followers but not yet acknowledged by them. Callers
+// use Full() to check whether more messages can be sent, call Add() whenever
+// they are sending a new append, and release "quota" via FreeLE() whenever an
+// ack is received.
+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
+}
+
+// NewInflights sets up an Inflights that allows up to 'size' inflight messages.
+func NewInflights(size int) *Inflights {
+ return &Inflights{
+ size: size,
+ }
+}
+
+// Clone returns an *Inflights that is identical to but shares no memory with
+// the receiver.
+func (in *Inflights) Clone() *Inflights {
+ ins := *in
+ ins.buffer = append([]uint64(nil), in.buffer...)
+ return &ins
+}
+
+// Add notifies the Inflights that a new message with the given index is being
+// dispatched. Full() must be called prior to Add() to verify that there is room
+// for one more message, and consecutive calls to add Add() must provide a
+// monotonic sequence of indexes.
+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.grow()
+ }
+ 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) grow() {
+ 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
+}
+
+// FreeLE frees the inflights smaller or equal to the given `to` flight.
+func (in *Inflights) FreeLE(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
+ }
+}
+
+// FreeFirstOne releases the first inflight. This is a no-op if nothing is
+// inflight.
+func (in *Inflights) FreeFirstOne() { in.FreeLE(in.buffer[in.start]) }
+
+// Full returns true if no more messages can be sent at the moment.
+func (in *Inflights) Full() bool {
+ return in.count == in.size
+}
+
+// Count returns the number of inflight messages.
+func (in *Inflights) Count() int { return in.count }
+
+// reset frees all inflights.
+func (in *Inflights) reset() {
+ in.count = 0
+ in.start = 0
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/tracker/progress.go b/vendor/go.etcd.io/etcd/raft/v3/tracker/progress.go
new file mode 100644
index 0000000000..a36e5261ac
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/tracker/progress.go
@@ -0,0 +1,255 @@
+// Copyright 2019 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 tracker
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// 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.
+//
+// NB(tbg): Progress is basically a state machine whose transitions are mostly
+// strewn around `*raft.raft`. Additionally, some fields are only used when in a
+// certain State. All of this isn't ideal.
+type Progress struct {
+ Match, Next uint64
+ // State defines how the leader should interact with the follower.
+ //
+ // When in StateProbe, leader sends at most one replication message
+ // per heartbeat interval. It also probes actual progress of the follower.
+ //
+ // When in StateReplicate, 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 StateSnapshot, leader should have sent out snapshot
+ // before and stops sending any replication message.
+ State StateType
+
+ // PendingSnapshot is used in StateSnapshot.
+ // 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.
+ //
+ // TODO(tbg): the leader should always have this set to true.
+ RecentActive bool
+
+ // ProbeSent is used while this follower is in StateProbe. When ProbeSent is
+ // true, raft should pause sending replication message to this peer until
+ // ProbeSent is reset. See ProbeAcked() and IsPaused().
+ ProbeSent 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.FreeLE with the index of the last
+ // received entry.
+ Inflights *Inflights
+
+ // IsLearner is true if this progress is tracked for a learner.
+ IsLearner bool
+}
+
+// ResetState moves the Progress into the specified State, resetting ProbeSent,
+// PendingSnapshot, and Inflights.
+func (pr *Progress) ResetState(state StateType) {
+ pr.ProbeSent = false
+ pr.PendingSnapshot = 0
+ pr.State = state
+ pr.Inflights.reset()
+}
+
+func max(a, b uint64) uint64 {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+func min(a, b uint64) uint64 {
+ if a > b {
+ return b
+ }
+ return a
+}
+
+// ProbeAcked is called when this peer has accepted an append. It resets
+// ProbeSent to signal that additional append messages should be sent without
+// further delay.
+func (pr *Progress) ProbeAcked() {
+ pr.ProbeSent = false
+}
+
+// BecomeProbe transitions into StateProbe. Next is reset to Match+1 or,
+// optionally and if larger, the index of the pending snapshot.
+func (pr *Progress) BecomeProbe() {
+ // If the original state is StateSnapshot, progress knows that
+ // the pending snapshot has been sent to this peer successfully, then
+ // probes from pendingSnapshot + 1.
+ if pr.State == StateSnapshot {
+ pendingSnapshot := pr.PendingSnapshot
+ pr.ResetState(StateProbe)
+ pr.Next = max(pr.Match+1, pendingSnapshot+1)
+ } else {
+ pr.ResetState(StateProbe)
+ pr.Next = pr.Match + 1
+ }
+}
+
+// BecomeReplicate transitions into StateReplicate, resetting Next to Match+1.
+func (pr *Progress) BecomeReplicate() {
+ pr.ResetState(StateReplicate)
+ pr.Next = pr.Match + 1
+}
+
+// BecomeSnapshot moves the Progress to StateSnapshot with the specified pending
+// snapshot index.
+func (pr *Progress) BecomeSnapshot(snapshoti uint64) {
+ pr.ResetState(StateSnapshot)
+ pr.PendingSnapshot = snapshoti
+}
+
+// MaybeUpdate is called when an MsgAppResp arrives from the follower, with the
+// index acked by it. The method 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.ProbeAcked()
+ }
+ pr.Next = max(pr.Next, n+1)
+ return updated
+}
+
+// OptimisticUpdate signals that appends all the way up to and including index n
+// are in-flight. As a result, Next is increased to n+1.
+func (pr *Progress) OptimisticUpdate(n uint64) { pr.Next = n + 1 }
+
+// MaybeDecrTo adjusts the Progress to the receipt of a MsgApp rejection. The
+// arguments are the index of the append message rejected by the follower, and
+// the hint that we want to decrease to.
+//
+// Rejections can happen spuriously as messages are sent out of order or
+// duplicated. In such cases, the rejection pertains to an index that the
+// Progress already knows were previously acknowledged, and false is returned
+// without changing the Progress.
+//
+// If the rejection is genuine, Next is lowered sensibly, and the Progress is
+// cleared for sending log entries.
+func (pr *Progress) MaybeDecrTo(rejected, matchHint uint64) bool {
+ if pr.State == StateReplicate {
+ // 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.
+ //
+ // TODO(tbg): why not use matchHint if it's larger?
+ pr.Next = pr.Match + 1
+ return true
+ }
+
+ // The rejection must be stale if "rejected" does not match next - 1. This
+ // is because non-replicating followers are probed one entry at a time.
+ if pr.Next-1 != rejected {
+ return false
+ }
+
+ pr.Next = max(min(rejected, matchHint+1), 1)
+ pr.ProbeSent = false
+ return true
+}
+
+// IsPaused returns whether sending log entries to this node has been throttled.
+// This is done when a node has rejected recent MsgApps, is currently waiting
+// for a snapshot, or has reached the MaxInflightMsgs limit. In normal
+// operation, this is false. A throttled node will be contacted less frequently
+// until it has reached a state in which it's able to accept a steady stream of
+// log entries again.
+func (pr *Progress) IsPaused() bool {
+ switch pr.State {
+ case StateProbe:
+ return pr.ProbeSent
+ case StateReplicate:
+ return pr.Inflights.Full()
+ case StateSnapshot:
+ return true
+ default:
+ panic("unexpected state")
+ }
+}
+
+func (pr *Progress) String() string {
+ var buf strings.Builder
+ fmt.Fprintf(&buf, "%s match=%d next=%d", pr.State, pr.Match, pr.Next)
+ if pr.IsLearner {
+ fmt.Fprint(&buf, " learner")
+ }
+ if pr.IsPaused() {
+ fmt.Fprint(&buf, " paused")
+ }
+ if pr.PendingSnapshot > 0 {
+ fmt.Fprintf(&buf, " pendingSnap=%d", pr.PendingSnapshot)
+ }
+ if !pr.RecentActive {
+ fmt.Fprintf(&buf, " inactive")
+ }
+ if n := pr.Inflights.Count(); n > 0 {
+ fmt.Fprintf(&buf, " inflight=%d", n)
+ if pr.Inflights.Full() {
+ fmt.Fprint(&buf, "[full]")
+ }
+ }
+ return buf.String()
+}
+
+// ProgressMap is a map of *Progress.
+type ProgressMap map[uint64]*Progress
+
+// String prints the ProgressMap in sorted key order, one Progress per line.
+func (m ProgressMap) String() string {
+ ids := make([]uint64, 0, len(m))
+ for k := range m {
+ ids = append(ids, k)
+ }
+ sort.Slice(ids, func(i, j int) bool {
+ return ids[i] < ids[j]
+ })
+ var buf strings.Builder
+ for _, id := range ids {
+ fmt.Fprintf(&buf, "%d: %s\n", id, m[id])
+ }
+ return buf.String()
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/tracker/state.go b/vendor/go.etcd.io/etcd/raft/v3/tracker/state.go
new file mode 100644
index 0000000000..285b4b8f58
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/tracker/state.go
@@ -0,0 +1,42 @@
+// Copyright 2019 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 tracker
+
+// StateType is the state of a tracked follower.
+type StateType uint64
+
+const (
+ // StateProbe indicates a follower whose last index isn't known. Such a
+ // follower is "probed" (i.e. an append sent periodically) to narrow down
+ // its last index. In the ideal (and common) case, only one round of probing
+ // is necessary as the follower will react with a hint. Followers that are
+ // probed over extended periods of time are often offline.
+ StateProbe StateType = iota
+ // StateReplicate is the state steady in which a follower eagerly receives
+ // log entries to append to its log.
+ StateReplicate
+ // StateSnapshot indicates a follower that needs log entries not available
+ // from the leader's Raft log. Such a follower needs a full snapshot to
+ // return to StateReplicate.
+ StateSnapshot
+)
+
+var prstmap = [...]string{
+ "StateProbe",
+ "StateReplicate",
+ "StateSnapshot",
+}
+
+func (st StateType) String() string { return prstmap[uint64(st)] }
diff --git a/vendor/go.etcd.io/etcd/raft/v3/tracker/tracker.go b/vendor/go.etcd.io/etcd/raft/v3/tracker/tracker.go
new file mode 100644
index 0000000000..72dcc73b86
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/tracker/tracker.go
@@ -0,0 +1,288 @@
+// Copyright 2019 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 tracker
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "go.etcd.io/etcd/raft/v3/quorum"
+ pb "go.etcd.io/etcd/raft/v3/raftpb"
+)
+
+// Config reflects the configuration tracked in a ProgressTracker.
+type Config struct {
+ Voters quorum.JointConfig
+ // AutoLeave is true if the configuration is joint and a transition to the
+ // incoming configuration should be carried out automatically by Raft when
+ // this is possible. If false, the configuration will be joint until the
+ // application initiates the transition manually.
+ AutoLeave bool
+ // Learners is a set of IDs corresponding to the learners active in the
+ // current configuration.
+ //
+ // Invariant: Learners and Voters does not intersect, i.e. if a peer is in
+ // either half of the joint config, it can't be a learner; if it is a
+ // learner it can't be in either half of the joint config. This invariant
+ // simplifies the implementation since it allows peers to have clarity about
+ // its current role without taking into account joint consensus.
+ Learners map[uint64]struct{}
+ // When we turn a voter into a learner during a joint consensus transition,
+ // we cannot add the learner directly when entering the joint state. This is
+ // because this would violate the invariant that the intersection of
+ // voters and learners is empty. For example, assume a Voter is removed and
+ // immediately re-added as a learner (or in other words, it is demoted):
+ //
+ // Initially, the configuration will be
+ //
+ // voters: {1 2 3}
+ // learners: {}
+ //
+ // and we want to demote 3. Entering the joint configuration, we naively get
+ //
+ // voters: {1 2} & {1 2 3}
+ // learners: {3}
+ //
+ // but this violates the invariant (3 is both voter and learner). Instead,
+ // we get
+ //
+ // voters: {1 2} & {1 2 3}
+ // learners: {}
+ // next_learners: {3}
+ //
+ // Where 3 is now still purely a voter, but we are remembering the intention
+ // to make it a learner upon transitioning into the final configuration:
+ //
+ // voters: {1 2}
+ // learners: {3}
+ // next_learners: {}
+ //
+ // Note that next_learners is not used while adding a learner that is not
+ // also a voter in the joint config. In this case, the learner is added
+ // right away when entering the joint configuration, so that it is caught up
+ // as soon as possible.
+ LearnersNext map[uint64]struct{}
+}
+
+func (c Config) String() string {
+ var buf strings.Builder
+ fmt.Fprintf(&buf, "voters=%s", c.Voters)
+ if c.Learners != nil {
+ fmt.Fprintf(&buf, " learners=%s", quorum.MajorityConfig(c.Learners).String())
+ }
+ if c.LearnersNext != nil {
+ fmt.Fprintf(&buf, " learners_next=%s", quorum.MajorityConfig(c.LearnersNext).String())
+ }
+ if c.AutoLeave {
+ fmt.Fprintf(&buf, " autoleave")
+ }
+ return buf.String()
+}
+
+// Clone returns a copy of the Config that shares no memory with the original.
+func (c *Config) Clone() Config {
+ clone := func(m map[uint64]struct{}) map[uint64]struct{} {
+ if m == nil {
+ return nil
+ }
+ mm := make(map[uint64]struct{}, len(m))
+ for k := range m {
+ mm[k] = struct{}{}
+ }
+ return mm
+ }
+ return Config{
+ Voters: quorum.JointConfig{clone(c.Voters[0]), clone(c.Voters[1])},
+ Learners: clone(c.Learners),
+ LearnersNext: clone(c.LearnersNext),
+ }
+}
+
+// ProgressTracker tracks the currently active configuration and the information
+// known about the nodes and learners in it. In particular, it tracks the match
+// index for each peer which in turn allows reasoning about the committed index.
+type ProgressTracker struct {
+ Config
+
+ Progress ProgressMap
+
+ Votes map[uint64]bool
+
+ MaxInflight int
+}
+
+// MakeProgressTracker initializes a ProgressTracker.
+func MakeProgressTracker(maxInflight int) ProgressTracker {
+ p := ProgressTracker{
+ MaxInflight: maxInflight,
+ Config: Config{
+ Voters: quorum.JointConfig{
+ quorum.MajorityConfig{},
+ nil, // only populated when used
+ },
+ Learners: nil, // only populated when used
+ LearnersNext: nil, // only populated when used
+ },
+ Votes: map[uint64]bool{},
+ Progress: map[uint64]*Progress{},
+ }
+ return p
+}
+
+// ConfState returns a ConfState representing the active configuration.
+func (p *ProgressTracker) ConfState() pb.ConfState {
+ return pb.ConfState{
+ Voters: p.Voters[0].Slice(),
+ VotersOutgoing: p.Voters[1].Slice(),
+ Learners: quorum.MajorityConfig(p.Learners).Slice(),
+ LearnersNext: quorum.MajorityConfig(p.LearnersNext).Slice(),
+ AutoLeave: p.AutoLeave,
+ }
+}
+
+// IsSingleton returns true if (and only if) there is only one voting member
+// (i.e. the leader) in the current configuration.
+func (p *ProgressTracker) IsSingleton() bool {
+ return len(p.Voters[0]) == 1 && len(p.Voters[1]) == 0
+}
+
+type matchAckIndexer map[uint64]*Progress
+
+var _ quorum.AckedIndexer = matchAckIndexer(nil)
+
+// AckedIndex implements IndexLookuper.
+func (l matchAckIndexer) AckedIndex(id uint64) (quorum.Index, bool) {
+ pr, ok := l[id]
+ if !ok {
+ return 0, false
+ }
+ return quorum.Index(pr.Match), true
+}
+
+// Committed returns the largest log index known to be committed based on what
+// the voting members of the group have acknowledged.
+func (p *ProgressTracker) Committed() uint64 {
+ return uint64(p.Voters.CommittedIndex(matchAckIndexer(p.Progress)))
+}
+
+func insertionSort(sl []uint64) {
+ a, b := 0, len(sl)
+ for i := a + 1; i < b; i++ {
+ for j := i; j > a && sl[j] < sl[j-1]; j-- {
+ sl[j], sl[j-1] = sl[j-1], sl[j]
+ }
+ }
+}
+
+// Visit invokes the supplied closure for all tracked progresses in stable order.
+func (p *ProgressTracker) Visit(f func(id uint64, pr *Progress)) {
+ n := len(p.Progress)
+ // We need to sort the IDs and don't want to allocate since this is hot code.
+ // The optimization here mirrors that in `(MajorityConfig).CommittedIndex`,
+ // see there for details.
+ var sl [7]uint64
+ var ids []uint64
+ if len(sl) >= n {
+ ids = sl[:n]
+ } else {
+ ids = make([]uint64, n)
+ }
+ for id := range p.Progress {
+ n--
+ ids[n] = id
+ }
+ insertionSort(ids)
+ for _, id := range ids {
+ f(id, p.Progress[id])
+ }
+}
+
+// QuorumActive returns true if the quorum is active from the view of the local
+// raft state machine. Otherwise, it returns false.
+func (p *ProgressTracker) QuorumActive() bool {
+ votes := map[uint64]bool{}
+ p.Visit(func(id uint64, pr *Progress) {
+ if pr.IsLearner {
+ return
+ }
+ votes[id] = pr.RecentActive
+ })
+
+ return p.Voters.VoteResult(votes) == quorum.VoteWon
+}
+
+// VoterNodes returns a sorted slice of voters.
+func (p *ProgressTracker) VoterNodes() []uint64 {
+ m := p.Voters.IDs()
+ nodes := make([]uint64, 0, len(m))
+ for id := range m {
+ nodes = append(nodes, id)
+ }
+ sort.Slice(nodes, func(i, j int) bool { return nodes[i] < nodes[j] })
+ return nodes
+}
+
+// LearnerNodes returns a sorted slice of learners.
+func (p *ProgressTracker) LearnerNodes() []uint64 {
+ if len(p.Learners) == 0 {
+ return nil
+ }
+ nodes := make([]uint64, 0, len(p.Learners))
+ for id := range p.Learners {
+ nodes = append(nodes, id)
+ }
+ sort.Slice(nodes, func(i, j int) bool { return nodes[i] < nodes[j] })
+ return nodes
+}
+
+// ResetVotes prepares for a new round of vote counting via recordVote.
+func (p *ProgressTracker) ResetVotes() {
+ p.Votes = map[uint64]bool{}
+}
+
+// RecordVote records that the node with the given id voted for this Raft
+// instance if v == true (and declined it otherwise).
+func (p *ProgressTracker) RecordVote(id uint64, v bool) {
+ _, ok := p.Votes[id]
+ if !ok {
+ p.Votes[id] = v
+ }
+}
+
+// TallyVotes returns the number of granted and rejected Votes, and whether the
+// election outcome is known.
+func (p *ProgressTracker) TallyVotes() (granted int, rejected int, _ quorum.VoteResult) {
+ // Make sure to populate granted/rejected correctly even if the Votes slice
+ // contains members no longer part of the configuration. This doesn't really
+ // matter in the way the numbers are used (they're informational), but might
+ // as well get it right.
+ for id, pr := range p.Progress {
+ if pr.IsLearner {
+ continue
+ }
+ v, voted := p.Votes[id]
+ if !voted {
+ continue
+ }
+ if v {
+ granted++
+ } else {
+ rejected++
+ }
+ }
+ result := p.Voters.VoteResult(p.Votes)
+ return granted, rejected, result
+}
diff --git a/vendor/go.etcd.io/etcd/raft/v3/util.go b/vendor/go.etcd.io/etcd/raft/v3/util.go
new file mode 100644
index 0000000000..94ab368f60
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/raft/v3/util.go
@@ -0,0 +1,233 @@
+// 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"
+ "strings"
+
+ pb "go.etcd.io/etcd/raft/v3/raftpb"
+)
+
+func (st StateType) MarshalJSON() ([]byte, error) {
+ return []byte(fmt.Sprintf("%q", st.String())), nil
+}
+
+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))
+ }
+}
+
+func DescribeHardState(hs pb.HardState) string {
+ var buf strings.Builder
+ fmt.Fprintf(&buf, "Term:%d", hs.Term)
+ if hs.Vote != 0 {
+ fmt.Fprintf(&buf, " Vote:%d", hs.Vote)
+ }
+ fmt.Fprintf(&buf, " Commit:%d", hs.Commit)
+ return buf.String()
+}
+
+func DescribeSoftState(ss SoftState) string {
+ return fmt.Sprintf("Lead:%d State:%s", ss.Lead, ss.RaftState)
+}
+
+func DescribeConfState(state pb.ConfState) string {
+ return fmt.Sprintf(
+ "Voters:%v VotersOutgoing:%v Learners:%v LearnersNext:%v AutoLeave:%v",
+ state.Voters, state.VotersOutgoing, state.Learners, state.LearnersNext, state.AutoLeave,
+ )
+}
+
+func DescribeSnapshot(snap pb.Snapshot) string {
+ m := snap.Metadata
+ return fmt.Sprintf("Index:%d Term:%d ConfState:%s", m.Index, m.Term, DescribeConfState(m.ConfState))
+}
+
+func DescribeReady(rd Ready, f EntryFormatter) string {
+ var buf strings.Builder
+ if rd.SoftState != nil {
+ fmt.Fprint(&buf, DescribeSoftState(*rd.SoftState))
+ buf.WriteByte('\n')
+ }
+ if !IsEmptyHardState(rd.HardState) {
+ fmt.Fprintf(&buf, "HardState %s", DescribeHardState(rd.HardState))
+ buf.WriteByte('\n')
+ }
+ if len(rd.ReadStates) > 0 {
+ fmt.Fprintf(&buf, "ReadStates %v\n", rd.ReadStates)
+ }
+ if len(rd.Entries) > 0 {
+ buf.WriteString("Entries:\n")
+ fmt.Fprint(&buf, DescribeEntries(rd.Entries, f))
+ }
+ if !IsEmptySnap(rd.Snapshot) {
+ fmt.Fprintf(&buf, "Snapshot %s\n", DescribeSnapshot(rd.Snapshot))
+ }
+ if len(rd.CommittedEntries) > 0 {
+ buf.WriteString("CommittedEntries:\n")
+ fmt.Fprint(&buf, DescribeEntries(rd.CommittedEntries, f))
+ }
+ if len(rd.Messages) > 0 {
+ buf.WriteString("Messages:\n")
+ for _, msg := range rd.Messages {
+ fmt.Fprint(&buf, DescribeMessage(msg, f))
+ buf.WriteByte('\n')
+ }
+ }
+ if buf.Len() > 0 {
+ return fmt.Sprintf("Ready MustSync=%t:\n%s", rd.MustSync, buf.String())
+ }
+ return ""
+}
+
+// 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 (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: %s", DescribeSnapshot(m.Snapshot))
+ }
+ return buf.String()
+}
+
+// PayloadSize is the size of the payload of this Entry. Notably, it does not
+// depend on its Index or Term.
+func PayloadSize(e pb.Entry) int {
+ return len(e.Data)
+}
+
+// DescribeEntry returns a concise human-readable description of an
+// Entry for debugging.
+func DescribeEntry(e pb.Entry, f EntryFormatter) string {
+ if f == nil {
+ f = func(data []byte) string { return fmt.Sprintf("%q", data) }
+ }
+
+ formatConfChange := func(cc pb.ConfChangeI) string {
+ // TODO(tbg): give the EntryFormatter a type argument so that it gets
+ // a chance to expose the Context.
+ return pb.ConfChangesToString(cc.AsV2().Changes)
+ }
+
+ var formatted string
+ switch e.Type {
+ case pb.EntryNormal:
+ formatted = f(e.Data)
+ case pb.EntryConfChange:
+ var cc pb.ConfChange
+ if err := cc.Unmarshal(e.Data); err != nil {
+ formatted = err.Error()
+ } else {
+ formatted = formatConfChange(cc)
+ }
+ case pb.EntryConfChangeV2:
+ var cc pb.ConfChangeV2
+ if err := cc.Unmarshal(e.Data); err != nil {
+ formatted = err.Error()
+ } else {
+ formatted = formatConfChange(cc)
+ }
+ }
+ if formatted != "" {
+ formatted = " " + formatted
+ }
+ return fmt.Sprintf("%d/%d %s%s", e.Term, e.Index, e.Type, formatted)
+}
+
+// DescribeEntries calls DescribeEntry for each Entry, adding a newline to
+// each.
+func DescribeEntries(ents []pb.Entry, f EntryFormatter) string {
+ var buf bytes.Buffer
+ for _, e := range ents {
+ _, _ = buf.WriteString(DescribeEntry(e, f) + "\n")
+ }
+ return buf.String()
+}
+
+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]
+}
+
+func assertConfStatesEquivalent(l Logger, cs1, cs2 pb.ConfState) {
+ err := cs1.Equivalent(cs2)
+ if err == nil {
+ return
+ }
+ l.Panic(err)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/LICENSE b/vendor/go.etcd.io/etcd/server/v3/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/auth/doc.go b/vendor/go.etcd.io/etcd/server/v3/auth/doc.go
new file mode 100644
index 0000000000..72741a1077
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/auth/jwt.go b/vendor/go.etcd.io/etcd/server/v3/auth/jwt.go
new file mode 100644
index 0000000000..a797794494
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/auth/jwt.go
@@ -0,0 +1,172 @@
+// 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/ecdsa"
+ "crypto/rsa"
+ "errors"
+ "time"
+
+ "github.com/golang-jwt/jwt/v4"
+ "go.uber.org/zap"
+)
+
+type tokenJWT struct {
+ lg *zap.Logger
+ signMethod jwt.SigningMethod
+ key interface{}
+ ttl time.Duration
+ verifyOnly bool
+}
+
+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 float64
+ )
+
+ parsed, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
+ if token.Method.Alg() != t.signMethod.Alg() {
+ return nil, errors.New("invalid signing method")
+ }
+ switch k := t.key.(type) {
+ case *rsa.PrivateKey:
+ return &k.PublicKey, nil
+ case *ecdsa.PrivateKey:
+ return &k.PublicKey, nil
+ default:
+ return t.key, nil
+ }
+ })
+
+ if err != nil {
+ t.lg.Warn(
+ "failed to parse a JWT token",
+ zap.String("token", token),
+ zap.Error(err),
+ )
+ return nil, false
+ }
+
+ claims, ok := parsed.Claims.(jwt.MapClaims)
+ if !parsed.Valid || !ok {
+ t.lg.Warn("invalid JWT token", zap.String("token", token))
+ return nil, false
+ }
+
+ username, ok = claims["username"].(string)
+ if !ok {
+ t.lg.Warn("failed to obtain user claims from jwt token")
+ return nil, false
+ }
+
+ revision, ok = claims["revision"].(float64)
+ if !ok {
+ t.lg.Warn("failed to obtain revision claims from jwt token")
+ return nil, false
+ }
+
+ return &AuthInfo{Username: username, Revision: uint64(revision)}, true
+}
+
+func (t *tokenJWT) assign(ctx context.Context, username string, revision uint64) (string, error) {
+ if t.verifyOnly {
+ return "", ErrVerifyOnly
+ }
+
+ // Future work: let a jwt token include permission information would be useful for
+ // permission checking in proxy side.
+ tk := jwt.NewWithClaims(t.signMethod,
+ jwt.MapClaims{
+ "username": username,
+ "revision": revision,
+ "exp": time.Now().Add(t.ttl).Unix(),
+ })
+
+ token, err := tk.SignedString(t.key)
+ if err != nil {
+ t.lg.Debug(
+ "failed to sign a JWT token",
+ zap.String("user-name", username),
+ zap.Uint64("revision", revision),
+ zap.Error(err),
+ )
+ return "", err
+ }
+
+ t.lg.Debug(
+ "created/assigned a new JWT token",
+ zap.String("user-name", username),
+ zap.Uint64("revision", revision),
+ zap.String("token", token),
+ )
+ return token, err
+}
+
+func newTokenProviderJWT(lg *zap.Logger, optMap map[string]string) (*tokenJWT, error) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ var err error
+ var opts jwtOptions
+ err = opts.ParseWithDefaults(optMap)
+ if err != nil {
+ lg.Error("problem loading JWT options", zap.Error(err))
+ return nil, ErrInvalidAuthOpts
+ }
+
+ var keys = make([]string, 0, len(optMap))
+ for k := range optMap {
+ if !knownOptions[k] {
+ keys = append(keys, k)
+ }
+ }
+ if len(keys) > 0 {
+ lg.Warn("unknown JWT options", zap.Strings("keys", keys))
+ }
+
+ key, err := opts.Key()
+ if err != nil {
+ return nil, err
+ }
+
+ t := &tokenJWT{
+ lg: lg,
+ ttl: opts.TTL,
+ signMethod: opts.SignMethod,
+ key: key,
+ }
+
+ switch t.signMethod.(type) {
+ case *jwt.SigningMethodECDSA:
+ if _, ok := t.key.(*ecdsa.PublicKey); ok {
+ t.verifyOnly = true
+ }
+ case *jwt.SigningMethodRSA, *jwt.SigningMethodRSAPSS:
+ if _, ok := t.key.(*rsa.PublicKey); ok {
+ t.verifyOnly = true
+ }
+ }
+
+ return t, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/auth/metrics.go b/vendor/go.etcd.io/etcd/server/v3/auth/metrics.go
new file mode 100644
index 0000000000..f7ce279202
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/auth/metrics.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 auth
+
+import (
+ "sync"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+ currentAuthRevision = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "auth",
+ Name: "revision",
+ Help: "The current revision of auth store.",
+ },
+ func() float64 {
+ reportCurrentAuthRevMu.RLock()
+ defer reportCurrentAuthRevMu.RUnlock()
+ return reportCurrentAuthRev()
+ },
+ )
+ // overridden by auth store initialization
+ reportCurrentAuthRevMu sync.RWMutex
+ reportCurrentAuthRev = func() float64 { return 0 }
+)
+
+func init() {
+ prometheus.MustRegister(currentAuthRevision)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/auth/nop.go b/vendor/go.etcd.io/etcd/server/v3/auth/nop.go
new file mode 100644
index 0000000000..d4378747bd
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/auth/options.go b/vendor/go.etcd.io/etcd/server/v3/auth/options.go
new file mode 100644
index 0000000000..0b01d2c4a3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/auth/options.go
@@ -0,0 +1,192 @@
+// 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 (
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "fmt"
+ "io/ioutil"
+ "time"
+
+ "github.com/golang-jwt/jwt/v4"
+)
+
+const (
+ optSignMethod = "sign-method"
+ optPublicKey = "pub-key"
+ optPrivateKey = "priv-key"
+ optTTL = "ttl"
+)
+
+var knownOptions = map[string]bool{
+ optSignMethod: true,
+ optPublicKey: true,
+ optPrivateKey: true,
+ optTTL: true,
+}
+
+var (
+ // DefaultTTL will be used when a 'ttl' is not specified
+ DefaultTTL = 5 * time.Minute
+)
+
+type jwtOptions struct {
+ SignMethod jwt.SigningMethod
+ PublicKey []byte
+ PrivateKey []byte
+ TTL time.Duration
+}
+
+// ParseWithDefaults will load options from the specified map or set defaults where appropriate
+func (opts *jwtOptions) ParseWithDefaults(optMap map[string]string) error {
+ if opts.TTL == 0 && optMap[optTTL] == "" {
+ opts.TTL = DefaultTTL
+ }
+
+ return opts.Parse(optMap)
+}
+
+// Parse will load options from the specified map
+func (opts *jwtOptions) Parse(optMap map[string]string) error {
+ var err error
+ if ttl := optMap[optTTL]; ttl != "" {
+ opts.TTL, err = time.ParseDuration(ttl)
+ if err != nil {
+ return err
+ }
+ }
+
+ if file := optMap[optPublicKey]; file != "" {
+ opts.PublicKey, err = ioutil.ReadFile(file)
+ if err != nil {
+ return err
+ }
+ }
+
+ if file := optMap[optPrivateKey]; file != "" {
+ opts.PrivateKey, err = ioutil.ReadFile(file)
+ if err != nil {
+ return err
+ }
+ }
+
+ // signing method is a required field
+ method := optMap[optSignMethod]
+ opts.SignMethod = jwt.GetSigningMethod(method)
+ if opts.SignMethod == nil {
+ return ErrInvalidAuthMethod
+ }
+
+ return nil
+}
+
+// Key will parse and return the appropriately typed key for the selected signature method
+func (opts *jwtOptions) Key() (interface{}, error) {
+ switch opts.SignMethod.(type) {
+ case *jwt.SigningMethodRSA, *jwt.SigningMethodRSAPSS:
+ return opts.rsaKey()
+ case *jwt.SigningMethodECDSA:
+ return opts.ecKey()
+ case *jwt.SigningMethodHMAC:
+ return opts.hmacKey()
+ default:
+ return nil, fmt.Errorf("unsupported signing method: %T", opts.SignMethod)
+ }
+}
+
+func (opts *jwtOptions) hmacKey() (interface{}, error) {
+ if len(opts.PrivateKey) == 0 {
+ return nil, ErrMissingKey
+ }
+ return opts.PrivateKey, nil
+}
+
+func (opts *jwtOptions) rsaKey() (interface{}, error) {
+ var (
+ priv *rsa.PrivateKey
+ pub *rsa.PublicKey
+ err error
+ )
+
+ if len(opts.PrivateKey) > 0 {
+ priv, err = jwt.ParseRSAPrivateKeyFromPEM(opts.PrivateKey)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if len(opts.PublicKey) > 0 {
+ pub, err = jwt.ParseRSAPublicKeyFromPEM(opts.PublicKey)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if priv == nil {
+ if pub == nil {
+ // Neither key given
+ return nil, ErrMissingKey
+ }
+ // Public key only, can verify tokens
+ return pub, nil
+ }
+
+ // both keys provided, make sure they match
+ if pub != nil && pub.E != priv.E && pub.N.Cmp(priv.N) != 0 {
+ return nil, ErrKeyMismatch
+ }
+
+ return priv, nil
+}
+
+func (opts *jwtOptions) ecKey() (interface{}, error) {
+ var (
+ priv *ecdsa.PrivateKey
+ pub *ecdsa.PublicKey
+ err error
+ )
+
+ if len(opts.PrivateKey) > 0 {
+ priv, err = jwt.ParseECPrivateKeyFromPEM(opts.PrivateKey)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if len(opts.PublicKey) > 0 {
+ pub, err = jwt.ParseECPublicKeyFromPEM(opts.PublicKey)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if priv == nil {
+ if pub == nil {
+ // Neither key given
+ return nil, ErrMissingKey
+ }
+ // Public key only, can verify tokens
+ return pub, nil
+ }
+
+ // both keys provided, make sure they match
+ if pub != nil && pub.Curve != priv.Curve &&
+ pub.X.Cmp(priv.X) != 0 && pub.Y.Cmp(priv.Y) != 0 {
+ return nil, ErrKeyMismatch
+ }
+
+ return priv, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/auth/range_perm_cache.go b/vendor/go.etcd.io/etcd/server/v3/auth/range_perm_cache.go
new file mode 100644
index 0000000000..e096710c32
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/auth/range_perm_cache.go
@@ -0,0 +1,205 @@
+// 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 (
+ "go.etcd.io/etcd/api/v3/authpb"
+ "go.etcd.io/etcd/pkg/v3/adt"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+
+ "go.uber.org/zap"
+)
+
+func getMergedPerms(lg *zap.Logger, tx backend.ReadTx, userName string) *unifiedRangePermissions {
+ user := getUser(lg, tx, userName)
+ if user == nil {
+ return nil
+ }
+
+ readPerms := adt.NewIntervalTree()
+ writePerms := adt.NewIntervalTree()
+
+ for _, roleName := range user.Roles {
+ role := getRole(lg, 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(
+ lg *zap.Logger,
+ cachedPerms *unifiedRangePermissions,
+ key, rangeEnd []byte,
+ permtyp authpb.Permission_Type) bool {
+ if isOpenEnded(rangeEnd) {
+ rangeEnd = nil
+ // nil rangeEnd will be converetd to []byte{}, the largest element of BytesAffineComparable,
+ // in NewBytesAffineInterval().
+ }
+
+ ivl := adt.NewBytesAffineInterval(key, rangeEnd)
+ switch permtyp {
+ case authpb.READ:
+ return cachedPerms.readPerms.Contains(ivl)
+ case authpb.WRITE:
+ return cachedPerms.writePerms.Contains(ivl)
+ default:
+ lg.Panic("unknown auth type", zap.String("auth-type", permtyp.String()))
+ }
+ return false
+}
+
+func checkKeyPoint(lg *zap.Logger, 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:
+ lg.Panic("unknown auth type", zap.String("auth-type", permtyp.String()))
+ }
+ return false
+}
+
+func (as *authStore) isRangeOpPermitted(userName string, key, rangeEnd []byte, permtyp authpb.Permission_Type) bool {
+ as.rangePermCacheMu.RLock()
+ defer as.rangePermCacheMu.RUnlock()
+
+ rangePerm, ok := as.rangePermCache[userName]
+ if !ok {
+ as.lg.Error(
+ "user doesn't exist",
+ zap.String("user-name", userName),
+ )
+ return false
+ }
+
+ if len(rangeEnd) == 0 {
+ return checkKeyPoint(as.lg, rangePerm, key, permtyp)
+ }
+
+ return checkKeyInterval(as.lg, rangePerm, key, rangeEnd, permtyp)
+}
+
+func (as *authStore) refreshRangePermCache(tx backend.ReadTx) {
+ // Note that every authentication configuration update calls this method and it invalidates the entire
+ // rangePermCache and reconstruct it based on information of users and roles stored in the backend.
+ // This can be a costly operation.
+ as.rangePermCacheMu.Lock()
+ defer as.rangePermCacheMu.Unlock()
+
+ as.rangePermCache = make(map[string]*unifiedRangePermissions)
+
+ users := getAllUsers(as.lg, tx)
+ for _, user := range users {
+ userName := string(user.Name)
+ perms := getMergedPerms(as.lg, tx, userName)
+ if perms == nil {
+ as.lg.Error(
+ "failed to create a merged permission",
+ zap.String("user-name", userName),
+ )
+ continue
+ }
+ as.rangePermCache[userName] = perms
+ }
+}
+
+type unifiedRangePermissions struct {
+ readPerms adt.IntervalTree
+ writePerms adt.IntervalTree
+}
+
+// Constraints related to key range
+// Assumptions:
+// a1. key must be non-nil
+// a2. []byte{} (in the case of string, "") is not a valid key of etcd
+// For representing an open-ended range, BytesAffineComparable uses []byte{} as the largest element.
+// a3. []byte{0x00} is the minimum valid etcd key
+//
+// Based on the above assumptions, key and rangeEnd must follow below rules:
+// b1. for representing a single key point, rangeEnd should be nil or zero length byte array (in the case of string, "")
+// Rule a2 guarantees that (X, []byte{}) for any X is not a valid range. So such ranges can be used for representing
+// a single key permission.
+//
+// b2. key range with upper limit, like (X, Y), larger or equal to X and smaller than Y
+//
+// b3. key range with open-ended, like (X, ), is represented like (X, []byte{0x00})
+// Because of rule a3, if we have (X, []byte{0x00}), such a range represents an empty range and makes no sense to have
+// such a permission. So we use []byte{0x00} for representing an open-ended permission.
+// Note that rangeEnd with []byte{0x00} will be converted into []byte{} before inserted into the interval tree
+// (rule a2 ensures that this is the largest element).
+// Special range like key = []byte{0x00} and rangeEnd = []byte{0x00} is treated as a range which matches with all keys.
+//
+// Treating a range whose rangeEnd with []byte{0x00} as an open-ended comes from the rules of Range() and Watch() API.
+
+func isOpenEnded(rangeEnd []byte) bool { // check rule b3
+ return len(rangeEnd) == 1 && rangeEnd[0] == 0
+}
+
+func isValidPermissionRange(key, rangeEnd []byte) bool {
+ if len(key) == 0 {
+ return false
+ }
+ if rangeEnd == nil || len(rangeEnd) == 0 { // ensure rule b1
+ return true
+ }
+
+ begin := adt.BytesAffineComparable(key)
+ end := adt.BytesAffineComparable(rangeEnd)
+ if begin.Compare(end) == -1 { // rule b2
+ return true
+ }
+
+ if isOpenEnded(rangeEnd) {
+ return true
+ }
+
+ return false
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/auth/simple_token.go b/vendor/go.etcd.io/etcd/server/v3/auth/simple_token.go
new file mode 100644
index 0000000000..be706522a5
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/auth/simple_token.go
@@ -0,0 +1,252 @@
+// 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 random 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"
+
+ "go.uber.org/zap"
+)
+
+const (
+ letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ defaultSimpleTokenLength = 16
+)
+
+// var for testing purposes
+// TODO: Remove this mutable global state - as it's race-prone.
+var (
+ simpleTokenTTLDefault = 300 * time.Second
+ simpleTokenTTLResolution = 1 * time.Second
+)
+
+type simpleTokenTTLKeeper struct {
+ tokens map[string]time.Time
+ donec chan struct{}
+ stopc chan struct{}
+ deleteTokenFunc func(string)
+ mu *sync.Mutex
+ simpleTokenTTL time.Duration
+}
+
+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(tm.simpleTokenTTL)
+}
+
+func (tm *simpleTokenTTLKeeper) resetSimpleToken(token string) {
+ if _, ok := tm.tokens[token]; ok {
+ tm.tokens[token] = time.Now().Add(tm.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 {
+ lg *zap.Logger
+ indexWaiter func(uint64) <-chan struct{}
+ simpleTokenKeeper *simpleTokenTTLKeeper
+ simpleTokensMu sync.Mutex
+ simpleTokens map[string]string // token -> username
+ simpleTokenTTL time.Duration
+}
+
+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 {
+ t.lg.Panic(
+ "failed to assign already-used simple token to a user",
+ zap.String("user-name", username),
+ zap.String("token", 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 name == username {
+ delete(t.simpleTokens, token)
+ t.simpleTokenKeeper.deleteSimpleToken(token)
+ }
+ }
+ t.simpleTokensMu.Unlock()
+}
+
+func (t *tokenSimple) enable() {
+ t.simpleTokensMu.Lock()
+ defer t.simpleTokensMu.Unlock()
+ if t.simpleTokenKeeper != nil { // already enabled
+ return
+ }
+ if t.simpleTokenTTL <= 0 {
+ t.simpleTokenTTL = simpleTokenTTLDefault
+ }
+
+ delf := func(tk string) {
+ if username, ok := t.simpleTokens[tk]; ok {
+ t.lg.Info(
+ "deleted a simple token",
+ zap.String("user-name", username),
+ zap.String("token", tk),
+ )
+ 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,
+ simpleTokenTTL: t.simpleTokenTTL,
+ }
+ 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.ParseUint(splitted[1], 10, 0)
+ if err != nil {
+ return false
+ }
+
+ select {
+ case <-t.indexWaiter(uint64(index)):
+ return true
+ case <-ctx.Done():
+ }
+
+ return false
+}
+
+func newTokenProviderSimple(lg *zap.Logger, indexWaiter func(uint64) <-chan struct{}, TokenTTL time.Duration) *tokenSimple {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &tokenSimple{
+ lg: lg,
+ simpleTokens: make(map[string]string),
+ indexWaiter: indexWaiter,
+ simpleTokenTTL: TokenTTL,
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/auth/store.go b/vendor/go.etcd.io/etcd/server/v3/auth/store.go
new file mode 100644
index 0000000000..67c5694cde
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/auth/store.go
@@ -0,0 +1,1336 @@
+// 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/base64"
+ "encoding/binary"
+ "errors"
+ "sort"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/authpb"
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+
+ "go.uber.org/zap"
+ "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")
+
+ 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")
+ ErrRoleEmpty = errors.New("auth: role name is empty")
+ ErrPermissionNotGiven = errors.New("auth: permission not given")
+ ErrAuthFailed = errors.New("auth: authentication failed, invalid user ID or password")
+ ErrNoPasswordUser = errors.New("auth: authentication failed, password was given for no password user")
+ 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")
+ ErrInvalidAuthMethod = errors.New("auth: invalid auth signature method")
+ ErrMissingKey = errors.New("auth: missing key data")
+ ErrKeyMismatch = errors.New("auth: public and private keys don't match")
+ ErrVerifyOnly = errors.New("auth: token signing attempted with verify-only key")
+)
+
+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{}
+
+// AuthStore defines auth storage interface.
+type AuthStore interface {
+ // AuthEnable turns on the authentication feature
+ AuthEnable() error
+
+ // AuthDisable turns off the authentication feature
+ AuthDisable()
+
+ // IsAuthEnabled returns true if the authentication feature is enabled.
+ IsAuthEnabled() bool
+
+ // 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
+
+ // BcryptCost gets strength of hashing bcrypted auth password
+ BcryptCost() int
+}
+
+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
+
+ lg *zap.Logger
+ be backend.Backend
+ enabled bool
+ enabledMu sync.RWMutex
+
+ // rangePermCache needs to be protected by rangePermCacheMu
+ // rangePermCacheMu needs to be write locked only in initialization phase or configuration changes
+ // Hot paths like Range(), needs to acquire read lock for improving performance
+ //
+ // Note that BatchTx and ReadTx cannot be a mutex for rangePermCache because they are independent resources
+ // see also: https://github.com/etcd-io/etcd/pull/13920#discussion_r849114855
+ rangePermCache map[string]*unifiedRangePermissions // username -> unifiedRangePermissions
+ rangePermCacheMu sync.RWMutex
+
+ tokenProvider TokenProvider
+ bcryptCost int // the algorithm cost / strength for hashing auth passwords
+}
+
+func (as *authStore) AuthEnable() error {
+ as.enabledMu.Lock()
+ defer as.enabledMu.Unlock()
+ if as.enabled {
+ as.lg.Info("authentication is already enabled; ignored auth enable request")
+ return nil
+ }
+ b := as.be
+ tx := b.BatchTx()
+ tx.LockInsideApply()
+ defer func() {
+ tx.Unlock()
+ b.ForceCommit()
+ }()
+
+ u := getUser(as.lg, tx, rootUser)
+ if u == nil {
+ return ErrRootUserNotExist
+ }
+
+ if !hasRootRole(u) {
+ return ErrRootRoleNotExist
+ }
+
+ tx.UnsafePut(buckets.Auth, enableFlagKey, authEnabled)
+
+ as.enabled = true
+ as.tokenProvider.enable()
+
+ as.refreshRangePermCache(tx)
+
+ as.setRevision(getRevision(tx))
+
+ as.lg.Info("enabled authentication")
+ return nil
+}
+
+func (as *authStore) AuthDisable() {
+ as.enabledMu.Lock()
+ defer as.enabledMu.Unlock()
+ if !as.enabled {
+ return
+ }
+ b := as.be
+ tx := b.BatchTx()
+ tx.LockInsideApply()
+ tx.UnsafePut(buckets.Auth, enableFlagKey, authDisabled)
+ as.commitRevision(tx)
+ tx.Unlock()
+ b.ForceCommit()
+
+ as.enabled = false
+ as.tokenProvider.disable()
+
+ as.lg.Info("disabled authentication")
+}
+
+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.LockInsideApply()
+ defer tx.Unlock()
+
+ user := getUser(as.lg, tx, username)
+ if user == nil {
+ return nil, ErrAuthFailed
+ }
+
+ if user.Options != nil && user.Options.NoPassword {
+ 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
+ }
+
+ as.lg.Debug(
+ "authenticated a user",
+ zap.String("user-name", username),
+ zap.String("token", token),
+ )
+ return &pb.AuthenticateResponse{Token: token}, nil
+}
+
+func (as *authStore) CheckPassword(username, password string) (uint64, error) {
+ if !as.IsAuthEnabled() {
+ return 0, ErrAuthNotEnabled
+ }
+
+ var user *authpb.User
+ // CompareHashAndPassword is very expensive, so we use closures
+ // to avoid putting it in the critical section of the tx lock.
+ revision, err := func() (uint64, error) {
+ tx := as.be.ReadTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user = getUser(as.lg, tx, username)
+ if user == nil {
+ return 0, ErrAuthFailed
+ }
+
+ if user.Options != nil && user.Options.NoPassword {
+ return 0, ErrNoPasswordUser
+ }
+
+ return getRevision(tx), nil
+ }()
+ if err != nil {
+ return 0, err
+ }
+
+ if bcrypt.CompareHashAndPassword(user.Password, []byte(password)) != nil {
+ as.lg.Info("invalid password", zap.String("user-name", username))
+ return 0, ErrAuthFailed
+ }
+ return revision, nil
+}
+
+func (as *authStore) Recover(be backend.Backend) {
+ enabled := false
+ as.be = be
+ tx := be.ReadTx()
+ tx.Lock()
+ _, vs := tx.UnsafeRange(buckets.Auth, enableFlagKey, nil, 0)
+ if len(vs) == 1 {
+ if bytes.Equal(vs[0], authEnabled) {
+ enabled = true
+ }
+ }
+
+ as.setRevision(getRevision(tx))
+ as.refreshRangePermCache(tx)
+
+ tx.Unlock()
+
+ as.enabledMu.Lock()
+ as.enabled = enabled
+ if enabled {
+ as.tokenProvider.enable()
+ }
+ as.enabledMu.Unlock()
+}
+
+func (as *authStore) selectPassword(password string, hashedPassword string) ([]byte, error) {
+ if password != "" && hashedPassword == "" {
+ // This path is for processing log entries created by etcd whose version is older than 3.5
+ return bcrypt.GenerateFromPassword([]byte(password), as.bcryptCost)
+ }
+ return base64.StdEncoding.DecodeString(hashedPassword)
+}
+
+func (as *authStore) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
+ if len(r.Name) == 0 {
+ return nil, ErrUserEmpty
+ }
+
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ user := getUser(as.lg, tx, r.Name)
+ if user != nil {
+ return nil, ErrUserAlreadyExist
+ }
+
+ options := r.Options
+ if options == nil {
+ options = &authpb.UserAddOptions{
+ NoPassword: false,
+ }
+ }
+
+ var password []byte
+ var err error
+
+ if !options.NoPassword {
+ password, err = as.selectPassword(r.Password, r.HashedPassword)
+ if err != nil {
+ return nil, ErrNoPasswordUser
+ }
+ }
+
+ newUser := &authpb.User{
+ Name: []byte(r.Name),
+ Password: password,
+ Options: options,
+ }
+
+ putUser(as.lg, tx, newUser)
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.lg.Info("added a user", zap.String("user-name", r.Name))
+ return &pb.AuthUserAddResponse{}, nil
+}
+
+func (as *authStore) UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) {
+ if as.enabled && r.Name == rootUser {
+ as.lg.Error("cannot delete 'root' user", zap.String("user-name", r.Name))
+ return nil, ErrInvalidAuthMgmt
+ }
+
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ user := getUser(as.lg, tx, r.Name)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ delUser(tx, r.Name)
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.tokenProvider.invalidateUser(r.Name)
+
+ as.lg.Info(
+ "deleted a user",
+ zap.String("user-name", r.Name),
+ zap.Strings("user-roles", user.Roles),
+ )
+ return &pb.AuthUserDeleteResponse{}, nil
+}
+
+func (as *authStore) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) {
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ user := getUser(as.lg, tx, r.Name)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ var password []byte
+ var err error
+
+ // Backward compatible with old versions of etcd, user options is nil
+ if user.Options == nil || !user.Options.NoPassword {
+ password, err = as.selectPassword(r.Password, r.HashedPassword)
+ if err != nil {
+ return nil, ErrNoPasswordUser
+ }
+ }
+
+ updatedUser := &authpb.User{
+ Name: []byte(r.Name),
+ Roles: user.Roles,
+ Password: password,
+ Options: user.Options,
+ }
+
+ putUser(as.lg, tx, updatedUser)
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.tokenProvider.invalidateUser(r.Name)
+
+ as.lg.Info(
+ "changed a password of a user",
+ zap.String("user-name", r.Name),
+ zap.Strings("user-roles", user.Roles),
+ )
+ return &pb.AuthUserChangePasswordResponse{}, nil
+}
+
+func (as *authStore) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) {
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ user := getUser(as.lg, tx, r.User)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ if r.Role != rootRole {
+ role := getRole(as.lg, tx, r.Role)
+ if role == nil {
+ return nil, ErrRoleNotFound
+ }
+ }
+
+ idx := sort.SearchStrings(user.Roles, r.Role)
+ if idx < len(user.Roles) && user.Roles[idx] == r.Role {
+ as.lg.Warn(
+ "ignored grant role request to a user",
+ zap.String("user-name", r.User),
+ zap.Strings("user-roles", user.Roles),
+ zap.String("duplicate-role-name", r.Role),
+ )
+ return &pb.AuthUserGrantRoleResponse{}, nil
+ }
+
+ user.Roles = append(user.Roles, r.Role)
+ sort.Strings(user.Roles)
+
+ putUser(as.lg, tx, user)
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.lg.Info(
+ "granted a role to a user",
+ zap.String("user-name", r.User),
+ zap.Strings("user-roles", user.Roles),
+ zap.String("added-role-name", r.Role),
+ )
+ return &pb.AuthUserGrantRoleResponse{}, nil
+}
+
+func (as *authStore) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ user := getUser(as.lg, 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.LockInsideApply()
+ users := getAllUsers(as.lg, 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 && r.Name == rootUser && r.Role == rootRole {
+ as.lg.Error(
+ "'root' user cannot revoke 'root' role",
+ zap.String("user-name", r.Name),
+ zap.String("role-name", r.Role),
+ )
+ return nil, ErrInvalidAuthMgmt
+ }
+
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ user := getUser(as.lg, tx, r.Name)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ updatedUser := &authpb.User{
+ Name: user.Name,
+ Password: user.Password,
+ Options: user.Options,
+ }
+
+ for _, role := range user.Roles {
+ if role != r.Role {
+ updatedUser.Roles = append(updatedUser.Roles, role)
+ }
+ }
+
+ if len(updatedUser.Roles) == len(user.Roles) {
+ return nil, ErrRoleNotGranted
+ }
+
+ putUser(as.lg, tx, updatedUser)
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.lg.Info(
+ "revoked a role from a user",
+ zap.String("user-name", r.Name),
+ zap.Strings("old-user-roles", user.Roles),
+ zap.Strings("new-user-roles", updatedUser.Roles),
+ zap.String("revoked-role-name", r.Role),
+ )
+ return &pb.AuthUserRevokeRoleResponse{}, nil
+}
+
+func (as *authStore) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ var resp pb.AuthRoleGetResponse
+
+ role := getRole(as.lg, 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.LockInsideApply()
+ roles := getAllRoles(as.lg, 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.LockInsideApply()
+ defer tx.Unlock()
+
+ role := getRole(as.lg, 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, r.Key) || !bytes.Equal(perm.RangeEnd, r.RangeEnd) {
+ updatedRole.KeyPermission = append(updatedRole.KeyPermission, perm)
+ }
+ }
+
+ if len(role.KeyPermission) == len(updatedRole.KeyPermission) {
+ return nil, ErrPermissionNotGranted
+ }
+
+ putRole(as.lg, tx, updatedRole)
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.lg.Info(
+ "revoked a permission on range",
+ zap.String("role-name", r.Role),
+ zap.String("key", string(r.Key)),
+ zap.String("range-end", string(r.RangeEnd)),
+ )
+ return &pb.AuthRoleRevokePermissionResponse{}, nil
+}
+
+func (as *authStore) RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) {
+ if as.enabled && r.Role == rootRole {
+ as.lg.Error("cannot delete 'root' role", zap.String("role-name", r.Role))
+ return nil, ErrInvalidAuthMgmt
+ }
+
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ role := getRole(as.lg, tx, r.Role)
+ if role == nil {
+ return nil, ErrRoleNotFound
+ }
+
+ delRole(tx, r.Role)
+
+ users := getAllUsers(as.lg, tx)
+ for _, user := range users {
+ updatedUser := &authpb.User{
+ Name: user.Name,
+ Password: user.Password,
+ Options: user.Options,
+ }
+
+ for _, role := range user.Roles {
+ if role != r.Role {
+ updatedUser.Roles = append(updatedUser.Roles, role)
+ }
+ }
+
+ if len(updatedUser.Roles) == len(user.Roles) {
+ continue
+ }
+
+ putUser(as.lg, tx, updatedUser)
+
+ }
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.lg.Info("deleted a role", zap.String("role-name", r.Role))
+ return &pb.AuthRoleDeleteResponse{}, nil
+}
+
+func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
+ if len(r.Name) == 0 {
+ return nil, ErrRoleEmpty
+ }
+
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ role := getRole(as.lg, tx, r.Name)
+ if role != nil {
+ return nil, ErrRoleAlreadyExist
+ }
+
+ newRole := &authpb.Role{
+ Name: []byte(r.Name),
+ }
+
+ putRole(as.lg, tx, newRole)
+
+ as.commitRevision(tx)
+
+ as.lg.Info("created a role", zap.String("role-name", 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) {
+ if r.Perm == nil {
+ return nil, ErrPermissionNotGiven
+ }
+ if !isValidPermissionRange(r.Perm.Key, r.Perm.RangeEnd) {
+ return nil, ErrInvalidAuthMgmt
+ }
+
+ tx := as.be.BatchTx()
+ tx.LockInsideApply()
+ defer tx.Unlock()
+
+ role := getRole(as.lg, 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, 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: r.Perm.Key,
+ RangeEnd: r.Perm.RangeEnd,
+ PermType: r.Perm.PermType,
+ }
+
+ role.KeyPermission = append(role.KeyPermission, newPerm)
+ sort.Sort(permSlice(role.KeyPermission))
+ }
+
+ putRole(as.lg, tx, role)
+
+ as.commitRevision(tx)
+ as.refreshRangePermCache(tx)
+
+ as.lg.Info(
+ "granted/updated a permission to a user",
+ zap.String("user-name", r.Name),
+ zap.String("permission-name", 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
+ }
+ rev := as.Revision()
+ if revision < rev {
+ as.lg.Warn("request auth revision is less than current node auth revision",
+ zap.Uint64("current node auth revision", rev),
+ zap.Uint64("request auth revision", revision),
+ zap.ByteString("request key", key),
+ zap.Error(ErrAuthOldRevision))
+ return ErrAuthOldRevision
+ }
+
+ tx := as.be.ReadTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(as.lg, tx, userName)
+ if user == nil {
+ as.lg.Error("cannot find a user for permission check", zap.String("user-name", userName))
+ return ErrPermissionDenied
+ }
+
+ // root role should have permission on all ranges
+ if hasRootRole(user) {
+ return nil
+ }
+
+ if as.isRangeOpPermitted(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 || authInfo.Username == "" {
+ return ErrUserEmpty
+ }
+
+ tx := as.be.ReadTx()
+ tx.Lock()
+ u := getUser(as.lg, tx, authInfo.Username)
+ tx.Unlock()
+
+ if u == nil {
+ return ErrUserNotFound
+ }
+
+ if !hasRootRole(u) {
+ return ErrPermissionDenied
+ }
+
+ return nil
+}
+
+func getUser(lg *zap.Logger, tx backend.ReadTx, username string) *authpb.User {
+ _, vs := tx.UnsafeRange(buckets.AuthUsers, []byte(username), nil, 0)
+ if len(vs) == 0 {
+ return nil
+ }
+
+ user := &authpb.User{}
+ err := user.Unmarshal(vs[0])
+ if err != nil {
+ lg.Panic(
+ "failed to unmarshal 'authpb.User'",
+ zap.String("user-name", username),
+ zap.Error(err),
+ )
+ }
+ return user
+}
+
+func getAllUsers(lg *zap.Logger, tx backend.ReadTx) []*authpb.User {
+ var vs [][]byte
+ err := tx.UnsafeForEach(buckets.AuthUsers, func(k []byte, v []byte) error {
+ vs = append(vs, v)
+ return nil
+ })
+ if err != nil {
+ lg.Panic("failed to get users",
+ zap.Error(err))
+ }
+ 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 {
+ lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err))
+ }
+ users[i] = user
+ }
+ return users
+}
+
+func putUser(lg *zap.Logger, tx backend.BatchTx, user *authpb.User) {
+ b, err := user.Marshal()
+ if err != nil {
+ lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err))
+ }
+ tx.UnsafePut(buckets.AuthUsers, user.Name, b)
+}
+
+func delUser(tx backend.BatchTx, username string) {
+ tx.UnsafeDelete(buckets.AuthUsers, []byte(username))
+}
+
+func getRole(lg *zap.Logger, tx backend.ReadTx, rolename string) *authpb.Role {
+ _, vs := tx.UnsafeRange(buckets.AuthRoles, []byte(rolename), nil, 0)
+ if len(vs) == 0 {
+ return nil
+ }
+
+ role := &authpb.Role{}
+ err := role.Unmarshal(vs[0])
+ if err != nil {
+ lg.Panic("failed to unmarshal 'authpb.Role'", zap.Error(err))
+ }
+ return role
+}
+
+func getAllRoles(lg *zap.Logger, tx backend.ReadTx) []*authpb.Role {
+ _, vs := tx.UnsafeRange(buckets.AuthRoles, []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 {
+ lg.Panic("failed to unmarshal 'authpb.Role'", zap.Error(err))
+ }
+ roles[i] = role
+ }
+ return roles
+}
+
+func putRole(lg *zap.Logger, tx backend.BatchTx, role *authpb.Role) {
+ b, err := role.Marshal()
+ if err != nil {
+ lg.Panic(
+ "failed to marshal 'authpb.Role'",
+ zap.String("role-name", string(role.Name)),
+ zap.Error(err),
+ )
+ }
+
+ tx.UnsafePut(buckets.AuthRoles, role.Name, b)
+}
+
+func delRole(tx backend.BatchTx, rolename string) {
+ tx.UnsafeDelete(buckets.AuthRoles, []byte(rolename))
+}
+
+func (as *authStore) IsAuthEnabled() bool {
+ as.enabledMu.RLock()
+ defer as.enabledMu.RUnlock()
+ return as.enabled
+}
+
+// NewAuthStore creates a new AuthStore.
+func NewAuthStore(lg *zap.Logger, be backend.Backend, tp TokenProvider, bcryptCost int) *authStore {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+
+ if bcryptCost < bcrypt.MinCost || bcryptCost > bcrypt.MaxCost {
+ lg.Warn(
+ "use default bcrypt cost instead of the invalid given cost",
+ zap.Int("min-cost", bcrypt.MinCost),
+ zap.Int("max-cost", bcrypt.MaxCost),
+ zap.Int("default-cost", bcrypt.DefaultCost),
+ zap.Int("given-cost", bcryptCost),
+ )
+ bcryptCost = bcrypt.DefaultCost
+ }
+
+ tx := be.BatchTx()
+ tx.LockOutsideApply()
+
+ tx.UnsafeCreateBucket(buckets.Auth)
+ tx.UnsafeCreateBucket(buckets.AuthUsers)
+ tx.UnsafeCreateBucket(buckets.AuthRoles)
+
+ enabled := false
+ _, vs := tx.UnsafeRange(buckets.Auth, enableFlagKey, nil, 0)
+ if len(vs) == 1 {
+ if bytes.Equal(vs[0], authEnabled) {
+ enabled = true
+ }
+ }
+
+ as := &authStore{
+ revision: getRevision(tx),
+ lg: lg,
+ be: be,
+ enabled: enabled,
+ rangePermCache: make(map[string]*unifiedRangePermissions),
+ tokenProvider: tp,
+ bcryptCost: bcryptCost,
+ }
+
+ if enabled {
+ as.tokenProvider.enable()
+ }
+
+ if as.Revision() == 0 {
+ as.commitRevision(tx)
+ }
+
+ as.setupMetricsReporter()
+
+ as.refreshRangePermCache(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(buckets.Auth, revisionKey, revBytes)
+}
+
+func getRevision(tx backend.ReadTx) uint64 {
+ _, vs := tx.UnsafeRange(buckets.Auth, 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) (ai *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 {
+ if len(chains) < 1 {
+ continue
+ }
+ ai = &AuthInfo{
+ Username: chains[0].Subject.CommonName,
+ Revision: as.Revision(),
+ }
+ md, ok := metadata.FromIncomingContext(ctx)
+ if !ok {
+ return nil
+ }
+
+ // gRPC-gateway proxy request to etcd server includes Grpcgateway-Accept
+ // header. The proxy uses etcd client server certificate. If the certificate
+ // has a CommonName we should never use this for authentication.
+ if gw := md["grpcgateway-accept"]; len(gw) > 0 {
+ as.lg.Warn(
+ "ignoring common name in gRPC-gateway proxy request",
+ zap.String("common-name", ai.Username),
+ zap.String("user-name", ai.Username),
+ zap.Uint64("revision", ai.Revision),
+ )
+ return nil
+ }
+ as.lg.Debug(
+ "found command name",
+ zap.String("common-name", ai.Username),
+ zap.String("user-name", ai.Username),
+ zap.Uint64("revision", ai.Revision),
+ )
+ break
+ }
+ return ai
+}
+
+func (as *authStore) AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error) {
+ if !as.IsAuthEnabled() {
+ return nil, nil
+ }
+ md, ok := metadata.FromIncomingContext(ctx)
+ if !ok {
+ return nil, nil
+ }
+
+ //TODO(mitake|hexfusion) review unifying key names
+ ts, ok := md[rpctypes.TokenFieldNameGRPC]
+ if !ok {
+ ts, ok = md[rpctypes.TokenFieldNameSwagger]
+ }
+ if !ok {
+ return nil, nil
+ }
+
+ token := ts[0]
+ authInfo, uok := as.authInfoFromToken(ctx, token)
+ if !uok {
+ as.lg.Warn("invalid auth token", zap.String("token", token))
+ return nil, ErrInvalidAuthToken
+ }
+
+ return authInfo, nil
+}
+
+func (as *authStore) GenTokenPrefix() (string, error) {
+ return as.tokenProvider.genTokenPrefix()
+}
+
+func decomposeOpts(lg *zap.Logger, 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 {
+ if lg != nil {
+ lg.Error("invalid token option", zap.String("option", optstr))
+ }
+ return "", nil, ErrInvalidAuthOpts
+ }
+
+ if _, ok := typeSpecificOpts[pair[0]]; ok {
+ if lg != nil {
+ lg.Error(
+ "invalid token option",
+ zap.String("option", optstr),
+ zap.String("duplicate-parameter", pair[0]),
+ )
+ }
+ return "", nil, ErrInvalidAuthOpts
+ }
+
+ typeSpecificOpts[pair[0]] = pair[1]
+ }
+
+ return tokenType, typeSpecificOpts, nil
+
+}
+
+// NewTokenProvider creates a new token provider.
+func NewTokenProvider(
+ lg *zap.Logger,
+ tokenOpts string,
+ indexWaiter func(uint64) <-chan struct{},
+ TokenTTL time.Duration) (TokenProvider, error) {
+ tokenType, typeSpecificOpts, err := decomposeOpts(lg, tokenOpts)
+ if err != nil {
+ return nil, ErrInvalidAuthOpts
+ }
+
+ switch tokenType {
+ case tokenTypeSimple:
+ if lg != nil {
+ lg.Warn("simple token is not cryptographically signed")
+ }
+ return newTokenProviderSimple(lg, indexWaiter, TokenTTL), nil
+
+ case tokenTypeJWT:
+ return newTokenProviderJWT(lg, typeSpecificOpts)
+
+ case "":
+ return newTokenProviderNop()
+
+ default:
+ if lg != nil {
+ lg.Warn(
+ "unknown token type",
+ zap.String("type", tokenType),
+ zap.Error(ErrInvalidAuthOpts),
+ )
+ }
+ 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 {
+ as.lg.Error(
+ "failed to generate prefix of internally used token",
+ zap.Error(err),
+ )
+ 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
+ as.lg.Error(
+ "failed to assign token for lease revoking",
+ zap.Error(err),
+ )
+ return ctx
+ }
+
+ mdMap := map[string]string{
+ rpctypes.TokenFieldNameGRPC: 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.LockInsideApply()
+ u := getUser(as.lg, tx, user)
+ tx.Unlock()
+
+ if u == nil {
+ as.lg.Warn(
+ "'has-role' requested for non-existing user",
+ zap.String("user-name", user),
+ zap.String("role-name", role),
+ )
+ return false
+ }
+
+ for _, r := range u.Roles {
+ if role == r {
+ return true
+ }
+ }
+ return false
+}
+
+func (as *authStore) BcryptCost() int {
+ return as.bcryptCost
+}
+
+func (as *authStore) setupMetricsReporter() {
+ reportCurrentAuthRevMu.Lock()
+ reportCurrentAuthRev = func() float64 {
+ return float64(as.Revision())
+ }
+ reportCurrentAuthRevMu.Unlock()
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/config/config.go b/vendor/go.etcd.io/etcd/server/v3/config/config.go
new file mode 100644
index 0000000000..0dac25c41f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/config/config.go
@@ -0,0 +1,343 @@
+// 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 config
+
+import (
+ "context"
+ "fmt"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/netutil"
+ "go.etcd.io/etcd/server/v3/datadir"
+ "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
+
+ bolt "go.etcd.io/bbolt"
+ "go.uber.org/zap"
+)
+
+// 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
+
+ SnapshotCount uint64
+
+ // SnapshotCatchUpEntries is the number of entries for a 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.
+ // WARNING: only change this for tests. Always use "DefaultSnapshotCatchUpEntries"
+ SnapshotCatchUpEntries uint64
+
+ MaxSnapFiles uint
+ MaxWALFiles uint
+
+ // BackendBatchInterval is the maximum time before commit the backend transaction.
+ BackendBatchInterval time.Duration
+ // BackendBatchLimit is the maximum operations before commit the backend transaction.
+ BackendBatchLimit int
+
+ // BackendFreelistType is the type of the backend boltdb freelist.
+ BackendFreelistType bolt.FreelistType
+
+ InitialPeerURLsMap types.URLsMap
+ InitialClusterToken string
+ NewCluster bool
+ PeerTLSInfo transport.TLSInfo
+
+ CORS map[string]struct{}
+
+ // HostWhitelist lists acceptable hostnames from client requests.
+ // If server is insecure (no TLS), server only accepts requests
+ // whose Host header value exists in this white list.
+ HostWhitelist map[string]struct{}
+
+ 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/etcd-io/etcd/issues/9333 for more detail.
+ InitialElectionTickAdvance bool
+
+ BootstrapTimeout time.Duration
+
+ AutoCompactionRetention time.Duration
+ AutoCompactionMode string
+ CompactionBatchLimit int
+ QuotaBackendBytes int64
+ MaxTxnOps uint
+
+ // MaxRequestBytes is the maximum request size to send over raft.
+ MaxRequestBytes uint
+
+ // MaxConcurrentStreams specifies the maximum number of concurrent
+ // streams that each client can open at a time.
+ MaxConcurrentStreams uint32
+
+ WarningApplyDuration time.Duration
+
+ StrictReconfigCheck bool
+
+ // ClientCertAuthEnabled is true when cert has been signed by the client CA.
+ ClientCertAuthEnabled bool
+
+ AuthToken string
+ BcryptCost uint
+ TokenTTL uint
+
+ // InitialCorruptCheck is true to check data corruption on boot
+ // before serving any peer/client traffic.
+ InitialCorruptCheck bool
+ CorruptCheckTime time.Duration
+ CompactHashCheckEnabled bool
+ CompactHashCheckTime time.Duration
+
+ // PreVote is true to enable Raft Pre-Vote.
+ PreVote bool
+
+ // SocketOpts are socket options passed to listener config.
+ SocketOpts transport.SocketOpts
+
+ // Logger logs server-side operations.
+ Logger *zap.Logger
+
+ ForceNewCluster bool
+
+ // EnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change.
+ EnableLeaseCheckpoint bool
+ // LeaseCheckpointInterval time.Duration is the wait duration between lease checkpoints.
+ LeaseCheckpointInterval time.Duration
+ // LeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled.
+ LeaseCheckpointPersist bool
+
+ EnableGRPCGateway bool
+
+ // ExperimentalEnableDistributedTracing enables distributed tracing using OpenTelemetry protocol.
+ ExperimentalEnableDistributedTracing bool
+ // ExperimentalTracerOptions are options for OpenTelemetry gRPC interceptor.
+ ExperimentalTracerOptions []otelgrpc.Option
+
+ WatchProgressNotifyInterval time.Duration
+
+ // UnsafeNoFsync disables all uses of fsync.
+ // Setting this is unsafe and will cause data loss.
+ UnsafeNoFsync bool `json:"unsafe-no-fsync"`
+
+ DowngradeCheckTime time.Duration
+
+ // ExperimentalMemoryMlock enables mlocking of etcd owned memory pages.
+ // The setting improves etcd tail latency in environments were:
+ // - memory pressure might lead to swapping pages to disk
+ // - disk latency might be unstable
+ // Currently all etcd memory gets mlocked, but in future the flag can
+ // be refined to mlock in-use area of bbolt only.
+ ExperimentalMemoryMlock bool `json:"experimental-memory-mlock"`
+
+ // ExperimentalTxnModeWriteWithSharedBuffer enable write transaction to use
+ // a shared buffer in its readonly check operations.
+ ExperimentalTxnModeWriteWithSharedBuffer bool `json:"experimental-txn-mode-write-with-shared-buffer"`
+
+ // ExperimentalBootstrapDefragThresholdMegabytes is the minimum number of megabytes needed to be freed for etcd server to
+ // consider running defrag during bootstrap. Needs to be set to non-zero value to take effect.
+ ExperimentalBootstrapDefragThresholdMegabytes uint `json:"experimental-bootstrap-defrag-threshold-megabytes"`
+
+ // V2Deprecation defines a phase of v2store deprecation process.
+ V2Deprecation V2DeprecationEnum `json:"v2-deprecation"`
+}
+
+// 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, c.Logger, 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 datadir.ToMemberDir(c.DataDir) }
+
+func (c *ServerConfig) WALDir() string {
+ if c.DedicatedWALDir != "" {
+ return c.DedicatedWALDir
+ }
+ return datadir.ToWalDir(c.DataDir)
+}
+
+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 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) BootstrapTimeoutEffective() time.Duration {
+ if c.BootstrapTimeout != 0 {
+ return c.BootstrapTimeout
+ }
+ return time.Second
+}
+
+func (c *ServerConfig) BackendPath() string { return datadir.ToBackendFileName(c.DataDir) }
diff --git a/vendor/go.etcd.io/etcd/server/v3/config/v2_deprecation.go b/vendor/go.etcd.io/etcd/server/v3/config/v2_deprecation.go
new file mode 100644
index 0000000000..828bd9a8f4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/config/v2_deprecation.go
@@ -0,0 +1,50 @@
+// Copyright 2021 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 config
+
+type V2DeprecationEnum string
+
+const (
+ // Default in v3.5. Issues a warning if v2store have meaningful content.
+ V2_DEPR_0_NOT_YET = V2DeprecationEnum("not-yet")
+ // Default in v3.6. Meaningful v2 state is not allowed.
+ // The V2 files are maintained for v3.5 rollback.
+ V2_DEPR_1_WRITE_ONLY = V2DeprecationEnum("write-only")
+ // V2store is WIPED if found !!!
+ V2_DEPR_1_WRITE_ONLY_DROP = V2DeprecationEnum("write-only-drop-data")
+ // V2store is neither written nor read. Usage of this configuration is blocking
+ // ability to rollback to etcd v3.5.
+ V2_DEPR_2_GONE = V2DeprecationEnum("gone")
+
+ V2_DEPR_DEFAULT = V2_DEPR_0_NOT_YET
+)
+
+func (e V2DeprecationEnum) IsAtLeast(v2d V2DeprecationEnum) bool {
+ return e.level() >= v2d.level()
+}
+
+func (e V2DeprecationEnum) level() int {
+ switch e {
+ case V2_DEPR_0_NOT_YET:
+ return 0
+ case V2_DEPR_1_WRITE_ONLY:
+ return 1
+ case V2_DEPR_1_WRITE_ONLY_DROP:
+ return 2
+ case V2_DEPR_2_GONE:
+ return 3
+ }
+ panic("Unknown V2DeprecationEnum: " + e)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/datadir/datadir.go b/vendor/go.etcd.io/etcd/server/v3/datadir/datadir.go
new file mode 100644
index 0000000000..fa4c51ad1a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/datadir/datadir.go
@@ -0,0 +1,40 @@
+// Copyright 2021 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 datadir
+
+import "path/filepath"
+
+const (
+ memberDirSegment = "member"
+ snapDirSegment = "snap"
+ walDirSegment = "wal"
+ backendFileSegment = "db"
+)
+
+func ToBackendFileName(dataDir string) string {
+ return filepath.Join(ToSnapDir(dataDir), backendFileSegment)
+}
+
+func ToSnapDir(dataDir string) string {
+ return filepath.Join(ToMemberDir(dataDir), snapDirSegment)
+}
+
+func ToWalDir(dataDir string) string {
+ return filepath.Join(ToMemberDir(dataDir), walDirSegment)
+}
+
+func ToMemberDir(dataDir string) string {
+ return filepath.Join(dataDir, memberDirSegment)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/datadir/doc.go b/vendor/go.etcd.io/etcd/server/v3/datadir/doc.go
new file mode 100644
index 0000000000..92ca4b253d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/datadir/doc.go
@@ -0,0 +1,17 @@
+// Copyright 2021 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 datadir
+
+// datadir contains functions to navigate file-layout of etcd data-directory.
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/config.go b/vendor/go.etcd.io/etcd/server/v3/embed/config.go
new file mode 100644
index 0000000000..8394b2ae1c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/config.go
@@ -0,0 +1,1061 @@
+// 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 embed
+
+import (
+ "crypto/tls"
+ "fmt"
+ "io/ioutil"
+ "math"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/logutil"
+ "go.etcd.io/etcd/client/pkg/v3/srv"
+ "go.etcd.io/etcd/client/pkg/v3/tlsutil"
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/flags"
+ "go.etcd.io/etcd/pkg/v3/netutil"
+ "go.etcd.io/etcd/server/v3/config"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor"
+
+ bolt "go.etcd.io/bbolt"
+ "go.uber.org/multierr"
+ "go.uber.org/zap"
+ "golang.org/x/crypto/bcrypt"
+ "google.golang.org/grpc"
+ "sigs.k8s.io/yaml"
+)
+
+const (
+ ClusterStateFlagNew = "new"
+ ClusterStateFlagExisting = "existing"
+
+ DefaultName = "default"
+ DefaultMaxSnapshots = 5
+ DefaultMaxWALs = 5
+ DefaultMaxTxnOps = uint(128)
+ DefaultWarningApplyDuration = 100 * time.Millisecond
+ DefaultMaxRequestBytes = 1.5 * 1024 * 1024
+ DefaultMaxConcurrentStreams = math.MaxUint32
+ DefaultGRPCKeepAliveMinTime = 5 * time.Second
+ DefaultGRPCKeepAliveInterval = 2 * time.Hour
+ DefaultGRPCKeepAliveTimeout = 20 * time.Second
+ DefaultDowngradeCheckTime = 5 * time.Second
+
+ DefaultListenPeerURLs = "http://localhost:2380"
+ DefaultListenClientURLs = "http://localhost:2379"
+
+ DefaultLogOutput = "default"
+ JournalLogOutput = "systemd/journal"
+ StdErrLogOutput = "stderr"
+ StdOutLogOutput = "stdout"
+
+ // DefaultLogRotationConfig is the default configuration used for log rotation.
+ // Log rotation is disabled by default.
+ // MaxSize = 100 // MB
+ // MaxAge = 0 // days (no limit)
+ // MaxBackups = 0 // no limit
+ // LocalTime = false // use computers local time, UTC by default
+ // Compress = false // compress the rotated log in gzip format
+ DefaultLogRotationConfig = `{"maxsize": 100, "maxage": 0, "maxbackups": 0, "localtime": false, "compress": false}`
+
+ // ExperimentalDistributedTracingAddress is the default collector address.
+ ExperimentalDistributedTracingAddress = "localhost:4317"
+ // ExperimentalDistributedTracingServiceName is the default etcd service name.
+ ExperimentalDistributedTracingServiceName = "etcd"
+
+ // DefaultStrictReconfigCheck is the default value for "--strict-reconfig-check" flag.
+ // It's enabled by default.
+ DefaultStrictReconfigCheck = true
+ // DefaultEnableV2 is the default value for "--enable-v2" flag.
+ // v2 API is disabled by default.
+ DefaultEnableV2 = false
+
+ // maxElectionMs specifies the maximum value of election timeout.
+ // More details are listed in ../Documentation/tuning.md#time-parameters.
+ maxElectionMs = 50000
+ // backend freelist map type
+ freelistArrayType = "array"
+)
+
+var (
+ ErrConflictBootstrapFlags = fmt.Errorf("multiple discovery or bootstrap flags are set. " +
+ "Choose one of \"initial-cluster\", \"discovery\" or \"discovery-srv\"")
+ ErrUnsetAdvertiseClientURLsFlag = fmt.Errorf("--advertise-client-urls is required when --listen-client-urls is set explicitly")
+ ErrLogRotationInvalidLogOutput = fmt.Errorf("--log-outputs requires a single file path when --log-rotate-config-json is defined")
+
+ DefaultInitialAdvertisePeerURLs = "http://localhost:2380"
+ DefaultAdvertiseClientURLs = "http://localhost:2379"
+
+ defaultHostname string
+ defaultHostStatus error
+
+ // indirection for testing
+ getCluster = srv.GetCluster
+)
+
+var (
+ // CompactorModePeriodic is periodic compaction mode
+ // for "Config.AutoCompactionMode" field.
+ // If "AutoCompactionMode" is CompactorModePeriodic and
+ // "AutoCompactionRetention" is "1h", it automatically compacts
+ // compacts storage every hour.
+ CompactorModePeriodic = v3compactor.ModePeriodic
+
+ // CompactorModeRevision is revision-based compaction mode
+ // for "Config.AutoCompactionMode" field.
+ // If "AutoCompactionMode" is CompactorModeRevision and
+ // "AutoCompactionRetention" is "1000", it compacts log on
+ // revision 5000 when the current revision is 6000.
+ // This runs every 5-minute if enough of logs have proceeded.
+ CompactorModeRevision = v3compactor.ModeRevision
+)
+
+func init() {
+ defaultHostname, defaultHostStatus = netutil.GetDefaultHost()
+}
+
+// Config holds the arguments for configuring an etcd server.
+type Config struct {
+ Name string `json:"name"`
+ Dir string `json:"data-dir"`
+ WalDir string `json:"wal-dir"`
+
+ SnapshotCount uint64 `json:"snapshot-count"`
+
+ // SnapshotCatchUpEntries is the number of entries for a 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.
+ // WARNING: only change this for tests.
+ // Always use "DefaultSnapshotCatchUpEntries"
+ SnapshotCatchUpEntries uint64
+
+ MaxSnapFiles uint `json:"max-snapshots"`
+ MaxWalFiles uint `json:"max-wals"`
+
+ // TickMs is the number of milliseconds between heartbeat ticks.
+ // TODO: decouple tickMs and heartbeat tick (current heartbeat tick = 1).
+ // make ticks a cluster wide configuration.
+ TickMs uint `json:"heartbeat-interval"`
+ ElectionMs uint `json:"election-timeout"`
+
+ // 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/etcd-io/etcd/issues/9333 for more detail.
+ InitialElectionTickAdvance bool `json:"initial-election-tick-advance"`
+
+ // BackendBatchInterval is the maximum time before commit the backend transaction.
+ BackendBatchInterval time.Duration `json:"backend-batch-interval"`
+ // BackendBatchLimit is the maximum operations before commit the backend transaction.
+ BackendBatchLimit int `json:"backend-batch-limit"`
+ // BackendFreelistType specifies the type of freelist that boltdb backend uses (array and map are supported types).
+ BackendFreelistType string `json:"backend-bbolt-freelist-type"`
+ QuotaBackendBytes int64 `json:"quota-backend-bytes"`
+ MaxTxnOps uint `json:"max-txn-ops"`
+ MaxRequestBytes uint `json:"max-request-bytes"`
+
+ // MaxConcurrentStreams specifies the maximum number of concurrent
+ // streams that each client can open at a time.
+ MaxConcurrentStreams uint32 `json:"max-concurrent-streams"`
+
+ ListenPeerUrls, ListenClientUrls, ListenClientHttpUrls []url.URL
+ AdvertisePeerUrls, AdvertiseClientUrls []url.URL
+ ClientTLSInfo transport.TLSInfo
+ ClientAutoTLS bool
+ PeerTLSInfo transport.TLSInfo
+ PeerAutoTLS bool
+ // SelfSignedCertValidity specifies the validity period of the client and peer certificates
+ // that are automatically generated by etcd when you specify ClientAutoTLS and PeerAutoTLS,
+ // the unit is year, and the default is 1
+ SelfSignedCertValidity uint `json:"self-signed-cert-validity"`
+
+ // CipherSuites is a list of supported TLS cipher suites between
+ // client/server and peers. If empty, Go auto-populates the list.
+ // Note that cipher suites are prioritized in the given order.
+ CipherSuites []string `json:"cipher-suites"`
+
+ // TlsMinVersion is the minimum accepted TLS version between client/server and peers.
+ TlsMinVersion string `json:"tls-min-version"`
+ // TlsMaxVersion is the maximum accepted TLS version between client/server and peers.
+ TlsMaxVersion string `json:"tls-max-version"`
+
+ ClusterState string `json:"initial-cluster-state"`
+ DNSCluster string `json:"discovery-srv"`
+ DNSClusterServiceName string `json:"discovery-srv-name"`
+ Dproxy string `json:"discovery-proxy"`
+ Durl string `json:"discovery"`
+ InitialCluster string `json:"initial-cluster"`
+ InitialClusterToken string `json:"initial-cluster-token"`
+ StrictReconfigCheck bool `json:"strict-reconfig-check"`
+
+ // EnableV2 exposes the deprecated V2 API surface.
+ // TODO: Delete in 3.6 (https://github.com/etcd-io/etcd/issues/12913)
+ // Deprecated in 3.5.
+ EnableV2 bool `json:"enable-v2"`
+
+ // AutoCompactionMode is either 'periodic' or 'revision'.
+ AutoCompactionMode string `json:"auto-compaction-mode"`
+ // AutoCompactionRetention is either duration string with time unit
+ // (e.g. '5m' for 5-minute), or revision unit (e.g. '5000').
+ // If no time unit is provided and compaction mode is 'periodic',
+ // the unit defaults to hour. For example, '5' translates into 5-hour.
+ AutoCompactionRetention string `json:"auto-compaction-retention"`
+
+ // GRPCKeepAliveMinTime is the minimum interval that a client should
+ // wait before pinging server. When client pings "too fast", server
+ // sends goaway and closes the connection (errors: too_many_pings,
+ // http2.ErrCodeEnhanceYourCalm). When too slow, nothing happens.
+ // Server expects client pings only when there is any active streams
+ // (PermitWithoutStream is set false).
+ GRPCKeepAliveMinTime time.Duration `json:"grpc-keepalive-min-time"`
+ // GRPCKeepAliveInterval is the frequency of server-to-client ping
+ // to check if a connection is alive. Close a non-responsive connection
+ // after an additional duration of Timeout. 0 to disable.
+ GRPCKeepAliveInterval time.Duration `json:"grpc-keepalive-interval"`
+ // GRPCKeepAliveTimeout is the additional duration of wait
+ // before closing a non-responsive connection. 0 to disable.
+ GRPCKeepAliveTimeout time.Duration `json:"grpc-keepalive-timeout"`
+
+ // SocketOpts are socket options passed to listener config.
+ SocketOpts transport.SocketOpts `json:"socket-options"`
+
+ // PreVote is true to enable Raft Pre-Vote.
+ // If enabled, Raft runs an additional election phase
+ // to check whether it would get enough votes to win
+ // an election, thus minimizing disruptions.
+ PreVote bool `json:"pre-vote"`
+
+ CORS map[string]struct{}
+
+ // HostWhitelist lists acceptable hostnames from HTTP client requests.
+ // Client origin policy protects against "DNS Rebinding" attacks
+ // to insecure etcd servers. That is, any website can simply create
+ // an authorized DNS name, and direct DNS to "localhost" (or any
+ // other address). Then, all HTTP endpoints of etcd server listening
+ // on "localhost" becomes accessible, thus vulnerable to DNS rebinding
+ // attacks. See "CVE-2018-5702" for more detail.
+ //
+ // 1. If client connection is secure via HTTPS, allow any hostnames.
+ // 2. If client connection is not secure and "HostWhitelist" is not empty,
+ // only allow HTTP requests whose Host field is listed in whitelist.
+ //
+ // Note that the client origin policy is enforced whether authentication
+ // is enabled or not, for tighter controls.
+ //
+ // By default, "HostWhitelist" is "*", which allows any hostnames.
+ // Note that when specifying hostnames, loopback addresses are not added
+ // automatically. To allow loopback interfaces, leave it empty or set it "*",
+ // or add them to whitelist manually (e.g. "localhost", "127.0.0.1", etc.).
+ //
+ // CVE-2018-5702 reference:
+ // - https://bugs.chromium.org/p/project-zero/issues/detail?id=1447#c2
+ // - https://github.com/transmission/transmission/pull/468
+ // - https://github.com/etcd-io/etcd/issues/9353
+ HostWhitelist map[string]struct{}
+
+ // UserHandlers is for registering users handlers and only used for
+ // embedding etcd into other applications.
+ // The map key is the route path for the handler, and
+ // you must ensure it can't be conflicted with etcd's.
+ UserHandlers map[string]http.Handler `json:"-"`
+ // ServiceRegister is for registering users' gRPC services. A simple usage example:
+ // cfg := embed.NewConfig()
+ // cfg.ServerRegister = func(s *grpc.Server) {
+ // pb.RegisterFooServer(s, &fooServer{})
+ // pb.RegisterBarServer(s, &barServer{})
+ // }
+ // embed.StartEtcd(cfg)
+ ServiceRegister func(*grpc.Server) `json:"-"`
+
+ AuthToken string `json:"auth-token"`
+ BcryptCost uint `json:"bcrypt-cost"`
+
+ // AuthTokenTTL specifies the TTL in seconds of the simple token
+ AuthTokenTTL uint `json:"auth-token-ttl"`
+
+ ExperimentalInitialCorruptCheck bool `json:"experimental-initial-corrupt-check"`
+ ExperimentalCorruptCheckTime time.Duration `json:"experimental-corrupt-check-time"`
+ ExperimentalCompactHashCheckEnabled bool `json:"experimental-compact-hash-check-enabled"`
+ ExperimentalCompactHashCheckTime time.Duration `json:"experimental-compact-hash-check-time"`
+ // ExperimentalEnableV2V3 configures URLs that expose deprecated V2 API working on V3 store.
+ // Deprecated in v3.5.
+ // TODO: Delete in v3.6 (https://github.com/etcd-io/etcd/issues/12913)
+ ExperimentalEnableV2V3 string `json:"experimental-enable-v2v3"`
+ // ExperimentalEnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change.
+ ExperimentalEnableLeaseCheckpoint bool `json:"experimental-enable-lease-checkpoint"`
+ // ExperimentalEnableLeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled.
+ // Requires experimental-enable-lease-checkpoint to be enabled.
+ // Deprecated in v3.6.
+ // TODO: Delete in v3.7
+ ExperimentalEnableLeaseCheckpointPersist bool `json:"experimental-enable-lease-checkpoint-persist"`
+ ExperimentalCompactionBatchLimit int `json:"experimental-compaction-batch-limit"`
+ ExperimentalWatchProgressNotifyInterval time.Duration `json:"experimental-watch-progress-notify-interval"`
+ // ExperimentalWarningApplyDuration is the time duration after which a warning is generated if applying request
+ // takes more time than this value.
+ ExperimentalWarningApplyDuration time.Duration `json:"experimental-warning-apply-duration"`
+ // ExperimentalBootstrapDefragThresholdMegabytes is the minimum number of megabytes needed to be freed for etcd server to
+ // consider running defrag during bootstrap. Needs to be set to non-zero value to take effect.
+ ExperimentalBootstrapDefragThresholdMegabytes uint `json:"experimental-bootstrap-defrag-threshold-megabytes"`
+
+ // ForceNewCluster starts a new cluster even if previously started; unsafe.
+ ForceNewCluster bool `json:"force-new-cluster"`
+
+ EnablePprof bool `json:"enable-pprof"`
+ Metrics string `json:"metrics"`
+ ListenMetricsUrls []url.URL
+ ListenMetricsUrlsJSON string `json:"listen-metrics-urls"`
+
+ // ExperimentalEnableDistributedTracing indicates if experimental tracing using OpenTelemetry is enabled.
+ ExperimentalEnableDistributedTracing bool `json:"experimental-enable-distributed-tracing"`
+ // ExperimentalDistributedTracingAddress is the address of the OpenTelemetry Collector.
+ // Can only be set if ExperimentalEnableDistributedTracing is true.
+ ExperimentalDistributedTracingAddress string `json:"experimental-distributed-tracing-address"`
+ // ExperimentalDistributedTracingServiceName is the name of the service.
+ // Can only be used if ExperimentalEnableDistributedTracing is true.
+ ExperimentalDistributedTracingServiceName string `json:"experimental-distributed-tracing-service-name"`
+ // ExperimentalDistributedTracingServiceInstanceID is the ID key of the service.
+ // This ID must be unique, as helps to distinguish instances of the same service
+ // that exist at the same time.
+ // Can only be used if ExperimentalEnableDistributedTracing is true.
+ ExperimentalDistributedTracingServiceInstanceID string `json:"experimental-distributed-tracing-instance-id"`
+
+ // Logger is logger options: currently only supports "zap".
+ // "capnslog" is removed in v3.5.
+ Logger string `json:"logger"`
+ // LogLevel configures log level. Only supports debug, info, warn, error, panic, or fatal. Default 'info'.
+ LogLevel string `json:"log-level"`
+ // LogOutputs is either:
+ // - "default" as os.Stderr,
+ // - "stderr" as os.Stderr,
+ // - "stdout" as os.Stdout,
+ // - file path to append server logs to.
+ // It can be multiple when "Logger" is zap.
+ LogOutputs []string `json:"log-outputs"`
+ // EnableLogRotation enables log rotation of a single LogOutputs file target.
+ EnableLogRotation bool `json:"enable-log-rotation"`
+ // LogRotationConfigJSON is a passthrough allowing a log rotation JSON config to be passed directly.
+ LogRotationConfigJSON string `json:"log-rotation-config-json"`
+ // ZapLoggerBuilder is used to build the zap logger.
+ ZapLoggerBuilder func(*Config) error
+
+ // logger logs server-side operations. The default is nil,
+ // and "setupLogging" must be called before starting server.
+ // Do not set logger directly.
+ loggerMu *sync.RWMutex
+ logger *zap.Logger
+ // EnableGRPCGateway enables grpc gateway.
+ // The gateway translates a RESTful HTTP API into gRPC.
+ EnableGRPCGateway bool `json:"enable-grpc-gateway"`
+
+ // UnsafeNoFsync disables all uses of fsync.
+ // Setting this is unsafe and will cause data loss.
+ UnsafeNoFsync bool `json:"unsafe-no-fsync"`
+
+ ExperimentalDowngradeCheckTime time.Duration `json:"experimental-downgrade-check-time"`
+
+ // ExperimentalMemoryMlock enables mlocking of etcd owned memory pages.
+ // The setting improves etcd tail latency in environments were:
+ // - memory pressure might lead to swapping pages to disk
+ // - disk latency might be unstable
+ // Currently all etcd memory gets mlocked, but in future the flag can
+ // be refined to mlock in-use area of bbolt only.
+ ExperimentalMemoryMlock bool `json:"experimental-memory-mlock"`
+
+ // ExperimentalTxnModeWriteWithSharedBuffer enables write transaction to use a shared buffer in its readonly check operations.
+ ExperimentalTxnModeWriteWithSharedBuffer bool `json:"experimental-txn-mode-write-with-shared-buffer"`
+
+ // V2Deprecation describes phase of API & Storage V2 support
+ V2Deprecation config.V2DeprecationEnum `json:"v2-deprecation"`
+}
+
+// configYAML holds the config suitable for yaml parsing
+type configYAML struct {
+ Config
+ configJSON
+}
+
+// configJSON has file options that are translated into Config options
+type configJSON struct {
+ ListenPeerUrls string `json:"listen-peer-urls"`
+ ListenClientUrls string `json:"listen-client-urls"`
+ ListenClientHttpUrls string `json:"listen-client-http-urls"`
+ AdvertisePeerUrls string `json:"initial-advertise-peer-urls"`
+ AdvertiseClientUrls string `json:"advertise-client-urls"`
+
+ CORSJSON string `json:"cors"`
+ HostWhitelistJSON string `json:"host-whitelist"`
+
+ ClientSecurityJSON securityConfig `json:"client-transport-security"`
+ PeerSecurityJSON securityConfig `json:"peer-transport-security"`
+}
+
+type securityConfig struct {
+ CertFile string `json:"cert-file"`
+ KeyFile string `json:"key-file"`
+ ClientCertFile string `json:"client-cert-file"`
+ ClientKeyFile string `json:"client-key-file"`
+ CertAuth bool `json:"client-cert-auth"`
+ TrustedCAFile string `json:"trusted-ca-file"`
+ AutoTLS bool `json:"auto-tls"`
+}
+
+// NewConfig creates a new Config populated with default values.
+func NewConfig() *Config {
+ lpurl, _ := url.Parse(DefaultListenPeerURLs)
+ apurl, _ := url.Parse(DefaultInitialAdvertisePeerURLs)
+ lcurl, _ := url.Parse(DefaultListenClientURLs)
+ acurl, _ := url.Parse(DefaultAdvertiseClientURLs)
+ cfg := &Config{
+ MaxSnapFiles: DefaultMaxSnapshots,
+ MaxWalFiles: DefaultMaxWALs,
+
+ Name: DefaultName,
+
+ SnapshotCount: etcdserver.DefaultSnapshotCount,
+ SnapshotCatchUpEntries: etcdserver.DefaultSnapshotCatchUpEntries,
+
+ MaxTxnOps: DefaultMaxTxnOps,
+ MaxRequestBytes: DefaultMaxRequestBytes,
+ MaxConcurrentStreams: DefaultMaxConcurrentStreams,
+ ExperimentalWarningApplyDuration: DefaultWarningApplyDuration,
+
+ GRPCKeepAliveMinTime: DefaultGRPCKeepAliveMinTime,
+ GRPCKeepAliveInterval: DefaultGRPCKeepAliveInterval,
+ GRPCKeepAliveTimeout: DefaultGRPCKeepAliveTimeout,
+
+ SocketOpts: transport.SocketOpts{
+ ReusePort: false,
+ ReuseAddress: false,
+ },
+
+ TickMs: 100,
+ ElectionMs: 1000,
+ InitialElectionTickAdvance: true,
+
+ ListenPeerUrls: []url.URL{*lpurl},
+ ListenClientUrls: []url.URL{*lcurl},
+ AdvertisePeerUrls: []url.URL{*apurl},
+ AdvertiseClientUrls: []url.URL{*acurl},
+
+ ClusterState: ClusterStateFlagNew,
+ InitialClusterToken: "etcd-cluster",
+
+ StrictReconfigCheck: DefaultStrictReconfigCheck,
+ Metrics: "basic",
+ EnableV2: DefaultEnableV2,
+
+ CORS: map[string]struct{}{"*": {}},
+ HostWhitelist: map[string]struct{}{"*": {}},
+
+ AuthToken: "simple",
+ BcryptCost: uint(bcrypt.DefaultCost),
+ AuthTokenTTL: 300,
+
+ PreVote: true,
+
+ loggerMu: new(sync.RWMutex),
+ logger: nil,
+ Logger: "zap",
+ LogOutputs: []string{DefaultLogOutput},
+ LogLevel: logutil.DefaultLogLevel,
+ EnableLogRotation: false,
+ LogRotationConfigJSON: DefaultLogRotationConfig,
+ EnableGRPCGateway: true,
+
+ ExperimentalDowngradeCheckTime: DefaultDowngradeCheckTime,
+ ExperimentalMemoryMlock: false,
+ ExperimentalTxnModeWriteWithSharedBuffer: true,
+
+ ExperimentalCompactHashCheckEnabled: false,
+ ExperimentalCompactHashCheckTime: time.Minute,
+
+ V2Deprecation: config.V2_DEPR_DEFAULT,
+ }
+ cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
+ return cfg
+}
+
+func ConfigFromFile(path string) (*Config, error) {
+ cfg := &configYAML{Config: *NewConfig()}
+ if err := cfg.configFromFile(path); err != nil {
+ return nil, err
+ }
+ return &cfg.Config, nil
+}
+
+func (cfg *configYAML) configFromFile(path string) error {
+ b, err := ioutil.ReadFile(path)
+ if err != nil {
+ return err
+ }
+
+ defaultInitialCluster := cfg.InitialCluster
+
+ err = yaml.Unmarshal(b, cfg)
+ if err != nil {
+ return err
+ }
+
+ if cfg.configJSON.ListenPeerUrls != "" {
+ u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenPeerUrls, ","))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unexpected error setting up listen-peer-urls: %v\n", err)
+ os.Exit(1)
+ }
+ cfg.Config.ListenPeerUrls = u
+ }
+
+ if cfg.configJSON.ListenClientUrls != "" {
+ u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenClientUrls, ","))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unexpected error setting up listen-client-urls: %v\n", err)
+ os.Exit(1)
+ }
+ cfg.Config.ListenClientUrls = u
+ }
+
+ if cfg.configJSON.ListenClientHttpUrls != "" {
+ u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenClientHttpUrls, ","))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unexpected error setting up listen-client-http-urls: %v\n", err)
+ os.Exit(1)
+ }
+ cfg.Config.ListenClientHttpUrls = u
+ }
+
+ if cfg.configJSON.AdvertisePeerUrls != "" {
+ u, err := types.NewURLs(strings.Split(cfg.configJSON.AdvertisePeerUrls, ","))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unexpected error setting up initial-advertise-peer-urls: %v\n", err)
+ os.Exit(1)
+ }
+ cfg.Config.AdvertisePeerUrls = u
+ }
+
+ if cfg.configJSON.AdvertiseClientUrls != "" {
+ u, err := types.NewURLs(strings.Split(cfg.configJSON.AdvertiseClientUrls, ","))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unexpected error setting up advertise-peer-urls: %v\n", err)
+ os.Exit(1)
+ }
+ cfg.Config.AdvertiseClientUrls = u
+ }
+
+ if cfg.ListenMetricsUrlsJSON != "" {
+ u, err := types.NewURLs(strings.Split(cfg.ListenMetricsUrlsJSON, ","))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unexpected error setting up listen-metrics-urls: %v\n", err)
+ os.Exit(1)
+ }
+ cfg.ListenMetricsUrls = []url.URL(u)
+ }
+
+ if cfg.CORSJSON != "" {
+ uv := flags.NewUniqueURLsWithExceptions(cfg.CORSJSON, "*")
+ cfg.CORS = uv.Values
+ }
+
+ if cfg.HostWhitelistJSON != "" {
+ uv := flags.NewUniqueStringsValue(cfg.HostWhitelistJSON)
+ cfg.HostWhitelist = uv.Values
+ }
+
+ // If a discovery flag is set, clear default initial cluster set by InitialClusterFromName
+ if (cfg.Durl != "" || cfg.DNSCluster != "") && cfg.InitialCluster == defaultInitialCluster {
+ cfg.InitialCluster = ""
+ }
+ if cfg.ClusterState == "" {
+ cfg.ClusterState = ClusterStateFlagNew
+ }
+
+ copySecurityDetails := func(tls *transport.TLSInfo, ysc *securityConfig) {
+ tls.CertFile = ysc.CertFile
+ tls.KeyFile = ysc.KeyFile
+ tls.ClientCertFile = ysc.ClientCertFile
+ tls.ClientKeyFile = ysc.ClientKeyFile
+ tls.ClientCertAuth = ysc.CertAuth
+ tls.TrustedCAFile = ysc.TrustedCAFile
+ }
+ copySecurityDetails(&cfg.ClientTLSInfo, &cfg.ClientSecurityJSON)
+ copySecurityDetails(&cfg.PeerTLSInfo, &cfg.PeerSecurityJSON)
+ cfg.ClientAutoTLS = cfg.ClientSecurityJSON.AutoTLS
+ cfg.PeerAutoTLS = cfg.PeerSecurityJSON.AutoTLS
+ if cfg.SelfSignedCertValidity == 0 {
+ cfg.SelfSignedCertValidity = 1
+ }
+ return cfg.Validate()
+}
+
+func updateCipherSuites(tls *transport.TLSInfo, ss []string) error {
+ if len(tls.CipherSuites) > 0 && len(ss) > 0 {
+ return fmt.Errorf("TLSInfo.CipherSuites is already specified (given %v)", ss)
+ }
+ if len(ss) > 0 {
+ cs, err := tlsutil.GetCipherSuites(ss)
+ if err != nil {
+ return err
+ }
+ tls.CipherSuites = cs
+ }
+ return nil
+}
+
+func updateMinMaxVersions(info *transport.TLSInfo, min, max string) {
+ // Validate() has been called to check the user input, so it should never fail.
+ var err error
+ if info.MinVersion, err = tlsutil.GetTLSVersion(min); err != nil {
+ panic(err)
+ }
+ if info.MaxVersion, err = tlsutil.GetTLSVersion(max); err != nil {
+ panic(err)
+ }
+}
+
+// Validate ensures that '*embed.Config' fields are properly configured.
+func (cfg *Config) Validate() error {
+ if err := cfg.setupLogging(); err != nil {
+ return err
+ }
+ if err := checkBindURLs(cfg.ListenPeerUrls); err != nil {
+ return err
+ }
+ if err := checkBindURLs(cfg.ListenClientUrls); err != nil {
+ return err
+ }
+ if err := checkBindURLs(cfg.ListenClientHttpUrls); err != nil {
+ return err
+ }
+ if len(cfg.ListenClientHttpUrls) == 0 {
+ cfg.logger.Warn("Running http and grpc server on single port. This is not recommended for production.")
+ }
+ if err := checkBindURLs(cfg.ListenMetricsUrls); err != nil {
+ return err
+ }
+ if err := checkHostURLs(cfg.AdvertisePeerUrls); err != nil {
+ addrs := cfg.getAdvertisePeerUrls()
+ return fmt.Errorf(`--initial-advertise-peer-urls %q must be "host:port" (%v)`, strings.Join(addrs, ","), err)
+ }
+ if err := checkHostURLs(cfg.AdvertiseClientUrls); err != nil {
+ addrs := cfg.getAdvertiseClientUrls()
+ return fmt.Errorf(`--advertise-client-urls %q must be "host:port" (%v)`, strings.Join(addrs, ","), err)
+ }
+ // Check if conflicting flags are passed.
+ nSet := 0
+ for _, v := range []bool{cfg.Durl != "", cfg.InitialCluster != "", cfg.DNSCluster != ""} {
+ if v {
+ nSet++
+ }
+ }
+
+ if cfg.ClusterState != ClusterStateFlagNew && cfg.ClusterState != ClusterStateFlagExisting {
+ return fmt.Errorf("unexpected clusterState %q", cfg.ClusterState)
+ }
+
+ if nSet > 1 {
+ return ErrConflictBootstrapFlags
+ }
+
+ if cfg.TickMs == 0 {
+ return fmt.Errorf("--heartbeat-interval must be >0 (set to %dms)", cfg.TickMs)
+ }
+ if cfg.ElectionMs == 0 {
+ return fmt.Errorf("--election-timeout must be >0 (set to %dms)", cfg.ElectionMs)
+ }
+ if 5*cfg.TickMs > cfg.ElectionMs {
+ return fmt.Errorf("--election-timeout[%vms] should be at least as 5 times as --heartbeat-interval[%vms]", cfg.ElectionMs, cfg.TickMs)
+ }
+ if cfg.ElectionMs > maxElectionMs {
+ return fmt.Errorf("--election-timeout[%vms] is too long, and should be set less than %vms", cfg.ElectionMs, maxElectionMs)
+ }
+
+ // check this last since proxying in etcdmain may make this OK
+ if cfg.ListenClientUrls != nil && cfg.AdvertiseClientUrls == nil {
+ return ErrUnsetAdvertiseClientURLsFlag
+ }
+
+ switch cfg.AutoCompactionMode {
+ case "":
+ case CompactorModeRevision, CompactorModePeriodic:
+ default:
+ return fmt.Errorf("unknown auto-compaction-mode %q", cfg.AutoCompactionMode)
+ }
+
+ if !cfg.ExperimentalEnableLeaseCheckpointPersist && cfg.ExperimentalEnableLeaseCheckpoint {
+ cfg.logger.Warn("Detected that checkpointing is enabled without persistence. Consider enabling experimental-enable-lease-checkpoint-persist")
+ }
+
+ if cfg.ExperimentalEnableLeaseCheckpointPersist && !cfg.ExperimentalEnableLeaseCheckpoint {
+ return fmt.Errorf("setting experimental-enable-lease-checkpoint-persist requires experimental-enable-lease-checkpoint")
+ }
+
+ if cfg.ExperimentalCompactHashCheckTime <= 0 {
+ return fmt.Errorf("--experimental-compact-hash-check-time must be >0 (set to %v)", cfg.ExperimentalCompactHashCheckTime)
+ }
+
+ minVersion, err := tlsutil.GetTLSVersion(cfg.TlsMinVersion)
+ if err != nil {
+ return err
+ }
+ maxVersion, err := tlsutil.GetTLSVersion(cfg.TlsMaxVersion)
+ if err != nil {
+ return err
+ }
+
+ // maxVersion == 0 means that Go selects the highest available version.
+ if maxVersion != 0 && minVersion > maxVersion {
+ return fmt.Errorf("min version (%s) is greater than max version (%s)", cfg.TlsMinVersion, cfg.TlsMaxVersion)
+ }
+
+ // Check if user attempted to configure ciphers for TLS1.3 only: Go does not support that currently.
+ if minVersion == tls.VersionTLS13 && len(cfg.CipherSuites) > 0 {
+ return fmt.Errorf("cipher suites cannot be configured when only TLS1.3 is enabled")
+ }
+
+ return nil
+}
+
+// PeerURLsMapAndToken sets up an initial peer URLsMap and cluster token for bootstrap or discovery.
+func (cfg *Config) PeerURLsMapAndToken(which string) (urlsmap types.URLsMap, token string, err error) {
+ token = cfg.InitialClusterToken
+ switch {
+ case cfg.Durl != "":
+ urlsmap = types.URLsMap{}
+ // If using discovery, generate a temporary cluster based on
+ // self's advertised peer URLs
+ urlsmap[cfg.Name] = cfg.AdvertisePeerUrls
+ token = cfg.Durl
+
+ case cfg.DNSCluster != "":
+ clusterStrs, cerr := cfg.GetDNSClusterNames()
+ lg := cfg.logger
+ if cerr != nil {
+ lg.Warn("failed to resolve during SRV discovery", zap.Error(cerr))
+ }
+ if len(clusterStrs) == 0 {
+ return nil, "", cerr
+ }
+ for _, s := range clusterStrs {
+ lg.Info("got bootstrap from DNS for etcd-server", zap.String("node", s))
+ }
+ clusterStr := strings.Join(clusterStrs, ",")
+ if strings.Contains(clusterStr, "https://") && cfg.PeerTLSInfo.TrustedCAFile == "" {
+ cfg.PeerTLSInfo.ServerName = cfg.DNSCluster
+ }
+ urlsmap, err = types.NewURLsMap(clusterStr)
+ // only etcd member must belong to the discovered cluster.
+ // proxy does not need to belong to the discovered cluster.
+ if which == "etcd" {
+ if _, ok := urlsmap[cfg.Name]; !ok {
+ return nil, "", fmt.Errorf("cannot find local etcd member %q in SRV records", cfg.Name)
+ }
+ }
+
+ default:
+ // We're statically configured, and cluster has appropriately been set.
+ urlsmap, err = types.NewURLsMap(cfg.InitialCluster)
+ }
+ return urlsmap, token, err
+}
+
+// GetDNSClusterNames uses DNS SRV records to get a list of initial nodes for cluster bootstrapping.
+// This function will return a list of one or more nodes, as well as any errors encountered while
+// performing service discovery.
+// Note: Because this checks multiple sets of SRV records, discovery should only be considered to have
+// failed if the returned node list is empty.
+func (cfg *Config) GetDNSClusterNames() ([]string, error) {
+ var (
+ clusterStrs []string
+ cerr error
+ serviceNameSuffix string
+ )
+ if cfg.DNSClusterServiceName != "" {
+ serviceNameSuffix = "-" + cfg.DNSClusterServiceName
+ }
+
+ lg := cfg.GetLogger()
+
+ // Use both etcd-server-ssl and etcd-server for discovery.
+ // Combine the results if both are available.
+ clusterStrs, cerr = getCluster("https", "etcd-server-ssl"+serviceNameSuffix, cfg.Name, cfg.DNSCluster, cfg.AdvertisePeerUrls)
+ if cerr != nil {
+ clusterStrs = make([]string, 0)
+ }
+ lg.Info(
+ "get cluster for etcd-server-ssl SRV",
+ zap.String("service-scheme", "https"),
+ zap.String("service-name", "etcd-server-ssl"+serviceNameSuffix),
+ zap.String("server-name", cfg.Name),
+ zap.String("discovery-srv", cfg.DNSCluster),
+ zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerUrls()),
+ zap.Strings("found-cluster", clusterStrs),
+ zap.Error(cerr),
+ )
+
+ defaultHTTPClusterStrs, httpCerr := getCluster("http", "etcd-server"+serviceNameSuffix, cfg.Name, cfg.DNSCluster, cfg.AdvertisePeerUrls)
+ if httpCerr == nil {
+ clusterStrs = append(clusterStrs, defaultHTTPClusterStrs...)
+ }
+ lg.Info(
+ "get cluster for etcd-server SRV",
+ zap.String("service-scheme", "http"),
+ zap.String("service-name", "etcd-server"+serviceNameSuffix),
+ zap.String("server-name", cfg.Name),
+ zap.String("discovery-srv", cfg.DNSCluster),
+ zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerUrls()),
+ zap.Strings("found-cluster", clusterStrs),
+ zap.Error(httpCerr),
+ )
+
+ return clusterStrs, multierr.Combine(cerr, httpCerr)
+}
+
+func (cfg Config) InitialClusterFromName(name string) (ret string) {
+ if len(cfg.AdvertisePeerUrls) == 0 {
+ return ""
+ }
+ n := name
+ if name == "" {
+ n = DefaultName
+ }
+ for i := range cfg.AdvertisePeerUrls {
+ ret = ret + "," + n + "=" + cfg.AdvertisePeerUrls[i].String()
+ }
+ return ret[1:]
+}
+
+func (cfg Config) IsNewCluster() bool { return cfg.ClusterState == ClusterStateFlagNew }
+func (cfg Config) ElectionTicks() int { return int(cfg.ElectionMs / cfg.TickMs) }
+
+func (cfg Config) V2DeprecationEffective() config.V2DeprecationEnum {
+ if cfg.V2Deprecation == "" {
+ return config.V2_DEPR_DEFAULT
+ }
+ return cfg.V2Deprecation
+}
+
+func (cfg Config) defaultPeerHost() bool {
+ return len(cfg.AdvertisePeerUrls) == 1 && cfg.AdvertisePeerUrls[0].String() == DefaultInitialAdvertisePeerURLs
+}
+
+func (cfg Config) defaultClientHost() bool {
+ return len(cfg.AdvertiseClientUrls) == 1 && cfg.AdvertiseClientUrls[0].String() == DefaultAdvertiseClientURLs
+}
+
+func (cfg *Config) ClientSelfCert() (err error) {
+ if !cfg.ClientAutoTLS {
+ return nil
+ }
+ if !cfg.ClientTLSInfo.Empty() {
+ cfg.logger.Warn("ignoring client auto TLS since certs given")
+ return nil
+ }
+ chosts := make([]string, 0, len(cfg.ListenClientUrls)+len(cfg.ListenClientHttpUrls))
+ for _, u := range cfg.ListenClientUrls {
+ chosts = append(chosts, u.Host)
+ }
+ for _, u := range cfg.ListenClientHttpUrls {
+ chosts = append(chosts, u.Host)
+ }
+ cfg.ClientTLSInfo, err = transport.SelfCert(cfg.logger, filepath.Join(cfg.Dir, "fixtures", "client"), chosts, cfg.SelfSignedCertValidity)
+ if err != nil {
+ return err
+ }
+ return updateCipherSuites(&cfg.ClientTLSInfo, cfg.CipherSuites)
+}
+
+func (cfg *Config) PeerSelfCert() (err error) {
+ if !cfg.PeerAutoTLS {
+ return nil
+ }
+ if !cfg.PeerTLSInfo.Empty() {
+ cfg.logger.Warn("ignoring peer auto TLS since certs given")
+ return nil
+ }
+ phosts := make([]string, len(cfg.ListenPeerUrls))
+ for i, u := range cfg.ListenPeerUrls {
+ phosts[i] = u.Host
+ }
+ cfg.PeerTLSInfo, err = transport.SelfCert(cfg.logger, filepath.Join(cfg.Dir, "fixtures", "peer"), phosts, cfg.SelfSignedCertValidity)
+ if err != nil {
+ return err
+ }
+ return updateCipherSuites(&cfg.PeerTLSInfo, cfg.CipherSuites)
+}
+
+// UpdateDefaultClusterFromName updates cluster advertise URLs with, if available, default host,
+// if advertise URLs are default values(localhost:2379,2380) AND if listen URL is 0.0.0.0.
+// e.g. advertise peer URL localhost:2380 or listen peer URL 0.0.0.0:2380
+// then the advertise peer host would be updated with machine's default host,
+// while keeping the listen URL's port.
+// User can work around this by explicitly setting URL with 127.0.0.1.
+// It returns the default hostname, if used, and the error, if any, from getting the machine's default host.
+// TODO: check whether fields are set instead of whether fields have default value
+func (cfg *Config) UpdateDefaultClusterFromName(defaultInitialCluster string) (string, error) {
+ if defaultHostname == "" || defaultHostStatus != nil {
+ // update 'initial-cluster' when only the name is specified (e.g. 'etcd --name=abc')
+ if cfg.Name != DefaultName && cfg.InitialCluster == defaultInitialCluster {
+ cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
+ }
+ return "", defaultHostStatus
+ }
+
+ used := false
+ pip, pport := cfg.ListenPeerUrls[0].Hostname(), cfg.ListenPeerUrls[0].Port()
+ if cfg.defaultPeerHost() && pip == "0.0.0.0" {
+ cfg.AdvertisePeerUrls[0] = url.URL{Scheme: cfg.AdvertisePeerUrls[0].Scheme, Host: fmt.Sprintf("%s:%s", defaultHostname, pport)}
+ used = true
+ }
+ // update 'initial-cluster' when only the name is specified (e.g. 'etcd --name=abc')
+ if cfg.Name != DefaultName && cfg.InitialCluster == defaultInitialCluster {
+ cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
+ }
+
+ cip, cport := cfg.ListenClientUrls[0].Hostname(), cfg.ListenClientUrls[0].Port()
+ if cfg.defaultClientHost() && cip == "0.0.0.0" {
+ cfg.AdvertiseClientUrls[0] = url.URL{Scheme: cfg.AdvertiseClientUrls[0].Scheme, Host: fmt.Sprintf("%s:%s", defaultHostname, cport)}
+ used = true
+ }
+ dhost := defaultHostname
+ if !used {
+ dhost = ""
+ }
+ return dhost, defaultHostStatus
+}
+
+// checkBindURLs returns an error if any URL uses a domain name.
+func checkBindURLs(urls []url.URL) error {
+ for _, url := range urls {
+ if url.Scheme == "unix" || url.Scheme == "unixs" {
+ continue
+ }
+ host, _, err := net.SplitHostPort(url.Host)
+ if err != nil {
+ return err
+ }
+ if host == "localhost" {
+ // special case for local address
+ // TODO: support /etc/hosts ?
+ continue
+ }
+ if net.ParseIP(host) == nil {
+ return fmt.Errorf("expected IP in URL for binding (%s)", url.String())
+ }
+ }
+ return nil
+}
+
+func checkHostURLs(urls []url.URL) error {
+ for _, url := range urls {
+ host, _, err := net.SplitHostPort(url.Host)
+ if err != nil {
+ return err
+ }
+ if host == "" {
+ return fmt.Errorf("unexpected empty host (%s)", url.String())
+ }
+ }
+ return nil
+}
+
+func (cfg *Config) getAdvertisePeerUrls() (ss []string) {
+ ss = make([]string, len(cfg.AdvertisePeerUrls))
+ for i := range cfg.AdvertisePeerUrls {
+ ss[i] = cfg.AdvertisePeerUrls[i].String()
+ }
+ return ss
+}
+
+func (cfg *Config) getListenPeerUrls() (ss []string) {
+ ss = make([]string, len(cfg.ListenPeerUrls))
+ for i := range cfg.ListenPeerUrls {
+ ss[i] = cfg.ListenPeerUrls[i].String()
+ }
+ return ss
+}
+
+func (cfg *Config) getAdvertiseClientUrls() (ss []string) {
+ ss = make([]string, len(cfg.AdvertiseClientUrls))
+ for i := range cfg.AdvertiseClientUrls {
+ ss[i] = cfg.AdvertiseClientUrls[i].String()
+ }
+ return ss
+}
+
+func (cfg *Config) getListenClientUrls() (ss []string) {
+ ss = make([]string, len(cfg.ListenClientUrls))
+ for i := range cfg.ListenClientUrls {
+ ss[i] = cfg.ListenClientUrls[i].String()
+ }
+ return ss
+}
+
+func (cfg *Config) getListenClientHttpUrls() (ss []string) {
+ ss = make([]string, len(cfg.ListenClientHttpUrls))
+ for i := range cfg.ListenClientHttpUrls {
+ ss[i] = cfg.ListenClientHttpUrls[i].String()
+ }
+ return ss
+}
+
+func (cfg *Config) getMetricsURLs() (ss []string) {
+ ss = make([]string, len(cfg.ListenMetricsUrls))
+ for i := range cfg.ListenMetricsUrls {
+ ss[i] = cfg.ListenMetricsUrls[i].String()
+ }
+ return ss
+}
+
+func parseBackendFreelistType(freelistType string) bolt.FreelistType {
+ if freelistType == freelistArrayType {
+ return bolt.FreelistArrayType
+ }
+
+ return bolt.FreelistMapType
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/config_logging.go b/vendor/go.etcd.io/etcd/server/v3/embed/config_logging.go
new file mode 100644
index 0000000000..9cb6e57776
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/config_logging.go
@@ -0,0 +1,265 @@
+// 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 embed
+
+import (
+ "crypto/tls"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/url"
+ "os"
+
+ "go.etcd.io/etcd/client/pkg/v3/logutil"
+ "go.uber.org/zap"
+ "go.uber.org/zap/zapcore"
+ "go.uber.org/zap/zapgrpc"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/grpclog"
+ "gopkg.in/natefinch/lumberjack.v2"
+)
+
+// GetLogger returns the logger.
+func (cfg Config) GetLogger() *zap.Logger {
+ cfg.loggerMu.RLock()
+ l := cfg.logger
+ cfg.loggerMu.RUnlock()
+ return l
+}
+
+// setupLogging initializes etcd logging.
+// Must be called after flag parsing or finishing configuring embed.Config.
+func (cfg *Config) setupLogging() error {
+ switch cfg.Logger {
+ case "capnslog": // removed in v3.5
+ return fmt.Errorf("--logger=capnslog is removed in v3.5")
+
+ case "zap":
+ if len(cfg.LogOutputs) == 0 {
+ cfg.LogOutputs = []string{DefaultLogOutput}
+ }
+ if len(cfg.LogOutputs) > 1 {
+ for _, v := range cfg.LogOutputs {
+ if v == DefaultLogOutput {
+ return fmt.Errorf("multi logoutput for %q is not supported yet", DefaultLogOutput)
+ }
+ }
+ }
+ if cfg.EnableLogRotation {
+ if err := setupLogRotation(cfg.LogOutputs, cfg.LogRotationConfigJSON); err != nil {
+ return err
+ }
+ }
+
+ outputPaths, errOutputPaths := make([]string, 0), make([]string, 0)
+ isJournal := false
+ for _, v := range cfg.LogOutputs {
+ switch v {
+ case DefaultLogOutput:
+ outputPaths = append(outputPaths, StdErrLogOutput)
+ errOutputPaths = append(errOutputPaths, StdErrLogOutput)
+
+ case JournalLogOutput:
+ isJournal = true
+
+ case StdErrLogOutput:
+ outputPaths = append(outputPaths, StdErrLogOutput)
+ errOutputPaths = append(errOutputPaths, StdErrLogOutput)
+
+ case StdOutLogOutput:
+ outputPaths = append(outputPaths, StdOutLogOutput)
+ errOutputPaths = append(errOutputPaths, StdOutLogOutput)
+
+ default:
+ var path string
+ if cfg.EnableLogRotation {
+ // append rotate scheme to logs managed by lumberjack log rotation
+ if v[0:1] == "/" {
+ path = fmt.Sprintf("rotate:/%%2F%s", v[1:])
+ } else {
+ path = fmt.Sprintf("rotate:/%s", v)
+ }
+ } else {
+ path = v
+ }
+ outputPaths = append(outputPaths, path)
+ errOutputPaths = append(errOutputPaths, path)
+ }
+ }
+
+ if !isJournal {
+ copied := logutil.DefaultZapLoggerConfig
+ copied.OutputPaths = outputPaths
+ copied.ErrorOutputPaths = errOutputPaths
+ copied = logutil.MergeOutputPaths(copied)
+ copied.Level = zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel))
+ if cfg.ZapLoggerBuilder == nil {
+ lg, err := copied.Build()
+ if err != nil {
+ return err
+ }
+ cfg.ZapLoggerBuilder = NewZapLoggerBuilder(lg)
+ }
+ } else {
+ if len(cfg.LogOutputs) > 1 {
+ for _, v := range cfg.LogOutputs {
+ if v != DefaultLogOutput {
+ return fmt.Errorf("running with systemd/journal but other '--log-outputs' values (%q) are configured with 'default'; override 'default' value with something else", cfg.LogOutputs)
+ }
+ }
+ }
+
+ // use stderr as fallback
+ syncer, lerr := getJournalWriteSyncer()
+ if lerr != nil {
+ return lerr
+ }
+
+ lvl := zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel))
+
+ // WARN: do not change field names in encoder config
+ // journald logging writer assumes field names of "level" and "caller"
+ cr := zapcore.NewCore(
+ zapcore.NewJSONEncoder(logutil.DefaultZapLoggerConfig.EncoderConfig),
+ syncer,
+ lvl,
+ )
+ if cfg.ZapLoggerBuilder == nil {
+ cfg.ZapLoggerBuilder = NewZapLoggerBuilder(zap.New(cr, zap.AddCaller(), zap.ErrorOutput(syncer)))
+ }
+ }
+
+ err := cfg.ZapLoggerBuilder(cfg)
+ if err != nil {
+ return err
+ }
+
+ logTLSHandshakeFailure := func(conn *tls.Conn, err error) {
+ state := conn.ConnectionState()
+ remoteAddr := conn.RemoteAddr().String()
+ serverName := state.ServerName
+ if len(state.PeerCertificates) > 0 {
+ cert := state.PeerCertificates[0]
+ ips := make([]string, len(cert.IPAddresses))
+ for i := range cert.IPAddresses {
+ ips[i] = cert.IPAddresses[i].String()
+ }
+ cfg.logger.Warn(
+ "rejected connection",
+ zap.String("remote-addr", remoteAddr),
+ zap.String("server-name", serverName),
+ zap.Strings("ip-addresses", ips),
+ zap.Strings("dns-names", cert.DNSNames),
+ zap.Error(err),
+ )
+ } else {
+ cfg.logger.Warn(
+ "rejected connection",
+ zap.String("remote-addr", remoteAddr),
+ zap.String("server-name", serverName),
+ zap.Error(err),
+ )
+ }
+ }
+ cfg.ClientTLSInfo.HandshakeFailure = logTLSHandshakeFailure
+ cfg.PeerTLSInfo.HandshakeFailure = logTLSHandshakeFailure
+
+ default:
+ return fmt.Errorf("unknown logger option %q", cfg.Logger)
+ }
+
+ return nil
+}
+
+// NewZapLoggerBuilder generates a zap logger builder that sets given loger
+// for embedded etcd.
+func NewZapLoggerBuilder(lg *zap.Logger) func(*Config) error {
+ return func(cfg *Config) error {
+ cfg.loggerMu.Lock()
+ defer cfg.loggerMu.Unlock()
+ cfg.logger = lg
+ return nil
+ }
+}
+
+// NewZapCoreLoggerBuilder - is a deprecated setter for the logger.
+// Deprecated: Use simpler NewZapLoggerBuilder. To be removed in etcd-3.6.
+func NewZapCoreLoggerBuilder(lg *zap.Logger, _ zapcore.Core, _ zapcore.WriteSyncer) func(*Config) error {
+ return NewZapLoggerBuilder(lg)
+}
+
+// SetupGlobalLoggers configures 'global' loggers (grpc, zapGlobal) based on the cfg.
+//
+// The method is not executed by embed server by default (since 3.5) to
+// enable setups where grpc/zap.Global logging is configured independently
+// or spans separate lifecycle (like in tests).
+func (cfg *Config) SetupGlobalLoggers() {
+ lg := cfg.GetLogger()
+ if lg != nil {
+ if cfg.LogLevel == "debug" {
+ grpc.EnableTracing = true
+ grpclog.SetLoggerV2(zapgrpc.NewLogger(lg))
+ } else {
+ grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, os.Stderr, os.Stderr))
+ }
+ zap.ReplaceGlobals(lg)
+ }
+}
+
+type logRotationConfig struct {
+ *lumberjack.Logger
+}
+
+// Sync implements zap.Sink
+func (logRotationConfig) Sync() error { return nil }
+
+// setupLogRotation initializes log rotation for a single file path target.
+func setupLogRotation(logOutputs []string, logRotateConfigJSON string) error {
+ var logRotationConfig logRotationConfig
+ outputFilePaths := 0
+ for _, v := range logOutputs {
+ switch v {
+ case DefaultLogOutput, StdErrLogOutput, StdOutLogOutput:
+ continue
+ default:
+ outputFilePaths++
+ }
+ }
+ // log rotation requires file target
+ if len(logOutputs) == 1 && outputFilePaths == 0 {
+ return ErrLogRotationInvalidLogOutput
+ }
+ // support max 1 file target for log rotation
+ if outputFilePaths > 1 {
+ return ErrLogRotationInvalidLogOutput
+ }
+
+ if err := json.Unmarshal([]byte(logRotateConfigJSON), &logRotationConfig); err != nil {
+ var unmarshalTypeError *json.UnmarshalTypeError
+ var syntaxError *json.SyntaxError
+ switch {
+ case errors.As(err, &syntaxError):
+ return fmt.Errorf("improperly formatted log rotation config: %w", err)
+ case errors.As(err, &unmarshalTypeError):
+ return fmt.Errorf("invalid log rotation config: %w", err)
+ }
+ }
+ zap.RegisterSink("rotate", func(u *url.URL) (zap.Sink, error) {
+ logRotationConfig.Filename = u.Path[1:]
+ return &logRotationConfig, nil
+ })
+ return nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_unix.go b/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_unix.go
new file mode 100644
index 0000000000..76bb73265f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_unix.go
@@ -0,0 +1,36 @@
+// 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.
+
+//go:build !windows
+// +build !windows
+
+package embed
+
+import (
+ "fmt"
+ "os"
+
+ "go.etcd.io/etcd/client/pkg/v3/logutil"
+
+ "go.uber.org/zap/zapcore"
+)
+
+// use stderr as fallback
+func getJournalWriteSyncer() (zapcore.WriteSyncer, error) {
+ jw, err := logutil.NewJournalWriter(os.Stderr)
+ if err != nil {
+ return nil, fmt.Errorf("can't find journal (%v)", err)
+ }
+ return zapcore.AddSync(jw), nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_windows.go b/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_windows.go
new file mode 100644
index 0000000000..58ed08631b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_windows.go
@@ -0,0 +1,28 @@
+// 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.
+
+//go:build windows
+// +build windows
+
+package embed
+
+import (
+ "os"
+
+ "go.uber.org/zap/zapcore"
+)
+
+func getJournalWriteSyncer() (zapcore.WriteSyncer, error) {
+ return zapcore.AddSync(os.Stderr), nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/config_tracing.go b/vendor/go.etcd.io/etcd/server/v3/embed/config_tracing.go
new file mode 100644
index 0000000000..44c2b066ba
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/config_tracing.go
@@ -0,0 +1,92 @@
+// Copyright 2022 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 embed
+
+import (
+ "context"
+
+ "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
+ "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
+ "go.opentelemetry.io/otel/propagation"
+ "go.opentelemetry.io/otel/sdk/resource"
+ tracesdk "go.opentelemetry.io/otel/sdk/trace"
+ semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
+ "go.uber.org/zap"
+)
+
+func setupTracingExporter(ctx context.Context, cfg *Config) (exporter tracesdk.SpanExporter, options []otelgrpc.Option, err error) {
+ exporter, err = otlptracegrpc.New(ctx,
+ otlptracegrpc.WithInsecure(),
+ otlptracegrpc.WithEndpoint(cfg.ExperimentalDistributedTracingAddress),
+ )
+ if err != nil {
+ return nil, nil, err
+ }
+
+ res, err := resource.New(ctx,
+ resource.WithAttributes(
+ semconv.ServiceNameKey.String(cfg.ExperimentalDistributedTracingServiceName),
+ ),
+ )
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if resWithIDKey := determineResourceWithIDKey(cfg.ExperimentalDistributedTracingServiceInstanceID); resWithIDKey != nil {
+ // Merge resources into a new
+ // resource in case of duplicates.
+ res, err = resource.Merge(res, resWithIDKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ options = append(options,
+ otelgrpc.WithPropagators(
+ propagation.NewCompositeTextMapPropagator(
+ propagation.TraceContext{},
+ propagation.Baggage{},
+ ),
+ ),
+ otelgrpc.WithTracerProvider(
+ tracesdk.NewTracerProvider(
+ tracesdk.WithBatcher(exporter),
+ tracesdk.WithResource(res),
+ tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.NeverSample())),
+ ),
+ ),
+ )
+
+ cfg.logger.Debug(
+ "distributed tracing enabled",
+ zap.String("address", cfg.ExperimentalDistributedTracingAddress),
+ zap.String("service-name", cfg.ExperimentalDistributedTracingServiceName),
+ zap.String("service-instance-id", cfg.ExperimentalDistributedTracingServiceInstanceID),
+ )
+
+ return exporter, options, err
+}
+
+// As Tracing service Instance ID must be unique, it should
+// never use the empty default string value, it's set if
+// if it's a non empty string.
+func determineResourceWithIDKey(serviceInstanceID string) *resource.Resource {
+ if serviceInstanceID != "" {
+ return resource.NewSchemaless(
+ (semconv.ServiceInstanceIDKey.String(serviceInstanceID)),
+ )
+ }
+ return nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/doc.go b/vendor/go.etcd.io/etcd/server/v3/embed/doc.go
new file mode 100644
index 0000000000..3449855b5c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/doc.go
@@ -0,0 +1,45 @@
+// 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 embed provides bindings for embedding an etcd server in a program.
+
+Launch an embedded etcd server using the configuration defaults:
+
+ import (
+ "log"
+ "time"
+
+ "go.etcd.io/etcd/server/v3/embed"
+ )
+
+ func main() {
+ cfg := embed.NewConfig()
+ cfg.Dir = "default.etcd"
+ e, err := embed.StartEtcd(cfg)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer e.Close()
+ select {
+ case <-e.Server.ReadyNotify():
+ log.Printf("Server is ready!")
+ case <-time.After(60 * time.Second):
+ e.Server.Stop() // trigger a shutdown
+ log.Printf("Server took too long to start!")
+ }
+ log.Fatal(<-e.Err())
+ }
+*/
+package embed
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/etcd.go b/vendor/go.etcd.io/etcd/server/v3/embed/etcd.go
new file mode 100644
index 0000000000..b4f4defe54
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/etcd.go
@@ -0,0 +1,903 @@
+// 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 embed
+
+import (
+ "context"
+ "crypto/tls"
+ "fmt"
+ "io/ioutil"
+ defaultLog "log"
+ "math"
+ "net"
+ "net/http"
+ "net/url"
+ "runtime"
+ "sort"
+ "strconv"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/client/v3/credentials"
+ "go.etcd.io/etcd/pkg/v3/debugutil"
+ runtimeutil "go.etcd.io/etcd/pkg/v3/runtime"
+ "go.etcd.io/etcd/server/v3/config"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3client"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
+ "go.etcd.io/etcd/server/v3/verify"
+
+ grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
+ "github.com/soheilhy/cmux"
+ "go.uber.org/zap"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials/insecure"
+ "google.golang.org/grpc/keepalive"
+)
+
+const (
+ // internal fd usage includes disk usage and transport usage.
+ // To read/write snapshot, snap pkg needs 1. In normal case, wal pkg needs
+ // at most 2 to read/lock/write WALs. One case that it needs to 2 is to
+ // read all logs after some snapshot index, which locates at the end of
+ // the second last and the head of the last. For purging, it needs to read
+ // directory, so it needs 1. For fd monitor, it needs 1.
+ // For transport, rafthttp builds two long-polling connections and at most
+ // four temporary connections with each member. There are at most 9 members
+ // in a cluster, so it should reserve 96.
+ // For the safety, we set the total reserved number to 150.
+ reservedInternalFDNum = 150
+)
+
+// Etcd contains a running etcd server and its listeners.
+type Etcd struct {
+ Peers []*peerListener
+ Clients []net.Listener
+ // a map of contexts for the servers that serves client requests.
+ sctxs map[string]*serveCtx
+ metricsListeners []net.Listener
+
+ tracingExporterShutdown func()
+
+ Server *etcdserver.EtcdServer
+
+ cfg Config
+ stopc chan struct{}
+ errc chan error
+
+ closeOnce sync.Once
+}
+
+type peerListener struct {
+ net.Listener
+ serve func() error
+ close func(context.Context) error
+}
+
+// StartEtcd launches the etcd server and HTTP handlers for client/server communication.
+// The returned Etcd.Server is not guaranteed to have joined the cluster. Wait
+// on the Etcd.Server.ReadyNotify() channel to know when it completes and is ready for use.
+func StartEtcd(inCfg *Config) (e *Etcd, err error) {
+ if err = inCfg.Validate(); err != nil {
+ return nil, err
+ }
+ serving := false
+ e = &Etcd{cfg: *inCfg, stopc: make(chan struct{})}
+ cfg := &e.cfg
+ defer func() {
+ if e == nil || err == nil {
+ return
+ }
+ if !serving {
+ // errored before starting gRPC server for serveCtx.serversC
+ for _, sctx := range e.sctxs {
+ close(sctx.serversC)
+ }
+ }
+ e.Close()
+ e = nil
+ }()
+
+ if !cfg.SocketOpts.Empty() {
+ cfg.logger.Info(
+ "configuring socket options",
+ zap.Bool("reuse-address", cfg.SocketOpts.ReuseAddress),
+ zap.Bool("reuse-port", cfg.SocketOpts.ReusePort),
+ )
+ }
+ e.cfg.logger.Info(
+ "configuring peer listeners",
+ zap.Strings("listen-peer-urls", e.cfg.getListenPeerUrls()),
+ )
+ if e.Peers, err = configurePeerListeners(cfg); err != nil {
+ return e, err
+ }
+
+ e.cfg.logger.Info(
+ "configuring client listeners",
+ zap.Strings("listen-client-urls", e.cfg.getListenClientUrls()),
+ )
+ if e.sctxs, err = configureClientListeners(cfg); err != nil {
+ return e, err
+ }
+
+ for _, sctx := range e.sctxs {
+ e.Clients = append(e.Clients, sctx.l)
+ }
+
+ var (
+ urlsmap types.URLsMap
+ token string
+ )
+ memberInitialized := true
+ if !isMemberInitialized(cfg) {
+ memberInitialized = false
+ urlsmap, token, err = cfg.PeerURLsMapAndToken("etcd")
+ if err != nil {
+ return e, fmt.Errorf("error setting up initial cluster: %v", err)
+ }
+ }
+
+ // AutoCompactionRetention defaults to "0" if not set.
+ if len(cfg.AutoCompactionRetention) == 0 {
+ cfg.AutoCompactionRetention = "0"
+ }
+ autoCompactionRetention, err := parseCompactionRetention(cfg.AutoCompactionMode, cfg.AutoCompactionRetention)
+ if err != nil {
+ return e, err
+ }
+
+ backendFreelistType := parseBackendFreelistType(cfg.BackendFreelistType)
+
+ srvcfg := config.ServerConfig{
+ Name: cfg.Name,
+ ClientURLs: cfg.AdvertiseClientUrls,
+ PeerURLs: cfg.AdvertisePeerUrls,
+ DataDir: cfg.Dir,
+ DedicatedWALDir: cfg.WalDir,
+ SnapshotCount: cfg.SnapshotCount,
+ SnapshotCatchUpEntries: cfg.SnapshotCatchUpEntries,
+ MaxSnapFiles: cfg.MaxSnapFiles,
+ MaxWALFiles: cfg.MaxWalFiles,
+ InitialPeerURLsMap: urlsmap,
+ InitialClusterToken: token,
+ DiscoveryURL: cfg.Durl,
+ DiscoveryProxy: cfg.Dproxy,
+ NewCluster: cfg.IsNewCluster(),
+ PeerTLSInfo: cfg.PeerTLSInfo,
+ TickMs: cfg.TickMs,
+ ElectionTicks: cfg.ElectionTicks(),
+ InitialElectionTickAdvance: cfg.InitialElectionTickAdvance,
+ AutoCompactionRetention: autoCompactionRetention,
+ AutoCompactionMode: cfg.AutoCompactionMode,
+ QuotaBackendBytes: cfg.QuotaBackendBytes,
+ BackendBatchLimit: cfg.BackendBatchLimit,
+ BackendFreelistType: backendFreelistType,
+ BackendBatchInterval: cfg.BackendBatchInterval,
+ MaxTxnOps: cfg.MaxTxnOps,
+ MaxRequestBytes: cfg.MaxRequestBytes,
+ MaxConcurrentStreams: cfg.MaxConcurrentStreams,
+ SocketOpts: cfg.SocketOpts,
+ StrictReconfigCheck: cfg.StrictReconfigCheck,
+ ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth,
+ AuthToken: cfg.AuthToken,
+ BcryptCost: cfg.BcryptCost,
+ TokenTTL: cfg.AuthTokenTTL,
+ CORS: cfg.CORS,
+ HostWhitelist: cfg.HostWhitelist,
+ InitialCorruptCheck: cfg.ExperimentalInitialCorruptCheck,
+ CorruptCheckTime: cfg.ExperimentalCorruptCheckTime,
+ CompactHashCheckEnabled: cfg.ExperimentalCompactHashCheckEnabled,
+ CompactHashCheckTime: cfg.ExperimentalCompactHashCheckTime,
+ PreVote: cfg.PreVote,
+ Logger: cfg.logger,
+ ForceNewCluster: cfg.ForceNewCluster,
+ EnableGRPCGateway: cfg.EnableGRPCGateway,
+ ExperimentalEnableDistributedTracing: cfg.ExperimentalEnableDistributedTracing,
+ UnsafeNoFsync: cfg.UnsafeNoFsync,
+ EnableLeaseCheckpoint: cfg.ExperimentalEnableLeaseCheckpoint,
+ LeaseCheckpointPersist: cfg.ExperimentalEnableLeaseCheckpointPersist,
+ CompactionBatchLimit: cfg.ExperimentalCompactionBatchLimit,
+ WatchProgressNotifyInterval: cfg.ExperimentalWatchProgressNotifyInterval,
+ DowngradeCheckTime: cfg.ExperimentalDowngradeCheckTime,
+ WarningApplyDuration: cfg.ExperimentalWarningApplyDuration,
+ ExperimentalMemoryMlock: cfg.ExperimentalMemoryMlock,
+ ExperimentalTxnModeWriteWithSharedBuffer: cfg.ExperimentalTxnModeWriteWithSharedBuffer,
+ ExperimentalBootstrapDefragThresholdMegabytes: cfg.ExperimentalBootstrapDefragThresholdMegabytes,
+ V2Deprecation: cfg.V2DeprecationEffective(),
+ }
+
+ if srvcfg.ExperimentalEnableDistributedTracing {
+ tctx := context.Background()
+ tracingExporter, opts, err := setupTracingExporter(tctx, cfg)
+ if err != nil {
+ return e, err
+ }
+ if tracingExporter == nil || len(opts) == 0 {
+ return e, fmt.Errorf("error setting up distributed tracing")
+ }
+ e.tracingExporterShutdown = func() { tracingExporter.Shutdown(tctx) }
+ srvcfg.ExperimentalTracerOptions = opts
+
+ e.cfg.logger.Info("distributed tracing setup enabled")
+ }
+
+ print(e.cfg.logger, *cfg, srvcfg, memberInitialized)
+
+ if e.Server, err = etcdserver.NewServer(srvcfg); err != nil {
+ return e, err
+ }
+
+ // buffer channel so goroutines on closed connections won't wait forever
+ e.errc = make(chan error, len(e.Peers)+len(e.Clients)+2*len(e.sctxs))
+
+ // newly started member ("memberInitialized==false")
+ // does not need corruption check
+ if memberInitialized && srvcfg.InitialCorruptCheck {
+ if err = e.Server.CorruptionChecker().InitialCheck(); err != nil {
+ // set "EtcdServer" to nil, so that it does not block on "EtcdServer.Close()"
+ // (nothing to close since rafthttp transports have not been started)
+
+ e.cfg.logger.Error("checkInitialHashKV failed", zap.Error(err))
+ e.Server.Cleanup()
+ e.Server = nil
+ return e, err
+ }
+ }
+ e.Server.Start()
+
+ if err = e.servePeers(); err != nil {
+ return e, err
+ }
+ if err = e.serveClients(); err != nil {
+ return e, err
+ }
+ if err = e.serveMetrics(); err != nil {
+ return e, err
+ }
+
+ e.cfg.logger.Info(
+ "now serving peer/client/metrics",
+ zap.String("local-member-id", e.Server.ID().String()),
+ zap.Strings("initial-advertise-peer-urls", e.cfg.getAdvertisePeerUrls()),
+ zap.Strings("listen-peer-urls", e.cfg.getListenPeerUrls()),
+ zap.Strings("advertise-client-urls", e.cfg.getAdvertiseClientUrls()),
+ zap.Strings("listen-client-urls", e.cfg.getListenClientUrls()),
+ zap.Strings("listen-metrics-urls", e.cfg.getMetricsURLs()),
+ )
+ serving = true
+ return e, nil
+}
+
+func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized bool) {
+ cors := make([]string, 0, len(ec.CORS))
+ for v := range ec.CORS {
+ cors = append(cors, v)
+ }
+ sort.Strings(cors)
+
+ hss := make([]string, 0, len(ec.HostWhitelist))
+ for v := range ec.HostWhitelist {
+ hss = append(hss, v)
+ }
+ sort.Strings(hss)
+
+ quota := ec.QuotaBackendBytes
+ if quota == 0 {
+ quota = etcdserver.DefaultQuotaBytes
+ }
+
+ lg.Info(
+ "starting an etcd server",
+ zap.String("etcd-version", version.Version),
+ zap.String("git-sha", version.GitSHA),
+ zap.String("go-version", runtime.Version()),
+ zap.String("go-os", runtime.GOOS),
+ zap.String("go-arch", runtime.GOARCH),
+ zap.Int("max-cpu-set", runtime.GOMAXPROCS(0)),
+ zap.Int("max-cpu-available", runtime.NumCPU()),
+ zap.Bool("member-initialized", memberInitialized),
+ zap.String("name", sc.Name),
+ zap.String("data-dir", sc.DataDir),
+ zap.String("wal-dir", ec.WalDir),
+ zap.String("wal-dir-dedicated", sc.DedicatedWALDir),
+ zap.String("member-dir", sc.MemberDir()),
+ zap.Bool("force-new-cluster", sc.ForceNewCluster),
+ zap.String("heartbeat-interval", fmt.Sprintf("%v", time.Duration(sc.TickMs)*time.Millisecond)),
+ zap.String("election-timeout", fmt.Sprintf("%v", time.Duration(sc.ElectionTicks*int(sc.TickMs))*time.Millisecond)),
+ zap.Bool("initial-election-tick-advance", sc.InitialElectionTickAdvance),
+ zap.Uint64("snapshot-count", sc.SnapshotCount),
+ zap.Uint("max-wals", sc.MaxWALFiles),
+ zap.Uint("max-snapshots", sc.MaxSnapFiles),
+ zap.Uint64("snapshot-catchup-entries", sc.SnapshotCatchUpEntries),
+ zap.Strings("initial-advertise-peer-urls", ec.getAdvertisePeerUrls()),
+ zap.Strings("listen-peer-urls", ec.getListenPeerUrls()),
+ zap.Strings("advertise-client-urls", ec.getAdvertiseClientUrls()),
+ zap.Strings("listen-client-urls", ec.getListenClientUrls()),
+ zap.Strings("listen-metrics-urls", ec.getMetricsURLs()),
+ zap.Strings("cors", cors),
+ zap.Strings("host-whitelist", hss),
+ zap.String("initial-cluster", sc.InitialPeerURLsMap.String()),
+ zap.String("initial-cluster-state", ec.ClusterState),
+ zap.String("initial-cluster-token", sc.InitialClusterToken),
+ zap.Int64("quota-backend-bytes", quota),
+ zap.Uint("max-request-bytes", sc.MaxRequestBytes),
+ zap.Uint32("max-concurrent-streams", sc.MaxConcurrentStreams),
+
+ zap.Bool("pre-vote", sc.PreVote),
+ zap.Bool("initial-corrupt-check", sc.InitialCorruptCheck),
+ zap.String("corrupt-check-time-interval", sc.CorruptCheckTime.String()),
+ zap.Bool("compact-check-time-enabled", sc.CompactHashCheckEnabled),
+ zap.Duration("compact-check-time-interval", sc.CompactHashCheckTime),
+ zap.String("auto-compaction-mode", sc.AutoCompactionMode),
+ zap.Duration("auto-compaction-retention", sc.AutoCompactionRetention),
+ zap.String("auto-compaction-interval", sc.AutoCompactionRetention.String()),
+ zap.String("discovery-url", sc.DiscoveryURL),
+ zap.String("discovery-proxy", sc.DiscoveryProxy),
+ zap.String("downgrade-check-interval", sc.DowngradeCheckTime.String()),
+ )
+}
+
+// Config returns the current configuration.
+func (e *Etcd) Config() Config {
+ return e.cfg
+}
+
+// Close gracefully shuts down all servers/listeners.
+// Client requests will be terminated with request timeout.
+// After timeout, enforce remaning requests be closed immediately.
+func (e *Etcd) Close() {
+ fields := []zap.Field{
+ zap.String("name", e.cfg.Name),
+ zap.String("data-dir", e.cfg.Dir),
+ zap.Strings("advertise-peer-urls", e.cfg.getAdvertisePeerUrls()),
+ zap.Strings("advertise-client-urls", e.cfg.getAdvertiseClientUrls()),
+ }
+ lg := e.GetLogger()
+ lg.Info("closing etcd server", fields...)
+ defer func() {
+ lg.Info("closed etcd server", fields...)
+ verify.MustVerifyIfEnabled(verify.Config{
+ Logger: lg,
+ DataDir: e.cfg.Dir,
+ ExactIndex: false,
+ })
+ lg.Sync()
+ }()
+
+ e.closeOnce.Do(func() {
+ close(e.stopc)
+ })
+
+ // close client requests with request timeout
+ timeout := 2 * time.Second
+ if e.Server != nil {
+ timeout = e.Server.Cfg.ReqTimeout()
+ }
+ for _, sctx := range e.sctxs {
+ for ss := range sctx.serversC {
+ ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ stopServers(ctx, ss)
+ cancel()
+ }
+ }
+
+ for _, sctx := range e.sctxs {
+ sctx.cancel()
+ }
+
+ for i := range e.Clients {
+ if e.Clients[i] != nil {
+ e.Clients[i].Close()
+ }
+ }
+
+ for i := range e.metricsListeners {
+ e.metricsListeners[i].Close()
+ }
+
+ // shutdown tracing exporter
+ if e.tracingExporterShutdown != nil {
+ e.tracingExporterShutdown()
+ }
+
+ // close rafthttp transports
+ if e.Server != nil {
+ e.Server.Stop()
+ }
+
+ // close all idle connections in peer handler (wait up to 1-second)
+ for i := range e.Peers {
+ if e.Peers[i] != nil && e.Peers[i].close != nil {
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ e.Peers[i].close(ctx)
+ cancel()
+ }
+ }
+ if e.errc != nil {
+ close(e.errc)
+ }
+}
+
+func stopServers(ctx context.Context, ss *servers) {
+ // first, close the http.Server
+ if ss.http != nil {
+ ss.http.Shutdown(ctx)
+ }
+ if ss.grpc == nil {
+ return
+ }
+ // do not grpc.Server.GracefulStop when grpc runs under http server
+ // See https://github.com/grpc/grpc-go/issues/1384#issuecomment-317124531
+ // and https://github.com/etcd-io/etcd/issues/8916
+ if ss.secure && ss.http != nil {
+ ss.grpc.Stop()
+ return
+ }
+
+ ch := make(chan struct{})
+ go func() {
+ defer close(ch)
+ // close listeners to stop accepting new connections,
+ // will block on any existing transports
+ ss.grpc.GracefulStop()
+ }()
+
+ // wait until all pending RPCs are finished
+ select {
+ case <-ch:
+ case <-ctx.Done():
+ // took too long, manually close open transports
+ // e.g. watch streams
+ ss.grpc.Stop()
+
+ // concurrent GracefulStop should be interrupted
+ <-ch
+ }
+}
+
+// Err - return channel used to report errors during etcd run/shutdown.
+// Since etcd 3.5 the channel is being closed when the etcd is over.
+func (e *Etcd) Err() <-chan error {
+ return e.errc
+}
+
+func configurePeerListeners(cfg *Config) (peers []*peerListener, err error) {
+ if err = updateCipherSuites(&cfg.PeerTLSInfo, cfg.CipherSuites); err != nil {
+ return nil, err
+ }
+ if err = cfg.PeerSelfCert(); err != nil {
+ cfg.logger.Fatal("failed to get peer self-signed certs", zap.Error(err))
+ }
+
+ updateMinMaxVersions(&cfg.PeerTLSInfo, cfg.TlsMinVersion, cfg.TlsMaxVersion)
+
+ if !cfg.PeerTLSInfo.Empty() {
+ cfg.logger.Info(
+ "starting with peer TLS",
+ zap.String("tls-info", fmt.Sprintf("%+v", cfg.PeerTLSInfo)),
+ zap.Strings("cipher-suites", cfg.CipherSuites),
+ )
+ }
+
+ peers = make([]*peerListener, len(cfg.ListenPeerUrls))
+ defer func() {
+ if err == nil {
+ return
+ }
+ for i := range peers {
+ if peers[i] != nil && peers[i].close != nil {
+ cfg.logger.Warn(
+ "closing peer listener",
+ zap.String("address", cfg.ListenPeerUrls[i].String()),
+ zap.Error(err),
+ )
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ peers[i].close(ctx)
+ cancel()
+ }
+ }
+ }()
+
+ for i, u := range cfg.ListenPeerUrls {
+ if u.Scheme == "http" {
+ if !cfg.PeerTLSInfo.Empty() {
+ cfg.logger.Warn("scheme is HTTP while key and cert files are present; ignoring key and cert files", zap.String("peer-url", u.String()))
+ }
+ if cfg.PeerTLSInfo.ClientCertAuth {
+ cfg.logger.Warn("scheme is HTTP while --peer-client-cert-auth is enabled; ignoring client cert auth for this URL", zap.String("peer-url", u.String()))
+ }
+ }
+ peers[i] = &peerListener{close: func(context.Context) error { return nil }}
+ peers[i].Listener, err = transport.NewListenerWithOpts(u.Host, u.Scheme,
+ transport.WithTLSInfo(&cfg.PeerTLSInfo),
+ transport.WithSocketOpts(&cfg.SocketOpts),
+ transport.WithTimeout(rafthttp.ConnReadTimeout, rafthttp.ConnWriteTimeout),
+ )
+ if err != nil {
+ return nil, err
+ }
+ // once serve, overwrite with 'http.Server.Shutdown'
+ peers[i].close = func(context.Context) error {
+ return peers[i].Listener.Close()
+ }
+ }
+ return peers, nil
+}
+
+// configure peer handlers after rafthttp.Transport started
+func (e *Etcd) servePeers() (err error) {
+ ph := etcdhttp.NewPeerHandler(e.GetLogger(), e.Server)
+ var peerTLScfg *tls.Config
+ if !e.cfg.PeerTLSInfo.Empty() {
+ if peerTLScfg, err = e.cfg.PeerTLSInfo.ServerConfig(); err != nil {
+ return err
+ }
+ }
+
+ for _, p := range e.Peers {
+ u := p.Listener.Addr().String()
+ gs := v3rpc.Server(e.Server, peerTLScfg, nil)
+ m := cmux.New(p.Listener)
+ go gs.Serve(m.Match(cmux.HTTP2()))
+ srv := &http.Server{
+ Handler: grpcHandlerFunc(gs, ph),
+ ReadTimeout: 5 * time.Minute,
+ ErrorLog: defaultLog.New(ioutil.Discard, "", 0), // do not log user error
+ }
+ go srv.Serve(m.Match(cmux.Any()))
+ p.serve = func() error {
+ e.cfg.logger.Info(
+ "cmux::serve",
+ zap.String("address", u),
+ )
+ return m.Serve()
+ }
+ p.close = func(ctx context.Context) error {
+ // gracefully shutdown http.Server
+ // close open listeners, idle connections
+ // until context cancel or time-out
+ e.cfg.logger.Info(
+ "stopping serving peer traffic",
+ zap.String("address", u),
+ )
+ stopServers(ctx, &servers{secure: peerTLScfg != nil, grpc: gs, http: srv})
+ e.cfg.logger.Info(
+ "stopped serving peer traffic",
+ zap.String("address", u),
+ )
+ m.Close()
+ return nil
+ }
+ }
+
+ // start peer servers in a goroutine
+ for _, pl := range e.Peers {
+ go func(l *peerListener) {
+ u := l.Addr().String()
+ e.cfg.logger.Info(
+ "serving peer traffic",
+ zap.String("address", u),
+ )
+ e.errHandler(l.serve())
+ }(pl)
+ }
+ return nil
+}
+
+func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err error) {
+ if err = updateCipherSuites(&cfg.ClientTLSInfo, cfg.CipherSuites); err != nil {
+ return nil, err
+ }
+ if err = cfg.ClientSelfCert(); err != nil {
+ cfg.logger.Fatal("failed to get client self-signed certs", zap.Error(err))
+ }
+
+ updateMinMaxVersions(&cfg.ClientTLSInfo, cfg.TlsMinVersion, cfg.TlsMaxVersion)
+
+ if cfg.EnablePprof {
+ cfg.logger.Info("pprof is enabled", zap.String("path", debugutil.HTTPPrefixPProf))
+ }
+
+ sctxs = make(map[string]*serveCtx)
+ for _, u := range append(cfg.ListenClientUrls, cfg.ListenClientHttpUrls...) {
+ if u.Scheme == "http" || u.Scheme == "unix" {
+ if !cfg.ClientTLSInfo.Empty() {
+ cfg.logger.Warn("scheme is HTTP while key and cert files are present; ignoring key and cert files", zap.String("client-url", u.String()))
+ }
+ if cfg.ClientTLSInfo.ClientCertAuth {
+ cfg.logger.Warn("scheme is HTTP while --client-cert-auth is enabled; ignoring client cert auth for this URL", zap.String("client-url", u.String()))
+ }
+ }
+ if (u.Scheme == "https" || u.Scheme == "unixs") && cfg.ClientTLSInfo.Empty() {
+ return nil, fmt.Errorf("TLS key/cert (--cert-file, --key-file) must be provided for client url %s with HTTPS scheme", u.String())
+ }
+ }
+
+ for _, u := range cfg.ListenClientUrls {
+ addr, secure, network := resolveUrl(u)
+ sctx := sctxs[addr]
+ if sctx == nil {
+ sctx = newServeCtx(cfg.logger)
+ sctxs[addr] = sctx
+ }
+ sctx.secure = sctx.secure || secure
+ sctx.insecure = sctx.insecure || !secure
+ sctx.scheme = u.Scheme
+ sctx.addr = addr
+ sctx.network = network
+ }
+ for _, u := range cfg.ListenClientHttpUrls {
+ addr, secure, network := resolveUrl(u)
+
+ sctx := sctxs[addr]
+ if sctx == nil {
+ sctx = newServeCtx(cfg.logger)
+ sctxs[addr] = sctx
+ } else if !sctx.httpOnly {
+ return nil, fmt.Errorf("cannot bind both --client-listen-urls and --client-listen-http-urls on the same url %s", u.String())
+ }
+ sctx.secure = sctx.secure || secure
+ sctx.insecure = sctx.insecure || !secure
+ sctx.scheme = u.Scheme
+ sctx.addr = addr
+ sctx.network = network
+ sctx.httpOnly = true
+ }
+
+ for _, sctx := range sctxs {
+ if sctx.l, err = transport.NewListenerWithOpts(sctx.addr, sctx.scheme,
+ transport.WithSocketOpts(&cfg.SocketOpts),
+ transport.WithSkipTLSInfoCheck(true),
+ ); err != nil {
+ return nil, err
+ }
+ // net.Listener will rewrite ipv4 0.0.0.0 to ipv6 [::], breaking
+ // hosts that disable ipv6. So, use the address given by the user.
+
+ if fdLimit, fderr := runtimeutil.FDLimit(); fderr == nil {
+ if fdLimit <= reservedInternalFDNum {
+ cfg.logger.Fatal(
+ "file descriptor limit of etcd process is too low; please set higher",
+ zap.Uint64("limit", fdLimit),
+ zap.Int("recommended-limit", reservedInternalFDNum),
+ )
+ }
+ sctx.l = transport.LimitListener(sctx.l, int(fdLimit-reservedInternalFDNum))
+ }
+
+ defer func(sctx *serveCtx) {
+ if err == nil || sctx.l == nil {
+ return
+ }
+ sctx.l.Close()
+ cfg.logger.Warn(
+ "closing peer listener",
+ zap.String("address", sctx.addr),
+ zap.Error(err),
+ )
+ }(sctx)
+ for k := range cfg.UserHandlers {
+ sctx.userHandlers[k] = cfg.UserHandlers[k]
+ }
+ sctx.serviceRegister = cfg.ServiceRegister
+ if cfg.EnablePprof || cfg.LogLevel == "debug" {
+ sctx.registerPprof()
+ }
+ if cfg.LogLevel == "debug" {
+ sctx.registerTrace()
+ }
+ }
+ return sctxs, nil
+}
+
+func resolveUrl(u url.URL) (addr string, secure bool, network string) {
+ addr = u.Host
+ network = "tcp"
+ if u.Scheme == "unix" || u.Scheme == "unixs" {
+ addr = u.Host + u.Path
+ network = "unix"
+ }
+ secure = u.Scheme == "https" || u.Scheme == "unixs"
+ return addr, secure, network
+}
+
+func (e *Etcd) serveClients() (err error) {
+ if !e.cfg.ClientTLSInfo.Empty() {
+ e.cfg.logger.Info(
+ "starting with client TLS",
+ zap.String("tls-info", fmt.Sprintf("%+v", e.cfg.ClientTLSInfo)),
+ zap.Strings("cipher-suites", e.cfg.CipherSuites),
+ )
+ }
+
+ // Start a client server goroutine for each listen address
+ var h http.Handler
+ if e.Config().EnableV2 {
+ if e.Config().V2DeprecationEffective().IsAtLeast(config.V2_DEPR_1_WRITE_ONLY) {
+ return fmt.Errorf("--enable-v2 and --v2-deprecation=%s are mutually exclusive", e.Config().V2DeprecationEffective())
+ }
+ e.cfg.logger.Warn("Flag `enable-v2` is deprecated and will get removed in etcd 3.6.")
+ if len(e.Config().ExperimentalEnableV2V3) > 0 {
+ e.cfg.logger.Warn("Flag `experimental-enable-v2v3` is deprecated and will get removed in etcd 3.6.")
+ srv := v2v3.NewServer(e.cfg.logger, v3client.New(e.Server), e.cfg.ExperimentalEnableV2V3)
+ h = v2http.NewClientHandler(e.GetLogger(), srv, e.Server.Cfg.ReqTimeout())
+ } else {
+ h = v2http.NewClientHandler(e.GetLogger(), e.Server, e.Server.Cfg.ReqTimeout())
+ }
+ } else {
+ mux := http.NewServeMux()
+ etcdhttp.HandleBasic(e.cfg.logger, mux, e.Server)
+ etcdhttp.HandleMetricsHealthForV3(e.cfg.logger, mux, e.Server)
+ h = mux
+ }
+
+ gopts := []grpc.ServerOption{}
+ if e.cfg.GRPCKeepAliveMinTime > time.Duration(0) {
+ gopts = append(gopts, grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
+ MinTime: e.cfg.GRPCKeepAliveMinTime,
+ PermitWithoutStream: false,
+ }))
+ }
+ if e.cfg.GRPCKeepAliveInterval > time.Duration(0) &&
+ e.cfg.GRPCKeepAliveTimeout > time.Duration(0) {
+ gopts = append(gopts, grpc.KeepaliveParams(keepalive.ServerParameters{
+ Time: e.cfg.GRPCKeepAliveInterval,
+ Timeout: e.cfg.GRPCKeepAliveTimeout,
+ }))
+ }
+
+ splitHttp := false
+ for _, sctx := range e.sctxs {
+ if sctx.httpOnly {
+ splitHttp = true
+ }
+ }
+
+ // start client servers in each goroutine
+ for _, sctx := range e.sctxs {
+ go func(s *serveCtx) {
+ e.errHandler(s.serve(e.Server, &e.cfg.ClientTLSInfo, h, e.errHandler, e.grpcGatewayDial(splitHttp), splitHttp, gopts...))
+ }(sctx)
+ }
+ return nil
+}
+
+func (e *Etcd) grpcGatewayDial(splitHttp bool) (grpcDial func(ctx context.Context) (*grpc.ClientConn, error)) {
+ if !e.cfg.EnableGRPCGateway {
+ return nil
+ }
+ sctx := e.pickGrpcGatewayServeContext(splitHttp)
+ addr := sctx.addr
+ if network := sctx.network; network == "unix" {
+ // explicitly define unix network for gRPC socket support
+ addr = fmt.Sprintf("%s:%s", network, addr)
+ }
+
+ opts := []grpc.DialOption{grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32))}
+ if sctx.secure {
+ tlscfg, tlsErr := e.cfg.ClientTLSInfo.ServerConfig()
+ if tlsErr != nil {
+ return func(ctx context.Context) (*grpc.ClientConn, error) {
+ return nil, tlsErr
+ }
+ }
+ dtls := tlscfg.Clone()
+ // trust local server
+ dtls.InsecureSkipVerify = true
+ bundle := credentials.NewBundle(credentials.Config{TLSConfig: dtls})
+ opts = append(opts, grpc.WithTransportCredentials(bundle.TransportCredentials()))
+ } else {
+ opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
+ }
+
+ return func(ctx context.Context) (*grpc.ClientConn, error) {
+ conn, err := grpc.DialContext(ctx, addr, opts...)
+ if err != nil {
+ sctx.lg.Error("grpc gateway failed to dial", zap.String("addr", addr), zap.Error(err))
+ return nil, err
+ }
+ return conn, err
+ }
+}
+
+func (e *Etcd) pickGrpcGatewayServeContext(splitHttp bool) *serveCtx {
+ for _, sctx := range e.sctxs {
+ if !splitHttp || !sctx.httpOnly {
+ return sctx
+ }
+ }
+ panic("Expect at least one context able to serve grpc")
+}
+
+func (e *Etcd) serveMetrics() (err error) {
+ if e.cfg.Metrics == "extensive" {
+ grpc_prometheus.EnableHandlingTimeHistogram()
+ }
+
+ if len(e.cfg.ListenMetricsUrls) > 0 {
+ metricsMux := http.NewServeMux()
+ etcdhttp.HandleMetricsHealthForV3(e.cfg.logger, metricsMux, e.Server)
+
+ for _, murl := range e.cfg.ListenMetricsUrls {
+ tlsInfo := &e.cfg.ClientTLSInfo
+ if murl.Scheme == "http" {
+ tlsInfo = nil
+ }
+ ml, err := transport.NewListenerWithOpts(murl.Host, murl.Scheme,
+ transport.WithTLSInfo(tlsInfo),
+ transport.WithSocketOpts(&e.cfg.SocketOpts),
+ )
+ if err != nil {
+ return err
+ }
+ e.metricsListeners = append(e.metricsListeners, ml)
+ go func(u url.URL, ln net.Listener) {
+ e.cfg.logger.Info(
+ "serving metrics",
+ zap.String("address", u.String()),
+ )
+ e.errHandler(http.Serve(ln, metricsMux))
+ }(murl, ml)
+ }
+ }
+ return nil
+}
+
+func (e *Etcd) errHandler(err error) {
+ select {
+ case <-e.stopc:
+ return
+ default:
+ }
+ select {
+ case <-e.stopc:
+ case e.errc <- err:
+ }
+}
+
+// GetLogger returns the logger.
+func (e *Etcd) GetLogger() *zap.Logger {
+ e.cfg.loggerMu.RLock()
+ l := e.cfg.logger
+ e.cfg.loggerMu.RUnlock()
+ return l
+}
+
+func parseCompactionRetention(mode, retention string) (ret time.Duration, err error) {
+ h, err := strconv.Atoi(retention)
+ if err == nil && h >= 0 {
+ switch mode {
+ case CompactorModeRevision:
+ ret = time.Duration(int64(h))
+ case CompactorModePeriodic:
+ ret = time.Duration(int64(h)) * time.Hour
+ }
+ } else {
+ // periodic compaction
+ ret, err = time.ParseDuration(retention)
+ if err != nil {
+ return 0, fmt.Errorf("error parsing CompactionRetention: %v", err)
+ }
+ }
+ return ret, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/serve.go b/vendor/go.etcd.io/etcd/server/v3/embed/serve.go
new file mode 100644
index 0000000000..91ec6e9a37
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/serve.go
@@ -0,0 +1,499 @@
+// 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 embed
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ defaultLog "log"
+ "net"
+ "net/http"
+ "strings"
+
+ etcdservergw "go.etcd.io/etcd/api/v3/etcdserverpb/gw"
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/pkg/v3/debugutil"
+ "go.etcd.io/etcd/pkg/v3/httputil"
+ "go.etcd.io/etcd/server/v3/config"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3client"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3election"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
+ v3electiongw "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"
+ v3lockgw "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
+
+ gw "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/soheilhy/cmux"
+ "github.com/tmc/grpc-websocket-proxy/wsproxy"
+ "go.uber.org/zap"
+ "golang.org/x/net/http2"
+ "golang.org/x/net/trace"
+ "google.golang.org/grpc"
+)
+
+type serveCtx struct {
+ lg *zap.Logger
+ l net.Listener
+
+ scheme string
+ addr string
+ network string
+ secure bool
+ insecure bool
+ httpOnly bool
+
+ ctx context.Context
+ cancel context.CancelFunc
+
+ userHandlers map[string]http.Handler
+ serviceRegister func(*grpc.Server)
+ serversC chan *servers
+}
+
+type servers struct {
+ secure bool
+ grpc *grpc.Server
+ http *http.Server
+}
+
+func newServeCtx(lg *zap.Logger) *serveCtx {
+ ctx, cancel := context.WithCancel(context.Background())
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &serveCtx{
+ lg: lg,
+ ctx: ctx,
+ cancel: cancel,
+ userHandlers: make(map[string]http.Handler),
+ serversC: make(chan *servers, 2), // in case sctx.insecure,sctx.secure true
+ }
+}
+
+// serve accepts incoming connections on the listener l,
+// creating a new service goroutine for each. The service goroutines
+// read requests and then call handler to reply to them.
+func (sctx *serveCtx) serve(
+ s *etcdserver.EtcdServer,
+ tlsinfo *transport.TLSInfo,
+ handler http.Handler,
+ errHandler func(error),
+ grpcDialForRestGatewayBackends func(ctx context.Context) (*grpc.ClientConn, error),
+ splitHttp bool,
+ gopts ...grpc.ServerOption) (err error) {
+ logger := defaultLog.New(ioutil.Discard, "etcdhttp", 0)
+ <-s.ReadyNotify()
+
+ sctx.lg.Info("ready to serve client requests")
+
+ m := cmux.New(sctx.l)
+ var server func() error
+ onlyGRPC := splitHttp && !sctx.httpOnly
+ onlyHttp := splitHttp && sctx.httpOnly
+ grpcEnabled := !onlyHttp
+ httpEnabled := !onlyGRPC
+
+ v3c := v3client.New(s)
+ servElection := v3election.NewElectionServer(v3c)
+ servLock := v3lock.NewLockServer(v3c)
+
+ // Make sure serversC is closed even if we prematurely exit the function.
+ defer close(sctx.serversC)
+ var gwmux *gw.ServeMux
+ if s.Cfg.EnableGRPCGateway {
+ // GRPC gateway connects to grpc server via connection provided by grpc dial.
+ gwmux, err = sctx.registerGateway(grpcDialForRestGatewayBackends)
+ if err != nil {
+ sctx.lg.Error("registerGateway failed", zap.Error(err))
+ return err
+ }
+ }
+ var traffic string
+ switch {
+ case onlyGRPC:
+ traffic = "grpc"
+ case onlyHttp:
+ traffic = "http"
+ default:
+ traffic = "grpc+http"
+ }
+
+ if sctx.insecure {
+ var gs *grpc.Server
+ var srv *http.Server
+ if httpEnabled {
+ httpmux := sctx.createMux(gwmux, handler)
+ srv = &http.Server{
+ Handler: createAccessController(sctx.lg, s, httpmux),
+ ErrorLog: logger, // do not log user error
+ }
+ if err := configureHttpServer(srv, s.Cfg); err != nil {
+ sctx.lg.Error("Configure http server failed", zap.Error(err))
+ return err
+ }
+ }
+ if grpcEnabled {
+ gs = v3rpc.Server(s, nil, nil, gopts...)
+ v3electionpb.RegisterElectionServer(gs, servElection)
+ v3lockpb.RegisterLockServer(gs, servLock)
+ if sctx.serviceRegister != nil {
+ sctx.serviceRegister(gs)
+ }
+ defer func(gs *grpc.Server) {
+ if err != nil {
+ sctx.lg.Warn("stopping insecure grpc server due to error", zap.Error(err))
+ gs.Stop()
+ sctx.lg.Warn("stopped insecure grpc server due to error", zap.Error(err))
+ }
+ }(gs)
+ }
+ if onlyGRPC {
+ server = func() error {
+ return gs.Serve(sctx.l)
+ }
+ } else {
+ server = m.Serve
+
+ httpl := m.Match(cmux.HTTP1())
+ go func(srvhttp *http.Server, tlsLis net.Listener) {
+ errHandler(srvhttp.Serve(tlsLis))
+ }(srv, httpl)
+
+ if grpcEnabled {
+ grpcl := m.Match(cmux.HTTP2())
+ go func(gs *grpc.Server, l net.Listener) {
+ errHandler(gs.Serve(l))
+ }(gs, grpcl)
+ }
+ }
+
+ sctx.serversC <- &servers{grpc: gs, http: srv}
+ sctx.lg.Info(
+ "serving client traffic insecurely; this is strongly discouraged!",
+ zap.String("traffic", traffic),
+ zap.String("address", sctx.l.Addr().String()),
+ )
+ }
+
+ if sctx.secure {
+ var gs *grpc.Server
+ var srv *http.Server
+
+ tlscfg, tlsErr := tlsinfo.ServerConfig()
+ if tlsErr != nil {
+ return tlsErr
+ }
+
+ if grpcEnabled {
+ gs = v3rpc.Server(s, tlscfg, nil, gopts...)
+ v3electionpb.RegisterElectionServer(gs, servElection)
+ v3lockpb.RegisterLockServer(gs, servLock)
+ if sctx.serviceRegister != nil {
+ sctx.serviceRegister(gs)
+ }
+ defer func(gs *grpc.Server) {
+ if err != nil {
+ sctx.lg.Warn("stopping secure grpc server due to error", zap.Error(err))
+ gs.Stop()
+ sctx.lg.Warn("stopped secure grpc server due to error", zap.Error(err))
+ }
+ }(gs)
+ }
+ if httpEnabled {
+ if grpcEnabled {
+ handler = grpcHandlerFunc(gs, handler)
+ }
+ httpmux := sctx.createMux(gwmux, handler)
+
+ srv = &http.Server{
+ Handler: createAccessController(sctx.lg, s, httpmux),
+ TLSConfig: tlscfg,
+ ErrorLog: logger, // do not log user error
+ }
+ if err := configureHttpServer(srv, s.Cfg); err != nil {
+ sctx.lg.Error("Configure https server failed", zap.Error(err))
+ return err
+ }
+ }
+
+ if onlyGRPC {
+ server = func() error { return gs.Serve(sctx.l) }
+ } else {
+ server = m.Serve
+
+ tlsl, err := transport.NewTLSListener(m.Match(cmux.Any()), tlsinfo)
+ if err != nil {
+ return err
+ }
+ go func(srvhttp *http.Server, tlsl net.Listener) {
+ errHandler(srvhttp.Serve(tlsl))
+ }(srv, tlsl)
+ }
+
+ sctx.serversC <- &servers{secure: true, grpc: gs, http: srv}
+ sctx.lg.Info(
+ "serving client traffic securely",
+ zap.String("traffic", traffic),
+ zap.String("address", sctx.l.Addr().String()),
+ )
+ }
+
+ return server()
+}
+
+func configureHttpServer(srv *http.Server, cfg config.ServerConfig) error {
+ // todo (ahrtr): should we support configuring other parameters in the future as well?
+ return http2.ConfigureServer(srv, &http2.Server{
+ MaxConcurrentStreams: cfg.MaxConcurrentStreams,
+ })
+}
+
+// grpcHandlerFunc returns an http.Handler that delegates to grpcServer on incoming gRPC
+// connections or otherHandler otherwise. Given in gRPC docs.
+func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler {
+ if otherHandler == nil {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ grpcServer.ServeHTTP(w, r)
+ })
+ }
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
+ grpcServer.ServeHTTP(w, r)
+ } else {
+ otherHandler.ServeHTTP(w, r)
+ }
+ })
+}
+
+type registerHandlerFunc func(context.Context, *gw.ServeMux, *grpc.ClientConn) error
+
+func (sctx *serveCtx) registerGateway(dial func(ctx context.Context) (*grpc.ClientConn, error)) (*gw.ServeMux, error) {
+ ctx := sctx.ctx
+
+ conn, err := dial(ctx)
+ if err != nil {
+ return nil, err
+ }
+ gwmux := gw.NewServeMux()
+
+ handlers := []registerHandlerFunc{
+ etcdservergw.RegisterKVHandler,
+ etcdservergw.RegisterWatchHandler,
+ etcdservergw.RegisterLeaseHandler,
+ etcdservergw.RegisterClusterHandler,
+ etcdservergw.RegisterMaintenanceHandler,
+ etcdservergw.RegisterAuthHandler,
+ v3lockgw.RegisterLockHandler,
+ v3electiongw.RegisterElectionHandler,
+ }
+ for _, h := range handlers {
+ if err := h(ctx, gwmux, conn); err != nil {
+ return nil, err
+ }
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ sctx.lg.Warn(
+ "failed to close connection",
+ zap.String("address", sctx.l.Addr().String()),
+ zap.Error(cerr),
+ )
+ }
+ }()
+
+ return gwmux, nil
+}
+
+type wsProxyZapLogger struct {
+ *zap.Logger
+}
+
+func (w wsProxyZapLogger) Warnln(i ...interface{}) {
+ w.Warn(fmt.Sprint(i...))
+}
+
+func (w wsProxyZapLogger) Debugln(i ...interface{}) {
+ w.Debug(fmt.Sprint(i...))
+}
+
+func (sctx *serveCtx) createMux(gwmux *gw.ServeMux, handler http.Handler) *http.ServeMux {
+ httpmux := http.NewServeMux()
+ for path, h := range sctx.userHandlers {
+ httpmux.Handle(path, h)
+ }
+
+ if gwmux != nil {
+ httpmux.Handle(
+ "/v3/",
+ wsproxy.WebsocketProxy(
+ gwmux,
+ wsproxy.WithRequestMutator(
+ // Default to the POST method for streams
+ func(_ *http.Request, outgoing *http.Request) *http.Request {
+ outgoing.Method = "POST"
+ return outgoing
+ },
+ ),
+ wsproxy.WithMaxRespBodyBufferSize(0x7fffffff),
+ wsproxy.WithLogger(wsProxyZapLogger{sctx.lg}),
+ ),
+ )
+ }
+ if handler != nil {
+ httpmux.Handle("/", handler)
+ }
+ return httpmux
+}
+
+// createAccessController wraps HTTP multiplexer:
+// - mutate gRPC gateway request paths
+// - check hostname whitelist
+// client HTTP requests goes here first
+func createAccessController(lg *zap.Logger, s *etcdserver.EtcdServer, mux *http.ServeMux) http.Handler {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &accessController{lg: lg, s: s, mux: mux}
+}
+
+type accessController struct {
+ lg *zap.Logger
+ s *etcdserver.EtcdServer
+ mux *http.ServeMux
+}
+
+func (ac *accessController) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ if req == nil {
+ http.Error(rw, "Request is nil", http.StatusBadRequest)
+ return
+ }
+ // redirect for backward compatibilities
+ if req.URL != nil && strings.HasPrefix(req.URL.Path, "/v3beta/") {
+ req.URL.Path = strings.Replace(req.URL.Path, "/v3beta/", "/v3/", 1)
+ }
+
+ if req.TLS == nil { // check origin if client connection is not secure
+ host := httputil.GetHostname(req)
+ if !ac.s.AccessController.IsHostWhitelisted(host) {
+ ac.lg.Warn(
+ "rejecting HTTP request to prevent DNS rebinding attacks",
+ zap.String("host", host),
+ )
+ http.Error(rw, errCVE20185702(host), http.StatusMisdirectedRequest)
+ return
+ }
+ } else if ac.s.Cfg.ClientCertAuthEnabled && ac.s.Cfg.EnableGRPCGateway &&
+ ac.s.AuthStore().IsAuthEnabled() && strings.HasPrefix(req.URL.Path, "/v3/") {
+ for _, chains := range req.TLS.VerifiedChains {
+ if len(chains) < 1 {
+ continue
+ }
+ if len(chains[0].Subject.CommonName) != 0 {
+ http.Error(rw, "CommonName of client sending a request against gateway will be ignored and not used as expected", http.StatusBadRequest)
+ return
+ }
+ }
+ }
+
+ // Write CORS header.
+ if ac.s.AccessController.OriginAllowed("*") {
+ addCORSHeader(rw, "*")
+ } else if origin := req.Header.Get("Origin"); ac.s.OriginAllowed(origin) {
+ addCORSHeader(rw, origin)
+ }
+
+ if req.Method == "OPTIONS" {
+ rw.WriteHeader(http.StatusOK)
+ return
+ }
+
+ ac.mux.ServeHTTP(rw, req)
+}
+
+// addCORSHeader adds the correct cors headers given an origin
+func addCORSHeader(w http.ResponseWriter, origin string) {
+ w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
+ w.Header().Add("Access-Control-Allow-Origin", origin)
+ w.Header().Add("Access-Control-Allow-Headers", "accept, content-type, authorization")
+}
+
+// https://github.com/transmission/transmission/pull/468
+func errCVE20185702(host string) string {
+ return fmt.Sprintf(`
+etcd received your request, but the Host header was unrecognized.
+
+To fix this, choose one of the following options:
+- Enable TLS, then any HTTPS request will be allowed.
+- Add the hostname you want to use to the whitelist in settings.
+ - e.g. etcd --host-whitelist %q
+
+This requirement has been added to help prevent "DNS Rebinding" attacks (CVE-2018-5702).
+`, host)
+}
+
+// WrapCORS wraps existing handler with CORS.
+// TODO: deprecate this after v2 proxy deprecate
+func WrapCORS(cors map[string]struct{}, h http.Handler) http.Handler {
+ return &corsHandler{
+ ac: &etcdserver.AccessController{CORS: cors},
+ h: h,
+ }
+}
+
+type corsHandler struct {
+ ac *etcdserver.AccessController
+ h http.Handler
+}
+
+func (ch *corsHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ if ch.ac.OriginAllowed("*") {
+ addCORSHeader(rw, "*")
+ } else if origin := req.Header.Get("Origin"); ch.ac.OriginAllowed(origin) {
+ addCORSHeader(rw, origin)
+ }
+
+ if req.Method == "OPTIONS" {
+ rw.WriteHeader(http.StatusOK)
+ return
+ }
+
+ ch.h.ServeHTTP(rw, req)
+}
+
+func (sctx *serveCtx) registerUserHandler(s string, h http.Handler) {
+ if sctx.userHandlers[s] != nil {
+ sctx.lg.Warn("path is already registered by user handler", zap.String("path", s))
+ return
+ }
+ sctx.userHandlers[s] = h
+}
+
+func (sctx *serveCtx) registerPprof() {
+ for p, h := range debugutil.PProfHandlers() {
+ sctx.registerUserHandler(p, h)
+ }
+}
+
+func (sctx *serveCtx) registerTrace() {
+ reqf := func(w http.ResponseWriter, r *http.Request) { trace.Render(w, r, true) }
+ sctx.registerUserHandler("/debug/requests", http.HandlerFunc(reqf))
+ evf := func(w http.ResponseWriter, r *http.Request) { trace.RenderEvents(w, r, true) }
+ sctx.registerUserHandler("/debug/events", http.HandlerFunc(evf))
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/embed/util.go b/vendor/go.etcd.io/etcd/server/v3/embed/util.go
new file mode 100644
index 0000000000..ad46153455
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/embed/util.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.
+
+package embed
+
+import (
+ "path/filepath"
+
+ "go.etcd.io/etcd/server/v3/wal"
+)
+
+func isMemberInitialized(cfg *Config) bool {
+ waldir := cfg.WalDir
+ if waldir == "" {
+ waldir = filepath.Join(cfg.Dir, "member", "wal")
+ }
+ return wal.Exist(waldir)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/capability.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/capability.go
new file mode 100644
index 0000000000..ea2f0e97e4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/capability.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 api
+
+import (
+ "sync"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.uber.org/zap"
+
+ "github.com/coreos/go-semver/semver"
+)
+
+type Capability string
+
+const (
+ AuthCapability Capability = "auth"
+ V3rpcCapability Capability = "v3rpc"
+)
+
+var (
+ // 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},
+ "3.4.0": {AuthCapability: true, V3rpcCapability: true},
+ "3.5.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(lg *zap.Logger, v *semver.Version) {
+ if v == nil {
+ // if recovered but version was never set by cluster
+ return
+ }
+ enableMapMu.Lock()
+ if curVersion != nil && !membership.IsValidVersionChange(v, curVersion) {
+ enableMapMu.Unlock()
+ return
+ }
+ curVersion = v
+ enabledMap = capabilityMaps[curVersion.String()]
+ enableMapMu.Unlock()
+
+ if lg != nil {
+ lg.Info(
+ "enabled capabilities for version",
+ zap.String("cluster-version", 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/go.etcd.io/etcd/server/v3/etcdserver/api/cluster.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/cluster.go
new file mode 100644
index 0000000000..f05997da52
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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 (
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+
+ "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/go.etcd.io/etcd/server/v3/etcdserver/api/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/doc.go
new file mode 100644
index 0000000000..f44881be66
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/base.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/base.go
new file mode 100644
index 0000000000..dcfa3f0695
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/base.go
@@ -0,0 +1,156 @@
+// 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 etcdhttp
+
+import (
+ "encoding/json"
+ "expvar"
+ "fmt"
+ "net/http"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes"
+ "go.uber.org/zap"
+)
+
+const (
+ configPath = "/config"
+ varsPath = "/debug/vars"
+ versionPath = "/version"
+)
+
+// HandleBasic adds handlers to a mux for serving JSON etcd client requests
+// that do not access the v2 store.
+func HandleBasic(lg *zap.Logger, mux *http.ServeMux, server etcdserver.ServerPeer) {
+ mux.HandleFunc(varsPath, serveVars)
+ mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion))
+}
+
+func versionHandler(c api.Cluster, fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ v := c.Version()
+ if v != nil {
+ fn(w, r, v.String())
+ } else {
+ fn(w, r, "not_decided")
+ }
+ }
+}
+
+func serveVersion(w http.ResponseWriter, r *http.Request, clusterV string) {
+ if !allowMethod(w, r, "GET") {
+ return
+ }
+ vs := version.Versions{
+ Server: version.Version,
+ Cluster: clusterV,
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ b, err := json.Marshal(&vs)
+ if err != nil {
+ panic(fmt.Sprintf("cannot marshal versions to json (%v)", err))
+ }
+ w.Write(b)
+}
+
+func serveVars(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r, "GET") {
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ fmt.Fprintf(w, "{\n")
+ first := true
+ expvar.Do(func(kv expvar.KeyValue) {
+ if !first {
+ fmt.Fprintf(w, ",\n")
+ }
+ first = false
+ fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
+ })
+ fmt.Fprintf(w, "\n}\n")
+}
+
+func allowMethod(w http.ResponseWriter, r *http.Request, m string) bool {
+ if m == r.Method {
+ return true
+ }
+ w.Header().Set("Allow", m)
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return false
+}
+
+// WriteError logs and writes the given Error to the ResponseWriter
+// If Error is an etcdErr, it is rendered to the ResponseWriter
+// Otherwise, it is assumed to be a StatusInternalServerError
+func WriteError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
+ if err == nil {
+ return
+ }
+ switch e := err.(type) {
+ case *v2error.Error:
+ e.WriteTo(w)
+
+ case *httptypes.HTTPError:
+ if et := e.WriteTo(w); et != nil {
+ if lg != nil {
+ lg.Debug(
+ "failed to write v2 HTTP error",
+ zap.String("remote-addr", r.RemoteAddr),
+ zap.String("internal-server-error", e.Error()),
+ zap.Error(et),
+ )
+ }
+ }
+
+ default:
+ switch err {
+ case etcdserver.ErrTimeoutDueToLeaderFail, etcdserver.ErrTimeoutDueToConnectionLost, etcdserver.ErrNotEnoughStartedMembers,
+ etcdserver.ErrUnhealthy:
+ if lg != nil {
+ lg.Warn(
+ "v2 response error",
+ zap.String("remote-addr", r.RemoteAddr),
+ zap.String("internal-server-error", err.Error()),
+ )
+ }
+
+ default:
+ if lg != nil {
+ lg.Warn(
+ "unexpected v2 response error",
+ zap.String("remote-addr", r.RemoteAddr),
+ zap.String("internal-server-error", err.Error()),
+ )
+ }
+ }
+
+ herr := httptypes.NewHTTPError(http.StatusInternalServerError, "Internal Server Error")
+ if et := herr.WriteTo(w); et != nil {
+ if lg != nil {
+ lg.Debug(
+ "failed to write v2 HTTP error",
+ zap.String("remote-addr", r.RemoteAddr),
+ zap.String("internal-server-error", err.Error()),
+ zap.Error(et),
+ )
+ }
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/doc.go
new file mode 100644
index 0000000000..a03b626204
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/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 etcdhttp implements HTTP transportation layer for etcdserver.
+package etcdhttp
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/metrics.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/metrics.go
new file mode 100644
index 0000000000..e16955fb11
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/metrics.go
@@ -0,0 +1,211 @@
+// 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 etcdhttp
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.uber.org/zap"
+)
+
+const (
+ PathMetrics = "/metrics"
+ PathHealth = "/health"
+ PathProxyMetrics = "/proxy/metrics"
+ PathProxyHealth = "/proxy/health"
+)
+
+// HandleMetricsHealth registers metrics and health handlers.
+func HandleMetricsHealth(lg *zap.Logger, mux *http.ServeMux, srv etcdserver.ServerV2) {
+ mux.Handle(PathMetrics, promhttp.Handler())
+ mux.Handle(PathHealth, NewHealthHandler(lg, func(excludedAlarms AlarmSet, serializable bool) Health { return checkV2Health(lg, srv, excludedAlarms) }))
+}
+
+// HandleMetricsHealthForV3 registers metrics and health handlers. it checks health by using v3 range request
+// and its corresponding timeout.
+func HandleMetricsHealthForV3(lg *zap.Logger, mux *http.ServeMux, srv *etcdserver.EtcdServer) {
+ mux.Handle(PathMetrics, promhttp.Handler())
+ mux.Handle(PathHealth, NewHealthHandler(lg, func(excludedAlarms AlarmSet, serializable bool) Health {
+ return checkV3Health(lg, srv, excludedAlarms, serializable)
+ }))
+}
+
+// HandlePrometheus registers prometheus handler on '/metrics'.
+func HandlePrometheus(mux *http.ServeMux) {
+ mux.Handle(PathMetrics, promhttp.Handler())
+}
+
+// NewHealthHandler handles '/health' requests.
+func NewHealthHandler(lg *zap.Logger, hfunc func(excludedAlarms AlarmSet, serializable bool) Health) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodGet {
+ w.Header().Set("Allow", http.MethodGet)
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ lg.Warn("/health error", zap.Int("status-code", http.StatusMethodNotAllowed))
+ return
+ }
+ excludedAlarms := getExcludedAlarms(r)
+ // Passing the query parameter "serializable=true" ensures that the
+ // health of the local etcd is checked vs the health of the cluster.
+ // This is useful for probes attempting to validate the liveness of
+ // the etcd process vs readiness of the cluster to serve requests.
+ serializableFlag := getSerializableFlag(r)
+ h := hfunc(excludedAlarms, serializableFlag)
+ defer func() {
+ if h.Health == "true" {
+ healthSuccess.Inc()
+ } else {
+ healthFailed.Inc()
+ }
+ }()
+ d, _ := json.Marshal(h)
+ if h.Health != "true" {
+ http.Error(w, string(d), http.StatusServiceUnavailable)
+ lg.Warn("/health error", zap.String("output", string(d)), zap.Int("status-code", http.StatusServiceUnavailable))
+ return
+ }
+ w.WriteHeader(http.StatusOK)
+ w.Write(d)
+ lg.Debug("/health OK", zap.Int("status-code", http.StatusOK))
+ }
+}
+
+var (
+ healthSuccess = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "health_success",
+ Help: "The total number of successful health checks",
+ })
+ healthFailed = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "health_failures",
+ Help: "The total number of failed health checks",
+ })
+)
+
+func init() {
+ prometheus.MustRegister(healthSuccess)
+ prometheus.MustRegister(healthFailed)
+}
+
+// Health defines etcd server health status.
+// TODO: remove manual parsing in etcdctl cluster-health
+type Health struct {
+ Health string `json:"health"`
+ Reason string `json:"reason"`
+}
+
+type AlarmSet map[string]struct{}
+
+func getExcludedAlarms(r *http.Request) (alarms AlarmSet) {
+ alarms = make(map[string]struct{}, 2)
+ alms, found := r.URL.Query()["exclude"]
+ if found {
+ for _, alm := range alms {
+ if len(alms) == 0 {
+ continue
+ }
+ alarms[alm] = struct{}{}
+ }
+ }
+ return alarms
+}
+
+func getSerializableFlag(r *http.Request) bool {
+ return r.URL.Query().Get("serializable") == "true"
+}
+
+// TODO: etcdserver.ErrNoLeader in health API
+
+func checkHealth(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSet, serializable bool) Health {
+ h := Health{}
+ h.Health = "true"
+ as := srv.Alarms()
+ if len(as) > 0 {
+ for _, v := range as {
+ alarmName := v.Alarm.String()
+ if _, found := excludedAlarms[alarmName]; found {
+ lg.Debug("/health excluded alarm", zap.String("alarm", v.String()))
+ continue
+ }
+
+ h.Health = "false"
+ switch v.Alarm {
+ case etcdserverpb.AlarmType_NOSPACE:
+ h.Reason = "ALARM NOSPACE"
+ case etcdserverpb.AlarmType_CORRUPT:
+ h.Reason = "ALARM CORRUPT"
+ default:
+ h.Reason = "ALARM UNKNOWN"
+ }
+ lg.Warn("serving /health false due to an alarm", zap.String("alarm", v.String()))
+ return h
+ }
+ }
+
+ if !serializable && uint64(srv.Leader()) == raft.None {
+ h.Health = "false"
+ h.Reason = "RAFT NO LEADER"
+ lg.Warn("serving /health false; no leader")
+ return h
+ }
+ return h
+}
+
+func checkV2Health(lg *zap.Logger, srv etcdserver.ServerV2, excludedAlarms AlarmSet) (h Health) {
+ if h = checkHealth(lg, srv, excludedAlarms, false); h.Health != "true" {
+ return
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ _, err := srv.Do(ctx, etcdserverpb.Request{Method: "QGET"})
+ cancel()
+ if err != nil {
+ h.Health = "false"
+ h.Reason = fmt.Sprintf("QGET ERROR:%s", err)
+ lg.Warn("serving /health false; QGET fails", zap.Error(err))
+ return
+ }
+ lg.Debug("serving /health true")
+ return
+}
+
+func checkV3Health(lg *zap.Logger, srv *etcdserver.EtcdServer, excludedAlarms AlarmSet, serializable bool) (h Health) {
+ if h = checkHealth(lg, srv, excludedAlarms, serializable); h.Health != "true" {
+ return
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), srv.Cfg.ReqTimeout())
+ _, err := srv.Range(ctx, &etcdserverpb.RangeRequest{KeysOnly: true, Limit: 1, Serializable: serializable})
+ cancel()
+ if err != nil && err != auth.ErrUserEmpty && err != auth.ErrPermissionDenied {
+ h.Health = "false"
+ h.Reason = fmt.Sprintf("RANGE ERROR:%s", err)
+ lg.Warn("serving /health false; Range fails", zap.Error(err))
+ return
+ }
+ lg.Debug("serving /health true")
+ return
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/peer.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/peer.go
new file mode 100644
index 0000000000..badc98634b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/peer.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 etcdhttp
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
+ "go.etcd.io/etcd/server/v3/lease/leasehttp"
+
+ "go.uber.org/zap"
+)
+
+const (
+ peerMembersPath = "/members"
+ peerMemberPromotePrefix = "/members/promote/"
+)
+
+// NewPeerHandler generates an http.Handler to handle etcd peer requests.
+func NewPeerHandler(lg *zap.Logger, s etcdserver.ServerPeerV2) http.Handler {
+ return newPeerHandler(lg, s, s.RaftHandler(), s.LeaseHandler(), s.HashKVHandler(), s.DowngradeEnabledHandler())
+}
+
+func newPeerHandler(
+ lg *zap.Logger,
+ s etcdserver.Server,
+ raftHandler http.Handler,
+ leaseHandler http.Handler,
+ hashKVHandler http.Handler,
+ downgradeEnabledHandler http.Handler,
+) http.Handler {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ peerMembersHandler := newPeerMembersHandler(lg, s.Cluster())
+ peerMemberPromoteHandler := newPeerMemberPromoteHandler(lg, s)
+
+ mux := http.NewServeMux()
+ mux.HandleFunc("/", http.NotFound)
+ mux.Handle(rafthttp.RaftPrefix, raftHandler)
+ mux.Handle(rafthttp.RaftPrefix+"/", raftHandler)
+ mux.Handle(peerMembersPath, peerMembersHandler)
+ mux.Handle(peerMemberPromotePrefix, peerMemberPromoteHandler)
+ if leaseHandler != nil {
+ mux.Handle(leasehttp.LeasePrefix, leaseHandler)
+ mux.Handle(leasehttp.LeaseInternalPrefix, leaseHandler)
+ }
+ if downgradeEnabledHandler != nil {
+ mux.Handle(etcdserver.DowngradeEnabledPath, downgradeEnabledHandler)
+ }
+ if hashKVHandler != nil {
+ mux.Handle(etcdserver.PeerHashKVPath, hashKVHandler)
+ }
+ mux.HandleFunc(versionPath, versionHandler(s.Cluster(), serveVersion))
+ return mux
+}
+
+func newPeerMembersHandler(lg *zap.Logger, cluster api.Cluster) http.Handler {
+ return &peerMembersHandler{
+ lg: lg,
+ cluster: cluster,
+ }
+}
+
+type peerMembersHandler struct {
+ lg *zap.Logger
+ cluster api.Cluster
+}
+
+func newPeerMemberPromoteHandler(lg *zap.Logger, s etcdserver.Server) http.Handler {
+ return &peerMemberPromoteHandler{
+ lg: lg,
+ cluster: s.Cluster(),
+ server: s,
+ }
+}
+
+type peerMemberPromoteHandler struct {
+ lg *zap.Logger
+ cluster api.Cluster
+ server etcdserver.Server
+}
+
+func (h *peerMembersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r, "GET") {
+ return
+ }
+ w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
+
+ if r.URL.Path != peerMembersPath {
+ http.Error(w, "bad path", http.StatusBadRequest)
+ return
+ }
+ ms := h.cluster.Members()
+ w.Header().Set("Content-Type", "application/json")
+ if err := json.NewEncoder(w).Encode(ms); err != nil {
+ h.lg.Warn("failed to encode membership members", zap.Error(err))
+ }
+}
+
+func (h *peerMemberPromoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r, "POST") {
+ return
+ }
+ w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
+
+ if !strings.HasPrefix(r.URL.Path, peerMemberPromotePrefix) {
+ http.Error(w, "bad path", http.StatusBadRequest)
+ return
+ }
+ idStr := strings.TrimPrefix(r.URL.Path, peerMemberPromotePrefix)
+ id, err := strconv.ParseUint(idStr, 10, 64)
+ if err != nil {
+ http.Error(w, fmt.Sprintf("member %s not found in cluster", idStr), http.StatusNotFound)
+ return
+ }
+
+ resp, err := h.server.PromoteMember(r.Context(), id)
+ if err != nil {
+ switch err {
+ case membership.ErrIDNotFound:
+ http.Error(w, err.Error(), http.StatusNotFound)
+ case membership.ErrMemberNotLearner:
+ http.Error(w, err.Error(), http.StatusPreconditionFailed)
+ case etcdserver.ErrLearnerNotReady:
+ http.Error(w, err.Error(), http.StatusPreconditionFailed)
+ default:
+ WriteError(h.lg, w, r, err)
+ }
+ h.lg.Warn(
+ "failed to promote a member",
+ zap.String("member-id", types.ID(id).String()),
+ zap.Error(err),
+ )
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ if err := json.NewEncoder(w).Encode(resp); err != nil {
+ h.lg.Warn("failed to encode members response", zap.Error(err))
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/cluster.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/cluster.go
new file mode 100644
index 0000000000..e177a63029
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/cluster.go
@@ -0,0 +1,935 @@
+// 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"
+ "errors"
+ "fmt"
+ "path"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/netutil"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+
+ "github.com/coreos/go-semver/semver"
+ "github.com/prometheus/client_golang/prometheus"
+ "go.uber.org/zap"
+)
+
+const maxLearners = 1
+
+// RaftCluster is a list of Members that belong to the same raft cluster
+type RaftCluster struct {
+ lg *zap.Logger
+
+ localID types.ID
+ cid types.ID
+
+ v2store v2store.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
+
+ downgradeInfo *DowngradeInfo
+}
+
+// ConfigChangeContext represents a context for confChange.
+type ConfigChangeContext struct {
+ Member
+ // IsPromote indicates if the config change is for promoting a learner member.
+ // This flag is needed because both adding a new member and promoting a learner member
+ // uses the same config change type 'ConfChangeAddNode'.
+ IsPromote bool `json:"isPromote"`
+}
+
+type ShouldApplyV3 bool
+
+const (
+ ApplyBoth = ShouldApplyV3(true)
+ ApplyV2storeOnly = ShouldApplyV3(false)
+)
+
+// NewClusterFromURLsMap creates a new raft cluster using provided urls map. Currently, it does not support creating
+// cluster with raft learner member.
+func NewClusterFromURLsMap(lg *zap.Logger, token string, urlsmap types.URLsMap) (*RaftCluster, error) {
+ c := NewCluster(lg)
+ 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(lg *zap.Logger, id types.ID, membs []*Member) *RaftCluster {
+ c := NewCluster(lg)
+ c.cid = id
+ for _, m := range membs {
+ c.members[m.ID] = m
+ }
+ return c
+}
+
+func NewCluster(lg *zap.Logger) *RaftCluster {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &RaftCluster{
+ lg: lg,
+ members: make(map[types.ID]*Member),
+ removed: make(map[types.ID]bool),
+ downgradeInfo: &DowngradeInfo{Enabled: false},
+ }
+}
+
+func (c *RaftCluster) ID() types.ID { return c.cid }
+
+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()
+}
+
+func (c *RaftCluster) VotingMembers() []*Member {
+ c.Lock()
+ defer c.Unlock()
+ var ms MembersByID
+ for _, m := range c.members {
+ if !m.IsLearner {
+ ms = append(ms, m.Clone())
+ }
+ }
+ sort.Sort(ms)
+ return []*Member(ms)
+}
+
+// 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 {
+ c.lg.Panic("two member with same name found", zap.String("name", 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.cid)
+ 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.cid = types.ID(binary.BigEndian.Uint64(hash[:8]))
+}
+
+func (c *RaftCluster) SetID(localID, cid types.ID) {
+ c.localID = localID
+ c.cid = cid
+}
+
+func (c *RaftCluster) SetStore(st v2store.Store) { c.v2store = st }
+
+func (c *RaftCluster) SetBackend(be backend.Backend) {
+ c.be = be
+ mustCreateBackendBuckets(c.be)
+}
+
+func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) {
+ c.Lock()
+ defer c.Unlock()
+
+ if c.v2store != nil {
+ c.version = clusterVersionFromStore(c.lg, c.v2store)
+ c.members, c.removed = membersFromStore(c.lg, c.v2store)
+ } else {
+ c.version = clusterVersionFromBackend(c.lg, c.be)
+ c.members, c.removed = membersFromBackend(c.lg, c.be)
+ }
+
+ if c.be != nil {
+ c.downgradeInfo = downgradeInfoFromBackend(c.lg, c.be)
+ }
+ d := &DowngradeInfo{Enabled: false}
+ if c.downgradeInfo != nil {
+ d = &DowngradeInfo{Enabled: c.downgradeInfo.Enabled, TargetVersion: c.downgradeInfo.TargetVersion}
+ }
+ mustDetectDowngrade(c.lg, c.version, d)
+ onSet(c.lg, c.version)
+
+ for _, m := range c.members {
+ c.lg.Info(
+ "recovered/added member from store",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("recovered-remote-peer-id", m.ID.String()),
+ zap.Strings("recovered-remote-peer-urls", m.PeerURLs),
+ )
+ }
+ if c.version != nil {
+ c.lg.Info(
+ "set cluster version from store",
+ zap.String("cluster-version", 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 {
+ // TODO: this must be switched to backend as well.
+ members, removed := membersFromStore(c.lg, c.v2store)
+ id := types.ID(cc.NodeID)
+ if removed[id] {
+ return ErrIDRemoved
+ }
+ switch cc.Type {
+ case raftpb.ConfChangeAddNode, raftpb.ConfChangeAddLearnerNode:
+ confChangeContext := new(ConfigChangeContext)
+ if err := json.Unmarshal(cc.Context, confChangeContext); err != nil {
+ c.lg.Panic("failed to unmarshal confChangeContext", zap.Error(err))
+ }
+
+ if confChangeContext.IsPromote { // promoting a learner member to voting member
+ if members[id] == nil {
+ return ErrIDNotFound
+ }
+ if !members[id].IsLearner {
+ return ErrMemberNotLearner
+ }
+ } else { // adding a new member
+ if members[id] != nil {
+ return ErrIDExists
+ }
+
+ urls := make(map[string]bool)
+ for _, m := range members {
+ for _, u := range m.PeerURLs {
+ urls[u] = true
+ }
+ }
+ for _, u := range confChangeContext.Member.PeerURLs {
+ if urls[u] {
+ return ErrPeerURLexists
+ }
+ }
+
+ if confChangeContext.Member.IsLearner { // the new member is a learner
+ numLearners := 0
+ for _, m := range members {
+ if m.IsLearner {
+ numLearners++
+ }
+ }
+ if numLearners+1 > maxLearners {
+ return ErrTooManyLearners
+ }
+ }
+ }
+ 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 {
+ c.lg.Panic("failed to unmarshal member", zap.Error(err))
+ }
+ for _, u := range m.PeerURLs {
+ if urls[u] {
+ return ErrPeerURLexists
+ }
+ }
+
+ default:
+ c.lg.Panic("unknown ConfChange type", zap.String("type", cc.Type.String()))
+ }
+ 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, shouldApplyV3 ShouldApplyV3) {
+ c.Lock()
+ defer c.Unlock()
+
+ var v2Err, beErr error
+ if c.v2store != nil {
+ v2Err = unsafeSaveMemberToStore(c.lg, c.v2store, m)
+ if v2Err != nil {
+ if e, ok := v2Err.(*v2error.Error); !ok || e.ErrorCode != v2error.EcodeNodeExist {
+ c.lg.Panic(
+ "failed to save member to store",
+ zap.String("member-id", m.ID.String()),
+ zap.Error(v2Err),
+ )
+ }
+ }
+ }
+ if c.be != nil && shouldApplyV3 {
+ beErr = unsafeSaveMemberToBackend(c.lg, c.be, m)
+ if beErr != nil && !errors.Is(beErr, errMemberAlreadyExist) {
+ c.lg.Panic(
+ "failed to save member to backend",
+ zap.String("member-id", m.ID.String()),
+ zap.Error(beErr),
+ )
+ }
+ }
+ // Panic if both storeV2 and backend report member already exist.
+ if v2Err != nil && (beErr != nil || c.be == nil) {
+ c.lg.Panic(
+ "failed to save member to store",
+ zap.String("member-id", m.ID.String()),
+ zap.Error(v2Err),
+ )
+ }
+
+ c.members[m.ID] = m
+
+ c.lg.Info(
+ "added member",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("added-peer-id", m.ID.String()),
+ zap.Strings("added-peer-peer-urls", m.PeerURLs),
+ )
+}
+
+// RemoveMember removes a member from the store.
+// The given id MUST exist, or the function panics.
+func (c *RaftCluster) RemoveMember(id types.ID, shouldApplyV3 ShouldApplyV3) {
+ c.Lock()
+ defer c.Unlock()
+ var v2Err, beErr error
+ if c.v2store != nil {
+ v2Err = unsafeDeleteMemberFromStore(c.v2store, id)
+ if v2Err != nil {
+ if e, ok := v2Err.(*v2error.Error); !ok || e.ErrorCode != v2error.EcodeKeyNotFound {
+ c.lg.Panic(
+ "failed to delete member from store",
+ zap.String("member-id", id.String()),
+ zap.Error(v2Err),
+ )
+ }
+ }
+ }
+ if c.be != nil && shouldApplyV3 {
+ beErr = unsafeDeleteMemberFromBackend(c.be, id)
+ if beErr != nil && !errors.Is(beErr, errMemberNotFound) {
+ c.lg.Panic(
+ "failed to delete member from backend",
+ zap.String("member-id", id.String()),
+ zap.Error(beErr),
+ )
+ }
+ }
+ // Panic if both storeV2 and backend report member not found.
+ if v2Err != nil && (beErr != nil || c.be == nil) {
+ c.lg.Panic(
+ "failed to delete member from store",
+ zap.String("member-id", id.String()),
+ zap.Error(v2Err),
+ )
+ }
+
+ m, ok := c.members[id]
+ delete(c.members, id)
+ c.removed[id] = true
+
+ if ok {
+ c.lg.Info(
+ "removed member",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("removed-remote-peer-id", id.String()),
+ zap.Strings("removed-remote-peer-urls", m.PeerURLs),
+ )
+ } else {
+ c.lg.Warn(
+ "skipped removing already removed member",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("removed-remote-peer-id", id.String()),
+ )
+ }
+}
+
+func (c *RaftCluster) UpdateAttributes(id types.ID, attr Attributes, shouldApplyV3 ShouldApplyV3) {
+ c.Lock()
+ defer c.Unlock()
+
+ if m, ok := c.members[id]; ok {
+ m.Attributes = attr
+ if c.v2store != nil {
+ mustUpdateMemberAttrInStore(c.lg, c.v2store, m)
+ }
+ if c.be != nil && shouldApplyV3 {
+ unsafeSaveMemberToBackend(c.lg, c.be, m)
+ }
+ return
+ }
+
+ _, ok := c.removed[id]
+ if !ok {
+ c.lg.Panic(
+ "failed to update; member unknown",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("unknown-remote-peer-id", id.String()),
+ )
+ }
+
+ c.lg.Warn(
+ "skipped attributes update of removed member",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("updated-peer-id", id.String()),
+ )
+}
+
+// PromoteMember marks the member's IsLearner RaftAttributes to false.
+func (c *RaftCluster) PromoteMember(id types.ID, shouldApplyV3 ShouldApplyV3) {
+ c.Lock()
+ defer c.Unlock()
+
+ c.members[id].RaftAttributes.IsLearner = false
+ if c.v2store != nil {
+ mustUpdateMemberInStore(c.lg, c.v2store, c.members[id])
+ }
+ if c.be != nil && shouldApplyV3 {
+ unsafeSaveMemberToBackend(c.lg, c.be, c.members[id])
+ }
+
+ c.lg.Info(
+ "promote member",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ )
+}
+
+func (c *RaftCluster) UpdateRaftAttributes(id types.ID, raftAttr RaftAttributes, shouldApplyV3 ShouldApplyV3) {
+ c.Lock()
+ defer c.Unlock()
+
+ c.members[id].RaftAttributes = raftAttr
+ if c.v2store != nil {
+ mustUpdateMemberInStore(c.lg, c.v2store, c.members[id])
+ }
+ if c.be != nil && shouldApplyV3 {
+ unsafeSaveMemberToBackend(c.lg, c.be, c.members[id])
+ }
+
+ c.lg.Info(
+ "updated member",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("updated-remote-peer-id", id.String()),
+ zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs),
+ )
+}
+
+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(*zap.Logger, *semver.Version), shouldApplyV3 ShouldApplyV3) {
+ c.Lock()
+ defer c.Unlock()
+ if c.version != nil {
+ c.lg.Info(
+ "updated cluster version",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("from", version.Cluster(c.version.String())),
+ zap.String("to", version.Cluster(ver.String())),
+ )
+ } else {
+ c.lg.Info(
+ "set initial cluster version",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ zap.String("cluster-version", version.Cluster(ver.String())),
+ )
+ }
+ oldVer := c.version
+ c.version = ver
+ mustDetectDowngrade(c.lg, c.version, c.downgradeInfo)
+ if c.v2store != nil {
+ mustSaveClusterVersionToStore(c.lg, c.v2store, ver)
+ }
+ if c.be != nil && shouldApplyV3 {
+ mustSaveClusterVersionToBackend(c.be, ver)
+ }
+ if oldVer != nil {
+ ClusterVersionMetrics.With(prometheus.Labels{"cluster_version": version.Cluster(oldVer.String())}).Set(0)
+ }
+ ClusterVersionMetrics.With(prometheus.Labels{"cluster_version": version.Cluster(ver.String())}).Set(1)
+ onSet(c.lg, ver)
+}
+
+func (c *RaftCluster) IsReadyToAddVotingMember() bool {
+ nmembers := 1
+ nstarted := 0
+
+ for _, member := range c.VotingMembers() {
+ 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/etcd-io/website/blob/main/content/docs/v2/admin_guide.md#restoring-the-cluster
+ c.lg.Debug("number of started member is 1; can accept add member request")
+ return true
+ }
+
+ nquorum := nmembers/2 + 1
+ if nstarted < nquorum {
+ c.lg.Warn(
+ "rejecting member add; started member will be less than quorum",
+ zap.Int("number-of-started-member", nstarted),
+ zap.Int("quorum", nquorum),
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ )
+ return false
+ }
+
+ return true
+}
+
+func (c *RaftCluster) IsReadyToRemoveVotingMember(id uint64) bool {
+ nmembers := 0
+ nstarted := 0
+
+ for _, member := range c.VotingMembers() {
+ if uint64(member.ID) == id {
+ continue
+ }
+
+ if member.IsStarted() {
+ nstarted++
+ }
+ nmembers++
+ }
+
+ nquorum := nmembers/2 + 1
+ if nstarted < nquorum {
+ c.lg.Warn(
+ "rejecting member remove; started member will be less than quorum",
+ zap.Int("number-of-started-member", nstarted),
+ zap.Int("quorum", nquorum),
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ )
+ return false
+ }
+
+ return true
+}
+
+func (c *RaftCluster) IsReadyToPromoteMember(id uint64) bool {
+ nmembers := 1 // We count the learner to be promoted for the future quorum
+ nstarted := 1 // and we also count it as started.
+
+ for _, member := range c.VotingMembers() {
+ if member.IsStarted() {
+ nstarted++
+ }
+ nmembers++
+ }
+
+ nquorum := nmembers/2 + 1
+ if nstarted < nquorum {
+ c.lg.Warn(
+ "rejecting member promote; started member will be less than quorum",
+ zap.Int("number-of-started-member", nstarted),
+ zap.Int("quorum", nquorum),
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ )
+ return false
+ }
+
+ return true
+}
+
+func membersFromStore(lg *zap.Logger, st v2store.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
+ }
+ lg.Panic("failed to get members from store", zap.String("path", StoreMembersPrefix), zap.Error(err))
+ }
+ for _, n := range e.Node.Nodes {
+ var m *Member
+ m, err = nodeToMember(lg, n)
+ if err != nil {
+ lg.Panic("failed to nodeToMember", zap.Error(err))
+ }
+ members[m.ID] = m
+ }
+
+ e, err = st.Get(storeRemovedMembersPrefix, true, true)
+ if err != nil {
+ if isKeyNotFound(err) {
+ return members, removed
+ }
+ lg.Panic(
+ "failed to get removed members from store",
+ zap.String("path", storeRemovedMembersPrefix),
+ zap.Error(err),
+ )
+ }
+ for _, n := range e.Node.Nodes {
+ removed[MustParseMemberIDFromKey(lg, n.Key)] = true
+ }
+ return members, removed
+}
+
+func membersFromBackend(lg *zap.Logger, be backend.Backend) (map[types.ID]*Member, map[types.ID]bool) {
+ return mustReadMembersFromBackend(lg, be)
+}
+
+func clusterVersionFromStore(lg *zap.Logger, st v2store.Store) *semver.Version {
+ e, err := st.Get(path.Join(storePrefix, "version"), false, false)
+ if err != nil {
+ if isKeyNotFound(err) {
+ return nil
+ }
+ lg.Panic(
+ "failed to get cluster version from store",
+ zap.String("path", path.Join(storePrefix, "version")),
+ zap.Error(err),
+ )
+ }
+ return semver.Must(semver.NewVersion(*e.Node.Value))
+}
+
+// The field is populated since etcd v3.5.
+func clusterVersionFromBackend(lg *zap.Logger, be backend.Backend) *semver.Version {
+ ckey := backendClusterVersionKey()
+ tx := be.ReadTx()
+ tx.RLock()
+ defer tx.RUnlock()
+ keys, vals := tx.UnsafeRange(buckets.Cluster, ckey, nil, 0)
+ if len(keys) == 0 {
+ return nil
+ }
+ if len(keys) != 1 {
+ lg.Panic(
+ "unexpected number of keys when getting cluster version from backend",
+ zap.Int("number-of-key", len(keys)),
+ )
+ }
+ return semver.Must(semver.NewVersion(string(vals[0])))
+}
+
+// The field is populated since etcd v3.5.
+func downgradeInfoFromBackend(lg *zap.Logger, be backend.Backend) *DowngradeInfo {
+ dkey := backendDowngradeKey()
+ tx := be.ReadTx()
+ tx.Lock()
+ defer tx.Unlock()
+ keys, vals := tx.UnsafeRange(buckets.Cluster, dkey, nil, 0)
+ if len(keys) == 0 {
+ return nil
+ }
+
+ if len(keys) != 1 {
+ lg.Panic(
+ "unexpected number of keys when getting cluster version from backend",
+ zap.Int("number-of-key", len(keys)),
+ )
+ }
+ var d DowngradeInfo
+ if err := json.Unmarshal(vals[0], &d); err != nil {
+ lg.Panic("failed to unmarshal downgrade information", zap.Error(err))
+ }
+
+ // verify the downgrade info from backend
+ if d.Enabled {
+ if _, err := semver.NewVersion(d.TargetVersion); err != nil {
+ lg.Panic(
+ "unexpected version format of the downgrade target version from backend",
+ zap.String("target-version", d.TargetVersion),
+ )
+ }
+ }
+ return &d
+}
+
+// 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(lg *zap.Logger, local *RaftCluster, existing *RaftCluster) error {
+ ems := existing.Members()
+ lms := local.Members()
+ if len(ems) != len(lms) {
+ return fmt.Errorf("member count is unequal")
+ }
+
+ ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
+ defer cancel()
+ for i := range ems {
+ var err error
+ ok := false
+ for j := range lms {
+ if ok, err = netutil.URLStringsEqual(ctx, lg, ems[i].PeerURLs, lms[j].PeerURLs); ok {
+ lms[j].ID = ems[i].ID
+ break
+ }
+ }
+ if !ok {
+ return fmt.Errorf("PeerURLs: no match found for existing member (%v, %v), last resolver error (%v)", ems[i].ID, ems[i].PeerURLs, err)
+ }
+ }
+ local.members = make(map[types.ID]*Member)
+ for _, m := range lms {
+ local.members[m.ID] = m
+ }
+ return nil
+}
+
+// IsValidVersionChange checks the two scenario when version is valid to change:
+// 1. Downgrade: cluster version is 1 minor version higher than local version,
+// cluster version should change.
+// 2. Cluster start: when not all members version are available, cluster version
+// is set to MinVersion(3.0), when all members are at higher version, cluster version
+// is lower than local version, cluster version should change
+func IsValidVersionChange(cv *semver.Version, lv *semver.Version) bool {
+ cv = &semver.Version{Major: cv.Major, Minor: cv.Minor}
+ lv = &semver.Version{Major: lv.Major, Minor: lv.Minor}
+
+ if isValidDowngrade(cv, lv) || (cv.Major == lv.Major && cv.LessThan(*lv)) {
+ return true
+ }
+ return false
+}
+
+// IsLocalMemberLearner returns if the local member is raft learner
+func (c *RaftCluster) IsLocalMemberLearner() bool {
+ c.Lock()
+ defer c.Unlock()
+ localMember, ok := c.members[c.localID]
+ if !ok {
+ c.lg.Panic(
+ "failed to find local ID in cluster members",
+ zap.String("cluster-id", c.cid.String()),
+ zap.String("local-member-id", c.localID.String()),
+ )
+ }
+ return localMember.IsLearner
+}
+
+// DowngradeInfo returns the downgrade status of the cluster
+func (c *RaftCluster) DowngradeInfo() *DowngradeInfo {
+ c.Lock()
+ defer c.Unlock()
+ if c.downgradeInfo == nil {
+ return &DowngradeInfo{Enabled: false}
+ }
+ d := &DowngradeInfo{Enabled: c.downgradeInfo.Enabled, TargetVersion: c.downgradeInfo.TargetVersion}
+ return d
+}
+
+func (c *RaftCluster) SetDowngradeInfo(d *DowngradeInfo, shouldApplyV3 ShouldApplyV3) {
+ c.Lock()
+ defer c.Unlock()
+
+ if c.be != nil && shouldApplyV3 {
+ mustSaveDowngradeToBackend(c.lg, c.be, d)
+ }
+
+ c.downgradeInfo = d
+
+ if d.Enabled {
+ c.lg.Info(
+ "The server is ready to downgrade",
+ zap.String("target-version", d.TargetVersion),
+ zap.String("server-version", version.Version),
+ )
+ }
+}
+
+// IsMemberExist returns if the member with the given id exists in cluster.
+func (c *RaftCluster) IsMemberExist(id types.ID) bool {
+ c.Lock()
+ defer c.Unlock()
+ _, ok := c.members[id]
+ return ok
+}
+
+// VotingMemberIDs returns the ID of voting members in cluster.
+func (c *RaftCluster) VotingMemberIDs() []types.ID {
+ c.Lock()
+ defer c.Unlock()
+ var ids []types.ID
+ for _, m := range c.members {
+ if !m.IsLearner {
+ ids = append(ids, m.ID)
+ }
+ }
+ sort.Sort(types.IDSlice(ids))
+ return ids
+}
+
+// PushMembershipToStorage is overriding storage information about cluster's
+// members, such that they fully reflect internal RaftCluster's storage.
+func (c *RaftCluster) PushMembershipToStorage() {
+ if c.be != nil {
+ TrimMembershipFromBackend(c.lg, c.be)
+ for _, m := range c.members {
+ unsafeSaveMemberToBackend(c.lg, c.be, m)
+ }
+ }
+ if c.v2store != nil {
+ TrimMembershipFromV2Store(c.lg, c.v2store)
+ for _, m := range c.members {
+ mustSaveMemberToStore(c.lg, c.v2store, m)
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/confstate.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/confstate.go
new file mode 100644
index 0000000000..3aa8c649b2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/confstate.go
@@ -0,0 +1,63 @@
+// Copyright 2021 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"
+ "log"
+
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+ "go.uber.org/zap"
+)
+
+var (
+ confStateKey = []byte("confState")
+)
+
+// MustUnsafeSaveConfStateToBackend persists confState using given transaction (tx).
+// confState in backend is persisted since etcd v3.5.
+func MustUnsafeSaveConfStateToBackend(lg *zap.Logger, tx backend.BatchTx, confState *raftpb.ConfState) {
+ confStateBytes, err := json.Marshal(confState)
+ if err != nil {
+ lg.Panic("Cannot marshal raftpb.ConfState", zap.Stringer("conf-state", confState), zap.Error(err))
+ }
+
+ tx.UnsafePut(buckets.Meta, confStateKey, confStateBytes)
+}
+
+// UnsafeConfStateFromBackend retrieves ConfState from the backend.
+// Returns nil if confState in backend is not persisted (e.g. backend writen by 0 {
+ return false, nil
+ }
+ }
+
+ return true, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/coder.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/coder.go
new file mode 100644
index 0000000000..cc28249697
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/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 "go.etcd.io/etcd/raft/v3/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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/doc.go
new file mode 100644
index 0000000000..a9486a8bb6
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/http.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/http.go
new file mode 100644
index 0000000000..f60383f479
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/http.go
@@ -0,0 +1,531 @@
+// 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"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ pioutil "go.etcd.io/etcd/pkg/v3/ioutil"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+
+ humanize "github.com/dustin/go-humanize"
+ "go.uber.org/zap"
+)
+
+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
+
+ // snapshotLimitByte limits the snapshot size to 1TB
+ snapshotLimitByte = 1 * 1024 * 1024 * 1024 * 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 {
+ lg *zap.Logger
+ localID types.ID
+ 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(t *Transport, r Raft, cid types.ID) http.Handler {
+ h := &pipelineHandler{
+ lg: t.Logger,
+ localID: t.ID,
+ tr: t,
+ r: r,
+ cid: cid,
+ }
+ if h.lg == nil {
+ h.lg = zap.NewNop()
+ }
+ return h
+}
+
+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(h.lg, h.localID, 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 {
+ h.lg.Warn(
+ "failed to read Raft message",
+ zap.String("local-member-id", h.localID.String()),
+ zap.Error(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 {
+ h.lg.Warn(
+ "failed to unmarshal Raft message",
+ zap.String("local-member-id", h.localID.String()),
+ zap.Error(err),
+ )
+ http.Error(w, "error unmarshalling 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:
+ h.lg.Warn(
+ "failed to process Raft message",
+ zap.String("local-member-id", h.localID.String()),
+ zap.Error(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 {
+ lg *zap.Logger
+ tr Transporter
+ r Raft
+ snapshotter *snap.Snapshotter
+
+ localID types.ID
+ cid types.ID
+}
+
+func newSnapshotHandler(t *Transport, r Raft, snapshotter *snap.Snapshotter, cid types.ID) http.Handler {
+ h := &snapshotHandler{
+ lg: t.Logger,
+ tr: t,
+ r: r,
+ snapshotter: snapshotter,
+ localID: t.ID,
+ cid: cid,
+ }
+ if h.lg == nil {
+ h.lg = zap.NewNop()
+ }
+ return h
+}
+
+const unknownSnapshotSender = "UNKNOWN_SNAPSHOT_SENDER"
+
+// 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) {
+ start := time.Now()
+
+ if r.Method != "POST" {
+ w.Header().Set("Allow", "POST")
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc()
+ return
+ }
+
+ w.Header().Set("X-Etcd-Cluster-ID", h.cid.String())
+
+ if err := checkClusterCompatibilityFromHeader(h.lg, h.localID, r.Header, h.cid); err != nil {
+ http.Error(w, err.Error(), http.StatusPreconditionFailed)
+ snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc()
+ 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(snapshotLimitByte)
+ from := types.ID(m.From).String()
+ if err != nil {
+ msg := fmt.Sprintf("failed to decode raft message (%v)", err)
+ h.lg.Warn(
+ "failed to decode Raft message",
+ zap.String("local-member-id", h.localID.String()),
+ zap.String("remote-snapshot-sender-id", from),
+ zap.Error(err),
+ )
+ http.Error(w, msg, http.StatusBadRequest)
+ recvFailures.WithLabelValues(r.RemoteAddr).Inc()
+ snapshotReceiveFailures.WithLabelValues(from).Inc()
+ return
+ }
+
+ msgSize := m.Size()
+ receivedBytes.WithLabelValues(from).Add(float64(msgSize))
+
+ if m.Type != raftpb.MsgSnap {
+ h.lg.Warn(
+ "unexpected Raft message type",
+ zap.String("local-member-id", h.localID.String()),
+ zap.String("remote-snapshot-sender-id", from),
+ zap.String("message-type", m.Type.String()),
+ )
+ http.Error(w, "wrong raft message type", http.StatusBadRequest)
+ snapshotReceiveFailures.WithLabelValues(from).Inc()
+ return
+ }
+
+ snapshotReceiveInflights.WithLabelValues(from).Inc()
+ defer func() {
+ snapshotReceiveInflights.WithLabelValues(from).Dec()
+ }()
+
+ h.lg.Info(
+ "receiving database snapshot",
+ zap.String("local-member-id", h.localID.String()),
+ zap.String("remote-snapshot-sender-id", from),
+ zap.Uint64("incoming-snapshot-index", m.Snapshot.Metadata.Index),
+ zap.Int("incoming-snapshot-message-size-bytes", msgSize),
+ zap.String("incoming-snapshot-message-size", humanize.Bytes(uint64(msgSize))),
+ )
+
+ // 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)
+ h.lg.Warn(
+ "failed to save incoming database snapshot",
+ zap.String("local-member-id", h.localID.String()),
+ zap.String("remote-snapshot-sender-id", from),
+ zap.Uint64("incoming-snapshot-index", m.Snapshot.Metadata.Index),
+ zap.Error(err),
+ )
+ http.Error(w, msg, http.StatusInternalServerError)
+ snapshotReceiveFailures.WithLabelValues(from).Inc()
+ return
+ }
+
+ receivedBytes.WithLabelValues(from).Add(float64(n))
+
+ downloadTook := time.Since(start)
+ h.lg.Info(
+ "received and saved database snapshot",
+ zap.String("local-member-id", h.localID.String()),
+ zap.String("remote-snapshot-sender-id", from),
+ zap.Uint64("incoming-snapshot-index", m.Snapshot.Metadata.Index),
+ zap.Int64("incoming-snapshot-size-bytes", n),
+ zap.String("incoming-snapshot-size", humanize.Bytes(uint64(n))),
+ zap.String("download-took", downloadTook.String()),
+ )
+
+ 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)
+ h.lg.Warn(
+ "failed to process Raft message",
+ zap.String("local-member-id", h.localID.String()),
+ zap.String("remote-snapshot-sender-id", from),
+ zap.Error(err),
+ )
+ http.Error(w, msg, http.StatusInternalServerError)
+ snapshotReceiveFailures.WithLabelValues(from).Inc()
+ }
+ return
+ }
+
+ // Write StatusNoContent header after the message has been processed by
+ // raft, which facilitates the client to report MsgSnap status.
+ w.WriteHeader(http.StatusNoContent)
+
+ snapshotReceive.WithLabelValues(from).Inc()
+ snapshotReceiveSeconds.WithLabelValues(from).Observe(time.Since(start).Seconds())
+}
+
+type streamHandler struct {
+ lg *zap.Logger
+ tr *Transport
+ peerGetter peerGetter
+ r Raft
+ id types.ID
+ cid types.ID
+}
+
+func newStreamHandler(t *Transport, pg peerGetter, r Raft, id, cid types.ID) http.Handler {
+ h := &streamHandler{
+ lg: t.Logger,
+ tr: t,
+ peerGetter: pg,
+ r: r,
+ id: id,
+ cid: cid,
+ }
+ if h.lg == nil {
+ h.lg = zap.NewNop()
+ }
+ return h
+}
+
+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(h.lg, h.tr.ID, 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(h.lg):
+ t = streamTypeMsgAppV2
+ case streamTypeMessage.endpoint(h.lg):
+ t = streamTypeMessage
+ default:
+ h.lg.Debug(
+ "ignored unexpected streaming request path",
+ zap.String("local-member-id", h.tr.ID.String()),
+ zap.String("remote-peer-id-stream-handler", h.id.String()),
+ zap.String("path", 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 {
+ h.lg.Warn(
+ "failed to parse path into ID",
+ zap.String("local-member-id", h.tr.ID.String()),
+ zap.String("remote-peer-id-stream-handler", h.id.String()),
+ zap.String("path", fromStr),
+ zap.Error(err),
+ )
+ http.Error(w, "invalid from", http.StatusNotFound)
+ return
+ }
+ if h.r.IsIDRemoved(uint64(from)) {
+ h.lg.Warn(
+ "rejected stream from remote peer because it was removed",
+ zap.String("local-member-id", h.tr.ID.String()),
+ zap.String("remote-peer-id-stream-handler", h.id.String()),
+ zap.String("remote-peer-id-from", from.String()),
+ )
+ 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, ","))
+ }
+ h.lg.Warn(
+ "failed to find remote peer in cluster",
+ zap.String("local-member-id", h.tr.ID.String()),
+ zap.String("remote-peer-id-stream-handler", h.id.String()),
+ zap.String("remote-peer-id-from", from.String()),
+ zap.String("cluster-id", h.cid.String()),
+ )
+ http.Error(w, "error sender not found", http.StatusNotFound)
+ return
+ }
+
+ wto := h.id.String()
+ if gto := r.Header.Get("X-Raft-To"); gto != wto {
+ h.lg.Warn(
+ "ignored streaming request; ID mismatch",
+ zap.String("local-member-id", h.tr.ID.String()),
+ zap.String("remote-peer-id-stream-handler", h.id.String()),
+ zap.String("remote-peer-id-header", gto),
+ zap.String("remote-peer-id-from", from.String()),
+ zap.String("cluster-id", h.cid.String()),
+ )
+ 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,
+ localID: h.tr.ID,
+ peerID: from,
+ }
+ 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(lg *zap.Logger, localID types.ID, header http.Header, cid types.ID) error {
+ remoteName := header.Get("X-Server-From")
+
+ remoteServer := serverVersion(header)
+ remoteVs := ""
+ if remoteServer != nil {
+ remoteVs = remoteServer.String()
+ }
+
+ remoteMinClusterVer := minClusterVersion(header)
+ remoteMinClusterVs := ""
+ if remoteMinClusterVer != nil {
+ remoteMinClusterVs = remoteMinClusterVer.String()
+ }
+
+ localServer, localMinCluster, err := checkVersionCompatibility(remoteName, remoteServer, remoteMinClusterVer)
+
+ localVs := ""
+ if localServer != nil {
+ localVs = localServer.String()
+ }
+ localMinClusterVs := ""
+ if localMinCluster != nil {
+ localMinClusterVs = localMinCluster.String()
+ }
+
+ if err != nil {
+ lg.Warn(
+ "failed to check version compatibility",
+ zap.String("local-member-id", localID.String()),
+ zap.String("local-member-cluster-id", cid.String()),
+ zap.String("local-member-server-version", localVs),
+ zap.String("local-member-server-minimum-cluster-version", localMinClusterVs),
+ zap.String("remote-peer-server-name", remoteName),
+ zap.String("remote-peer-server-version", remoteVs),
+ zap.String("remote-peer-server-minimum-cluster-version", remoteMinClusterVs),
+ zap.Error(err),
+ )
+ return errIncompatibleVersion
+ }
+ if gcid := header.Get("X-Etcd-Cluster-ID"); gcid != cid.String() {
+ lg.Warn(
+ "request cluster ID mismatch",
+ zap.String("local-member-id", localID.String()),
+ zap.String("local-member-cluster-id", cid.String()),
+ zap.String("local-member-server-version", localVs),
+ zap.String("local-member-server-minimum-cluster-version", localMinClusterVs),
+ zap.String("remote-peer-server-name", remoteName),
+ zap.String("remote-peer-server-version", remoteVs),
+ zap.String("remote-peer-server-minimum-cluster-version", remoteMinClusterVs),
+ zap.String("remote-peer-cluster-id", gcid),
+ )
+ 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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/metrics.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/metrics.go
new file mode 100644
index 0000000000..02fff84be7
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/metrics.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 "github.com/prometheus/client_golang/prometheus"
+
+var (
+ activePeers = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "active_peers",
+ Help: "The current number of active peer connections.",
+ },
+ []string{"Local", "Remote"},
+ )
+
+ disconnectedPeers = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "disconnected_peers_total",
+ Help: "The total number of disconnected peers.",
+ },
+ []string{"Local", "Remote"},
+ )
+
+ 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"},
+ )
+
+ snapshotSend = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_send_success",
+ Help: "Total number of successful snapshot sends",
+ },
+ []string{"To"},
+ )
+
+ snapshotSendInflights = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_send_inflights_total",
+ Help: "Total number of inflight snapshot sends",
+ },
+ []string{"To"},
+ )
+
+ snapshotSendFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_send_failures",
+ Help: "Total number of snapshot send failures",
+ },
+ []string{"To"},
+ )
+
+ snapshotSendSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_send_total_duration_seconds",
+ Help: "Total latency distributions of v3 snapshot sends",
+
+ // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
+ // highest bucket start of 0.1 sec * 2^9 == 51.2 sec
+ Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
+ },
+ []string{"To"},
+ )
+
+ snapshotReceive = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_receive_success",
+ Help: "Total number of successful snapshot receives",
+ },
+ []string{"From"},
+ )
+
+ snapshotReceiveInflights = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_receive_inflights_total",
+ Help: "Total number of inflight snapshot receives",
+ },
+ []string{"From"},
+ )
+
+ snapshotReceiveFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_receive_failures",
+ Help: "Total number of snapshot receive failures",
+ },
+ []string{"From"},
+ )
+
+ snapshotReceiveSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "snapshot_receive_total_duration_seconds",
+ Help: "Total latency distributions of v3 snapshot receives",
+
+ // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
+ // highest bucket start of 0.1 sec * 2^9 == 51.2 sec
+ Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
+ },
+ []string{"From"},
+ )
+
+ rttSec = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "peer_round_trip_time_seconds",
+ Help: "Round-Trip-Time histogram between peers",
+
+ // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2
+ // highest bucket start of 0.0001 sec * 2^15 == 3.2768 sec
+ Buckets: prometheus.ExponentialBuckets(0.0001, 2, 16),
+ },
+ []string{"To"},
+ )
+)
+
+func init() {
+ prometheus.MustRegister(activePeers)
+ prometheus.MustRegister(disconnectedPeers)
+ prometheus.MustRegister(sentBytes)
+ prometheus.MustRegister(receivedBytes)
+ prometheus.MustRegister(sentFailures)
+ prometheus.MustRegister(recvFailures)
+
+ prometheus.MustRegister(snapshotSend)
+ prometheus.MustRegister(snapshotSendInflights)
+ prometheus.MustRegister(snapshotSendFailures)
+ prometheus.MustRegister(snapshotSendSeconds)
+ prometheus.MustRegister(snapshotReceive)
+ prometheus.MustRegister(snapshotReceiveInflights)
+ prometheus.MustRegister(snapshotReceiveFailures)
+ prometheus.MustRegister(snapshotReceiveSeconds)
+
+ prometheus.MustRegister(rttSec)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msg_codec.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msg_codec.go
new file mode 100644
index 0000000000..7db880baa2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/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"
+
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3/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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msgappv2_codec.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msgappv2_codec.go
new file mode 100644
index 0000000000..9a7f4a1770
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/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"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
+)
+
+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] = 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] = 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 = 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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer.go
new file mode 100644
index 0000000000..444d6bde94
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer.go
@@ -0,0 +1,367 @@
+// 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"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+ stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
+
+ "go.uber.org/zap"
+ "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.
+ DefaultConnReadTimeout = 5 * time.Second
+ DefaultConnWriteTimeout = 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"
+)
+
+var (
+ ConnReadTimeout = DefaultConnReadTimeout
+ ConnWriteTimeout = DefaultConnWriteTimeout
+)
+
+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 {
+ lg *zap.Logger
+
+ localID types.ID
+ // 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(t *Transport, urls types.URLs, peerID types.ID, fs *stats.FollowerStats) *peer {
+ if t.Logger != nil {
+ t.Logger.Info("starting remote peer", zap.String("remote-peer-id", peerID.String()))
+ }
+ defer func() {
+ if t.Logger != nil {
+ t.Logger.Info("started remote peer", zap.String("remote-peer-id", peerID.String()))
+ }
+ }()
+
+ status := newPeerStatus(t.Logger, t.ID, peerID)
+ picker := newURLPicker(urls)
+ errorc := t.ErrorC
+ r := t.Raft
+ pipeline := &pipeline{
+ peerID: peerID,
+ tr: t,
+ picker: picker,
+ status: status,
+ followerStats: fs,
+ raft: r,
+ errorc: errorc,
+ }
+ pipeline.start()
+
+ p := &peer{
+ lg: t.Logger,
+ localID: t.ID,
+ id: peerID,
+ r: r,
+ status: status,
+ picker: picker,
+ msgAppV2Writer: startStreamWriter(t.Logger, t.ID, peerID, status, fs, r),
+ writer: startStreamWriter(t.Logger, t.ID, peerID, status, fs, r),
+ pipeline: pipeline,
+ snapSender: newSnapshotSender(t, 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 {
+ if t.Logger != nil {
+ t.Logger.Warn("failed to process Raft message", zap.Error(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 {
+ if t.Logger != nil {
+ t.Logger.Warn("failed to process Raft message", zap.Error(err))
+ }
+ }
+ case <-p.stopc:
+ return
+ }
+ }
+ }()
+
+ p.msgAppV2Reader = &streamReader{
+ lg: t.Logger,
+ peerID: peerID,
+ typ: streamTypeMsgAppV2,
+ tr: t,
+ picker: picker,
+ status: status,
+ recvc: p.recvc,
+ propc: p.propc,
+ rl: rate.NewLimiter(t.DialRetryFrequency, 1),
+ }
+ p.msgAppReader = &streamReader{
+ lg: t.Logger,
+ peerID: peerID,
+ typ: streamTypeMessage,
+ tr: t,
+ picker: picker,
+ status: status,
+ recvc: p.recvc,
+ propc: p.propc,
+ rl: rate.NewLimiter(t.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() {
+ if p.lg != nil {
+ p.lg.Warn(
+ "dropped internal Raft message since sending buffer is full (overloaded network)",
+ zap.String("message-type", m.Type.String()),
+ zap.String("local-member-id", p.localID.String()),
+ zap.String("from", types.ID(m.From).String()),
+ zap.String("remote-peer-id", p.id.String()),
+ zap.String("remote-peer-name", name),
+ zap.Bool("remote-peer-active", p.status.isActive()),
+ )
+ }
+ } else {
+ if p.lg != nil {
+ p.lg.Warn(
+ "dropped internal Raft message since sending buffer is full (overloaded network)",
+ zap.String("message-type", m.Type.String()),
+ zap.String("local-member-id", p.localID.String()),
+ zap.String("from", types.ID(m.From).String()),
+ zap.String("remote-peer-id", p.id.String()),
+ zap.String("remote-peer-name", name),
+ zap.Bool("remote-peer-active", p.status.isActive()),
+ )
+ }
+ }
+ 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:
+ if p.lg != nil {
+ p.lg.Panic("unknown stream type", zap.String("type", conn.t.String()))
+ }
+ }
+ 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() {
+ if p.lg != nil {
+ p.lg.Info("stopping remote peer", zap.String("remote-peer-id", p.id.String()))
+ }
+
+ defer func() {
+ if p.lg != nil {
+ p.lg.Info("stopped remote peer", zap.String("remote-peer-id", p.id.String()))
+ }
+ }()
+
+ 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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer_status.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer_status.go
new file mode 100644
index 0000000000..cad19b2fbc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer_status.go
@@ -0,0 +1,90 @@
+// 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 (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+
+ "go.uber.org/zap"
+)
+
+type failureType struct {
+ source string
+ action string
+}
+
+type peerStatus struct {
+ lg *zap.Logger
+ local types.ID
+ id types.ID
+ mu sync.Mutex // protect variables below
+ active bool
+ since time.Time
+}
+
+func newPeerStatus(lg *zap.Logger, local, id types.ID) *peerStatus {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &peerStatus{lg: lg, local: local, id: id}
+}
+
+func (s *peerStatus) activate() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if !s.active {
+ s.lg.Info("peer became active", zap.String("peer-id", s.id.String()))
+ s.active = true
+ s.since = time.Now()
+
+ activePeers.WithLabelValues(s.local.String(), s.id.String()).Inc()
+ }
+}
+
+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 {
+ s.lg.Warn("peer became inactive (message send to peer failed)", zap.String("peer-id", s.id.String()), zap.Error(errors.New(msg)))
+ s.active = false
+ s.since = time.Time{}
+
+ activePeers.WithLabelValues(s.local.String(), s.id.String()).Dec()
+ disconnectedPeers.WithLabelValues(s.local.String(), s.id.String()).Inc()
+ return
+ }
+
+ if s.lg != nil {
+ s.lg.Debug("peer deactivated again", zap.String("peer-id", s.id.String()), zap.Error(errors.New(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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/pipeline.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/pipeline.go
new file mode 100644
index 0000000000..de3b459118
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/pipeline.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 rafthttp
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "io/ioutil"
+ "runtime"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
+
+ "go.uber.org/zap"
+)
+
+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()
+ }
+
+ if p.tr != nil && p.tr.Logger != nil {
+ p.tr.Logger.Info(
+ "started HTTP pipelining with remote peer",
+ zap.String("local-member-id", p.tr.ID.String()),
+ zap.String("remote-peer-id", p.peerID.String()),
+ )
+ }
+}
+
+func (p *pipeline) stop() {
+ close(p.stopc)
+ p.wg.Wait()
+
+ if p.tr != nil && p.tr.Logger != nil {
+ p.tr.Logger.Info(
+ "stopped HTTP pipelining with remote peer",
+ zap.String("local-member-id", p.tr.ID.String()),
+ zap.String("remote-peer-id", p.peerID.String()),
+ )
+ }
+}
+
+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(p.tr.Logger, 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:
+ cancel()
+ case <-p.stopc:
+ waitSchedule()
+ cancel()
+ }
+ }()
+
+ resp, err := p.tr.pipelineRt.RoundTrip(req)
+ done <- struct{}{}
+ if err != nil {
+ p.picker.unreachable(u)
+ return err
+ }
+ defer resp.Body.Close()
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ p.picker.unreachable(u)
+ return err
+ }
+
+ err = checkPostResponse(p.tr.Logger, 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() { runtime.Gosched() }
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/probing_status.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/probing_status.go
new file mode 100644
index 0000000000..672a579ce6
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/probing_status.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 rafthttp
+
+import (
+ "time"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/xiang90/probing"
+ "go.uber.org/zap"
+)
+
+const (
+ // RoundTripperNameRaftMessage is the name of round-tripper that sends
+ // all other Raft messages, other than "snap.Message".
+ RoundTripperNameRaftMessage = "ROUND_TRIPPER_RAFT_MESSAGE"
+ // RoundTripperNameSnapshot is the name of round-tripper that sends merged snapshot message.
+ RoundTripperNameSnapshot = "ROUND_TRIPPER_SNAPSHOT"
+)
+
+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(lg *zap.Logger, p probing.Prober, id string, us []string, roundTripperName string, rttSecProm *prometheus.HistogramVec) {
+ 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 {
+ if lg != nil {
+ lg.Warn("failed to add peer into prober", zap.String("remote-peer-id", id), zap.Error(err))
+ }
+ return
+ }
+
+ go monitorProbingStatus(lg, s, id, roundTripperName, rttSecProm)
+}
+
+func monitorProbingStatus(lg *zap.Logger, s probing.Status, id string, roundTripperName string, rttSecProm *prometheus.HistogramVec) {
+ // set the first interval short to log error early.
+ interval := statusErrorInterval
+ for {
+ select {
+ case <-time.After(interval):
+ if !s.Health() {
+ if lg != nil {
+ lg.Warn(
+ "prober detected unhealthy status",
+ zap.String("round-tripper-name", roundTripperName),
+ zap.String("remote-peer-id", id),
+ zap.Duration("rtt", s.SRTT()),
+ zap.Error(s.Err()),
+ )
+ }
+ interval = statusErrorInterval
+ } else {
+ interval = statusMonitoringInterval
+ }
+ if s.ClockDiff() > time.Second {
+ if lg != nil {
+ lg.Warn(
+ "prober found high clock drift",
+ zap.String("round-tripper-name", roundTripperName),
+ zap.String("remote-peer-id", id),
+ zap.Duration("clock-drift", s.ClockDiff()),
+ zap.Duration("rtt", s.SRTT()),
+ zap.Error(s.Err()),
+ )
+ }
+ }
+ rttSecProm.WithLabelValues(id).Observe(s.SRTT().Seconds())
+
+ case <-s.StopNotify():
+ return
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/remote.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/remote.go
new file mode 100644
index 0000000000..eddb3f4da1
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/remote.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 rafthttp
+
+import (
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+
+ "go.uber.org/zap"
+)
+
+type remote struct {
+ lg *zap.Logger
+ localID types.ID
+ id types.ID
+ status *peerStatus
+ pipeline *pipeline
+}
+
+func startRemote(tr *Transport, urls types.URLs, id types.ID) *remote {
+ picker := newURLPicker(urls)
+ status := newPeerStatus(tr.Logger, tr.ID, id)
+ pipeline := &pipeline{
+ peerID: id,
+ tr: tr,
+ picker: picker,
+ status: status,
+ raft: tr.Raft,
+ errorc: tr.ErrorC,
+ }
+ pipeline.start()
+
+ return &remote{
+ lg: tr.Logger,
+ localID: tr.ID,
+ id: id,
+ status: status,
+ pipeline: pipeline,
+ }
+}
+
+func (g *remote) send(m raftpb.Message) {
+ select {
+ case g.pipeline.msgc <- m:
+ default:
+ if g.status.isActive() {
+ if g.lg != nil {
+ g.lg.Warn(
+ "dropped internal Raft message since sending buffer is full (overloaded network)",
+ zap.String("message-type", m.Type.String()),
+ zap.String("local-member-id", g.localID.String()),
+ zap.String("from", types.ID(m.From).String()),
+ zap.String("remote-peer-id", g.id.String()),
+ zap.Bool("remote-peer-active", g.status.isActive()),
+ )
+ }
+ } else {
+ if g.lg != nil {
+ g.lg.Warn(
+ "dropped Raft message since sending buffer is full (overloaded network)",
+ zap.String("message-type", m.Type.String()),
+ zap.String("local-member-id", g.localID.String()),
+ zap.String("from", types.ID(m.From).String()),
+ zap.String("remote-peer-id", g.id.String()),
+ zap.Bool("remote-peer-active", g.status.isActive()),
+ )
+ }
+ }
+ 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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/snapshot_sender.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/snapshot_sender.go
new file mode 100644
index 0000000000..84eb56bd0b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/snapshot_sender.go
@@ -0,0 +1,201 @@
+// 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"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/httputil"
+ pioutil "go.etcd.io/etcd/pkg/v3/ioutil"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+
+ "github.com/dustin/go-humanize"
+ "go.uber.org/zap"
+)
+
+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) {
+ start := time.Now()
+
+ m := merged.Message
+ to := types.ID(m.To).String()
+
+ body := createSnapBody(s.tr.Logger, merged)
+ defer body.Close()
+
+ u := s.picker.pick()
+ req := createPostRequest(s.tr.Logger, u, RaftSnapshotPrefix, body, "application/octet-stream", s.tr.URLs, s.from, s.cid)
+
+ snapshotSizeVal := uint64(merged.TotalSize)
+ snapshotSize := humanize.Bytes(snapshotSizeVal)
+ if s.tr.Logger != nil {
+ s.tr.Logger.Info(
+ "sending database snapshot",
+ zap.Uint64("snapshot-index", m.Snapshot.Metadata.Index),
+ zap.String("remote-peer-id", to),
+ zap.Uint64("bytes", snapshotSizeVal),
+ zap.String("size", snapshotSize),
+ )
+ }
+
+ snapshotSendInflights.WithLabelValues(to).Inc()
+ defer func() {
+ snapshotSendInflights.WithLabelValues(to).Dec()
+ }()
+
+ err := s.post(req)
+ defer merged.CloseWithError(err)
+ if err != nil {
+ if s.tr.Logger != nil {
+ s.tr.Logger.Warn(
+ "failed to send database snapshot",
+ zap.Uint64("snapshot-index", m.Snapshot.Metadata.Index),
+ zap.String("remote-peer-id", to),
+ zap.Uint64("bytes", snapshotSizeVal),
+ zap.String("size", snapshotSize),
+ zap.Error(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(to).Inc()
+ snapshotSendFailures.WithLabelValues(to).Inc()
+ return
+ }
+ s.status.activate()
+ s.r.ReportSnapshot(m.To, raft.SnapshotFinish)
+
+ if s.tr.Logger != nil {
+ s.tr.Logger.Info(
+ "sent database snapshot",
+ zap.Uint64("snapshot-index", m.Snapshot.Metadata.Index),
+ zap.String("remote-peer-id", to),
+ zap.Uint64("bytes", snapshotSizeVal),
+ zap.String("size", snapshotSize),
+ )
+ }
+
+ sentBytes.WithLabelValues(to).Add(float64(merged.TotalSize))
+ snapshotSend.WithLabelValues(to).Inc()
+ snapshotSendSeconds.WithLabelValues(to).Observe(time.Since(start).Seconds())
+}
+
+// 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(s.tr.Logger, r.resp, r.body, req, s.to)
+ }
+}
+
+func createSnapBody(lg *zap.Logger, merged snap.Message) io.ReadCloser {
+ buf := new(bytes.Buffer)
+ enc := &messageEncoder{w: buf}
+ // encode raft message
+ if err := enc.encode(&merged.Message); err != nil {
+ if lg != nil {
+ lg.Panic("failed to encode message", zap.Error(err))
+ }
+ }
+
+ return &pioutil.ReaderAndCloser{
+ Reader: io.MultiReader(buf, merged.ReadCloser),
+ Closer: merged.ReadCloser,
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/stream.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/stream.go
new file mode 100644
index 0000000000..1b180fca3f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/stream.go
@@ -0,0 +1,713 @@
+// 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"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/httputil"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
+
+ "github.com/coreos/go-semver/semver"
+ "go.uber.org/zap"
+ "golang.org/x/time/rate"
+)
+
+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},
+ "3.4.0": {streamTypeMsgAppV2, streamTypeMessage},
+ "3.5.0": {streamTypeMsgAppV2, streamTypeMessage},
+ }
+)
+
+type streamType string
+
+func (t streamType) endpoint(lg *zap.Logger) string {
+ switch t {
+ case streamTypeMsgAppV2:
+ return path.Join(RaftStreamPrefix, "msgapp")
+ case streamTypeMessage:
+ return path.Join(RaftStreamPrefix, "message")
+ default:
+ if lg != nil {
+ lg.Panic("unhandled stream type", zap.String("stream-type", t.String()))
+ }
+ 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
+
+ localID types.ID
+ peerID types.ID
+}
+
+// streamWriter writes messages to the attached outgoingConn.
+type streamWriter struct {
+ lg *zap.Logger
+
+ localID types.ID
+ 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(lg *zap.Logger, local, id types.ID, status *peerStatus, fs *stats.FollowerStats, r Raft) *streamWriter {
+ w := &streamWriter{
+ lg: lg,
+
+ localID: local,
+ 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
+
+ if cw.lg != nil {
+ cw.lg.Info(
+ "started stream writer with remote peer",
+ zap.String("local-member-id", cw.localID.String()),
+ zap.String("remote-peer-id", cw.peerID.String()),
+ )
+ }
+
+ 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()
+ if cw.lg != nil {
+ cw.lg.Warn(
+ "lost TCP streaming connection with remote peer",
+ zap.String("stream-writer-type", t.String()),
+ zap.String("local-member-id", cw.localID.String()),
+ zap.String("remote-peer-id", cw.peerID.String()),
+ )
+ }
+ 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()
+ if cw.lg != nil {
+ cw.lg.Warn(
+ "lost TCP streaming connection with remote peer",
+ zap.String("stream-writer-type", t.String()),
+ zap.String("local-member-id", cw.localID.String()),
+ zap.String("remote-peer-id", cw.peerID.String()),
+ )
+ }
+ 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:
+ if cw.lg != nil {
+ cw.lg.Panic("unhandled stream type", zap.String("stream-type", t.String()))
+ }
+ }
+ if cw.lg != nil {
+ cw.lg.Info(
+ "set message encoder",
+ zap.String("from", conn.localID.String()),
+ zap.String("to", conn.peerID.String()),
+ zap.String("stream-type", t.String()),
+ )
+ }
+ flusher = conn.Flusher
+ unflushed = 0
+ cw.status.activate()
+ cw.closer = conn.Closer
+ cw.working = true
+ cw.mu.Unlock()
+
+ if closed {
+ if cw.lg != nil {
+ cw.lg.Warn(
+ "closed TCP streaming connection with remote peer",
+ zap.String("stream-writer-type", t.String()),
+ zap.String("local-member-id", cw.localID.String()),
+ zap.String("remote-peer-id", cw.peerID.String()),
+ )
+ }
+ }
+ if cw.lg != nil {
+ cw.lg.Info(
+ "established TCP streaming connection with remote peer",
+ zap.String("stream-writer-type", t.String()),
+ zap.String("local-member-id", cw.localID.String()),
+ zap.String("remote-peer-id", cw.peerID.String()),
+ )
+ }
+ heartbeatc, msgc = tickc.C, cw.msgc
+
+ case <-cw.stopc:
+ if cw.close() {
+ if cw.lg != nil {
+ cw.lg.Warn(
+ "closed TCP streaming connection with remote peer",
+ zap.String("stream-writer-type", t.String()),
+ zap.String("remote-peer-id", cw.peerID.String()),
+ )
+ }
+ }
+ if cw.lg != nil {
+ cw.lg.Info(
+ "stopped TCP streaming connection with remote peer",
+ zap.String("stream-writer-type", t.String()),
+ zap.String("remote-peer-id", cw.peerID.String()),
+ )
+ }
+ 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 {
+ if cw.lg != nil {
+ cw.lg.Warn(
+ "failed to close connection with remote peer",
+ zap.String("remote-peer-id", cw.peerID.String()),
+ zap.Error(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 {
+ lg *zap.Logger
+
+ 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
+
+ if cr.lg != nil {
+ cr.lg.Info(
+ "started stream reader with remote peer",
+ zap.String("stream-reader-type", t.String()),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("remote-peer-id", cr.peerID.String()),
+ )
+ }
+
+ 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()
+ if cr.lg != nil {
+ cr.lg.Info(
+ "established TCP streaming connection with remote peer",
+ zap.String("stream-reader-type", cr.typ.String()),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("remote-peer-id", cr.peerID.String()),
+ )
+ }
+ err = cr.decodeLoop(rc, t)
+ if cr.lg != nil {
+ cr.lg.Warn(
+ "lost TCP streaming connection with remote peer",
+ zap.String("stream-reader-type", cr.typ.String()),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("remote-peer-id", cr.peerID.String()),
+ zap.Error(err),
+ )
+ }
+ 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 {
+ if cr.lg != nil {
+ cr.lg.Info(
+ "stopped stream reader with remote peer",
+ zap.String("stream-reader-type", t.String()),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("remote-peer-id", cr.peerID.String()),
+ )
+ }
+ close(cr.done)
+ return
+ }
+ if err != nil {
+ if cr.lg != nil {
+ cr.lg.Warn(
+ "rate limit on stream reader with remote peer",
+ zap.String("stream-reader-type", t.String()),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("remote-peer-id", cr.peerID.String()),
+ zap.Error(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:
+ if cr.lg != nil {
+ cr.lg.Panic("unknown stream type", zap.String("type", t.String()))
+ }
+ }
+ 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()
+
+ // gofail: labelRaftDropHeartbeat:
+ for {
+ m, err := dec.decode()
+ if err != nil {
+ cr.mu.Lock()
+ cr.close()
+ cr.mu.Unlock()
+ return err
+ }
+
+ // gofail-go: var raftDropHeartbeat struct{}
+ // continue labelRaftDropHeartbeat
+ 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() {
+ if cr.lg != nil {
+ cr.lg.Warn(
+ "dropped internal Raft message since receiving buffer is full (overloaded network)",
+ zap.String("message-type", m.Type.String()),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("from", types.ID(m.From).String()),
+ zap.String("remote-peer-id", types.ID(m.To).String()),
+ zap.Bool("remote-peer-active", cr.status.isActive()),
+ )
+ }
+ } else {
+ if cr.lg != nil {
+ cr.lg.Warn(
+ "dropped Raft message since receiving buffer is full (overloaded network)",
+ zap.String("message-type", m.Type.String()),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("from", types.ID(m.From).String()),
+ zap.String("remote-peer-id", types.ID(m.To).String()),
+ zap.Bool("remote-peer-active", cr.status.isActive()),
+ )
+ }
+ }
+ 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.lg), cr.tr.ID.String())
+
+ if cr.lg != nil {
+ cr.lg.Debug(
+ "dial stream reader",
+ zap.String("from", cr.tr.ID.String()),
+ zap.String("to", cr.peerID.String()),
+ zap.String("address", uu.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():
+ if cr.lg != nil {
+ cr.lg.Warn(
+ "request sent was ignored by remote peer due to server version incompatibility",
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("remote-peer-id", cr.peerID.String()),
+ zap.Error(errIncompatibleVersion),
+ )
+ }
+ return nil, errIncompatibleVersion
+
+ case ErrClusterIDMismatch.Error():
+ if cr.lg != nil {
+ cr.lg.Warn(
+ "request sent was ignored by remote peer due to cluster ID mismatch",
+ zap.String("remote-peer-id", cr.peerID.String()),
+ zap.String("remote-peer-cluster-id", resp.Header.Get("X-Etcd-Cluster-ID")),
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("local-member-cluster-id", cr.tr.ClusterID.String()),
+ zap.Error(ErrClusterIDMismatch),
+ )
+ }
+ 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 {
+ if cr.lg != nil {
+ cr.lg.Warn(
+ "failed to close remote peer connection",
+ zap.String("local-member-id", cr.tr.ID.String()),
+ zap.String("remote-peer-id", cr.peerID.String()),
+ zap.Error(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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/transport.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/transport.go
new file mode 100644
index 0000000000..a1969549a9
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/transport.go
@@ -0,0 +1,447 @@
+// 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"
+
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+ stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
+
+ "github.com/xiang90/probing"
+ "go.uber.org/zap"
+ "golang.org/x/time/rate"
+)
+
+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 {
+ Logger *zap.Logger
+
+ 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
+ // LeaderStats is 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
+
+ pipelineProber probing.Prober
+ streamProber 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.pipelineProber = probing.NewProber(t.pipelineRt)
+ t.streamProber = probing.NewProber(t.streamRt)
+
+ // 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
+ }
+
+ if t.Logger != nil {
+ t.Logger.Debug(
+ "ignored message send request; unknown remote peer target",
+ zap.String("type", m.Type.String()),
+ zap.String("unknown-target-peer-id", to.String()),
+ )
+ }
+ }
+}
+
+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.pipelineProber.RemoveAll()
+ t.streamProber.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 {
+ if t.Logger != nil {
+ t.Logger.Panic("failed NewURLs", zap.Strings("urls", us), zap.Error(err))
+ }
+ }
+ t.remotes[id] = startRemote(t, urls, id)
+
+ if t.Logger != nil {
+ t.Logger.Info(
+ "added new remote peer",
+ zap.String("local-member-id", t.ID.String()),
+ zap.String("remote-peer-id", id.String()),
+ zap.Strings("remote-peer-urls", us),
+ )
+ }
+}
+
+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 {
+ if t.Logger != nil {
+ t.Logger.Panic("failed NewURLs", zap.Strings("urls", us), zap.Error(err))
+ }
+ }
+ fs := t.LeaderStats.Follower(id.String())
+ t.peers[id] = startPeer(t, urls, id, fs)
+ addPeerToProber(t.Logger, t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rttSec)
+ addPeerToProber(t.Logger, t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rttSec)
+
+ if t.Logger != nil {
+ t.Logger.Info(
+ "added remote peer",
+ zap.String("local-member-id", t.ID.String()),
+ zap.String("remote-peer-id", id.String()),
+ zap.Strings("remote-peer-urls", us),
+ )
+ }
+}
+
+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 {
+ if t.Logger != nil {
+ t.Logger.Panic("unexpected removal of unknown remote peer", zap.String("remote-peer-id", id.String()))
+ }
+ }
+ delete(t.peers, id)
+ delete(t.LeaderStats.Followers, id.String())
+ t.pipelineProber.Remove(id.String())
+ t.streamProber.Remove(id.String())
+
+ if t.Logger != nil {
+ t.Logger.Info(
+ "removed remote peer",
+ zap.String("local-member-id", t.ID.String()),
+ zap.String("removed-remote-peer-id", id.String()),
+ )
+ }
+}
+
+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 {
+ if t.Logger != nil {
+ t.Logger.Panic("failed NewURLs", zap.Strings("urls", us), zap.Error(err))
+ }
+ }
+ t.peers[id].update(urls)
+
+ t.pipelineProber.Remove(id.String())
+ addPeerToProber(t.Logger, t.pipelineProber, id.String(), us, RoundTripperNameSnapshot, rttSec)
+ t.streamProber.Remove(id.String())
+ addPeerToProber(t.Logger, t.streamProber, id.String(), us, RoundTripperNameRaftMessage, rttSec)
+
+ if t.Logger != nil {
+ t.Logger.Info(
+ "updated remote peer",
+ zap.String("local-member-id", t.ID.String()),
+ zap.String("updated-remote-peer-id", id.String()),
+ zap.Strings("updated-remote-peer-urls", us),
+ )
+ }
+}
+
+func (t *Transport) ActiveSince(id types.ID) time.Time {
+ t.mu.RLock()
+ defer t.mu.RUnlock()
+ 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() {
+ t.mu.RLock()
+ defer t.mu.RUnlock()
+ for _, p := range t.peers {
+ p.(Pausable).Pause()
+ }
+}
+
+func (t *Transport) Resume() {
+ t.mu.RLock()
+ defer t.mu.RUnlock()
+ 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
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/urlpick.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/urlpick.go
new file mode 100644
index 0000000000..fc6054a78a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/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"
+
+ "go.etcd.io/etcd/client/pkg/v3/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/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/util.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/util.go
new file mode 100644
index 0000000000..6d0e6bdd6b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/util.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 rafthttp
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+
+ "github.com/coreos/go-semver/semver"
+ "go.uber.org/zap"
+)
+
+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.NewListenerWithOpts(u.Host, u.Scheme, transport.WithTLSInfo(tlsinfo), transport.WithTimeout(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(lg *zap.Logger, 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 {
+ if lg != nil {
+ lg.Panic("unexpected new request error", zap.Error(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(lg *zap.Logger, 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():
+ if lg != nil {
+ lg.Error(
+ "request sent was ignored by peer",
+ zap.String("remote-peer-id", to.String()),
+ )
+ }
+ return errIncompatibleVersion
+ case ErrClusterIDMismatch.Error():
+ if lg != nil {
+ lg.Error(
+ "request sent was ignored due to cluster ID mismatch",
+ zap.String("remote-peer-id", to.String()),
+ zap.String("remote-peer-cluster-id", resp.Header.Get("X-Etcd-Cluster-ID")),
+ zap.String("local-member-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))
+}
+
+// checkVersionCompatibility checks whether the given version is compatible
+// with the local version.
+func checkVersionCompatibility(name string, server, minCluster *semver.Version) (
+ localServer *semver.Version,
+ localMinCluster *semver.Version,
+ err error) {
+ localServer = semver.Must(semver.NewVersion(version.Version))
+ localMinCluster = semver.Must(semver.NewVersion(version.MinClusterVersion))
+ if compareMajorMinorVersion(server, localMinCluster) == -1 {
+ return localServer, localMinCluster, fmt.Errorf("remote version is too low: remote[%s]=%s, local=%s", name, server, localServer)
+ }
+ if compareMajorMinorVersion(minCluster, localServer) == 1 {
+ return localServer, localMinCluster, fmt.Errorf("local version is too low: remote[%s]=%s, local=%s", name, server, localServer)
+ }
+ return localServer, localMinCluster, 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/go.etcd.io/etcd/server/v3/etcdserver/api/snap/db.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/db.go
new file mode 100644
index 0000000000..af653e1d5f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/db.go
@@ -0,0 +1,100 @@
+// 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"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/fileutil"
+
+ humanize "github.com/dustin/go-humanize"
+ "go.uber.org/zap"
+)
+
+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) {
+ start := time.Now()
+
+ 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 {
+ fsyncStart := time.Now()
+ err = fileutil.Fsync(f)
+ snapDBFsyncSec.Observe(time.Since(fsyncStart).Seconds())
+ }
+ 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
+ }
+
+ s.lg.Info(
+ "saved database snapshot to disk",
+ zap.String("path", fn),
+ zap.Int64("bytes", n),
+ zap.String("size", humanize.Bytes(uint64(n))),
+ )
+
+ snapDBSaveSec.Observe(time.Since(start).Seconds())
+ 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
+ }
+ fn := s.dbFilePath(id)
+ if fileutil.Exist(fn) {
+ return fn, nil
+ }
+ if s.lg != nil {
+ s.lg.Warn(
+ "failed to find [SNAPSHOT-INDEX].snap.db",
+ zap.Uint64("snapshot-index", id),
+ zap.String("snapshot-file-path", fn),
+ zap.Error(ErrNoDBSnapshot),
+ )
+ }
+ return "", ErrNoDBSnapshot
+}
+
+func (s *Snapshotter) dbFilePath(id uint64) string {
+ return filepath.Join(s.dir, fmt.Sprintf("%016x.snap.db", id))
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/doc.go
new file mode 100644
index 0000000000..dcc5db5798
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/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 snap handles Raft nodes' states with snapshots.
+// The snapshot logic is internal to etcd server and raft package.
+package snap
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/message.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/message.go
new file mode 100644
index 0000000000..523b52b85c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/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"
+
+ "go.etcd.io/etcd/pkg/v3/ioutil"
+ "go.etcd.io/etcd/raft/v3/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/go.etcd.io/etcd/server/v3/etcdserver/api/snap/metrics.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/metrics.go
new file mode 100644
index 0000000000..2affecf472
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/metrics.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 snap
+
+import "github.com/prometheus/client_golang/prometheus"
+
+var (
+ snapMarshallingSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "snap",
+ Name: "save_marshalling_duration_seconds",
+ Help: "The marshalling cost distributions of save called by snapshot.",
+
+ // 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),
+ })
+
+ snapSaveSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "snap",
+ Name: "save_total_duration_seconds",
+ Help: "The total latency distributions of save called by snapshot.",
+
+ // 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),
+ })
+
+ snapFsyncSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "snap",
+ Name: "fsync_duration_seconds",
+ Help: "The latency distributions of fsync called by snap.",
+
+ // 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),
+ })
+
+ snapDBSaveSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "snap_db",
+ Name: "save_total_duration_seconds",
+ Help: "The total latency distributions of v3 snapshot save",
+
+ // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
+ // highest bucket start of 0.1 sec * 2^9 == 51.2 sec
+ Buckets: prometheus.ExponentialBuckets(0.1, 2, 10),
+ })
+
+ snapDBFsyncSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "snap_db",
+ Name: "fsync_duration_seconds",
+ Help: "The latency distributions of fsyncing .snap.db file",
+
+ // 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),
+ })
+)
+
+func init() {
+ prometheus.MustRegister(snapMarshallingSec)
+ prometheus.MustRegister(snapSaveSec)
+ prometheus.MustRegister(snapFsyncSec)
+ prometheus.MustRegister(snapDBSaveSec)
+ prometheus.MustRegister(snapDBFsyncSec)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.pb.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.pb.go
new file mode 100644
index 0000000000..6fd2b9c008
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.pb.go
@@ -0,0 +1,344 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: snap.proto
+
+package snappb
+
+import (
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+ proto "github.com/golang/protobuf/proto"
+)
+
+// 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.ProtoPackageIsVersion3 // 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_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `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 fileDescriptor_f2e3c045ebf84d00, []int{0}
+}
+func (m *Snapshot) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Snapshot.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Snapshot) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Snapshot.Merge(m, src)
+}
+func (m *Snapshot) XXX_Size() int {
+ return m.Size()
+}
+func (m *Snapshot) XXX_DiscardUnknown() {
+ xxx_messageInfo_Snapshot.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Snapshot proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterType((*Snapshot)(nil), "snappb.snapshot")
+}
+
+func init() { proto.RegisterFile("snap.proto", fileDescriptor_f2e3c045ebf84d00) }
+
+var fileDescriptor_f2e3c045ebf84d00 = []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,
+}
+
+func (m *Snapshot) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Snapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Data != nil {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintSnap(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x12
+ }
+ i = encodeVarintSnap(dAtA, i, uint64(m.Crc))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintSnap(dAtA []byte, offset int, v uint64) int {
+ offset -= sovSnap(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *Snapshot) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ 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) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+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 < 0 {
+ return ErrInvalidLengthSnap
+ }
+ 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) || (iNdEx+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
+ depth := 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
+ }
+ }
+ case 1:
+ iNdEx += 8
+ 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
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthSnap
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupSnap
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthSnap
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthSnap = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowSnap = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupSnap = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.proto b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.proto
new file mode 100644
index 0000000000..cd3d21d0ee
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.proto
@@ -0,0 +1,14 @@
+syntax = "proto2";
+package snappb;
+
+import "gogoproto/gogo.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.goproto_getters_all) = false;
+
+message snapshot {
+ optional uint32 crc = 1 [(gogoproto.nullable) = false];
+ optional bytes data = 2;
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snapshotter.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snapshotter.go
new file mode 100644
index 0000000000..52cc0ae267
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snapshotter.go
@@ -0,0 +1,301 @@
+// 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"
+ "hash/crc32"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ pioutil "go.etcd.io/etcd/pkg/v3/ioutil"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb"
+ "go.etcd.io/etcd/server/v3/wal/walpb"
+
+ "go.uber.org/zap"
+)
+
+const snapSuffix = ".snap"
+
+var (
+ 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 {
+ lg *zap.Logger
+ dir string
+}
+
+func New(lg *zap.Logger, dir string) *Snapshotter {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &Snapshotter{
+ lg: lg,
+ 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
+ }
+ snapMarshallingSec.Observe(time.Since(start).Seconds())
+
+ spath := filepath.Join(s.dir, fname)
+
+ fsyncStart := time.Now()
+ err = pioutil.WriteAndSyncFile(spath, d, 0666)
+ snapFsyncSec.Observe(time.Since(fsyncStart).Seconds())
+
+ if err != nil {
+ s.lg.Warn("failed to write a snap file", zap.String("path", spath), zap.Error(err))
+ rerr := os.Remove(spath)
+ if rerr != nil {
+ s.lg.Warn("failed to remove a broken snap file", zap.String("path", spath), zap.Error(err))
+ }
+ return err
+ }
+
+ snapSaveSec.Observe(time.Since(start).Seconds())
+ return nil
+}
+
+// Load returns the newest snapshot.
+func (s *Snapshotter) Load() (*raftpb.Snapshot, error) {
+ return s.loadMatching(func(*raftpb.Snapshot) bool { return true })
+}
+
+// LoadNewestAvailable loads the newest snapshot available that is in walSnaps.
+func (s *Snapshotter) LoadNewestAvailable(walSnaps []walpb.Snapshot) (*raftpb.Snapshot, error) {
+ return s.loadMatching(func(snapshot *raftpb.Snapshot) bool {
+ m := snapshot.Metadata
+ for i := len(walSnaps) - 1; i >= 0; i-- {
+ if m.Term == walSnaps[i].Term && m.Index == walSnaps[i].Index {
+ return true
+ }
+ }
+ return false
+ })
+}
+
+// loadMatching returns the newest snapshot where matchFn returns true.
+func (s *Snapshotter) loadMatching(matchFn func(*raftpb.Snapshot) bool) (*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.lg, s.dir, name); err == nil && matchFn(snap) {
+ return snap, nil
+ }
+ }
+ return nil, ErrNoSnapshot
+}
+
+func loadSnap(lg *zap.Logger, dir, name string) (*raftpb.Snapshot, error) {
+ fpath := filepath.Join(dir, name)
+ snap, err := Read(lg, fpath)
+ if err != nil {
+ brokenPath := fpath + ".broken"
+ if lg != nil {
+ lg.Warn("failed to read a snap file", zap.String("path", fpath), zap.Error(err))
+ }
+ if rerr := os.Rename(fpath, brokenPath); rerr != nil {
+ if lg != nil {
+ lg.Warn("failed to rename a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath), zap.Error(rerr))
+ }
+ } else {
+ if lg != nil {
+ lg.Warn("renamed to a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath))
+ }
+ }
+ }
+ return snap, err
+}
+
+// Read reads the snapshot named by snapname and returns the snapshot.
+func Read(lg *zap.Logger, snapname string) (*raftpb.Snapshot, error) {
+ b, err := ioutil.ReadFile(snapname)
+ if err != nil {
+ if lg != nil {
+ lg.Warn("failed to read a snap file", zap.String("path", snapname), zap.Error(err))
+ }
+ return nil, err
+ }
+
+ if len(b) == 0 {
+ if lg != nil {
+ lg.Warn("failed to read empty snapshot file", zap.String("path", snapname))
+ }
+ return nil, ErrEmptySnapshot
+ }
+
+ var serializedSnap snappb.Snapshot
+ if err = serializedSnap.Unmarshal(b); err != nil {
+ if lg != nil {
+ lg.Warn("failed to unmarshal snappb.Snapshot", zap.String("path", snapname), zap.Error(err))
+ }
+ return nil, err
+ }
+
+ if len(serializedSnap.Data) == 0 || serializedSnap.Crc == 0 {
+ if lg != nil {
+ lg.Warn("failed to read empty snapshot data", zap.String("path", snapname))
+ }
+ return nil, ErrEmptySnapshot
+ }
+
+ crc := crc32.Update(0, crcTable, serializedSnap.Data)
+ if crc != serializedSnap.Crc {
+ if lg != nil {
+ lg.Warn("snap file is corrupt",
+ zap.String("path", snapname),
+ zap.Uint32("prev-crc", serializedSnap.Crc),
+ zap.Uint32("new-crc", crc),
+ )
+ }
+ return nil, ErrCRCMismatch
+ }
+
+ var snap raftpb.Snapshot
+ if err = snap.Unmarshal(serializedSnap.Data); err != nil {
+ if lg != nil {
+ lg.Warn("failed to unmarshal raftpb.Snapshot", zap.String("path", snapname), zap.Error(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
+ }
+ filenames, err := s.cleanupSnapdir(names)
+ if err != nil {
+ return nil, err
+ }
+ snaps := checkSuffix(s.lg, filenames)
+ if len(snaps) == 0 {
+ return nil, ErrNoSnapshot
+ }
+ sort.Sort(sort.Reverse(sort.StringSlice(snaps)))
+ return snaps, nil
+}
+
+func checkSuffix(lg *zap.Logger, 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 {
+ if lg != nil {
+ lg.Warn("found unexpected non-snap file; skipping", zap.String("path", names[i]))
+ }
+ }
+ }
+ }
+ return snaps
+}
+
+// cleanupSnapdir removes any files that should not be in the snapshot directory:
+// - db.tmp prefixed files that can be orphaned by defragmentation
+func (s *Snapshotter) cleanupSnapdir(filenames []string) (names []string, err error) {
+ names = make([]string, 0, len(filenames))
+ for _, filename := range filenames {
+ if strings.HasPrefix(filename, "db.tmp") {
+ s.lg.Info("found orphaned defragmentation file; deleting", zap.String("path", filename))
+ if rmErr := os.Remove(filepath.Join(s.dir, filename)); rmErr != nil && !os.IsNotExist(rmErr) {
+ return names, fmt.Errorf("failed to remove orphaned .snap.db file %s: %v", filename, rmErr)
+ }
+ } else {
+ names = append(names, filename)
+ }
+ }
+ return names, nil
+}
+
+func (s *Snapshotter) ReleaseSnapDBs(snap raftpb.Snapshot) error {
+ dir, err := os.Open(s.dir)
+ if err != nil {
+ return err
+ }
+ defer dir.Close()
+ filenames, err := dir.Readdirnames(-1)
+ if err != nil {
+ return err
+ }
+ for _, filename := range filenames {
+ if strings.HasSuffix(filename, ".snap.db") {
+ hexIndex := strings.TrimSuffix(filepath.Base(filename), ".snap.db")
+ index, err := strconv.ParseUint(hexIndex, 16, 64)
+ if err != nil {
+ s.lg.Error("failed to parse index from filename", zap.String("path", filename), zap.String("error", err.Error()))
+ continue
+ }
+ if index < snap.Metadata.Index {
+ s.lg.Info("found orphaned .snap.db file; deleting", zap.String("path", filename))
+ if rmErr := os.Remove(filepath.Join(s.dir, filename)); rmErr != nil && !os.IsNotExist(rmErr) {
+ s.lg.Error("failed to remove orphaned .snap.db file", zap.String("path", filename), zap.String("error", rmErr.Error()))
+ }
+ }
+ }
+ }
+ return nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth.go
new file mode 100644
index 0000000000..e76ee8b2a1
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth.go
@@ -0,0 +1,670 @@
+// 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 v2auth implements etcd authentication.
+package v2auth
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "path"
+ "reflect"
+ "sort"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+
+ "go.uber.org/zap"
+ "golang.org/x/crypto/bcrypt"
+)
+
+const (
+ // StorePermsPrefix is the internal prefix of the storage layer dedicated to storing user data.
+ StorePermsPrefix = "/2"
+
+ // RootRoleName is the name of the ROOT role, with privileges to manage the cluster.
+ RootRoleName = "root"
+
+ // GuestRoleName is the name of the role that defines the privileges of an unauthenticated user.
+ GuestRoleName = "guest"
+)
+
+var rootRole = Role{
+ Role: RootRoleName,
+ Permissions: Permissions{
+ KV: RWPermission{
+ Read: []string{"/*"},
+ Write: []string{"/*"},
+ },
+ },
+}
+
+var guestRole = Role{
+ Role: GuestRoleName,
+ Permissions: Permissions{
+ KV: RWPermission{
+ Read: []string{"/*"},
+ Write: []string{"/*"},
+ },
+ },
+}
+
+type doer interface {
+ Do(context.Context, etcdserverpb.Request) (etcdserver.Response, error)
+}
+
+type Store interface {
+ AllUsers() ([]string, error)
+ GetUser(name string) (User, error)
+ CreateOrUpdateUser(user User) (out User, created bool, err error)
+ CreateUser(user User) (User, error)
+ DeleteUser(name string) error
+ UpdateUser(user User) (User, error)
+ AllRoles() ([]string, error)
+ GetRole(name string) (Role, error)
+ CreateRole(role Role) error
+ DeleteRole(name string) error
+ UpdateRole(role Role) (Role, error)
+ AuthEnabled() bool
+ EnableAuth() error
+ DisableAuth() error
+ PasswordStore
+}
+
+type PasswordStore interface {
+ CheckPassword(user User, password string) bool
+ HashPassword(password string) (string, error)
+}
+
+type store struct {
+ lg *zap.Logger
+ server doer
+ timeout time.Duration
+ ensuredOnce bool
+
+ PasswordStore
+}
+
+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"`
+}
+
+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"`
+}
+
+func (p *Permissions) IsEmpty() bool {
+ return p == nil || (len(p.KV.Read) == 0 && len(p.KV.Write) == 0)
+}
+
+type RWPermission struct {
+ Read []string `json:"read"`
+ Write []string `json:"write"`
+}
+
+type Error struct {
+ Status int
+ Errmsg string
+}
+
+func (ae Error) Error() string { return ae.Errmsg }
+func (ae Error) HTTPStatus() int { return ae.Status }
+
+func authErr(hs int, s string, v ...interface{}) Error {
+ return Error{Status: hs, Errmsg: fmt.Sprintf("auth: "+s, v...)}
+}
+
+func NewStore(lg *zap.Logger, server doer, timeout time.Duration) Store {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ s := &store{
+ lg: lg,
+ server: server,
+ timeout: timeout,
+ PasswordStore: passwordStore{},
+ }
+ return s
+}
+
+// passwordStore implements PasswordStore using bcrypt to hash user passwords
+type passwordStore struct{}
+
+func (passwordStore) CheckPassword(user User, password string) bool {
+ err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
+ return err == nil
+}
+
+func (passwordStore) HashPassword(password string) (string, error) {
+ hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
+ return string(hash), err
+}
+
+func (s *store) AllUsers() ([]string, error) {
+ resp, err := s.requestResource("/users/", false)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return []string{}, nil
+ }
+ }
+ return nil, err
+ }
+ var nodes []string
+ for _, n := range resp.Event.Node.Nodes {
+ _, user := path.Split(n.Key)
+ nodes = append(nodes, user)
+ }
+ sort.Strings(nodes)
+ return nodes, nil
+}
+
+func (s *store) GetUser(name string) (User, error) { return s.getUser(name, false) }
+
+// CreateOrUpdateUser should be only used for creating the new user or when you are not
+// sure if it is a create or update. (When only password is passed in, we are not sure
+// if it is a update or create)
+func (s *store) CreateOrUpdateUser(user User) (out User, created bool, err error) {
+ _, err = s.getUser(user.User, true)
+ if err == nil {
+ out, err = s.UpdateUser(user)
+ return out, false, err
+ }
+ u, err := s.CreateUser(user)
+ return u, true, err
+}
+
+func (s *store) CreateUser(user User) (User, error) {
+ // Attach root role to root user.
+ if user.User == "root" {
+ user = attachRootRole(user)
+ }
+ u, err := s.createUserInternal(user)
+ if err == nil {
+ s.lg.Info("created a user", zap.String("user-name", user.User))
+ }
+ return u, err
+}
+
+func (s *store) createUserInternal(user User) (User, error) {
+ if user.Password == "" {
+ return user, authErr(http.StatusBadRequest, "Cannot create user %s with an empty password", user.User)
+ }
+ hash, err := s.HashPassword(user.Password)
+ if err != nil {
+ return user, err
+ }
+ user.Password = hash
+
+ _, err = s.createResource("/users/"+user.User, user)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeNodeExist {
+ return user, authErr(http.StatusConflict, "User %s already exists.", user.User)
+ }
+ }
+ }
+ return user, err
+}
+
+func (s *store) DeleteUser(name string) error {
+ if s.AuthEnabled() && name == "root" {
+ return authErr(http.StatusForbidden, "Cannot delete root user while auth is enabled.")
+ }
+ err := s.deleteResource("/users/" + name)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return authErr(http.StatusNotFound, "User %s does not exist", name)
+ }
+ }
+ return err
+ }
+ s.lg.Info("deleted a user", zap.String("user-name", name))
+ return nil
+}
+
+func (s *store) UpdateUser(user User) (User, error) {
+ old, err := s.getUser(user.User, true)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return user, authErr(http.StatusNotFound, "User %s doesn't exist.", user.User)
+ }
+ }
+ return old, err
+ }
+
+ newUser, err := old.merge(s.lg, user, s.PasswordStore)
+ if err != nil {
+ return old, err
+ }
+ if reflect.DeepEqual(old, newUser) {
+ return old, authErr(http.StatusBadRequest, "User not updated. Use grant/revoke/password to update the user.")
+ }
+ _, err = s.updateResource("/users/"+user.User, newUser)
+ if err == nil {
+ s.lg.Info("updated a user", zap.String("user-name", user.User))
+ }
+ return newUser, err
+}
+
+func (s *store) AllRoles() ([]string, error) {
+ nodes := []string{RootRoleName}
+ resp, err := s.requestResource("/roles/", false)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return nodes, nil
+ }
+ }
+ return nil, err
+ }
+ for _, n := range resp.Event.Node.Nodes {
+ _, role := path.Split(n.Key)
+ nodes = append(nodes, role)
+ }
+ sort.Strings(nodes)
+ return nodes, nil
+}
+
+func (s *store) GetRole(name string) (Role, error) { return s.getRole(name, false) }
+
+func (s *store) CreateRole(role Role) error {
+ if role.Role == RootRoleName {
+ return authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", role.Role)
+ }
+ _, err := s.createResource("/roles/"+role.Role, role)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeNodeExist {
+ return authErr(http.StatusConflict, "Role %s already exists.", role.Role)
+ }
+ }
+ }
+ if err == nil {
+ s.lg.Info("created a new role", zap.String("role-name", role.Role))
+ }
+ return err
+}
+
+func (s *store) DeleteRole(name string) error {
+ if name == RootRoleName {
+ return authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", name)
+ }
+ err := s.deleteResource("/roles/" + name)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return authErr(http.StatusNotFound, "Role %s doesn't exist.", name)
+ }
+ }
+ }
+ if err == nil {
+ s.lg.Info("delete a new role", zap.String("role-name", name))
+ }
+ return err
+}
+
+func (s *store) UpdateRole(role Role) (Role, error) {
+ if role.Role == RootRoleName {
+ return Role{}, authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", role.Role)
+ }
+ old, err := s.getRole(role.Role, true)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return role, authErr(http.StatusNotFound, "Role %s doesn't exist.", role.Role)
+ }
+ }
+ return old, err
+ }
+ newRole, err := old.merge(s.lg, role)
+ if err != nil {
+ return old, err
+ }
+ if reflect.DeepEqual(old, newRole) {
+ return old, authErr(http.StatusBadRequest, "Role not updated. Use grant/revoke to update the role.")
+ }
+ _, err = s.updateResource("/roles/"+role.Role, newRole)
+ if err == nil {
+ s.lg.Info("updated a new role", zap.String("role-name", role.Role))
+ }
+ return newRole, err
+}
+
+func (s *store) AuthEnabled() bool {
+ return s.detectAuth()
+}
+
+func (s *store) EnableAuth() error {
+ if s.AuthEnabled() {
+ return authErr(http.StatusConflict, "already enabled")
+ }
+
+ if _, err := s.getUser("root", true); err != nil {
+ return authErr(http.StatusConflict, "No root user available, please create one")
+ }
+ if _, err := s.getRole(GuestRoleName, true); err != nil {
+ s.lg.Info(
+ "no guest role access found; creating default",
+ zap.String("role-name", GuestRoleName),
+ )
+ if err := s.CreateRole(guestRole); err != nil {
+ s.lg.Warn(
+ "failed to create a guest role; aborting auth enable",
+ zap.String("role-name", GuestRoleName),
+ zap.Error(err),
+ )
+ return err
+ }
+ }
+
+ if err := s.enableAuth(); err != nil {
+ s.lg.Warn("failed to enable auth", zap.Error(err))
+ return err
+ }
+
+ s.lg.Info("enabled auth")
+ return nil
+}
+
+func (s *store) DisableAuth() error {
+ if !s.AuthEnabled() {
+ return authErr(http.StatusConflict, "already disabled")
+ }
+
+ err := s.disableAuth()
+ if err == nil {
+ s.lg.Info("disabled auth")
+ } else {
+ s.lg.Warn("failed to disable auth", zap.Error(err))
+ }
+ return err
+}
+
+// merge applies the properties of the passed-in User to the User on which it
+// is called and returns a new User with these modifications applied. Think of
+// all Users as immutable sets of data. Merge allows you to perform the set
+// operations (desired grants and revokes) atomically
+func (ou User) merge(lg *zap.Logger, nu User, s PasswordStore) (User, error) {
+ var out User
+ if ou.User != nu.User {
+ return out, authErr(http.StatusConflict, "Merging user data with conflicting usernames: %s %s", ou.User, nu.User)
+ }
+ out.User = ou.User
+ if nu.Password != "" {
+ hash, err := s.HashPassword(nu.Password)
+ if err != nil {
+ return ou, err
+ }
+ out.Password = hash
+ } else {
+ out.Password = ou.Password
+ }
+ currentRoles := types.NewUnsafeSet(ou.Roles...)
+ for _, g := range nu.Grant {
+ if currentRoles.Contains(g) {
+ lg.Warn(
+ "attempted to grant a duplicate role for a user",
+ zap.String("user-name", nu.User),
+ zap.String("role-name", g),
+ )
+ return User{}, authErr(http.StatusConflict, fmt.Sprintf("Granting duplicate role %s for user %s", g, nu.User))
+ }
+ currentRoles.Add(g)
+ }
+ for _, r := range nu.Revoke {
+ if !currentRoles.Contains(r) {
+ lg.Warn(
+ "attempted to revoke a ungranted role for a user",
+ zap.String("user-name", nu.User),
+ zap.String("role-name", r),
+ )
+ return User{}, authErr(http.StatusConflict, fmt.Sprintf("Revoking ungranted role %s for user %s", r, nu.User))
+ }
+ currentRoles.Remove(r)
+ }
+ out.Roles = currentRoles.Values()
+ sort.Strings(out.Roles)
+ return out, nil
+}
+
+// merge for a role works the same as User above -- atomic Role application to
+// each of the substructures.
+func (r Role) merge(lg *zap.Logger, n Role) (Role, error) {
+ var out Role
+ var err error
+ if r.Role != n.Role {
+ return out, authErr(http.StatusConflict, "Merging role with conflicting names: %s %s", r.Role, n.Role)
+ }
+ out.Role = r.Role
+ out.Permissions, err = r.Permissions.Grant(n.Grant)
+ if err != nil {
+ return out, err
+ }
+ out.Permissions, err = out.Permissions.Revoke(lg, n.Revoke)
+ return out, err
+}
+
+func (r Role) HasKeyAccess(key string, write bool) bool {
+ if r.Role == RootRoleName {
+ return true
+ }
+ return r.Permissions.KV.HasAccess(key, write)
+}
+
+func (r Role) HasRecursiveAccess(key string, write bool) bool {
+ if r.Role == RootRoleName {
+ return true
+ }
+ return r.Permissions.KV.HasRecursiveAccess(key, write)
+}
+
+// Grant adds a set of permissions to the permission object on which it is called,
+// returning a new permission object.
+func (p Permissions) Grant(n *Permissions) (Permissions, error) {
+ var out Permissions
+ var err error
+ if n == nil {
+ return p, nil
+ }
+ out.KV, err = p.KV.Grant(n.KV)
+ return out, err
+}
+
+// Revoke removes a set of permissions to the permission object on which it is called,
+// returning a new permission object.
+func (p Permissions) Revoke(lg *zap.Logger, n *Permissions) (Permissions, error) {
+ var out Permissions
+ var err error
+ if n == nil {
+ return p, nil
+ }
+ out.KV, err = p.KV.Revoke(lg, n.KV)
+ return out, err
+}
+
+// Grant adds a set of permissions to the permission object on which it is called,
+// returning a new permission object.
+func (rw RWPermission) Grant(n RWPermission) (RWPermission, error) {
+ var out RWPermission
+ currentRead := types.NewUnsafeSet(rw.Read...)
+ for _, r := range n.Read {
+ if currentRead.Contains(r) {
+ return out, authErr(http.StatusConflict, "Granting duplicate read permission %s", r)
+ }
+ currentRead.Add(r)
+ }
+ currentWrite := types.NewUnsafeSet(rw.Write...)
+ for _, w := range n.Write {
+ if currentWrite.Contains(w) {
+ return out, authErr(http.StatusConflict, "Granting duplicate write permission %s", w)
+ }
+ currentWrite.Add(w)
+ }
+ out.Read = currentRead.Values()
+ out.Write = currentWrite.Values()
+ sort.Strings(out.Read)
+ sort.Strings(out.Write)
+ return out, nil
+}
+
+// Revoke removes a set of permissions to the permission object on which it is called,
+// returning a new permission object.
+func (rw RWPermission) Revoke(lg *zap.Logger, n RWPermission) (RWPermission, error) {
+ var out RWPermission
+ currentRead := types.NewUnsafeSet(rw.Read...)
+ for _, r := range n.Read {
+ if !currentRead.Contains(r) {
+ lg.Info(
+ "revoking ungranted read permission",
+ zap.String("read-permission", r),
+ )
+ continue
+ }
+ currentRead.Remove(r)
+ }
+ currentWrite := types.NewUnsafeSet(rw.Write...)
+ for _, w := range n.Write {
+ if !currentWrite.Contains(w) {
+ lg.Info(
+ "revoking ungranted write permission",
+ zap.String("write-permission", w),
+ )
+ continue
+ }
+ currentWrite.Remove(w)
+ }
+ out.Read = currentRead.Values()
+ out.Write = currentWrite.Values()
+ sort.Strings(out.Read)
+ sort.Strings(out.Write)
+ return out, nil
+}
+
+func (rw RWPermission) HasAccess(key string, write bool) bool {
+ var list []string
+ if write {
+ list = rw.Write
+ } else {
+ list = rw.Read
+ }
+ for _, pat := range list {
+ match, err := simpleMatch(pat, key)
+ if err == nil && match {
+ return true
+ }
+ }
+ return false
+}
+
+func (rw RWPermission) HasRecursiveAccess(key string, write bool) bool {
+ list := rw.Read
+ if write {
+ list = rw.Write
+ }
+ for _, pat := range list {
+ match, err := prefixMatch(pat, key)
+ if err == nil && match {
+ return true
+ }
+ }
+ return false
+}
+
+func simpleMatch(pattern string, key string) (match bool, err error) {
+ if pattern[len(pattern)-1] == '*' {
+ return strings.HasPrefix(key, pattern[:len(pattern)-1]), nil
+ }
+ return key == pattern, nil
+}
+
+func prefixMatch(pattern string, key string) (match bool, err error) {
+ if pattern[len(pattern)-1] != '*' {
+ return false, nil
+ }
+ return strings.HasPrefix(key, pattern[:len(pattern)-1]), nil
+}
+
+func attachRootRole(u User) User {
+ inRoles := false
+ for _, r := range u.Roles {
+ if r == RootRoleName {
+ inRoles = true
+ break
+ }
+ }
+ if !inRoles {
+ u.Roles = append(u.Roles, RootRoleName)
+ }
+ return u
+}
+
+func (s *store) getUser(name string, quorum bool) (User, error) {
+ resp, err := s.requestResource("/users/"+name, quorum)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return User{}, authErr(http.StatusNotFound, "User %s does not exist.", name)
+ }
+ }
+ return User{}, err
+ }
+ var u User
+ err = json.Unmarshal([]byte(*resp.Event.Node.Value), &u)
+ if err != nil {
+ return u, err
+ }
+ // Attach root role to root user.
+ if u.User == "root" {
+ u = attachRootRole(u)
+ }
+ return u, nil
+}
+
+func (s *store) getRole(name string, quorum bool) (Role, error) {
+ if name == RootRoleName {
+ return rootRole, nil
+ }
+ resp, err := s.requestResource("/roles/"+name, quorum)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return Role{}, authErr(http.StatusNotFound, "Role %s does not exist.", name)
+ }
+ }
+ return Role{}, err
+ }
+ var r Role
+ err = json.Unmarshal([]byte(*resp.Event.Node.Value), &r)
+ return r, err
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth_requests.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth_requests.go
new file mode 100644
index 0000000000..6c8c50c8cc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth_requests.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 v2auth
+
+import (
+ "context"
+ "encoding/json"
+ "path"
+
+ "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+
+ "go.uber.org/zap"
+)
+
+func (s *store) ensureAuthDirectories() error {
+ if s.ensuredOnce {
+ return nil
+ }
+ for _, res := range []string{StorePermsPrefix, StorePermsPrefix + "/users/", StorePermsPrefix + "/roles/"} {
+ ctx, cancel := context.WithTimeout(context.Background(), s.timeout)
+ pe := false
+ rr := etcdserverpb.Request{
+ Method: "PUT",
+ Path: res,
+ Dir: true,
+ PrevExist: &pe,
+ }
+ _, err := s.server.Do(ctx, rr)
+ cancel()
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeNodeExist {
+ continue
+ }
+ }
+ s.lg.Warn(
+ "failed to create auth directories",
+ zap.Error(err),
+ )
+ return err
+ }
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), s.timeout)
+ defer cancel()
+ pe := false
+ rr := etcdserverpb.Request{
+ Method: "PUT",
+ Path: StorePermsPrefix + "/enabled",
+ Val: "false",
+ PrevExist: &pe,
+ }
+ _, err := s.server.Do(ctx, rr)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeNodeExist {
+ s.ensuredOnce = true
+ return nil
+ }
+ }
+ return err
+ }
+ s.ensuredOnce = true
+ return nil
+}
+
+func (s *store) enableAuth() error {
+ _, err := s.updateResource("/enabled", true)
+ return err
+}
+func (s *store) disableAuth() error {
+ _, err := s.updateResource("/enabled", false)
+ return err
+}
+
+func (s *store) detectAuth() bool {
+ if s.server == nil {
+ return false
+ }
+ value, err := s.requestResource("/enabled", false)
+ if err != nil {
+ if e, ok := err.(*v2error.Error); ok {
+ if e.ErrorCode == v2error.EcodeKeyNotFound {
+ return false
+ }
+ }
+ s.lg.Warn(
+ "failed to detect auth settings",
+ zap.Error(err),
+ )
+ return false
+ }
+
+ var u bool
+ err = json.Unmarshal([]byte(*value.Event.Node.Value), &u)
+ if err != nil {
+ s.lg.Warn(
+ "internal bookkeeping value for enabled isn't valid JSON",
+ zap.Error(err),
+ )
+ return false
+ }
+ return u
+}
+
+func (s *store) requestResource(res string, quorum bool) (etcdserver.Response, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), s.timeout)
+ defer cancel()
+ p := path.Join(StorePermsPrefix, res)
+ method := "GET"
+ if quorum {
+ method = "QGET"
+ }
+ rr := etcdserverpb.Request{
+ Method: method,
+ Path: p,
+ Dir: false, // TODO: always false?
+ }
+ return s.server.Do(ctx, rr)
+}
+
+func (s *store) updateResource(res string, value interface{}) (etcdserver.Response, error) {
+ return s.setResource(res, value, true)
+}
+func (s *store) createResource(res string, value interface{}) (etcdserver.Response, error) {
+ return s.setResource(res, value, false)
+}
+func (s *store) setResource(res string, value interface{}, prevexist bool) (etcdserver.Response, error) {
+ err := s.ensureAuthDirectories()
+ if err != nil {
+ return etcdserver.Response{}, err
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), s.timeout)
+ defer cancel()
+ data, err := json.Marshal(value)
+ if err != nil {
+ return etcdserver.Response{}, err
+ }
+ p := path.Join(StorePermsPrefix, res)
+ rr := etcdserverpb.Request{
+ Method: "PUT",
+ Path: p,
+ Val: string(data),
+ PrevExist: &prevexist,
+ }
+ return s.server.Do(ctx, rr)
+}
+
+func (s *store) deleteResource(res string) error {
+ err := s.ensureAuthDirectories()
+ if err != nil {
+ return err
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), s.timeout)
+ defer cancel()
+ pex := true
+ p := path.Join(StorePermsPrefix, res)
+ _, err = s.server.Do(ctx, etcdserverpb.Request{
+ Method: "DELETE",
+ Path: p,
+ PrevExist: &pex,
+ })
+ return err
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery/discovery.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery/discovery.go
new file mode 100644
index 0000000000..9f1bc0adf5
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery/discovery.go
@@ -0,0 +1,412 @@
+// 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 v2discovery provides an implementation of the cluster discovery that
+// is used by etcd with v2 client.
+package v2discovery
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math"
+ "net/http"
+ "net/url"
+ "path"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/client/v2"
+
+ "github.com/jonboulle/clockwork"
+ "go.uber.org/zap"
+)
+
+var (
+ 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(lg *zap.Logger, durl, dproxyurl string, id types.ID, config string) (string, error) {
+ d, err := newDiscovery(lg, 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(lg *zap.Logger, durl, dproxyurl string) (string, error) {
+ d, err := newDiscovery(lg, durl, dproxyurl, 0)
+ if err != nil {
+ return "", err
+ }
+ return d.getCluster()
+}
+
+type discovery struct {
+ lg *zap.Logger
+ 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(lg *zap.Logger, proxy string) (func(*http.Request) (*url.URL, error), error) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ 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)
+ }
+
+ lg.Info("running proxy with discovery", zap.String("proxy-url", proxyURL.String()))
+ return http.ProxyURL(proxyURL), nil
+}
+
+func newDiscovery(lg *zap.Logger, durl, dproxyurl string, id types.ID) (*discovery, error) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ u, err := url.Parse(durl)
+ if err != nil {
+ return nil, err
+ }
+ token := u.Path
+ u.Path = ""
+ pf, err := newProxyFunc(lg, 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{
+ lg: lg,
+ 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, uint64, 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 {
+ d.lg.Warn(
+ "failed to get from discovery server",
+ zap.String("discovery-url", d.url.String()),
+ zap.String("path", path.Join(configKey, "size")),
+ zap.Error(err),
+ zap.String("err-detail", ce.Detail()),
+ )
+ return d.checkClusterRetry()
+ }
+ return nil, 0, 0, err
+ }
+ size, err := strconv.ParseUint(resp.Node.Value, 10, 0)
+ 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 {
+ d.lg.Warn(
+ "failed to get from discovery server",
+ zap.String("discovery-url", d.url.String()),
+ zap.String("path", d.cluster),
+ zap.Error(err),
+ zap.String("err-detail", 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 uint64(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()) {
+ d.lg.Info(
+ "found self from discovery server",
+ zap.String("discovery-url", d.url.String()),
+ zap.String("self", path.Base(d.selfKey())),
+ )
+ } else {
+ d.lg.Info(
+ "found peer from discovery server",
+ zap.String("discovery-url", d.url.String()),
+ zap.String("peer", path.Base(n.Key)),
+ )
+ }
+ }
+
+ // wait for others
+ for uint64(len(all)) < size {
+ d.lg.Info(
+ "found peers from discovery server; waiting for more",
+ zap.String("discovery-url", d.url.String()),
+ zap.Int("found-peers", len(all)),
+ zap.Int("needed-peers", int(size-uint64(len(all)))),
+ )
+ resp, err := w.Next(context.Background())
+ if err != nil {
+ if ce, ok := err.(*client.ClusterError); ok {
+ d.lg.Warn(
+ "error while waiting for peers",
+ zap.String("discovery-url", d.url.String()),
+ zap.Error(err),
+ zap.String("err-detail", ce.Detail()),
+ )
+ return d.waitNodesRetry()
+ }
+ return nil, err
+ }
+ d.lg.Info(
+ "found peer from discovery server",
+ zap.String("discovery-url", d.url.String()),
+ zap.String("peer", path.Base(resp.Node.Key)),
+ )
+ all = append(all, resp.Node)
+ }
+ d.lg.Info(
+ "found all needed peers from discovery server",
+ zap.String("discovery-url", d.url.String()),
+ zap.Int("found-peers", len(all)),
+ )
+ return all, nil
+}
+
+func (d *discovery) selfKey() string {
+ return path.Join("/", d.cluster, d.id.String())
+}
+
+func nodesToCluster(ns []*client.Node, size uint64) (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 uint64(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/go.etcd.io/etcd/server/v3/etcdserver/api/v2error/error.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2error/error.go
new file mode 100644
index 0000000000..623863254a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2error/error.go
@@ -0,0 +1,165 @@
+// 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 v2error describes errors in etcd project. When any change happens,
+// https://github.com/etcd-io/website/blob/main/content/docs/v2/errorcode.md
+// needs to be updated correspondingly.
+// To be deprecated in favor of v3 APIs.
+package v2error
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/capability.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/capability.go
new file mode 100644
index 0000000000..718b5ed502
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/capability.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 v2http
+
+import (
+ "fmt"
+ "net/http"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes"
+)
+
+func authCapabilityHandler(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ if !api.IsCapabilityEnabled(api.AuthCapability) {
+ notCapable(w, r, api.AuthCapability)
+ return
+ }
+ fn(w, r)
+ }
+}
+
+func notCapable(w http.ResponseWriter, r *http.Request, c api.Capability) {
+ herr := httptypes.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Not capable of accessing %s feature during rolling upgrades.", c))
+ if err := herr.WriteTo(w); err != nil {
+ // TODO: the following plog was removed, add the logging back if possible
+ // plog.Debugf("error writing HTTPError (%v) to %s", err, r.RemoteAddr)
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client.go
new file mode 100644
index 0000000000..17b420732e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client.go
@@ -0,0 +1,756 @@
+// 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 v2http
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "path"
+ "strconv"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes"
+ stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+
+ "github.com/jonboulle/clockwork"
+ "go.uber.org/zap"
+)
+
+const (
+ authPrefix = "/v2/auth"
+ keysPrefix = "/v2/keys"
+ machinesPrefix = "/v2/machines"
+ membersPrefix = "/v2/members"
+ statsPrefix = "/v2/stats"
+)
+
+// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests.
+func NewClientHandler(lg *zap.Logger, server etcdserver.ServerPeer, timeout time.Duration) http.Handler {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ mux := http.NewServeMux()
+ etcdhttp.HandleBasic(lg, mux, server)
+ etcdhttp.HandleMetricsHealth(lg, mux, server)
+ handleV2(lg, mux, server, timeout)
+ return requestLogger(lg, mux)
+}
+
+func handleV2(lg *zap.Logger, mux *http.ServeMux, server etcdserver.ServerV2, timeout time.Duration) {
+ sec := v2auth.NewStore(lg, server, timeout)
+ kh := &keysHandler{
+ lg: lg,
+ sec: sec,
+ server: server,
+ cluster: server.Cluster(),
+ timeout: timeout,
+ clientCertAuthEnabled: server.ClientCertAuthEnabled(),
+ }
+
+ sh := &statsHandler{
+ lg: lg,
+ stats: server,
+ }
+
+ mh := &membersHandler{
+ lg: lg,
+ sec: sec,
+ server: server,
+ cluster: server.Cluster(),
+ timeout: timeout,
+ clock: clockwork.NewRealClock(),
+ clientCertAuthEnabled: server.ClientCertAuthEnabled(),
+ }
+
+ mah := &machinesHandler{cluster: server.Cluster()}
+
+ sech := &authHandler{
+ lg: lg,
+ sec: sec,
+ cluster: server.Cluster(),
+ clientCertAuthEnabled: server.ClientCertAuthEnabled(),
+ }
+ mux.HandleFunc("/", http.NotFound)
+ mux.Handle(keysPrefix, kh)
+ mux.Handle(keysPrefix+"/", kh)
+ mux.HandleFunc(statsPrefix+"/store", sh.serveStore)
+ mux.HandleFunc(statsPrefix+"/self", sh.serveSelf)
+ mux.HandleFunc(statsPrefix+"/leader", sh.serveLeader)
+ mux.Handle(membersPrefix, mh)
+ mux.Handle(membersPrefix+"/", mh)
+ mux.Handle(machinesPrefix, mah)
+ handleAuth(mux, sech)
+}
+
+type keysHandler struct {
+ lg *zap.Logger
+ sec v2auth.Store
+ server etcdserver.ServerV2
+ cluster api.Cluster
+ timeout time.Duration
+ clientCertAuthEnabled bool
+}
+
+func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "HEAD", "GET", "PUT", "POST", "DELETE") {
+ return
+ }
+
+ w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
+
+ ctx, cancel := context.WithTimeout(context.Background(), h.timeout)
+ defer cancel()
+ clock := clockwork.NewRealClock()
+ startTime := clock.Now()
+ rr, noValueOnSuccess, err := parseKeyRequest(r, clock)
+ if err != nil {
+ writeKeyError(h.lg, w, err)
+ return
+ }
+ // The path must be valid at this point (we've parsed the request successfully).
+ if !hasKeyPrefixAccess(h.lg, h.sec, r, r.URL.Path[len(keysPrefix):], rr.Recursive, h.clientCertAuthEnabled) {
+ writeKeyNoAuth(w)
+ return
+ }
+ if !rr.Wait {
+ reportRequestReceived(rr)
+ }
+ resp, err := h.server.Do(ctx, rr)
+ if err != nil {
+ err = trimErrorPrefix(err, etcdserver.StoreKeysPrefix)
+ writeKeyError(h.lg, w, err)
+ reportRequestFailed(rr, err)
+ return
+ }
+ switch {
+ case resp.Event != nil:
+ if err := writeKeyEvent(w, resp, noValueOnSuccess); err != nil {
+ // Should never be reached
+ h.lg.Warn("failed to write key event", zap.Error(err))
+ }
+ reportRequestCompleted(rr, startTime)
+ case resp.Watcher != nil:
+ ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout)
+ defer cancel()
+ handleKeyWatch(ctx, h.lg, w, resp, rr.Stream)
+ default:
+ writeKeyError(h.lg, w, errors.New("received response with no Event/Watcher"))
+ }
+}
+
+type machinesHandler struct {
+ cluster api.Cluster
+}
+
+func (h *machinesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET", "HEAD") {
+ return
+ }
+ endpoints := h.cluster.ClientURLs()
+ w.Write([]byte(strings.Join(endpoints, ", ")))
+}
+
+type membersHandler struct {
+ lg *zap.Logger
+ sec v2auth.Store
+ server etcdserver.ServerV2
+ cluster api.Cluster
+ timeout time.Duration
+ clock clockwork.Clock
+ clientCertAuthEnabled bool
+}
+
+func (h *membersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET", "POST", "DELETE", "PUT") {
+ return
+ }
+ if !hasWriteRootAccess(h.lg, h.sec, r, h.clientCertAuthEnabled) {
+ writeNoAuth(h.lg, w, r)
+ return
+ }
+ w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
+
+ ctx, cancel := context.WithTimeout(context.Background(), h.timeout)
+ defer cancel()
+
+ switch r.Method {
+ case "GET":
+ switch trimPrefix(r.URL.Path, membersPrefix) {
+ case "":
+ mc := newMemberCollection(h.cluster.Members())
+ w.Header().Set("Content-Type", "application/json")
+ if err := json.NewEncoder(w).Encode(mc); err != nil {
+ h.lg.Warn("failed to encode members response", zap.Error(err))
+ }
+ case "leader":
+ id := h.server.Leader()
+ if id == 0 {
+ writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusServiceUnavailable, "During election"))
+ return
+ }
+ m := newMember(h.cluster.Member(id))
+ w.Header().Set("Content-Type", "application/json")
+ if err := json.NewEncoder(w).Encode(m); err != nil {
+ h.lg.Warn("failed to encode members response", zap.Error(err))
+ }
+ default:
+ writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, "Not found"))
+ }
+
+ case "POST":
+ req := httptypes.MemberCreateRequest{}
+ if ok := unmarshalRequest(h.lg, r, &req, w); !ok {
+ return
+ }
+ now := h.clock.Now()
+ m := membership.NewMember("", req.PeerURLs, "", &now)
+ _, err := h.server.AddMember(ctx, *m)
+ switch {
+ case err == membership.ErrIDExists || err == membership.ErrPeerURLexists:
+ writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error()))
+ return
+ case err != nil:
+ h.lg.Warn(
+ "failed to add a member",
+ zap.String("member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ writeError(h.lg, w, r, err)
+ return
+ }
+ res := newMember(m)
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusCreated)
+ if err := json.NewEncoder(w).Encode(res); err != nil {
+ h.lg.Warn("failed to encode members response", zap.Error(err))
+ }
+
+ case "DELETE":
+ id, ok := getID(h.lg, r.URL.Path, w)
+ if !ok {
+ return
+ }
+ _, err := h.server.RemoveMember(ctx, uint64(id))
+ switch {
+ case err == membership.ErrIDRemoved:
+ writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusGone, fmt.Sprintf("Member permanently removed: %s", id)))
+ case err == membership.ErrIDNotFound:
+ writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", id)))
+ case err != nil:
+ h.lg.Warn(
+ "failed to remove a member",
+ zap.String("member-id", id.String()),
+ zap.Error(err),
+ )
+ writeError(h.lg, w, r, err)
+ default:
+ w.WriteHeader(http.StatusNoContent)
+ }
+
+ case "PUT":
+ id, ok := getID(h.lg, r.URL.Path, w)
+ if !ok {
+ return
+ }
+ req := httptypes.MemberUpdateRequest{}
+ if ok := unmarshalRequest(h.lg, r, &req, w); !ok {
+ return
+ }
+ m := membership.Member{
+ ID: id,
+ RaftAttributes: membership.RaftAttributes{PeerURLs: req.PeerURLs.StringSlice()},
+ }
+ _, err := h.server.UpdateMember(ctx, m)
+ switch {
+ case err == membership.ErrPeerURLexists:
+ writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error()))
+ case err == membership.ErrIDNotFound:
+ writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", id)))
+ case err != nil:
+ h.lg.Warn(
+ "failed to update a member",
+ zap.String("member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ writeError(h.lg, w, r, err)
+ default:
+ w.WriteHeader(http.StatusNoContent)
+ }
+ }
+}
+
+type statsHandler struct {
+ lg *zap.Logger
+ stats stats.Stats
+}
+
+func (h *statsHandler) serveStore(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET") {
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(h.stats.StoreStats())
+}
+
+func (h *statsHandler) serveSelf(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET") {
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(h.stats.SelfStats())
+}
+
+func (h *statsHandler) serveLeader(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET") {
+ return
+ }
+ stats := h.stats.LeaderStats()
+ if stats == nil {
+ etcdhttp.WriteError(h.lg, w, r, httptypes.NewHTTPError(http.StatusForbidden, "not current leader"))
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(stats)
+}
+
+// parseKeyRequest converts a received http.Request on keysPrefix to
+// a server Request, performing validation of supplied fields as appropriate.
+// If any validation fails, an empty Request and non-nil error is returned.
+func parseKeyRequest(r *http.Request, clock clockwork.Clock) (etcdserverpb.Request, bool, error) {
+ var noValueOnSuccess bool
+ emptyReq := etcdserverpb.Request{}
+
+ err := r.ParseForm()
+ if err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidForm,
+ err.Error(),
+ )
+ }
+
+ if !strings.HasPrefix(r.URL.Path, keysPrefix) {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidForm,
+ "incorrect key prefix",
+ )
+ }
+ p := path.Join(etcdserver.StoreKeysPrefix, r.URL.Path[len(keysPrefix):])
+
+ var pIdx, wIdx uint64
+ if pIdx, err = getUint64(r.Form, "prevIndex"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeIndexNaN,
+ `invalid value for "prevIndex"`,
+ )
+ }
+ if wIdx, err = getUint64(r.Form, "waitIndex"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeIndexNaN,
+ `invalid value for "waitIndex"`,
+ )
+ }
+
+ var rec, sort, wait, dir, quorum, stream bool
+ if rec, err = getBool(r.Form, "recursive"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `invalid value for "recursive"`,
+ )
+ }
+ if sort, err = getBool(r.Form, "sorted"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `invalid value for "sorted"`,
+ )
+ }
+ if wait, err = getBool(r.Form, "wait"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `invalid value for "wait"`,
+ )
+ }
+ // TODO(jonboulle): define what parameters dir is/isn't compatible with?
+ if dir, err = getBool(r.Form, "dir"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `invalid value for "dir"`,
+ )
+ }
+ if quorum, err = getBool(r.Form, "quorum"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `invalid value for "quorum"`,
+ )
+ }
+ if stream, err = getBool(r.Form, "stream"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `invalid value for "stream"`,
+ )
+ }
+
+ if wait && r.Method != "GET" {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `"wait" can only be used with GET requests`,
+ )
+ }
+
+ pV := r.FormValue("prevValue")
+ if _, ok := r.Form["prevValue"]; ok && pV == "" {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodePrevValueRequired,
+ `"prevValue" cannot be empty`,
+ )
+ }
+
+ if noValueOnSuccess, err = getBool(r.Form, "noValueOnSuccess"); err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ `invalid value for "noValueOnSuccess"`,
+ )
+ }
+
+ // TTL is nullable, so leave it null if not specified
+ // or an empty string
+ var ttl *uint64
+ if len(r.FormValue("ttl")) > 0 {
+ i, err := getUint64(r.Form, "ttl")
+ if err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeTTLNaN,
+ `invalid value for "ttl"`,
+ )
+ }
+ ttl = &i
+ }
+
+ // prevExist is nullable, so leave it null if not specified
+ var pe *bool
+ if _, ok := r.Form["prevExist"]; ok {
+ bv, err := getBool(r.Form, "prevExist")
+ if err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ "invalid value for prevExist",
+ )
+ }
+ pe = &bv
+ }
+
+ // refresh is nullable, so leave it null if not specified
+ var refresh *bool
+ if _, ok := r.Form["refresh"]; ok {
+ bv, err := getBool(r.Form, "refresh")
+ if err != nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeInvalidField,
+ "invalid value for refresh",
+ )
+ }
+ refresh = &bv
+ if refresh != nil && *refresh {
+ val := r.FormValue("value")
+ if _, ok := r.Form["value"]; ok && val != "" {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeRefreshValue,
+ `A value was provided on a refresh`,
+ )
+ }
+ if ttl == nil {
+ return emptyReq, false, v2error.NewRequestError(
+ v2error.EcodeRefreshTTLRequired,
+ `No TTL value set`,
+ )
+ }
+ }
+ }
+
+ rr := etcdserverpb.Request{
+ Method: r.Method,
+ Path: p,
+ Val: r.FormValue("value"),
+ Dir: dir,
+ PrevValue: pV,
+ PrevIndex: pIdx,
+ PrevExist: pe,
+ Wait: wait,
+ Since: wIdx,
+ Recursive: rec,
+ Sorted: sort,
+ Quorum: quorum,
+ Stream: stream,
+ }
+
+ if pe != nil {
+ rr.PrevExist = pe
+ }
+
+ if refresh != nil {
+ rr.Refresh = refresh
+ }
+
+ // Null TTL is equivalent to unset Expiration
+ if ttl != nil {
+ expr := time.Duration(*ttl) * time.Second
+ rr.Expiration = clock.Now().Add(expr).UnixNano()
+ }
+
+ return rr, noValueOnSuccess, nil
+}
+
+// writeKeyEvent trims the prefix of key path in a single Event under
+// StoreKeysPrefix, serializes it and writes the resulting JSON to the given
+// ResponseWriter, along with the appropriate headers.
+func writeKeyEvent(w http.ResponseWriter, resp etcdserver.Response, noValueOnSuccess bool) error {
+ ev := resp.Event
+ if ev == nil {
+ return errors.New("cannot write empty Event")
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Header().Set("X-Etcd-Index", fmt.Sprint(ev.EtcdIndex))
+ w.Header().Set("X-Raft-Index", fmt.Sprint(resp.Index))
+ w.Header().Set("X-Raft-Term", fmt.Sprint(resp.Term))
+
+ if ev.IsCreated() {
+ w.WriteHeader(http.StatusCreated)
+ }
+
+ ev = trimEventPrefix(ev, etcdserver.StoreKeysPrefix)
+ if noValueOnSuccess &&
+ (ev.Action == v2store.Set || ev.Action == v2store.CompareAndSwap ||
+ ev.Action == v2store.Create || ev.Action == v2store.Update) {
+ ev.Node = nil
+ ev.PrevNode = nil
+ }
+ return json.NewEncoder(w).Encode(ev)
+}
+
+func writeKeyNoAuth(w http.ResponseWriter) {
+ e := v2error.NewError(v2error.EcodeUnauthorized, "Insufficient credentials", 0)
+ e.WriteTo(w)
+}
+
+// writeKeyError logs and writes the given Error to the ResponseWriter.
+// If Error is not an etcdErr, the error will be converted to an etcd error.
+func writeKeyError(lg *zap.Logger, w http.ResponseWriter, err error) {
+ if err == nil {
+ return
+ }
+ switch e := err.(type) {
+ case *v2error.Error:
+ e.WriteTo(w)
+ default:
+ switch err {
+ case etcdserver.ErrTimeoutDueToLeaderFail, etcdserver.ErrTimeoutDueToConnectionLost:
+ if lg != nil {
+ lg.Warn(
+ "v2 response error",
+ zap.String("internal-server-error", err.Error()),
+ )
+ }
+ default:
+ if lg != nil {
+ lg.Warn(
+ "unexpected v2 response error",
+ zap.String("internal-server-error", err.Error()),
+ )
+ }
+ }
+ ee := v2error.NewError(v2error.EcodeRaftInternal, err.Error(), 0)
+ ee.WriteTo(w)
+ }
+}
+
+func handleKeyWatch(ctx context.Context, lg *zap.Logger, w http.ResponseWriter, resp etcdserver.Response, stream bool) {
+ wa := resp.Watcher
+ defer wa.Remove()
+ ech := wa.EventChan()
+ var nch <-chan bool
+ if x, ok := w.(http.CloseNotifier); ok {
+ nch = x.CloseNotify()
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.Header().Set("X-Etcd-Index", fmt.Sprint(wa.StartIndex()))
+ w.Header().Set("X-Raft-Index", fmt.Sprint(resp.Index))
+ w.Header().Set("X-Raft-Term", fmt.Sprint(resp.Term))
+ w.WriteHeader(http.StatusOK)
+
+ // Ensure headers are flushed early, in case of long polling
+ w.(http.Flusher).Flush()
+
+ for {
+ select {
+ case <-nch:
+ // Client closed connection. Nothing to do.
+ return
+ case <-ctx.Done():
+ // Timed out. net/http will close the connection for us, so nothing to do.
+ return
+ case ev, ok := <-ech:
+ if !ok {
+ // If the channel is closed this may be an indication of
+ // that notifications are much more than we are able to
+ // send to the client in time. Then we simply end streaming.
+ return
+ }
+ ev = trimEventPrefix(ev, etcdserver.StoreKeysPrefix)
+ if err := json.NewEncoder(w).Encode(ev); err != nil {
+ // Should never be reached
+ lg.Warn("failed to encode event", zap.Error(err))
+ return
+ }
+ if !stream {
+ return
+ }
+ w.(http.Flusher).Flush()
+ }
+ }
+}
+
+func trimEventPrefix(ev *v2store.Event, prefix string) *v2store.Event {
+ if ev == nil {
+ return nil
+ }
+ // Since the *Event may reference one in the store history
+ // history, we must copy it before modifying
+ e := ev.Clone()
+ trimNodeExternPrefix(e.Node, prefix)
+ trimNodeExternPrefix(e.PrevNode, prefix)
+ return e
+}
+
+func trimNodeExternPrefix(n *v2store.NodeExtern, prefix string) {
+ if n == nil {
+ return
+ }
+ n.Key = strings.TrimPrefix(n.Key, prefix)
+ for _, nn := range n.Nodes {
+ trimNodeExternPrefix(nn, prefix)
+ }
+}
+
+func trimErrorPrefix(err error, prefix string) error {
+ if e, ok := err.(*v2error.Error); ok {
+ e.Cause = strings.TrimPrefix(e.Cause, prefix)
+ }
+ return err
+}
+
+func unmarshalRequest(lg *zap.Logger, r *http.Request, req json.Unmarshaler, w http.ResponseWriter) bool {
+ ctype := r.Header.Get("Content-Type")
+ semicolonPosition := strings.Index(ctype, ";")
+ if semicolonPosition != -1 {
+ ctype = strings.TrimSpace(strings.ToLower(ctype[0:semicolonPosition]))
+ }
+ if ctype != "application/json" {
+ writeError(lg, w, r, httptypes.NewHTTPError(http.StatusUnsupportedMediaType, fmt.Sprintf("Bad Content-Type %s, accept application/json", ctype)))
+ return false
+ }
+ b, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ writeError(lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, err.Error()))
+ return false
+ }
+ if err := req.UnmarshalJSON(b); err != nil {
+ writeError(lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, err.Error()))
+ return false
+ }
+ return true
+}
+
+func getID(lg *zap.Logger, p string, w http.ResponseWriter) (types.ID, bool) {
+ idStr := trimPrefix(p, membersPrefix)
+ if idStr == "" {
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return 0, false
+ }
+ id, err := types.IDFromString(idStr)
+ if err != nil {
+ writeError(lg, w, nil, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", idStr)))
+ return 0, false
+ }
+ return id, true
+}
+
+// getUint64 extracts a uint64 by the given key from a Form. If the key does
+// not exist in the form, 0 is returned. If the key exists but the value is
+// badly formed, an error is returned. If multiple values are present only the
+// first is considered.
+func getUint64(form url.Values, key string) (i uint64, err error) {
+ if vals, ok := form[key]; ok {
+ i, err = strconv.ParseUint(vals[0], 10, 64)
+ }
+ return
+}
+
+// getBool extracts a bool by the given key from a Form. If the key does not
+// exist in the form, false is returned. If the key exists but the value is
+// badly formed, an error is returned. If multiple values are present only the
+// first is considered.
+func getBool(form url.Values, key string) (b bool, err error) {
+ if vals, ok := form[key]; ok {
+ b, err = strconv.ParseBool(vals[0])
+ }
+ return
+}
+
+// trimPrefix removes a given prefix and any slash following the prefix
+// e.g.: trimPrefix("foo", "foo") == trimPrefix("foo/", "foo") == ""
+func trimPrefix(p, prefix string) (s string) {
+ s = strings.TrimPrefix(p, prefix)
+ s = strings.TrimPrefix(s, "/")
+ return
+}
+
+func newMemberCollection(ms []*membership.Member) *httptypes.MemberCollection {
+ c := httptypes.MemberCollection(make([]httptypes.Member, len(ms)))
+
+ for i, m := range ms {
+ c[i] = newMember(m)
+ }
+
+ return &c
+}
+
+func newMember(m *membership.Member) httptypes.Member {
+ tm := httptypes.Member{
+ ID: m.ID.String(),
+ Name: m.Name,
+ PeerURLs: make([]string, len(m.PeerURLs)),
+ ClientURLs: make([]string, len(m.ClientURLs)),
+ }
+
+ copy(tm.PeerURLs, m.PeerURLs)
+ copy(tm.ClientURLs, m.ClientURLs)
+
+ return tm
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client_auth.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client_auth.go
new file mode 100644
index 0000000000..2c6e7744ed
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client_auth.go
@@ -0,0 +1,604 @@
+// 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 v2http
+
+import (
+ "encoding/json"
+ "net/http"
+ "path"
+ "strings"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes"
+
+ "go.uber.org/zap"
+)
+
+type authHandler struct {
+ lg *zap.Logger
+ sec v2auth.Store
+ cluster api.Cluster
+ clientCertAuthEnabled bool
+}
+
+func hasWriteRootAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, clientCertAuthEnabled bool) bool {
+ if r.Method == "GET" || r.Method == "HEAD" {
+ return true
+ }
+ return hasRootAccess(lg, sec, r, clientCertAuthEnabled)
+}
+
+func userFromBasicAuth(lg *zap.Logger, sec v2auth.Store, r *http.Request) *v2auth.User {
+ username, password, ok := r.BasicAuth()
+ if !ok {
+ lg.Warn("malformed basic auth encoding")
+ return nil
+ }
+ user, err := sec.GetUser(username)
+ if err != nil {
+ return nil
+ }
+
+ ok = sec.CheckPassword(user, password)
+ if !ok {
+ lg.Warn("incorrect password", zap.String("user-name", username))
+ return nil
+ }
+ return &user
+}
+
+func userFromClientCertificate(lg *zap.Logger, sec v2auth.Store, r *http.Request) *v2auth.User {
+ if r.TLS == nil {
+ return nil
+ }
+
+ for _, chains := range r.TLS.VerifiedChains {
+ for _, chain := range chains {
+ lg.Debug("found common name", zap.String("common-name", chain.Subject.CommonName))
+ user, err := sec.GetUser(chain.Subject.CommonName)
+ if err == nil {
+ lg.Debug(
+ "authenticated a user via common name",
+ zap.String("user-name", user.User),
+ zap.String("common-name", chain.Subject.CommonName),
+ )
+ return &user
+ }
+ }
+ }
+ return nil
+}
+
+func hasRootAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, clientCertAuthEnabled bool) bool {
+ if sec == nil {
+ // No store means no auth available, eg, tests.
+ return true
+ }
+ if !sec.AuthEnabled() {
+ return true
+ }
+
+ var rootUser *v2auth.User
+ if r.Header.Get("Authorization") == "" && clientCertAuthEnabled {
+ rootUser = userFromClientCertificate(lg, sec, r)
+ if rootUser == nil {
+ return false
+ }
+ } else {
+ rootUser = userFromBasicAuth(lg, sec, r)
+ if rootUser == nil {
+ return false
+ }
+ }
+
+ for _, role := range rootUser.Roles {
+ if role == v2auth.RootRoleName {
+ return true
+ }
+ }
+
+ lg.Warn(
+ "a user does not have root role for resource",
+ zap.String("root-user", rootUser.User),
+ zap.String("root-role-name", v2auth.RootRoleName),
+ zap.String("resource-path", r.URL.Path),
+ )
+ return false
+}
+
+func hasKeyPrefixAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, key string, recursive, clientCertAuthEnabled bool) bool {
+ if sec == nil {
+ // No store means no auth available, eg, tests.
+ return true
+ }
+ if !sec.AuthEnabled() {
+ return true
+ }
+
+ var user *v2auth.User
+ if r.Header.Get("Authorization") == "" {
+ if clientCertAuthEnabled {
+ user = userFromClientCertificate(lg, sec, r)
+ }
+ if user == nil {
+ return hasGuestAccess(lg, sec, r, key)
+ }
+ } else {
+ user = userFromBasicAuth(lg, sec, r)
+ if user == nil {
+ return false
+ }
+ }
+
+ writeAccess := r.Method != "GET" && r.Method != "HEAD"
+ for _, roleName := range user.Roles {
+ role, err := sec.GetRole(roleName)
+ if err != nil {
+ continue
+ }
+ if recursive {
+ if role.HasRecursiveAccess(key, writeAccess) {
+ return true
+ }
+ } else if role.HasKeyAccess(key, writeAccess) {
+ return true
+ }
+ }
+
+ lg.Warn(
+ "invalid access for user on key",
+ zap.String("user-name", user.User),
+ zap.String("key", key),
+ )
+ return false
+}
+
+func hasGuestAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, key string) bool {
+ writeAccess := r.Method != "GET" && r.Method != "HEAD"
+ role, err := sec.GetRole(v2auth.GuestRoleName)
+ if err != nil {
+ return false
+ }
+ if role.HasKeyAccess(key, writeAccess) {
+ return true
+ }
+
+ lg.Warn(
+ "invalid access for a guest role on key",
+ zap.String("role-name", v2auth.GuestRoleName),
+ zap.String("key", key),
+ )
+ return false
+}
+
+func writeNoAuth(lg *zap.Logger, w http.ResponseWriter, r *http.Request) {
+ herr := httptypes.NewHTTPError(http.StatusUnauthorized, "Insufficient credentials")
+ if err := herr.WriteTo(w); err != nil {
+ lg.Debug(
+ "failed to write v2 HTTP error",
+ zap.String("remote-addr", r.RemoteAddr),
+ zap.Error(err),
+ )
+ }
+}
+
+func handleAuth(mux *http.ServeMux, sh *authHandler) {
+ mux.HandleFunc(authPrefix+"/roles", authCapabilityHandler(sh.baseRoles))
+ mux.HandleFunc(authPrefix+"/roles/", authCapabilityHandler(sh.handleRoles))
+ mux.HandleFunc(authPrefix+"/users", authCapabilityHandler(sh.baseUsers))
+ mux.HandleFunc(authPrefix+"/users/", authCapabilityHandler(sh.handleUsers))
+ mux.HandleFunc(authPrefix+"/enable", authCapabilityHandler(sh.enableDisable))
+}
+
+func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET") {
+ return
+ }
+ if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) {
+ writeNoAuth(sh.lg, w, r)
+ return
+ }
+
+ w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
+ w.Header().Set("Content-Type", "application/json")
+
+ roles, err := sh.sec.AllRoles()
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ if roles == nil {
+ roles = make([]string, 0)
+ }
+
+ err = r.ParseForm()
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+
+ var rolesCollections struct {
+ Roles []v2auth.Role `json:"roles"`
+ }
+ for _, roleName := range roles {
+ var role v2auth.Role
+ role, err = sh.sec.GetRole(roleName)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ rolesCollections.Roles = append(rolesCollections.Roles, role)
+ }
+ err = json.NewEncoder(w).Encode(rolesCollections)
+
+ if err != nil {
+ sh.lg.Warn(
+ "failed to encode base roles",
+ zap.String("url", r.URL.String()),
+ zap.Error(err),
+ )
+ writeError(sh.lg, w, r, err)
+ return
+ }
+}
+
+func (sh *authHandler) handleRoles(w http.ResponseWriter, r *http.Request) {
+ subpath := path.Clean(r.URL.Path[len(authPrefix):])
+ // Split "/roles/rolename/command".
+ // First item is an empty string, second is "roles"
+ pieces := strings.Split(subpath, "/")
+ if len(pieces) == 2 {
+ sh.baseRoles(w, r)
+ return
+ }
+ if len(pieces) != 3 {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path"))
+ return
+ }
+ sh.forRole(w, r, pieces[2])
+}
+
+func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role string) {
+ if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") {
+ return
+ }
+ if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) {
+ writeNoAuth(sh.lg, w, r)
+ return
+ }
+ w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
+ w.Header().Set("Content-Type", "application/json")
+
+ switch r.Method {
+ case "GET":
+ data, err := sh.sec.GetRole(role)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ err = json.NewEncoder(w).Encode(data)
+ if err != nil {
+ sh.lg.Warn(
+ "failed to encode a role",
+ zap.String("url", r.URL.String()),
+ zap.Error(err),
+ )
+ return
+ }
+ return
+
+ case "PUT":
+ var in v2auth.Role
+ err := json.NewDecoder(r.Body).Decode(&in)
+ if err != nil {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body."))
+ return
+ }
+ if in.Role != role {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON name does not match the name in the URL"))
+ return
+ }
+
+ var out v2auth.Role
+
+ // create
+ if in.Grant.IsEmpty() && in.Revoke.IsEmpty() {
+ err = sh.sec.CreateRole(in)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ w.WriteHeader(http.StatusCreated)
+ out = in
+ } else {
+ if !in.Permissions.IsEmpty() {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON contains both permissions and grant/revoke"))
+ return
+ }
+ out, err = sh.sec.UpdateRole(in)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ w.WriteHeader(http.StatusOK)
+ }
+
+ err = json.NewEncoder(w).Encode(out)
+ if err != nil {
+ sh.lg.Warn(
+ "failed to encode a role",
+ zap.String("url", r.URL.String()),
+ zap.Error(err),
+ )
+ return
+ }
+ return
+
+ case "DELETE":
+ err := sh.sec.DeleteRole(role)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ }
+}
+
+type userWithRoles struct {
+ User string `json:"user"`
+ Roles []v2auth.Role `json:"roles,omitempty"`
+}
+
+type usersCollections struct {
+ Users []userWithRoles `json:"users"`
+}
+
+func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET") {
+ return
+ }
+ if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) {
+ writeNoAuth(sh.lg, w, r)
+ return
+ }
+ w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
+ w.Header().Set("Content-Type", "application/json")
+
+ users, err := sh.sec.AllUsers()
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ if users == nil {
+ users = make([]string, 0)
+ }
+
+ err = r.ParseForm()
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+
+ ucs := usersCollections{}
+ for _, userName := range users {
+ var user v2auth.User
+ user, err = sh.sec.GetUser(userName)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+
+ uwr := userWithRoles{User: user.User}
+ for _, roleName := range user.Roles {
+ var role v2auth.Role
+ role, err = sh.sec.GetRole(roleName)
+ if err != nil {
+ continue
+ }
+ uwr.Roles = append(uwr.Roles, role)
+ }
+
+ ucs.Users = append(ucs.Users, uwr)
+ }
+ err = json.NewEncoder(w).Encode(ucs)
+
+ if err != nil {
+ sh.lg.Warn(
+ "failed to encode users",
+ zap.String("url", r.URL.String()),
+ zap.Error(err),
+ )
+ writeError(sh.lg, w, r, err)
+ return
+ }
+}
+
+func (sh *authHandler) handleUsers(w http.ResponseWriter, r *http.Request) {
+ subpath := path.Clean(r.URL.Path[len(authPrefix):])
+ // Split "/users/username".
+ // First item is an empty string, second is "users"
+ pieces := strings.Split(subpath, "/")
+ if len(pieces) == 2 {
+ sh.baseUsers(w, r)
+ return
+ }
+ if len(pieces) != 3 {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path"))
+ return
+ }
+ sh.forUser(w, r, pieces[2])
+}
+
+func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user string) {
+ if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") {
+ return
+ }
+ if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) {
+ writeNoAuth(sh.lg, w, r)
+ return
+ }
+ w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
+ w.Header().Set("Content-Type", "application/json")
+
+ switch r.Method {
+ case "GET":
+ u, err := sh.sec.GetUser(user)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+
+ err = r.ParseForm()
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+
+ uwr := userWithRoles{User: u.User}
+ for _, roleName := range u.Roles {
+ var role v2auth.Role
+ role, err = sh.sec.GetRole(roleName)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ uwr.Roles = append(uwr.Roles, role)
+ }
+ err = json.NewEncoder(w).Encode(uwr)
+
+ if err != nil {
+ sh.lg.Warn(
+ "failed to encode roles",
+ zap.String("url", r.URL.String()),
+ zap.Error(err),
+ )
+ return
+ }
+ return
+
+ case "PUT":
+ var u v2auth.User
+ err := json.NewDecoder(r.Body).Decode(&u)
+ if err != nil {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body."))
+ return
+ }
+ if u.User != user {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON name does not match the name in the URL"))
+ return
+ }
+
+ var (
+ out v2auth.User
+ created bool
+ )
+
+ if len(u.Grant) == 0 && len(u.Revoke) == 0 {
+ // create or update
+ if len(u.Roles) != 0 {
+ out, err = sh.sec.CreateUser(u)
+ } else {
+ // if user passes in both password and roles, we are unsure about his/her
+ // intention.
+ out, created, err = sh.sec.CreateOrUpdateUser(u)
+ }
+
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ } else {
+ // update case
+ if len(u.Roles) != 0 {
+ writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON contains both roles and grant/revoke"))
+ return
+ }
+ out, err = sh.sec.UpdateUser(u)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ }
+
+ if created {
+ w.WriteHeader(http.StatusCreated)
+ } else {
+ w.WriteHeader(http.StatusOK)
+ }
+
+ out.Password = ""
+
+ err = json.NewEncoder(w).Encode(out)
+ if err != nil {
+ sh.lg.Warn(
+ "failed to encode a user",
+ zap.String("url", r.URL.String()),
+ zap.Error(err),
+ )
+ return
+ }
+ return
+
+ case "DELETE":
+ err := sh.sec.DeleteUser(user)
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ }
+}
+
+type enabled struct {
+ Enabled bool `json:"enabled"`
+}
+
+func (sh *authHandler) enableDisable(w http.ResponseWriter, r *http.Request) {
+ if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") {
+ return
+ }
+ if !hasWriteRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) {
+ writeNoAuth(sh.lg, w, r)
+ return
+ }
+ w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
+ w.Header().Set("Content-Type", "application/json")
+ isEnabled := sh.sec.AuthEnabled()
+ switch r.Method {
+ case "GET":
+ jsonDict := enabled{isEnabled}
+ err := json.NewEncoder(w).Encode(jsonDict)
+ if err != nil {
+ sh.lg.Warn(
+ "failed to encode a auth state",
+ zap.String("url", r.URL.String()),
+ zap.Error(err),
+ )
+ }
+
+ case "PUT":
+ err := sh.sec.EnableAuth()
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+
+ case "DELETE":
+ err := sh.sec.DisableAuth()
+ if err != nil {
+ writeError(sh.lg, w, r, err)
+ return
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/doc.go
new file mode 100644
index 0000000000..475c4b1f95
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/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 v2http provides etcd client and server implementations.
+package v2http
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/http.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/http.go
new file mode 100644
index 0000000000..88138b80a8
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/http.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 v2http
+
+import (
+ "math"
+ "net/http"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes"
+
+ "go.uber.org/zap"
+)
+
+const (
+ // time to wait for a Watch request
+ defaultWatchTimeout = time.Duration(math.MaxInt64)
+)
+
+func writeError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
+ if err == nil {
+ return
+ }
+ if e, ok := err.(v2auth.Error); ok {
+ herr := httptypes.NewHTTPError(e.HTTPStatus(), e.Error())
+ if et := herr.WriteTo(w); et != nil {
+ if lg != nil {
+ lg.Debug(
+ "failed to write v2 HTTP error",
+ zap.String("remote-addr", r.RemoteAddr),
+ zap.String("v2auth-error", e.Error()),
+ zap.Error(et),
+ )
+ }
+ }
+ return
+ }
+ etcdhttp.WriteError(lg, w, r, err)
+}
+
+// allowMethod verifies that the given method is one of the allowed methods,
+// and if not, it writes an error to w. A boolean is returned indicating
+// whether or not the method is allowed.
+func allowMethod(w http.ResponseWriter, m string, ms ...string) bool {
+ for _, meth := range ms {
+ if m == meth {
+ return true
+ }
+ }
+ w.Header().Set("Allow", strings.Join(ms, ","))
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return false
+}
+
+func requestLogger(lg *zap.Logger, handler http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if lg != nil {
+ lg.Debug(
+ "handling HTTP request",
+ zap.String("method", r.Method),
+ zap.String("request-uri", r.RequestURI),
+ zap.String("remote-addr", r.RemoteAddr),
+ )
+ }
+ handler.ServeHTTP(w, r)
+ })
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/errors.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/errors.go
new file mode 100644
index 0000000000..79e366f24a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/errors.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 httptypes
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+)
+
+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 {
+ panic(fmt.Sprintf("failed to marshal HTTPError: %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/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/member.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/member.go
new file mode 100644
index 0000000000..a5467be91e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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"
+
+ "go.etcd.io/etcd/client/pkg/v3/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/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/metrics.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/metrics.go
new file mode 100644
index 0000000000..bdbd8c71c1
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/metrics.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 v2http
+
+import (
+ "net/http"
+ "strconv"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+ incomingEvents = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "http",
+ Name: "received_total",
+ Help: "Counter of requests received into the system (successfully parsed and authd).",
+ }, []string{"method"})
+
+ failedEvents = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "http",
+ Name: "failed_total",
+ Help: "Counter of handle failures of requests (non-watches), by method (GET/PUT etc.) and code (400, 500 etc.).",
+ }, []string{"method", "code"})
+
+ successfulEventsHandlingSec = prometheus.NewHistogramVec(
+ prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "http",
+ Name: "successful_duration_seconds",
+ Help: "Bucketed histogram of processing time (s) of successfully handled requests (non-watches), by method (GET/PUT etc.).",
+
+ // lowest bucket start of upper bound 0.0005 sec (0.5 ms) with factor 2
+ // highest bucket start of 0.0005 sec * 2^12 == 2.048 sec
+ Buckets: prometheus.ExponentialBuckets(0.0005, 2, 13),
+ }, []string{"method"})
+)
+
+func init() {
+ prometheus.MustRegister(incomingEvents)
+ prometheus.MustRegister(failedEvents)
+ prometheus.MustRegister(successfulEventsHandlingSec)
+}
+
+func reportRequestReceived(request etcdserverpb.Request) {
+ incomingEvents.WithLabelValues(methodFromRequest(request)).Inc()
+}
+
+func reportRequestCompleted(request etcdserverpb.Request, startTime time.Time) {
+ method := methodFromRequest(request)
+ successfulEventsHandlingSec.WithLabelValues(method).Observe(time.Since(startTime).Seconds())
+}
+
+func reportRequestFailed(request etcdserverpb.Request, err error) {
+ method := methodFromRequest(request)
+ failedEvents.WithLabelValues(method, strconv.Itoa(codeFromError(err))).Inc()
+}
+
+func methodFromRequest(request etcdserverpb.Request) string {
+ if request.Method == "GET" && request.Quorum {
+ return "QGET"
+ }
+ return request.Method
+}
+
+func codeFromError(err error) int {
+ if err == nil {
+ return http.StatusInternalServerError
+ }
+ switch e := err.(type) {
+ case *v2error.Error:
+ return e.StatusCode()
+ case *httptypes.HTTPError:
+ return e.Code
+ default:
+ return http.StatusInternalServerError
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/leader.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/leader.go
new file mode 100644
index 0000000000..f17cecc2c3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/leader.go
@@ -0,0 +1,135 @@
+// 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 v2stats
+
+import (
+ "encoding/json"
+ "math"
+ "sync"
+ "time"
+
+ "go.uber.org/zap"
+)
+
+// LeaderStats is used by the leader in an etcd cluster, and encapsulates
+// statistics about communication with its followers
+type LeaderStats struct {
+ lg *zap.Logger
+ 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(lg *zap.Logger, id string) *LeaderStats {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &LeaderStats{
+ lg: lg,
+ 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 {
+ ls.lg.Error("failed to marshal leader stats", zap.Error(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/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/queue.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/queue.go
new file mode 100644
index 0000000000..2c3dff3d0f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/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 v2stats
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/server.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/server.go
new file mode 100644
index 0000000000..45effb1edc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/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 v2stats
+
+import (
+ "encoding/json"
+ "log"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/raft/v3"
+)
+
+// 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/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/stats.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/stats.go
new file mode 100644
index 0000000000..cbf60215a2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/stats.go
@@ -0,0 +1,26 @@
+// 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 v2stats defines a standard interface for etcd cluster statistics.
+package v2stats
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/doc.go
new file mode 100644
index 0000000000..1933e4cd5a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store defines etcd's in-memory key/value store in v2 API.
+// To be deprecated in favor of v3 storage.
+package v2store
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event.go
new file mode 100644
index 0000000000..33e901744d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_history.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_history.go
new file mode 100644
index 0000000000..c9bcdca051
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store
+
+import (
+ "fmt"
+ "path"
+ "strings"
+ "sync"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+)
+
+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, *v2error.Error) {
+ eh.rwl.RLock()
+ defer eh.rwl.RUnlock()
+
+ // index should be after the event history's StartIndex
+ if index < eh.StartIndex {
+ return nil,
+ v2error.NewError(v2error.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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_queue.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_queue.go
new file mode 100644
index 0000000000..7ea03de8c9
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/metrics.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/metrics.go
new file mode 100644
index 0000000000..5adea1efdd
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/metrics.go
@@ -0,0 +1,130 @@
+// 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 v2store
+
+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(readAction string) {
+ readCounter.WithLabelValues(readAction).Inc()
+}
+
+func reportReadFailure(readAction string) {
+ readCounter.WithLabelValues(readAction).Inc()
+ readFailedCounter.WithLabelValues(readAction).Inc()
+}
+
+func reportWriteSuccess(writeAction string) {
+ writeCounter.WithLabelValues(writeAction).Inc()
+}
+
+func reportWriteFailure(writeAction string) {
+ writeCounter.WithLabelValues(writeAction).Inc()
+ writeFailedCounter.WithLabelValues(writeAction).Inc()
+}
+
+func reportExpiredKey() {
+ expireCounter.Inc()
+}
+
+func reportWatchRequest() {
+ watchRequests.Inc()
+}
+
+func reportWatcherAdded() {
+ watcherCount.Inc()
+}
+
+func reportWatcherRemoved() {
+ watcherCount.Dec()
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node.go
new file mode 100644
index 0000000000..9fe6263e2e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node.go
@@ -0,0 +1,396 @@
+// 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 v2store
+
+import (
+ "path"
+ "sort"
+ "time"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+
+ "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, *v2error.Error) {
+ if n.IsDir() {
+ return "", v2error.NewError(v2error.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) *v2error.Error {
+ if n.IsDir() {
+ return v2error.NewError(v2error.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, *v2error.Error) {
+ if !n.IsDir() {
+ return nil, v2error.NewError(v2error.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, *v2error.Error) {
+ if !n.IsDir() {
+ return nil, v2error.NewError(v2error.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) *v2error.Error {
+ if !n.IsDir() {
+ return v2error.NewError(v2error.EcodeNotDir, "", n.store.CurrentIndex)
+ }
+
+ _, name := path.Split(child.Path)
+
+ if _, ok := n.Children[name]; ok {
+ return v2error.NewError(v2error.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)) *v2error.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 v2error.NewError(v2error.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 v2error.NewError(v2error.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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node_extern.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node_extern.go
new file mode 100644
index 0000000000..b3bf5f3c97
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/stats.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/stats.go
new file mode 100644
index 0000000000..9151799da7
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store
+
+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: atomic.LoadUint64(&s.GetSuccess),
+ GetFail: atomic.LoadUint64(&s.GetFail),
+ SetSuccess: atomic.LoadUint64(&s.SetSuccess),
+ SetFail: atomic.LoadUint64(&s.SetFail),
+ DeleteSuccess: atomic.LoadUint64(&s.DeleteSuccess),
+ DeleteFail: atomic.LoadUint64(&s.DeleteFail),
+ UpdateSuccess: atomic.LoadUint64(&s.UpdateSuccess),
+ UpdateFail: atomic.LoadUint64(&s.UpdateFail),
+ CreateSuccess: atomic.LoadUint64(&s.CreateSuccess),
+ CreateFail: atomic.LoadUint64(&s.CreateFail),
+ CompareAndSwapSuccess: atomic.LoadUint64(&s.CompareAndSwapSuccess),
+ CompareAndSwapFail: atomic.LoadUint64(&s.CompareAndSwapFail),
+ CompareAndDeleteSuccess: atomic.LoadUint64(&s.CompareAndDeleteSuccess),
+ CompareAndDeleteFail: atomic.LoadUint64(&s.CompareAndDeleteFail),
+ ExpireCount: atomic.LoadUint64(&s.ExpireCount),
+ Watchers: atomic.LoadUint64(&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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/store.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/store.go
new file mode 100644
index 0000000000..32cb26ad96
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/store.go
@@ -0,0 +1,799 @@
+// 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 v2store
+
+import (
+ "encoding/json"
+ "fmt"
+ "path"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+
+ "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 *v2error.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 *v2error.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 *v2error.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 != v2error.EcodeKeyNotFound {
+ err = getErr
+ return nil, err
+ }
+
+ if expireOpts.Refresh {
+ if getErr != nil {
+ err = getErr
+ return nil, err
+ }
+ 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 *v2error.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, v2error.NewError(v2error.EcodeRootROnly, "/", s.CurrentIndex)
+ }
+
+ n, err := s.internalGet(nodePath)
+ if err != nil {
+ return nil, err
+ }
+ if n.IsDir() { // can only compare and swap file
+ err = v2error.NewError(v2error.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 = v2error.NewError(v2error.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
+ if err := n.Write(value, s.CurrentIndex); err != nil {
+ return nil, err
+ }
+ 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 *v2error.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, v2error.NewError(v2error.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 *v2error.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, v2error.NewError(v2error.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, v2error.NewError(v2error.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, *v2error.Error)) (*node, *v2error.Error) {
+ components := strings.Split(nodePath, "/")
+
+ curr := s.Root
+ var err *v2error.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 *v2error.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, v2error.NewError(v2error.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, v2error.NewError(v2error.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
+
+ if err := n.Write(newValue, nextIndex); err != nil {
+ return nil, fmt.Errorf("nodePath %v : %v", nodePath, err)
+ }
+
+ 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, *v2error.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, v2error.NewError(v2error.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, v2error.NewError(v2error.EcodeNotFile, nodePath, currIndex)
+ }
+ e.PrevNode = n.Repr(false, false, s.clock)
+
+ if err := n.Remove(false, false, nil); err != nil {
+ return nil, err
+ }
+ } else {
+ return nil, v2error.NewError(v2error.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
+ if err := d.Add(n); err != nil {
+ return nil, err
+ }
+
+ // 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, *v2error.Error) {
+ nodePath = path.Clean(path.Join("/", nodePath))
+
+ walkFunc := func(parent *node, name string) (*node, *v2error.Error) {
+
+ if !parent.IsDir() {
+ err := v2error.NewError(v2error.EcodeNotDir, parent.Path, s.CurrentIndex)
+ return nil, err
+ }
+
+ child, ok := parent.Children[name]
+ if ok {
+ return child, nil
+ }
+
+ return nil, v2error.NewError(v2error.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, *v2error.Error) {
+ node, ok := parent.Children[dirName]
+
+ if ok {
+ if node.IsDir() {
+ return node, nil
+ }
+
+ return nil, v2error.NewError(v2error.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.RLock()
+
+ 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.RUnlock()
+ 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 goroutines.
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/ttl_key_heap.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/ttl_key_heap.go
new file mode 100644
index 0000000000..477d2b9f3a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/ttl_key_heap.go
@@ -0,0 +1,97 @@
+// 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 v2store
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher.go
new file mode 100644
index 0000000000..4b1e846a2f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store
+
+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/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher_hub.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher_hub.go
new file mode 100644
index 0000000000..dc5c8f2bb5
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/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 v2store
+
+import (
+ "container/list"
+ "path"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+)
+
+// 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, *v2error.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/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/cluster.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/cluster.go
new file mode 100644
index 0000000000..d275e05718
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/cluster.go
@@ -0,0 +1,31 @@
+// 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 v2v3
+
+import (
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+
+ "github.com/coreos/go-semver/semver"
+)
+
+func (s *v2v3Server) ID() types.ID {
+ // TODO: use an actual member ID
+ return types.ID(0xe7cd2f00d)
+}
+func (s *v2v3Server) ClientURLs() []string { panic("STUB") }
+func (s *v2v3Server) Members() []*membership.Member { panic("STUB") }
+func (s *v2v3Server) Member(id types.ID) *membership.Member { panic("STUB") }
+func (s *v2v3Server) Version() *semver.Version { panic("STUB") }
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/doc.go
new file mode 100644
index 0000000000..2ff372f187
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/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 v2v3 provides a ServerV2 implementation backed by clientv3.Client.
+package v2v3
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/server.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/server.go
new file mode 100644
index 0000000000..71557ceb5c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/server.go
@@ -0,0 +1,130 @@
+// 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 v2v3
+
+import (
+ "context"
+ "net/http"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+
+ "github.com/coreos/go-semver/semver"
+ "go.uber.org/zap"
+)
+
+type fakeStats struct{}
+
+func (s *fakeStats) SelfStats() []byte { return nil }
+func (s *fakeStats) LeaderStats() []byte { return nil }
+func (s *fakeStats) StoreStats() []byte { return nil }
+
+type v2v3Server struct {
+ lg *zap.Logger
+ c *clientv3.Client
+ store *v2v3Store
+ fakeStats
+}
+
+func NewServer(lg *zap.Logger, c *clientv3.Client, pfx string) etcdserver.ServerPeer {
+ return &v2v3Server{lg: lg, c: c, store: newStore(c, pfx)}
+}
+
+func (s *v2v3Server) ClientCertAuthEnabled() bool { return false }
+
+func (s *v2v3Server) LeaseHandler() http.Handler { panic("STUB: lease handler") }
+func (s *v2v3Server) RaftHandler() http.Handler { panic("STUB: raft handler") }
+
+func (s *v2v3Server) Leader() types.ID {
+ ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
+ defer cancel()
+ resp, err := s.c.Status(ctx, s.c.Endpoints()[0])
+ if err != nil {
+ return 0
+ }
+ return types.ID(resp.Leader)
+}
+
+func (s *v2v3Server) AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) {
+ // adding member as learner is not supported by V2 Server.
+ resp, err := s.c.MemberAdd(ctx, memb.PeerURLs)
+ if err != nil {
+ return nil, err
+ }
+ return v3MembersToMembership(resp.Members), nil
+}
+
+func (s *v2v3Server) RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error) {
+ resp, err := s.c.MemberRemove(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+ return v3MembersToMembership(resp.Members), nil
+}
+
+func (s *v2v3Server) PromoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) {
+ resp, err := s.c.MemberPromote(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+ return v3MembersToMembership(resp.Members), nil
+}
+
+func (s *v2v3Server) UpdateMember(ctx context.Context, m membership.Member) ([]*membership.Member, error) {
+ resp, err := s.c.MemberUpdate(ctx, uint64(m.ID), m.PeerURLs)
+ if err != nil {
+ return nil, err
+ }
+ return v3MembersToMembership(resp.Members), nil
+}
+
+func v3MembersToMembership(v3membs []*pb.Member) []*membership.Member {
+ membs := make([]*membership.Member, len(v3membs))
+ for i, m := range v3membs {
+ membs[i] = &membership.Member{
+ ID: types.ID(m.ID),
+ RaftAttributes: membership.RaftAttributes{
+ PeerURLs: m.PeerURLs,
+ IsLearner: m.IsLearner,
+ },
+ Attributes: membership.Attributes{
+ Name: m.Name,
+ ClientURLs: m.ClientURLs,
+ },
+ }
+ }
+ return membs
+}
+
+func (s *v2v3Server) ClusterVersion() *semver.Version { return s.Version() }
+func (s *v2v3Server) Cluster() api.Cluster { return s }
+func (s *v2v3Server) Alarms() []*pb.AlarmMember { return nil }
+func (s *v2v3Server) LeaderChangedNotify() <-chan struct{} { return nil }
+
+func (s *v2v3Server) Do(ctx context.Context, r pb.Request) (etcdserver.Response, error) {
+ applier := etcdserver.NewApplierV2(s.lg, s.store, nil)
+ reqHandler := etcdserver.NewStoreRequestV2Handler(s.store, applier)
+ req := (*etcdserver.RequestV2)(&r)
+ resp, err := req.Handle(ctx, reqHandler)
+ if resp.Err != nil {
+ return resp, resp.Err
+ }
+ return resp, err
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/store.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/store.go
new file mode 100644
index 0000000000..6d78cab719
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/store.go
@@ -0,0 +1,638 @@
+// 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 v2v3
+
+import (
+ "context"
+ "fmt"
+ "path"
+ "sort"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/client/v3/concurrency"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+)
+
+// store implements the Store interface for V2 using
+// a v3 client.
+type v2v3Store struct {
+ c *clientv3.Client
+ // pfx is the v3 prefix where keys should be stored.
+ pfx string
+ ctx context.Context
+}
+
+const maxPathDepth = 63
+
+var errUnsupported = fmt.Errorf("TTLs are unsupported")
+
+func NewStore(c *clientv3.Client, pfx string) v2store.Store { return newStore(c, pfx) }
+
+func newStore(c *clientv3.Client, pfx string) *v2v3Store { return &v2v3Store{c, pfx, c.Ctx()} }
+
+func (s *v2v3Store) Index() uint64 { panic("STUB") }
+
+func (s *v2v3Store) Get(nodePath string, recursive, sorted bool) (*v2store.Event, error) {
+ key := s.mkPath(nodePath)
+ resp, err := s.c.Txn(s.ctx).Then(
+ clientv3.OpGet(key+"/"),
+ clientv3.OpGet(key),
+ ).Commit()
+ if err != nil {
+ return nil, err
+ }
+
+ if kvs := resp.Responses[0].GetResponseRange().Kvs; len(kvs) != 0 || isRoot(nodePath) {
+ nodes, err := s.getDir(nodePath, recursive, sorted, resp.Header.Revision)
+ if err != nil {
+ return nil, err
+ }
+ cidx, midx := uint64(0), uint64(0)
+ if len(kvs) > 0 {
+ cidx, midx = mkV2Rev(kvs[0].CreateRevision), mkV2Rev(kvs[0].ModRevision)
+ }
+ return &v2store.Event{
+ Action: v2store.Get,
+ Node: &v2store.NodeExtern{
+ Key: nodePath,
+ Dir: true,
+ Nodes: nodes,
+ CreatedIndex: cidx,
+ ModifiedIndex: midx,
+ },
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+ }
+
+ kvs := resp.Responses[1].GetResponseRange().Kvs
+ if len(kvs) == 0 {
+ return nil, v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+
+ return &v2store.Event{
+ Action: v2store.Get,
+ Node: s.mkV2Node(kvs[0]),
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) getDir(nodePath string, recursive, sorted bool, rev int64) ([]*v2store.NodeExtern, error) {
+ rootNodes, err := s.getDirDepth(nodePath, 1, rev)
+ if err != nil || !recursive {
+ if sorted {
+ sort.Sort(v2store.NodeExterns(rootNodes))
+ }
+ return rootNodes, err
+ }
+ nextNodes := rootNodes
+ nodes := make(map[string]*v2store.NodeExtern)
+ // Breadth walk the subdirectories
+ for i := 2; len(nextNodes) > 0; i++ {
+ for _, n := range nextNodes {
+ nodes[n.Key] = n
+ if parent := nodes[path.Dir(n.Key)]; parent != nil {
+ parent.Nodes = append(parent.Nodes, n)
+ }
+ }
+ if nextNodes, err = s.getDirDepth(nodePath, i, rev); err != nil {
+ return nil, err
+ }
+ }
+
+ if sorted {
+ sort.Sort(v2store.NodeExterns(rootNodes))
+ }
+ return rootNodes, nil
+}
+
+func (s *v2v3Store) getDirDepth(nodePath string, depth int, rev int64) ([]*v2store.NodeExtern, error) {
+ pd := s.mkPathDepth(nodePath, depth)
+ resp, err := s.c.Get(s.ctx, pd, clientv3.WithPrefix(), clientv3.WithRev(rev))
+ if err != nil {
+ return nil, err
+ }
+
+ nodes := make([]*v2store.NodeExtern, len(resp.Kvs))
+ for i, kv := range resp.Kvs {
+ nodes[i] = s.mkV2Node(kv)
+ }
+ return nodes, nil
+}
+
+func (s *v2v3Store) Set(
+ nodePath string,
+ dir bool,
+ value string,
+ expireOpts v2store.TTLOptionSet,
+) (*v2store.Event, error) {
+ if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() {
+ return nil, errUnsupported
+ }
+
+ if isRoot(nodePath) {
+ return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0)
+ }
+
+ ecode := 0
+ applyf := func(stm concurrency.STM) error {
+ // build path if any directories in path do not exist
+ dirs := []string{}
+ for p := path.Dir(nodePath); !isRoot(p); p = path.Dir(p) {
+ pp := s.mkPath(p)
+ if stm.Rev(pp) > 0 {
+ ecode = v2error.EcodeNotDir
+ return nil
+ }
+ if stm.Rev(pp+"/") == 0 {
+ dirs = append(dirs, pp+"/")
+ }
+ }
+ for _, d := range dirs {
+ stm.Put(d, "")
+ }
+
+ key := s.mkPath(nodePath)
+ if dir {
+ if stm.Rev(key) != 0 {
+ // exists as non-dir
+ ecode = v2error.EcodeNotDir
+ return nil
+ }
+ key = key + "/"
+ } else if stm.Rev(key+"/") != 0 {
+ ecode = v2error.EcodeNotFile
+ return nil
+ }
+ stm.Put(key, value, clientv3.WithPrevKV())
+ stm.Put(s.mkActionKey(), v2store.Set)
+ return nil
+ }
+
+ resp, err := s.newSTM(applyf)
+ if err != nil {
+ return nil, err
+ }
+ if ecode != 0 {
+ return nil, v2error.NewError(ecode, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+
+ createRev := resp.Header.Revision
+ var pn *v2store.NodeExtern
+ if pkv := prevKeyFromPuts(resp); pkv != nil {
+ pn = s.mkV2Node(pkv)
+ createRev = pkv.CreateRevision
+ }
+
+ vp := &value
+ if dir {
+ vp = nil
+ }
+ return &v2store.Event{
+ Action: v2store.Set,
+ Node: &v2store.NodeExtern{
+ Key: nodePath,
+ Value: vp,
+ Dir: dir,
+ ModifiedIndex: mkV2Rev(resp.Header.Revision),
+ CreatedIndex: mkV2Rev(createRev),
+ },
+ PrevNode: pn,
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) Update(nodePath, newValue string, expireOpts v2store.TTLOptionSet) (*v2store.Event, error) {
+ if isRoot(nodePath) {
+ return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0)
+ }
+
+ if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() {
+ return nil, errUnsupported
+ }
+
+ key := s.mkPath(nodePath)
+ ecode := 0
+ applyf := func(stm concurrency.STM) error {
+ if rev := stm.Rev(key + "/"); rev != 0 {
+ ecode = v2error.EcodeNotFile
+ return nil
+ }
+ if rev := stm.Rev(key); rev == 0 {
+ ecode = v2error.EcodeKeyNotFound
+ return nil
+ }
+ stm.Put(key, newValue, clientv3.WithPrevKV())
+ stm.Put(s.mkActionKey(), v2store.Update)
+ return nil
+ }
+
+ resp, err := s.newSTM(applyf)
+ if err != nil {
+ return nil, err
+ }
+ if ecode != 0 {
+ return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+
+ pkv := prevKeyFromPuts(resp)
+ return &v2store.Event{
+ Action: v2store.Update,
+ Node: &v2store.NodeExtern{
+ Key: nodePath,
+ Value: &newValue,
+ ModifiedIndex: mkV2Rev(resp.Header.Revision),
+ CreatedIndex: mkV2Rev(pkv.CreateRevision),
+ },
+ PrevNode: s.mkV2Node(pkv),
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) Create(
+ nodePath string,
+ dir bool,
+ value string,
+ unique bool,
+ expireOpts v2store.TTLOptionSet,
+) (*v2store.Event, error) {
+ if isRoot(nodePath) {
+ return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0)
+ }
+ if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() {
+ return nil, errUnsupported
+ }
+ ecode := 0
+ applyf := func(stm concurrency.STM) error {
+ ecode = 0
+ key := s.mkPath(nodePath)
+ if unique {
+ // append unique item under the node path
+ for {
+ key = nodePath + "/" + fmt.Sprintf("%020s", time.Now())
+ key = path.Clean(path.Join("/", key))
+ key = s.mkPath(key)
+ if stm.Rev(key) == 0 {
+ break
+ }
+ }
+ }
+ if stm.Rev(key) > 0 || stm.Rev(key+"/") > 0 {
+ ecode = v2error.EcodeNodeExist
+ return nil
+ }
+ // build path if any directories in path do not exist
+ dirs := []string{}
+ for p := path.Dir(nodePath); !isRoot(p); p = path.Dir(p) {
+ pp := s.mkPath(p)
+ if stm.Rev(pp) > 0 {
+ ecode = v2error.EcodeNotDir
+ return nil
+ }
+ if stm.Rev(pp+"/") == 0 {
+ dirs = append(dirs, pp+"/")
+ }
+ }
+ for _, d := range dirs {
+ stm.Put(d, "")
+ }
+
+ if dir {
+ // directories marked with extra slash in key name
+ key += "/"
+ }
+ stm.Put(key, value)
+ stm.Put(s.mkActionKey(), v2store.Create)
+ return nil
+ }
+
+ resp, err := s.newSTM(applyf)
+ if err != nil {
+ return nil, err
+ }
+ if ecode != 0 {
+ return nil, v2error.NewError(ecode, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+
+ var v *string
+ if !dir {
+ v = &value
+ }
+
+ return &v2store.Event{
+ Action: v2store.Create,
+ Node: &v2store.NodeExtern{
+ Key: nodePath,
+ Value: v,
+ Dir: dir,
+ ModifiedIndex: mkV2Rev(resp.Header.Revision),
+ CreatedIndex: mkV2Rev(resp.Header.Revision),
+ },
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) CompareAndSwap(
+ nodePath string,
+ prevValue string,
+ prevIndex uint64,
+ value string,
+ expireOpts v2store.TTLOptionSet,
+) (*v2store.Event, error) {
+ if isRoot(nodePath) {
+ return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0)
+ }
+ if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() {
+ return nil, errUnsupported
+ }
+
+ key := s.mkPath(nodePath)
+ resp, err := s.c.Txn(s.ctx).If(
+ s.mkCompare(nodePath, prevValue, prevIndex)...,
+ ).Then(
+ clientv3.OpPut(key, value, clientv3.WithPrevKV()),
+ clientv3.OpPut(s.mkActionKey(), v2store.CompareAndSwap),
+ ).Else(
+ clientv3.OpGet(key),
+ clientv3.OpGet(key+"/"),
+ ).Commit()
+
+ if err != nil {
+ return nil, err
+ }
+ if !resp.Succeeded {
+ return nil, compareFail(nodePath, prevValue, prevIndex, resp)
+ }
+
+ pkv := resp.Responses[0].GetResponsePut().PrevKv
+ return &v2store.Event{
+ Action: v2store.CompareAndSwap,
+ Node: &v2store.NodeExtern{
+ Key: nodePath,
+ Value: &value,
+ CreatedIndex: mkV2Rev(pkv.CreateRevision),
+ ModifiedIndex: mkV2Rev(resp.Header.Revision),
+ },
+ PrevNode: s.mkV2Node(pkv),
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) Delete(nodePath string, dir, recursive bool) (*v2store.Event, error) {
+ if isRoot(nodePath) {
+ return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0)
+ }
+ if !dir && !recursive {
+ return s.deleteNode(nodePath)
+ }
+ if !recursive {
+ return s.deleteEmptyDir(nodePath)
+ }
+
+ dels := make([]clientv3.Op, maxPathDepth+1)
+ dels[0] = clientv3.OpDelete(s.mkPath(nodePath)+"/", clientv3.WithPrevKV())
+ for i := 1; i < maxPathDepth; i++ {
+ dels[i] = clientv3.OpDelete(s.mkPathDepth(nodePath, i), clientv3.WithPrefix())
+ }
+ dels[maxPathDepth] = clientv3.OpPut(s.mkActionKey(), v2store.Delete)
+
+ resp, err := s.c.Txn(s.ctx).If(
+ clientv3.Compare(clientv3.Version(s.mkPath(nodePath)+"/"), ">", 0),
+ clientv3.Compare(clientv3.Version(s.mkPathDepth(nodePath, maxPathDepth)+"/"), "=", 0),
+ ).Then(
+ dels...,
+ ).Commit()
+ if err != nil {
+ return nil, err
+ }
+ if !resp.Succeeded {
+ return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+ dresp := resp.Responses[0].GetResponseDeleteRange()
+ return &v2store.Event{
+ Action: v2store.Delete,
+ PrevNode: s.mkV2Node(dresp.PrevKvs[0]),
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) deleteEmptyDir(nodePath string) (*v2store.Event, error) {
+ resp, err := s.c.Txn(s.ctx).If(
+ clientv3.Compare(clientv3.Version(s.mkPathDepth(nodePath, 1)), "=", 0).WithPrefix(),
+ ).Then(
+ clientv3.OpDelete(s.mkPath(nodePath)+"/", clientv3.WithPrevKV()),
+ clientv3.OpPut(s.mkActionKey(), v2store.Delete),
+ ).Commit()
+ if err != nil {
+ return nil, err
+ }
+ if !resp.Succeeded {
+ return nil, v2error.NewError(v2error.EcodeDirNotEmpty, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+ dresp := resp.Responses[0].GetResponseDeleteRange()
+ if len(dresp.PrevKvs) == 0 {
+ return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+ return &v2store.Event{
+ Action: v2store.Delete,
+ PrevNode: s.mkV2Node(dresp.PrevKvs[0]),
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) deleteNode(nodePath string) (*v2store.Event, error) {
+ resp, err := s.c.Txn(s.ctx).If(
+ clientv3.Compare(clientv3.Version(s.mkPath(nodePath)+"/"), "=", 0),
+ ).Then(
+ clientv3.OpDelete(s.mkPath(nodePath), clientv3.WithPrevKV()),
+ clientv3.OpPut(s.mkActionKey(), v2store.Delete),
+ ).Commit()
+ if err != nil {
+ return nil, err
+ }
+ if !resp.Succeeded {
+ return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+ pkvs := resp.Responses[0].GetResponseDeleteRange().PrevKvs
+ if len(pkvs) == 0 {
+ return nil, v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+ pkv := pkvs[0]
+ return &v2store.Event{
+ Action: v2store.Delete,
+ Node: &v2store.NodeExtern{
+ Key: nodePath,
+ CreatedIndex: mkV2Rev(pkv.CreateRevision),
+ ModifiedIndex: mkV2Rev(resp.Header.Revision),
+ },
+ PrevNode: s.mkV2Node(pkv),
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func (s *v2v3Store) CompareAndDelete(nodePath, prevValue string, prevIndex uint64) (*v2store.Event, error) {
+ if isRoot(nodePath) {
+ return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0)
+ }
+
+ key := s.mkPath(nodePath)
+ resp, err := s.c.Txn(s.ctx).If(
+ s.mkCompare(nodePath, prevValue, prevIndex)...,
+ ).Then(
+ clientv3.OpDelete(key, clientv3.WithPrevKV()),
+ clientv3.OpPut(s.mkActionKey(), v2store.CompareAndDelete),
+ ).Else(
+ clientv3.OpGet(key),
+ clientv3.OpGet(key+"/"),
+ ).Commit()
+
+ if err != nil {
+ return nil, err
+ }
+ if !resp.Succeeded {
+ return nil, compareFail(nodePath, prevValue, prevIndex, resp)
+ }
+
+ // len(pkvs) > 1 since txn only succeeds when key exists
+ pkv := resp.Responses[0].GetResponseDeleteRange().PrevKvs[0]
+ return &v2store.Event{
+ Action: v2store.CompareAndDelete,
+ Node: &v2store.NodeExtern{
+ Key: nodePath,
+ CreatedIndex: mkV2Rev(pkv.CreateRevision),
+ ModifiedIndex: mkV2Rev(resp.Header.Revision),
+ },
+ PrevNode: s.mkV2Node(pkv),
+ EtcdIndex: mkV2Rev(resp.Header.Revision),
+ }, nil
+}
+
+func compareFail(nodePath, prevValue string, prevIndex uint64, resp *clientv3.TxnResponse) error {
+ if dkvs := resp.Responses[1].GetResponseRange().Kvs; len(dkvs) > 0 {
+ return v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+ kvs := resp.Responses[0].GetResponseRange().Kvs
+ if len(kvs) == 0 {
+ return v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision))
+ }
+ kv := kvs[0]
+ indexMatch := prevIndex == 0 || kv.ModRevision == int64(prevIndex)
+ valueMatch := prevValue == "" || string(kv.Value) == prevValue
+ var cause string
+ switch {
+ case indexMatch && !valueMatch:
+ cause = fmt.Sprintf("[%v != %v]", prevValue, string(kv.Value))
+ case valueMatch && !indexMatch:
+ cause = fmt.Sprintf("[%v != %v]", prevIndex, kv.ModRevision)
+ default:
+ cause = fmt.Sprintf("[%v != %v] [%v != %v]", prevValue, string(kv.Value), prevIndex, kv.ModRevision)
+ }
+ return v2error.NewError(v2error.EcodeTestFailed, cause, mkV2Rev(resp.Header.Revision))
+}
+
+func (s *v2v3Store) mkCompare(nodePath, prevValue string, prevIndex uint64) []clientv3.Cmp {
+ key := s.mkPath(nodePath)
+ cmps := []clientv3.Cmp{clientv3.Compare(clientv3.Version(key), ">", 0)}
+ if prevIndex != 0 {
+ cmps = append(cmps, clientv3.Compare(clientv3.ModRevision(key), "=", mkV3Rev(prevIndex)))
+ }
+ if prevValue != "" {
+ cmps = append(cmps, clientv3.Compare(clientv3.Value(key), "=", prevValue))
+ }
+ return cmps
+}
+
+func (s *v2v3Store) JsonStats() []byte { panic("STUB") }
+func (s *v2v3Store) DeleteExpiredKeys(cutoff time.Time) { panic("STUB") }
+
+func (s *v2v3Store) Version() int { return 2 }
+
+// TODO: move this out of the Store interface?
+
+func (s *v2v3Store) Save() ([]byte, error) { panic("STUB") }
+func (s *v2v3Store) Recovery(state []byte) error { panic("STUB") }
+func (s *v2v3Store) Clone() v2store.Store { panic("STUB") }
+func (s *v2v3Store) SaveNoCopy() ([]byte, error) { panic("STUB") }
+func (s *v2v3Store) HasTTLKeys() bool { panic("STUB") }
+
+func (s *v2v3Store) mkPath(nodePath string) string { return s.mkPathDepth(nodePath, 0) }
+
+func (s *v2v3Store) mkNodePath(p string) string {
+ return path.Clean(p[len(s.pfx)+len("/k/000/"):])
+}
+
+// mkPathDepth makes a path to a key that encodes its directory depth
+// for fast directory listing. If a depth is provided, it is added
+// to the computed depth.
+func (s *v2v3Store) mkPathDepth(nodePath string, depth int) string {
+ normalForm := path.Clean(path.Join("/", nodePath))
+ n := strings.Count(normalForm, "/") + depth
+ return fmt.Sprintf("%s/%03d/k/%s", s.pfx, n, normalForm)
+}
+
+func (s *v2v3Store) mkActionKey() string { return s.pfx + "/act" }
+
+func isRoot(s string) bool { return len(s) == 0 || s == "/" || s == "/0" || s == "/1" }
+
+func mkV2Rev(v3Rev int64) uint64 {
+ if v3Rev == 0 {
+ return 0
+ }
+ return uint64(v3Rev - 1)
+}
+
+func mkV3Rev(v2Rev uint64) int64 {
+ if v2Rev == 0 {
+ return 0
+ }
+ return int64(v2Rev + 1)
+}
+
+// mkV2Node creates a V2 NodeExtern from a V3 KeyValue
+func (s *v2v3Store) mkV2Node(kv *mvccpb.KeyValue) *v2store.NodeExtern {
+ if kv == nil {
+ return nil
+ }
+ n := &v2store.NodeExtern{
+ Key: s.mkNodePath(string(kv.Key)),
+ Dir: kv.Key[len(kv.Key)-1] == '/',
+ CreatedIndex: mkV2Rev(kv.CreateRevision),
+ ModifiedIndex: mkV2Rev(kv.ModRevision),
+ }
+ if !n.Dir {
+ v := string(kv.Value)
+ n.Value = &v
+ }
+ return n
+}
+
+// prevKeyFromPuts gets the prev key that is being put; ignores
+// the put action response.
+func prevKeyFromPuts(resp *clientv3.TxnResponse) *mvccpb.KeyValue {
+ for _, r := range resp.Responses {
+ pkv := r.GetResponsePut().PrevKv
+ if pkv != nil && pkv.CreateRevision > 0 {
+ return pkv
+ }
+ }
+ return nil
+}
+
+func (s *v2v3Store) newSTM(applyf func(concurrency.STM) error) (*clientv3.TxnResponse, error) {
+ return concurrency.NewSTM(s.c, applyf, concurrency.WithIsolation(concurrency.Serializable))
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/watcher.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/watcher.go
new file mode 100644
index 0000000000..046c25d450
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/watcher.go
@@ -0,0 +1,142 @@
+// 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 v2v3
+
+import (
+ "context"
+ "strings"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2error"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+)
+
+func (s *v2v3Store) Watch(prefix string, recursive, stream bool, sinceIndex uint64) (v2store.Watcher, error) {
+ ctx, cancel := context.WithCancel(s.ctx)
+ wch := s.c.Watch(
+ ctx,
+ // TODO: very pricey; use a single store-wide watch in future
+ s.pfx,
+ clientv3.WithPrefix(),
+ clientv3.WithRev(int64(sinceIndex)),
+ clientv3.WithCreatedNotify(),
+ clientv3.WithPrevKV())
+ resp, ok := <-wch
+ if err := resp.Err(); err != nil || !ok {
+ cancel()
+ return nil, v2error.NewError(v2error.EcodeRaftInternal, prefix, 0)
+ }
+
+ evc, donec := make(chan *v2store.Event), make(chan struct{})
+ go func() {
+ defer func() {
+ close(evc)
+ close(donec)
+ }()
+ for resp := range wch {
+ for _, ev := range s.mkV2Events(resp) {
+ k := ev.Node.Key
+ if recursive {
+ if !strings.HasPrefix(k, prefix) {
+ continue
+ }
+ // accept events on hidden keys given in prefix
+ k = strings.Replace(k, prefix, "/", 1)
+ // ignore hidden keys deeper than prefix
+ if strings.Contains(k, "/_") {
+ continue
+ }
+ }
+ if !recursive && k != prefix {
+ continue
+ }
+ select {
+ case evc <- ev:
+ case <-ctx.Done():
+ return
+ }
+ if !stream {
+ return
+ }
+ }
+ }
+ }()
+
+ return &v2v3Watcher{
+ startRev: resp.Header.Revision,
+ evc: evc,
+ donec: donec,
+ cancel: cancel,
+ }, nil
+}
+
+func (s *v2v3Store) mkV2Events(wr clientv3.WatchResponse) (evs []*v2store.Event) {
+ ak := s.mkActionKey()
+ for _, rev := range mkRevs(wr) {
+ var act, key *clientv3.Event
+ for _, ev := range rev {
+ if string(ev.Kv.Key) == ak {
+ act = ev
+ } else if key != nil && len(key.Kv.Key) < len(ev.Kv.Key) {
+ // use longest key to ignore intermediate new
+ // directories from Create.
+ key = ev
+ } else if key == nil {
+ key = ev
+ }
+ }
+ if act != nil && act.Kv != nil && key != nil {
+ v2ev := &v2store.Event{
+ Action: string(act.Kv.Value),
+ Node: s.mkV2Node(key.Kv),
+ PrevNode: s.mkV2Node(key.PrevKv),
+ EtcdIndex: mkV2Rev(wr.Header.Revision),
+ }
+ evs = append(evs, v2ev)
+ }
+ }
+ return evs
+}
+
+func mkRevs(wr clientv3.WatchResponse) (revs [][]*clientv3.Event) {
+ var curRev []*clientv3.Event
+ for _, ev := range wr.Events {
+ if curRev != nil && ev.Kv.ModRevision != curRev[0].Kv.ModRevision {
+ revs = append(revs, curRev)
+ curRev = nil
+ }
+ curRev = append(curRev, ev)
+ }
+ if curRev != nil {
+ revs = append(revs, curRev)
+ }
+ return revs
+}
+
+type v2v3Watcher struct {
+ startRev int64
+ evc chan *v2store.Event
+ donec chan struct{}
+ cancel context.CancelFunc
+}
+
+func (w *v2v3Watcher) StartIndex() uint64 { return mkV2Rev(w.startRev) }
+
+func (w *v2v3Watcher) Remove() {
+ w.cancel()
+ <-w.donec
+}
+
+func (w *v2v3Watcher) EventChan() chan *v2store.Event { return w.evc }
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm/alarms.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm/alarms.go
new file mode 100644
index 0000000000..5d4a641cea
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm/alarms.go
@@ -0,0 +1,153 @@
+// 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 v3alarm manages health status alarms in etcd.
+package v3alarm
+
+import (
+ "sync"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+
+ "go.uber.org/zap"
+)
+
+type BackendGetter interface {
+ Backend() backend.Backend
+}
+
+type alarmSet map[types.ID]*pb.AlarmMember
+
+// AlarmStore persists alarms to the backend.
+type AlarmStore struct {
+ lg *zap.Logger
+ mu sync.Mutex
+ types map[pb.AlarmType]alarmSet
+
+ bg BackendGetter
+}
+
+func NewAlarmStore(lg *zap.Logger, bg BackendGetter) (*AlarmStore, error) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ ret := &AlarmStore{lg: lg, 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 {
+ a.lg.Panic("failed to marshal alarm member", zap.Error(err))
+ }
+
+ b := a.bg.Backend()
+ b.BatchTx().LockInsideApply()
+ b.BatchTx().UnsafePut(buckets.Alarm, 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 {
+ a.lg.Panic("failed to marshal alarm member", zap.Error(err))
+ }
+
+ b := a.bg.Backend()
+ b.BatchTx().LockInsideApply()
+ b.BatchTx().UnsafeDelete(buckets.Alarm, 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.LockOutsideApply()
+ tx.UnsafeCreateBucket(buckets.Alarm)
+ err := tx.UnsafeForEach(buckets.Alarm, 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/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/doc.go
new file mode 100644
index 0000000000..a6a4d7edfa
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/doc.go
@@ -0,0 +1,44 @@
+// 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 v3client provides clientv3 interfaces from an etcdserver.
+//
+// Use v3client by creating an EtcdServer instance, then wrapping it with v3client.New:
+//
+// import (
+// "context"
+//
+// "go.etcd.io/etcd/server/v3/embed"
+// "go.etcd.io/etcd/server/v3/etcdserver/api/v3client"
+// )
+//
+// ...
+//
+// // create an embedded EtcdServer from the default configuration
+// cfg := embed.NewConfig()
+// cfg.Dir = "default.etcd"
+// e, err := embed.StartEtcd(cfg)
+// if err != nil {
+// // handle error!
+// }
+//
+// // wrap the EtcdServer with v3client
+// cli := v3client.New(e.Server)
+//
+// // use like an ordinary clientv3
+// resp, err := cli.Put(context.TODO(), "some-key", "it works!")
+// if err != nil {
+// // handle error!
+// }
+package v3client
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/v3client.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/v3client.go
new file mode 100644
index 0000000000..8342dc434c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/v3client.go
@@ -0,0 +1,67 @@
+// 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 v3client
+
+import (
+ "context"
+ "time"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
+ "go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter"
+)
+
+// New creates a clientv3 client that wraps an in-process EtcdServer. Instead
+// of making gRPC calls through sockets, the client makes direct function calls
+// to the etcd server through its api/v3rpc function interfaces.
+func New(s *etcdserver.EtcdServer) *clientv3.Client {
+ c := clientv3.NewCtxClient(context.Background(), clientv3.WithZapLogger(s.Logger()))
+
+ kvc := adapter.KvServerToKvClient(v3rpc.NewQuotaKVServer(s))
+ c.KV = clientv3.NewKVFromKVClient(kvc, c)
+
+ lc := adapter.LeaseServerToLeaseClient(v3rpc.NewQuotaLeaseServer(s))
+ c.Lease = clientv3.NewLeaseFromLeaseClient(lc, c, time.Second)
+
+ wc := adapter.WatchServerToWatchClient(v3rpc.NewWatchServer(s))
+ c.Watcher = &watchWrapper{clientv3.NewWatchFromWatchClient(wc, c)}
+
+ mc := adapter.MaintenanceServerToMaintenanceClient(v3rpc.NewMaintenanceServer(s))
+ c.Maintenance = clientv3.NewMaintenanceFromMaintenanceClient(mc, c)
+
+ clc := adapter.ClusterServerToClusterClient(v3rpc.NewClusterServer(s))
+ c.Cluster = clientv3.NewClusterFromClusterClient(clc, c)
+
+ a := adapter.AuthServerToAuthClient(v3rpc.NewAuthServer(s))
+ c.Auth = clientv3.NewAuthFromAuthClient(a, c)
+
+ return c
+}
+
+// BlankContext implements Stringer on a context so the ctx string doesn't
+// depend on the context's WithValue data, which tends to be unsynchronized
+// (e.g., x/net/trace), causing ctx.String() to throw data races.
+type blankContext struct{ context.Context }
+
+func (*blankContext) String() string { return "(blankCtx)" }
+
+// watchWrapper wraps clientv3 watch calls to blank out the context
+// to avoid races on trace data.
+type watchWrapper struct{ clientv3.Watcher }
+
+func (ww *watchWrapper) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
+ return ww.Watcher.Watch(&blankContext{ctx}, key, opts...)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/compactor.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/compactor.go
new file mode 100644
index 0000000000..e352670c12
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/compactor.go
@@ -0,0 +1,73 @@
+// 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 v3compactor
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+
+ "github.com/jonboulle/clockwork"
+ "go.uber.org/zap"
+)
+
+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
+}
+
+// New returns a new Compactor based on given "mode".
+func New(
+ lg *zap.Logger,
+ mode string,
+ retention time.Duration,
+ rg RevGetter,
+ c Compactable,
+) (Compactor, error) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ switch mode {
+ case ModePeriodic:
+ return newPeriodic(lg, clockwork.NewRealClock(), retention, rg, c), nil
+ case ModeRevision:
+ return newRevision(lg, clockwork.NewRealClock(), int64(retention), rg, c), nil
+ default:
+ return nil, fmt.Errorf("unsupported compaction mode %s", mode)
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/doc.go
new file mode 100644
index 0000000000..bb28046ce4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/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 v3compactor implements automated policies for compacting etcd's mvcc storage.
+package v3compactor
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/periodic.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/periodic.go
new file mode 100644
index 0000000000..083c72ede2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/periodic.go
@@ -0,0 +1,205 @@
+// 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 v3compactor
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/mvcc"
+
+ "github.com/jonboulle/clockwork"
+ "go.uber.org/zap"
+)
+
+// Periodic compacts the log by purging revisions older than
+// the configured retention time.
+type Periodic struct {
+ lg *zap.Logger
+ 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(lg *zap.Logger, clock clockwork.Clock, h time.Duration, rg RevGetter, c Compactable) *Periodic {
+ pc := &Periodic{
+ lg: lg,
+ clock: clock,
+ period: h,
+ rg: rg,
+ c: c,
+ revs: make([]int64, 0),
+ }
+ pc.ctx, pc.cancel = context.WithCancel(context.Background())
+ return pc
+}
+
+/*
+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 (pc *Periodic) Run() {
+ compactInterval := pc.getCompactInterval()
+ retryInterval := pc.getRetryInterval()
+ retentions := pc.getRetentions()
+
+ go func() {
+ lastSuccess := pc.clock.Now()
+ baseInterval := pc.period
+ for {
+ pc.revs = append(pc.revs, pc.rg.Rev())
+ if len(pc.revs) > retentions {
+ pc.revs = pc.revs[1:] // pc.revs[0] is always the rev at pc.period ago
+ }
+
+ select {
+ case <-pc.ctx.Done():
+ return
+ case <-pc.clock.After(retryInterval):
+ pc.mu.Lock()
+ p := pc.paused
+ pc.mu.Unlock()
+ if p {
+ continue
+ }
+ }
+
+ if pc.clock.Now().Sub(lastSuccess) < baseInterval {
+ continue
+ }
+
+ // wait up to initial given period
+ if baseInterval == pc.period {
+ baseInterval = compactInterval
+ }
+ rev := pc.revs[0]
+
+ pc.lg.Info(
+ "starting auto periodic compaction",
+ zap.Int64("revision", rev),
+ zap.Duration("compact-period", pc.period),
+ )
+ startTime := pc.clock.Now()
+ _, err := pc.c.Compact(pc.ctx, &pb.CompactionRequest{Revision: rev})
+ if err == nil || err == mvcc.ErrCompacted {
+ pc.lg.Info(
+ "completed auto periodic compaction",
+ zap.Int64("revision", rev),
+ zap.Duration("compact-period", pc.period),
+ zap.Duration("took", pc.clock.Now().Sub(startTime)),
+ )
+ lastSuccess = pc.clock.Now()
+ } else {
+ pc.lg.Warn(
+ "failed auto periodic compaction",
+ zap.Int64("revision", rev),
+ zap.Duration("compact-period", pc.period),
+ zap.Duration("retry-interval", retryInterval),
+ zap.Error(err),
+ )
+ }
+ }
+ }()
+}
+
+// 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 (pc *Periodic) getCompactInterval() time.Duration {
+ itv := pc.period
+ if itv > time.Hour {
+ itv = time.Hour
+ }
+ return itv
+}
+
+func (pc *Periodic) getRetentions() int {
+ return int(pc.period/pc.getRetryInterval()) + 1
+}
+
+const retryDivisor = 10
+
+func (pc *Periodic) getRetryInterval() time.Duration {
+ itv := pc.period
+ if itv > time.Hour {
+ itv = time.Hour
+ }
+ return itv / retryDivisor
+}
+
+// Stop stops periodic compactor.
+func (pc *Periodic) Stop() {
+ pc.cancel()
+}
+
+// Pause pauses periodic compactor.
+func (pc *Periodic) Pause() {
+ pc.mu.Lock()
+ pc.paused = true
+ pc.mu.Unlock()
+}
+
+// Resume resumes periodic compactor.
+func (pc *Periodic) Resume() {
+ pc.mu.Lock()
+ pc.paused = false
+ pc.mu.Unlock()
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/revision.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/revision.go
new file mode 100644
index 0000000000..83be627947
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/revision.go
@@ -0,0 +1,130 @@
+// 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 v3compactor
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/mvcc"
+
+ "github.com/jonboulle/clockwork"
+ "go.uber.org/zap"
+)
+
+// Revision compacts the log by purging revisions older than
+// the configured reivison number. Compaction happens every 5 minutes.
+type Revision struct {
+ lg *zap.Logger
+
+ 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(lg *zap.Logger, clock clockwork.Clock, retention int64, rg RevGetter, c Compactable) *Revision {
+ rc := &Revision{
+ lg: lg,
+ clock: clock,
+ retention: retention,
+ rg: rg,
+ c: c,
+ }
+ rc.ctx, rc.cancel = context.WithCancel(context.Background())
+ return rc
+}
+
+const revInterval = 5 * time.Minute
+
+// Run runs revision-based compactor.
+func (rc *Revision) Run() {
+ prev := int64(0)
+ go func() {
+ for {
+ select {
+ case <-rc.ctx.Done():
+ return
+ case <-rc.clock.After(revInterval):
+ rc.mu.Lock()
+ p := rc.paused
+ rc.mu.Unlock()
+ if p {
+ continue
+ }
+ }
+
+ rev := rc.rg.Rev() - rc.retention
+ if rev <= 0 || rev == prev {
+ continue
+ }
+
+ now := time.Now()
+ rc.lg.Info(
+ "starting auto revision compaction",
+ zap.Int64("revision", rev),
+ zap.Int64("revision-compaction-retention", rc.retention),
+ )
+ _, err := rc.c.Compact(rc.ctx, &pb.CompactionRequest{Revision: rev})
+ if err == nil || err == mvcc.ErrCompacted {
+ prev = rev
+ rc.lg.Info(
+ "completed auto revision compaction",
+ zap.Int64("revision", rev),
+ zap.Int64("revision-compaction-retention", rc.retention),
+ zap.Duration("took", time.Since(now)),
+ )
+ } else {
+ rc.lg.Warn(
+ "failed auto revision compaction",
+ zap.Int64("revision", rev),
+ zap.Int64("revision-compaction-retention", rc.retention),
+ zap.Duration("retry-interval", revInterval),
+ zap.Error(err),
+ )
+ }
+ }
+ }()
+}
+
+// Stop stops revision-based compactor.
+func (rc *Revision) Stop() {
+ rc.cancel()
+}
+
+// Pause pauses revision-based compactor.
+func (rc *Revision) Pause() {
+ rc.mu.Lock()
+ rc.paused = true
+ rc.mu.Unlock()
+}
+
+// Resume resumes revision-based compactor.
+func (rc *Revision) Resume() {
+ rc.mu.Lock()
+ rc.paused = false
+ rc.mu.Unlock()
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/doc.go
new file mode 100644
index 0000000000..d6fefd7415
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/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 v3election provides a v3 election service from an etcdserver.
+package v3election
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/election.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/election.go
new file mode 100644
index 0000000000..78b26ad7cc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/election.go
@@ -0,0 +1,134 @@
+// 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 v3election
+
+import (
+ "context"
+ "errors"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/client/v3/concurrency"
+ epb "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
+)
+
+// ErrMissingLeaderKey is returned when election API request
+// is missing the "leader" field.
+var ErrMissingLeaderKey = errors.New(`"leader" field must be provided`)
+
+type electionServer struct {
+ c *clientv3.Client
+}
+
+func NewElectionServer(c *clientv3.Client) epb.ElectionServer {
+ return &electionServer{c}
+}
+
+func (es *electionServer) Campaign(ctx context.Context, req *epb.CampaignRequest) (*epb.CampaignResponse, error) {
+ s, err := es.session(ctx, req.Lease)
+ if err != nil {
+ return nil, err
+ }
+ e := concurrency.NewElection(s, string(req.Name))
+ if err = e.Campaign(ctx, string(req.Value)); err != nil {
+ return nil, err
+ }
+ return &epb.CampaignResponse{
+ Header: e.Header(),
+ Leader: &epb.LeaderKey{
+ Name: req.Name,
+ Key: []byte(e.Key()),
+ Rev: e.Rev(),
+ Lease: int64(s.Lease()),
+ },
+ }, nil
+}
+
+func (es *electionServer) Proclaim(ctx context.Context, req *epb.ProclaimRequest) (*epb.ProclaimResponse, error) {
+ if req.Leader == nil {
+ return nil, ErrMissingLeaderKey
+ }
+ s, err := es.session(ctx, req.Leader.Lease)
+ if err != nil {
+ return nil, err
+ }
+ e := concurrency.ResumeElection(s, string(req.Leader.Name), string(req.Leader.Key), req.Leader.Rev)
+ if err := e.Proclaim(ctx, string(req.Value)); err != nil {
+ return nil, err
+ }
+ return &epb.ProclaimResponse{Header: e.Header()}, nil
+}
+
+func (es *electionServer) Observe(req *epb.LeaderRequest, stream epb.Election_ObserveServer) error {
+ s, err := es.session(stream.Context(), -1)
+ if err != nil {
+ return err
+ }
+ e := concurrency.NewElection(s, string(req.Name))
+ ch := e.Observe(stream.Context())
+ for stream.Context().Err() == nil {
+ select {
+ case <-stream.Context().Done():
+ case resp, ok := <-ch:
+ if !ok {
+ return nil
+ }
+ lresp := &epb.LeaderResponse{Header: resp.Header, Kv: resp.Kvs[0]}
+ if err := stream.Send(lresp); err != nil {
+ return err
+ }
+ }
+ }
+ return stream.Context().Err()
+}
+
+func (es *electionServer) Leader(ctx context.Context, req *epb.LeaderRequest) (*epb.LeaderResponse, error) {
+ s, err := es.session(ctx, -1)
+ if err != nil {
+ return nil, err
+ }
+ l, lerr := concurrency.NewElection(s, string(req.Name)).Leader(ctx)
+ if lerr != nil {
+ return nil, lerr
+ }
+ return &epb.LeaderResponse{Header: l.Header, Kv: l.Kvs[0]}, nil
+}
+
+func (es *electionServer) Resign(ctx context.Context, req *epb.ResignRequest) (*epb.ResignResponse, error) {
+ if req.Leader == nil {
+ return nil, ErrMissingLeaderKey
+ }
+ s, err := es.session(ctx, req.Leader.Lease)
+ if err != nil {
+ return nil, err
+ }
+ e := concurrency.ResumeElection(s, string(req.Leader.Name), string(req.Leader.Key), req.Leader.Rev)
+ if err := e.Resign(ctx); err != nil {
+ return nil, err
+ }
+ return &epb.ResignResponse{Header: e.Header()}, nil
+}
+
+func (es *electionServer) session(ctx context.Context, lease int64) (*concurrency.Session, error) {
+ s, err := concurrency.NewSession(
+ es.c,
+ concurrency.WithLease(clientv3.LeaseID(lease)),
+ concurrency.WithContext(ctx),
+ )
+ if err != nil {
+ return nil, err
+ }
+ s.Orphan()
+ return s, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go
new file mode 100644
index 0000000000..4a6e5e724c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go
@@ -0,0 +1,454 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: server/etcdserver/api/v3election/v3electionpb/v3election.proto
+
+/*
+Package v3electionpb is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package gw
+
+import (
+ "context"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/grpc-ecosystem/grpc-gateway/utilities"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/status"
+)
+
+// Suppress "imported and not used" errors
+var _ codes.Code
+var _ io.Reader
+var _ status.Status
+var _ = runtime.String
+var _ = utilities.NewDoubleArray
+var _ = descriptor.ForMessage
+
+func request_Election_Campaign_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.CampaignRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Campaign(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Election_Campaign_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.CampaignRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Campaign(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Election_Proclaim_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.ProclaimRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Proclaim(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Election_Proclaim_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.ProclaimRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Proclaim(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Election_Leader_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.LeaderRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Leader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Election_Leader_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.LeaderRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Leader(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Election_Observe_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (v3electionpb.Election_ObserveClient, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.LeaderRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ stream, err := client.Observe(ctx, &protoReq)
+ if err != nil {
+ return nil, metadata, err
+ }
+ header, err := stream.Header()
+ if err != nil {
+ return nil, metadata, err
+ }
+ metadata.HeaderMD = header
+ return stream, metadata, nil
+
+}
+
+func request_Election_Resign_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.ResignRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Resign(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Election_Resign_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3electionpb.ResignRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Resign(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+// v3electionpb.RegisterElectionHandlerServer registers the http handlers for service Election to "mux".
+// UnaryRPC :call v3electionpb.ElectionServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterElectionHandlerServer(ctx context.Context, mux *runtime.ServeMux, server v3electionpb.ElectionServer) error {
+
+ mux.Handle("POST", pattern_Election_Campaign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Election_Campaign_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Campaign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Election_Proclaim_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Election_Proclaim_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Proclaim_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Election_Leader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Election_Leader_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Leader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Election_Observe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
+ _, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ })
+
+ mux.Handle("POST", pattern_Election_Resign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Election_Resign_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Resign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// RegisterElectionHandlerFromEndpoint is same as RegisterElectionHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterElectionHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterElectionHandler(ctx, mux, conn)
+}
+
+// RegisterElectionHandler registers the http handlers for service Election to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterElectionHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterElectionHandlerClient(ctx, mux, v3electionpb.NewElectionClient(conn))
+}
+
+// v3electionpb.RegisterElectionHandlerClient registers the http handlers for service Election
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ElectionClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ElectionClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "ElectionClient" to call the correct interceptors.
+func RegisterElectionHandlerClient(ctx context.Context, mux *runtime.ServeMux, client v3electionpb.ElectionClient) error {
+
+ mux.Handle("POST", pattern_Election_Campaign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Election_Campaign_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Campaign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Election_Proclaim_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Election_Proclaim_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Proclaim_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Election_Leader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Election_Leader_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Leader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Election_Observe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Election_Observe_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Observe_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Election_Resign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Election_Resign_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Election_Resign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Election_Campaign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "campaign"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Election_Proclaim_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "proclaim"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Election_Leader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "leader"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Election_Observe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "observe"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Election_Resign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "resign"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_Election_Campaign_0 = runtime.ForwardResponseMessage
+
+ forward_Election_Proclaim_0 = runtime.ForwardResponseMessage
+
+ forward_Election_Leader_0 = runtime.ForwardResponseMessage
+
+ forward_Election_Observe_0 = runtime.ForwardResponseStream
+
+ forward_Election_Resign_0 = runtime.ForwardResponseMessage
+)
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.pb.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.pb.go
new file mode 100644
index 0000000000..81cf59b9b2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.pb.go
@@ -0,0 +1,2541 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: v3election.proto
+
+package v3electionpb
+
+import (
+ context "context"
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+ proto "github.com/golang/protobuf/proto"
+ etcdserverpb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ mvccpb "go.etcd.io/etcd/api/v3/mvccpb"
+ _ "google.golang.org/genproto/googleapis/api/annotations"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// 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.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type CampaignRequest struct {
+ // name is the election's identifier for the campaign.
+ Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // lease is the ID of the lease attached to leadership of the election. If the
+ // lease expires or is revoked before resigning leadership, then the
+ // leadership is transferred to the next campaigner, if any.
+ Lease int64 `protobuf:"varint,2,opt,name=lease,proto3" json:"lease,omitempty"`
+ // value is the initial proclaimed value set when the campaigner wins the
+ // election.
+ Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *CampaignRequest) Reset() { *m = CampaignRequest{} }
+func (m *CampaignRequest) String() string { return proto.CompactTextString(m) }
+func (*CampaignRequest) ProtoMessage() {}
+func (*CampaignRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{0}
+}
+func (m *CampaignRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *CampaignRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_CampaignRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *CampaignRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CampaignRequest.Merge(m, src)
+}
+func (m *CampaignRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *CampaignRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_CampaignRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CampaignRequest proto.InternalMessageInfo
+
+func (m *CampaignRequest) GetName() []byte {
+ if m != nil {
+ return m.Name
+ }
+ return nil
+}
+
+func (m *CampaignRequest) GetLease() int64 {
+ if m != nil {
+ return m.Lease
+ }
+ return 0
+}
+
+func (m *CampaignRequest) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+type CampaignResponse struct {
+ Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
+ // leader describes the resources used for holding leadereship of the election.
+ Leader *LeaderKey `protobuf:"bytes,2,opt,name=leader,proto3" json:"leader,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *CampaignResponse) Reset() { *m = CampaignResponse{} }
+func (m *CampaignResponse) String() string { return proto.CompactTextString(m) }
+func (*CampaignResponse) ProtoMessage() {}
+func (*CampaignResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{1}
+}
+func (m *CampaignResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *CampaignResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_CampaignResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *CampaignResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CampaignResponse.Merge(m, src)
+}
+func (m *CampaignResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *CampaignResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_CampaignResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CampaignResponse proto.InternalMessageInfo
+
+func (m *CampaignResponse) GetHeader() *etcdserverpb.ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *CampaignResponse) GetLeader() *LeaderKey {
+ if m != nil {
+ return m.Leader
+ }
+ return nil
+}
+
+type LeaderKey struct {
+ // name is the election identifier that correponds to the leadership key.
+ Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // key is an opaque key representing the ownership of the election. If the key
+ // is deleted, then leadership is lost.
+ Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
+ // rev is the creation revision of the key. It can be used to test for ownership
+ // of an election during transactions by testing the key's creation revision
+ // matches rev.
+ Rev int64 `protobuf:"varint,3,opt,name=rev,proto3" json:"rev,omitempty"`
+ // lease is the lease ID of the election leader.
+ Lease int64 `protobuf:"varint,4,opt,name=lease,proto3" json:"lease,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LeaderKey) Reset() { *m = LeaderKey{} }
+func (m *LeaderKey) String() string { return proto.CompactTextString(m) }
+func (*LeaderKey) ProtoMessage() {}
+func (*LeaderKey) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{2}
+}
+func (m *LeaderKey) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LeaderKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LeaderKey.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LeaderKey) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LeaderKey.Merge(m, src)
+}
+func (m *LeaderKey) XXX_Size() int {
+ return m.Size()
+}
+func (m *LeaderKey) XXX_DiscardUnknown() {
+ xxx_messageInfo_LeaderKey.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LeaderKey proto.InternalMessageInfo
+
+func (m *LeaderKey) GetName() []byte {
+ if m != nil {
+ return m.Name
+ }
+ return nil
+}
+
+func (m *LeaderKey) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+func (m *LeaderKey) GetRev() int64 {
+ if m != nil {
+ return m.Rev
+ }
+ return 0
+}
+
+func (m *LeaderKey) GetLease() int64 {
+ if m != nil {
+ return m.Lease
+ }
+ return 0
+}
+
+type LeaderRequest struct {
+ // name is the election identifier for the leadership information.
+ Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LeaderRequest) Reset() { *m = LeaderRequest{} }
+func (m *LeaderRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaderRequest) ProtoMessage() {}
+func (*LeaderRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{3}
+}
+func (m *LeaderRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LeaderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LeaderRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LeaderRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LeaderRequest.Merge(m, src)
+}
+func (m *LeaderRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *LeaderRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_LeaderRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LeaderRequest proto.InternalMessageInfo
+
+func (m *LeaderRequest) GetName() []byte {
+ if m != nil {
+ return m.Name
+ }
+ return nil
+}
+
+type LeaderResponse struct {
+ Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
+ // kv is the key-value pair representing the latest leader update.
+ Kv *mvccpb.KeyValue `protobuf:"bytes,2,opt,name=kv,proto3" json:"kv,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LeaderResponse) Reset() { *m = LeaderResponse{} }
+func (m *LeaderResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaderResponse) ProtoMessage() {}
+func (*LeaderResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{4}
+}
+func (m *LeaderResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LeaderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LeaderResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LeaderResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LeaderResponse.Merge(m, src)
+}
+func (m *LeaderResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *LeaderResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_LeaderResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LeaderResponse proto.InternalMessageInfo
+
+func (m *LeaderResponse) GetHeader() *etcdserverpb.ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *LeaderResponse) GetKv() *mvccpb.KeyValue {
+ if m != nil {
+ return m.Kv
+ }
+ return nil
+}
+
+type ResignRequest struct {
+ // leader is the leadership to relinquish by resignation.
+ Leader *LeaderKey `protobuf:"bytes,1,opt,name=leader,proto3" json:"leader,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ResignRequest) Reset() { *m = ResignRequest{} }
+func (m *ResignRequest) String() string { return proto.CompactTextString(m) }
+func (*ResignRequest) ProtoMessage() {}
+func (*ResignRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{5}
+}
+func (m *ResignRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ResignRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ResignRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ResignRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ResignRequest.Merge(m, src)
+}
+func (m *ResignRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *ResignRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_ResignRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ResignRequest proto.InternalMessageInfo
+
+func (m *ResignRequest) GetLeader() *LeaderKey {
+ if m != nil {
+ return m.Leader
+ }
+ return nil
+}
+
+type ResignResponse struct {
+ Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ResignResponse) Reset() { *m = ResignResponse{} }
+func (m *ResignResponse) String() string { return proto.CompactTextString(m) }
+func (*ResignResponse) ProtoMessage() {}
+func (*ResignResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{6}
+}
+func (m *ResignResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ResignResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ResignResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ResignResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ResignResponse.Merge(m, src)
+}
+func (m *ResignResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *ResignResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_ResignResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ResignResponse proto.InternalMessageInfo
+
+func (m *ResignResponse) GetHeader() *etcdserverpb.ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type ProclaimRequest struct {
+ // leader is the leadership hold on the election.
+ Leader *LeaderKey `protobuf:"bytes,1,opt,name=leader,proto3" json:"leader,omitempty"`
+ // value is an update meant to overwrite the leader's current value.
+ Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ProclaimRequest) Reset() { *m = ProclaimRequest{} }
+func (m *ProclaimRequest) String() string { return proto.CompactTextString(m) }
+func (*ProclaimRequest) ProtoMessage() {}
+func (*ProclaimRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{7}
+}
+func (m *ProclaimRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ProclaimRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ProclaimRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ProclaimRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ProclaimRequest.Merge(m, src)
+}
+func (m *ProclaimRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *ProclaimRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_ProclaimRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ProclaimRequest proto.InternalMessageInfo
+
+func (m *ProclaimRequest) GetLeader() *LeaderKey {
+ if m != nil {
+ return m.Leader
+ }
+ return nil
+}
+
+func (m *ProclaimRequest) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+type ProclaimResponse struct {
+ Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ProclaimResponse) Reset() { *m = ProclaimResponse{} }
+func (m *ProclaimResponse) String() string { return proto.CompactTextString(m) }
+func (*ProclaimResponse) ProtoMessage() {}
+func (*ProclaimResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_c9b1f26cc432a035, []int{8}
+}
+func (m *ProclaimResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *ProclaimResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_ProclaimResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *ProclaimResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ProclaimResponse.Merge(m, src)
+}
+func (m *ProclaimResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *ProclaimResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_ProclaimResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ProclaimResponse proto.InternalMessageInfo
+
+func (m *ProclaimResponse) GetHeader() *etcdserverpb.ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*CampaignRequest)(nil), "v3electionpb.CampaignRequest")
+ proto.RegisterType((*CampaignResponse)(nil), "v3electionpb.CampaignResponse")
+ proto.RegisterType((*LeaderKey)(nil), "v3electionpb.LeaderKey")
+ proto.RegisterType((*LeaderRequest)(nil), "v3electionpb.LeaderRequest")
+ proto.RegisterType((*LeaderResponse)(nil), "v3electionpb.LeaderResponse")
+ proto.RegisterType((*ResignRequest)(nil), "v3electionpb.ResignRequest")
+ proto.RegisterType((*ResignResponse)(nil), "v3electionpb.ResignResponse")
+ proto.RegisterType((*ProclaimRequest)(nil), "v3electionpb.ProclaimRequest")
+ proto.RegisterType((*ProclaimResponse)(nil), "v3electionpb.ProclaimResponse")
+}
+
+func init() { proto.RegisterFile("v3election.proto", fileDescriptor_c9b1f26cc432a035) }
+
+var fileDescriptor_c9b1f26cc432a035 = []byte{
+ // 531 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xcf, 0x6e, 0xd3, 0x40,
+ 0x10, 0xc6, 0x59, 0x27, 0x84, 0x32, 0xa4, 0xad, 0x65, 0x82, 0x08, 0x21, 0xb8, 0xd1, 0x72, 0xa9,
+ 0x72, 0xb0, 0x51, 0xc3, 0x29, 0x27, 0x04, 0x02, 0x55, 0x2a, 0x12, 0xe0, 0x03, 0x82, 0xe3, 0xda,
+ 0x1d, 0xb9, 0x91, 0x1d, 0xaf, 0xb1, 0x5d, 0x4b, 0xb9, 0xf2, 0x0a, 0x1c, 0xe0, 0x91, 0x38, 0x22,
+ 0xf1, 0x02, 0x28, 0xf0, 0x20, 0x68, 0x77, 0xed, 0xfa, 0x8f, 0x12, 0x84, 0x9a, 0xdb, 0x78, 0xe7,
+ 0xdb, 0xf9, 0xcd, 0x37, 0x3b, 0x09, 0xe8, 0xf9, 0x0c, 0x43, 0xf4, 0xb2, 0x05, 0x8f, 0xac, 0x38,
+ 0xe1, 0x19, 0x37, 0xfa, 0xd5, 0x49, 0xec, 0x8e, 0x06, 0x3e, 0xf7, 0xb9, 0x4c, 0xd8, 0x22, 0x52,
+ 0x9a, 0xd1, 0x11, 0x66, 0xde, 0xb9, 0xcd, 0xe2, 0x85, 0x2d, 0x82, 0x14, 0x93, 0x1c, 0x93, 0xd8,
+ 0xb5, 0x93, 0xd8, 0x2b, 0x04, 0xc3, 0x2b, 0xc1, 0x32, 0xf7, 0xbc, 0xd8, 0xb5, 0x83, 0xbc, 0xc8,
+ 0x8c, 0x7d, 0xce, 0xfd, 0x10, 0x65, 0x8e, 0x45, 0x11, 0xcf, 0x98, 0x20, 0xa5, 0x2a, 0x4b, 0xdf,
+ 0xc1, 0xe1, 0x0b, 0xb6, 0x8c, 0xd9, 0xc2, 0x8f, 0x1c, 0xfc, 0x74, 0x89, 0x69, 0x66, 0x18, 0xd0,
+ 0x8d, 0xd8, 0x12, 0x87, 0x64, 0x42, 0x8e, 0xfb, 0x8e, 0x8c, 0x8d, 0x01, 0xdc, 0x0c, 0x91, 0xa5,
+ 0x38, 0xd4, 0x26, 0xe4, 0xb8, 0xe3, 0xa8, 0x0f, 0x71, 0x9a, 0xb3, 0xf0, 0x12, 0x87, 0x1d, 0x29,
+ 0x55, 0x1f, 0x74, 0x05, 0x7a, 0x55, 0x32, 0x8d, 0x79, 0x94, 0xa2, 0xf1, 0x14, 0x7a, 0x17, 0xc8,
+ 0xce, 0x31, 0x91, 0x55, 0xef, 0x9c, 0x8c, 0xad, 0xba, 0x0f, 0xab, 0xd4, 0x9d, 0x4a, 0x8d, 0x53,
+ 0x68, 0x0d, 0x1b, 0x7a, 0xa1, 0xba, 0xa5, 0xc9, 0x5b, 0xf7, 0xad, 0xfa, 0xa8, 0xac, 0xd7, 0x32,
+ 0x77, 0x86, 0x2b, 0xa7, 0x90, 0xd1, 0x8f, 0x70, 0xfb, 0xea, 0x70, 0xa3, 0x0f, 0x1d, 0x3a, 0x01,
+ 0xae, 0x64, 0xb9, 0xbe, 0x23, 0x42, 0x71, 0x92, 0x60, 0x2e, 0x1d, 0x74, 0x1c, 0x11, 0x56, 0x5e,
+ 0xbb, 0x35, 0xaf, 0xf4, 0x31, 0xec, 0xab, 0xd2, 0xff, 0x18, 0x13, 0xbd, 0x80, 0x83, 0x52, 0xb4,
+ 0x93, 0xf1, 0x09, 0x68, 0x41, 0x5e, 0x98, 0xd6, 0x2d, 0xf5, 0xa2, 0xd6, 0x19, 0xae, 0xde, 0x8b,
+ 0x01, 0x3b, 0x5a, 0x90, 0xd3, 0x67, 0xb0, 0xef, 0x60, 0x5a, 0x7b, 0xb5, 0x6a, 0x56, 0xe4, 0xff,
+ 0x66, 0xf5, 0x0a, 0x0e, 0xca, 0x0a, 0xbb, 0xf4, 0x4a, 0x3f, 0xc0, 0xe1, 0xdb, 0x84, 0x7b, 0x21,
+ 0x5b, 0x2c, 0xaf, 0xdb, 0x4b, 0xb5, 0x48, 0x5a, 0x7d, 0x91, 0x4e, 0x41, 0xaf, 0x2a, 0xef, 0xd2,
+ 0xe3, 0xc9, 0xd7, 0x2e, 0xec, 0xbd, 0x2c, 0x1a, 0x30, 0x02, 0xd8, 0x2b, 0xf7, 0xd3, 0x78, 0xd4,
+ 0xec, 0xac, 0xf5, 0x53, 0x18, 0x99, 0xdb, 0xd2, 0x8a, 0x42, 0x27, 0x9f, 0x7f, 0xfe, 0xf9, 0xa2,
+ 0x8d, 0xe8, 0x3d, 0x3b, 0x9f, 0xd9, 0xa5, 0xd0, 0xf6, 0x0a, 0xd9, 0x9c, 0x4c, 0x05, 0xac, 0xf4,
+ 0xd0, 0x86, 0xb5, 0xa6, 0xd6, 0x86, 0xb5, 0xad, 0x6f, 0x81, 0xc5, 0x85, 0x4c, 0xc0, 0x3c, 0xe8,
+ 0xa9, 0xd9, 0x1a, 0x0f, 0x37, 0x4d, 0xbc, 0x04, 0x8d, 0x37, 0x27, 0x0b, 0x8c, 0x29, 0x31, 0x43,
+ 0x7a, 0xb7, 0x81, 0x51, 0x0f, 0x25, 0x20, 0x3e, 0xdc, 0x7a, 0xe3, 0xca, 0x81, 0xef, 0x42, 0x39,
+ 0x92, 0x94, 0x07, 0x74, 0xd0, 0xa0, 0x70, 0x55, 0x78, 0x4e, 0xa6, 0x4f, 0x88, 0x70, 0xa3, 0x16,
+ 0xb4, 0xcd, 0x69, 0x2c, 0x7e, 0x9b, 0xd3, 0xdc, 0xe9, 0x2d, 0x6e, 0x12, 0x29, 0x9a, 0x93, 0xe9,
+ 0x73, 0xfd, 0xfb, 0xda, 0x24, 0x3f, 0xd6, 0x26, 0xf9, 0xb5, 0x36, 0xc9, 0xb7, 0xdf, 0xe6, 0x0d,
+ 0xb7, 0x27, 0xff, 0x18, 0x67, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x9c, 0xe6, 0x7c, 0x66, 0xa9,
+ 0x05, 0x00, 0x00,
+}
+
+// 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
+
+// ElectionClient is the client API for Election service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type ElectionClient interface {
+ // Campaign waits to acquire leadership in an election, returning a LeaderKey
+ // representing the leadership if successful. The LeaderKey can then be used
+ // to issue new values on the election, transactionally guard API requests on
+ // leadership still being held, and resign from the election.
+ Campaign(ctx context.Context, in *CampaignRequest, opts ...grpc.CallOption) (*CampaignResponse, error)
+ // Proclaim updates the leader's posted value with a new value.
+ Proclaim(ctx context.Context, in *ProclaimRequest, opts ...grpc.CallOption) (*ProclaimResponse, error)
+ // Leader returns the current election proclamation, if any.
+ Leader(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (*LeaderResponse, error)
+ // Observe streams election proclamations in-order as made by the election's
+ // elected leaders.
+ Observe(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (Election_ObserveClient, error)
+ // Resign releases election leadership so other campaigners may acquire
+ // leadership on the election.
+ Resign(ctx context.Context, in *ResignRequest, opts ...grpc.CallOption) (*ResignResponse, error)
+}
+
+type electionClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewElectionClient(cc *grpc.ClientConn) ElectionClient {
+ return &electionClient{cc}
+}
+
+func (c *electionClient) Campaign(ctx context.Context, in *CampaignRequest, opts ...grpc.CallOption) (*CampaignResponse, error) {
+ out := new(CampaignResponse)
+ err := c.cc.Invoke(ctx, "/v3electionpb.Election/Campaign", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *electionClient) Proclaim(ctx context.Context, in *ProclaimRequest, opts ...grpc.CallOption) (*ProclaimResponse, error) {
+ out := new(ProclaimResponse)
+ err := c.cc.Invoke(ctx, "/v3electionpb.Election/Proclaim", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *electionClient) Leader(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (*LeaderResponse, error) {
+ out := new(LeaderResponse)
+ err := c.cc.Invoke(ctx, "/v3electionpb.Election/Leader", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *electionClient) Observe(ctx context.Context, in *LeaderRequest, opts ...grpc.CallOption) (Election_ObserveClient, error) {
+ stream, err := c.cc.NewStream(ctx, &_Election_serviceDesc.Streams[0], "/v3electionpb.Election/Observe", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &electionObserveClient{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 Election_ObserveClient interface {
+ Recv() (*LeaderResponse, error)
+ grpc.ClientStream
+}
+
+type electionObserveClient struct {
+ grpc.ClientStream
+}
+
+func (x *electionObserveClient) Recv() (*LeaderResponse, error) {
+ m := new(LeaderResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *electionClient) Resign(ctx context.Context, in *ResignRequest, opts ...grpc.CallOption) (*ResignResponse, error) {
+ out := new(ResignResponse)
+ err := c.cc.Invoke(ctx, "/v3electionpb.Election/Resign", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// ElectionServer is the server API for Election service.
+type ElectionServer interface {
+ // Campaign waits to acquire leadership in an election, returning a LeaderKey
+ // representing the leadership if successful. The LeaderKey can then be used
+ // to issue new values on the election, transactionally guard API requests on
+ // leadership still being held, and resign from the election.
+ Campaign(context.Context, *CampaignRequest) (*CampaignResponse, error)
+ // Proclaim updates the leader's posted value with a new value.
+ Proclaim(context.Context, *ProclaimRequest) (*ProclaimResponse, error)
+ // Leader returns the current election proclamation, if any.
+ Leader(context.Context, *LeaderRequest) (*LeaderResponse, error)
+ // Observe streams election proclamations in-order as made by the election's
+ // elected leaders.
+ Observe(*LeaderRequest, Election_ObserveServer) error
+ // Resign releases election leadership so other campaigners may acquire
+ // leadership on the election.
+ Resign(context.Context, *ResignRequest) (*ResignResponse, error)
+}
+
+// UnimplementedElectionServer can be embedded to have forward compatible implementations.
+type UnimplementedElectionServer struct {
+}
+
+func (*UnimplementedElectionServer) Campaign(ctx context.Context, req *CampaignRequest) (*CampaignResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Campaign not implemented")
+}
+func (*UnimplementedElectionServer) Proclaim(ctx context.Context, req *ProclaimRequest) (*ProclaimResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Proclaim not implemented")
+}
+func (*UnimplementedElectionServer) Leader(ctx context.Context, req *LeaderRequest) (*LeaderResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Leader not implemented")
+}
+func (*UnimplementedElectionServer) Observe(req *LeaderRequest, srv Election_ObserveServer) error {
+ return status.Errorf(codes.Unimplemented, "method Observe not implemented")
+}
+func (*UnimplementedElectionServer) Resign(ctx context.Context, req *ResignRequest) (*ResignResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Resign not implemented")
+}
+
+func RegisterElectionServer(s *grpc.Server, srv ElectionServer) {
+ s.RegisterService(&_Election_serviceDesc, srv)
+}
+
+func _Election_Campaign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CampaignRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ElectionServer).Campaign(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/v3electionpb.Election/Campaign",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ElectionServer).Campaign(ctx, req.(*CampaignRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Election_Proclaim_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ProclaimRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ElectionServer).Proclaim(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/v3electionpb.Election/Proclaim",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ElectionServer).Proclaim(ctx, req.(*ProclaimRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Election_Leader_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LeaderRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ElectionServer).Leader(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/v3electionpb.Election/Leader",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ElectionServer).Leader(ctx, req.(*LeaderRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Election_Observe_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(LeaderRequest)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(ElectionServer).Observe(m, &electionObserveServer{stream})
+}
+
+type Election_ObserveServer interface {
+ Send(*LeaderResponse) error
+ grpc.ServerStream
+}
+
+type electionObserveServer struct {
+ grpc.ServerStream
+}
+
+func (x *electionObserveServer) Send(m *LeaderResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func _Election_Resign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ResignRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ElectionServer).Resign(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/v3electionpb.Election/Resign",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ElectionServer).Resign(ctx, req.(*ResignRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Election_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "v3electionpb.Election",
+ HandlerType: (*ElectionServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Campaign",
+ Handler: _Election_Campaign_Handler,
+ },
+ {
+ MethodName: "Proclaim",
+ Handler: _Election_Proclaim_Handler,
+ },
+ {
+ MethodName: "Leader",
+ Handler: _Election_Leader_Handler,
+ },
+ {
+ MethodName: "Resign",
+ Handler: _Election_Resign_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "Observe",
+ Handler: _Election_Observe_Handler,
+ ServerStreams: true,
+ },
+ },
+ Metadata: "v3election.proto",
+}
+
+func (m *CampaignRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *CampaignRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CampaignRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if len(m.Value) > 0 {
+ i -= len(m.Value)
+ copy(dAtA[i:], m.Value)
+ i = encodeVarintV3Election(dAtA, i, uint64(len(m.Value)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if m.Lease != 0 {
+ i = encodeVarintV3Election(dAtA, i, uint64(m.Lease))
+ i--
+ dAtA[i] = 0x10
+ }
+ if len(m.Name) > 0 {
+ i -= len(m.Name)
+ copy(dAtA[i:], m.Name)
+ i = encodeVarintV3Election(dAtA, i, uint64(len(m.Name)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *CampaignResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *CampaignResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *CampaignResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Leader != nil {
+ {
+ size, err := m.Leader.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.Header != nil {
+ {
+ size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *LeaderKey) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaderKey) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LeaderKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Lease != 0 {
+ i = encodeVarintV3Election(dAtA, i, uint64(m.Lease))
+ i--
+ dAtA[i] = 0x20
+ }
+ if m.Rev != 0 {
+ i = encodeVarintV3Election(dAtA, i, uint64(m.Rev))
+ i--
+ dAtA[i] = 0x18
+ }
+ if len(m.Key) > 0 {
+ i -= len(m.Key)
+ copy(dAtA[i:], m.Key)
+ i = encodeVarintV3Election(dAtA, i, uint64(len(m.Key)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Name) > 0 {
+ i -= len(m.Name)
+ copy(dAtA[i:], m.Name)
+ i = encodeVarintV3Election(dAtA, i, uint64(len(m.Name)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *LeaderRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaderRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LeaderRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if len(m.Name) > 0 {
+ i -= len(m.Name)
+ copy(dAtA[i:], m.Name)
+ i = encodeVarintV3Election(dAtA, i, uint64(len(m.Name)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *LeaderResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaderResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LeaderResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Kv != nil {
+ {
+ size, err := m.Kv.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.Header != nil {
+ {
+ size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ResignRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ResignRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ResignRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Leader != nil {
+ {
+ size, err := m.Leader.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ResignResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ResignResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ResignResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Header != nil {
+ {
+ size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ProclaimRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ProclaimRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ProclaimRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if len(m.Value) > 0 {
+ i -= len(m.Value)
+ copy(dAtA[i:], m.Value)
+ i = encodeVarintV3Election(dAtA, i, uint64(len(m.Value)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.Leader != nil {
+ {
+ size, err := m.Leader.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *ProclaimResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ProclaimResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ProclaimResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Header != nil {
+ {
+ size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Election(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintV3Election(dAtA []byte, offset int, v uint64) int {
+ offset -= sovV3Election(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *CampaignRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.Lease != 0 {
+ n += 1 + sovV3Election(uint64(m.Lease))
+ }
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *CampaignResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.Leader != nil {
+ l = m.Leader.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *LeaderKey) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.Rev != 0 {
+ n += 1 + sovV3Election(uint64(m.Rev))
+ }
+ if m.Lease != 0 {
+ n += 1 + sovV3Election(uint64(m.Lease))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *LeaderRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *LeaderResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.Kv != nil {
+ l = m.Kv.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *ResignRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Leader != nil {
+ l = m.Leader.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *ResignResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *ProclaimRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Leader != nil {
+ l = m.Leader.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *ProclaimResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovV3Election(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovV3Election(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozV3Election(x uint64) (n int) {
+ return sovV3Election(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *CampaignRequest) 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 ErrIntOverflowV3Election
+ }
+ 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: CampaignRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: CampaignRequest: 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 != 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Lease |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
+ if m.Value == nil {
+ m.Value = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *CampaignResponse) 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 ErrIntOverflowV3Election
+ }
+ 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: CampaignResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: CampaignResponse: 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &etcdserverpb.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 Leader", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Leader == nil {
+ m.Leader = &LeaderKey{}
+ }
+ if err := m.Leader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *LeaderKey) 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 ErrIntOverflowV3Election
+ }
+ 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: LeaderKey: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaderKey: 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Rev", wireType)
+ }
+ m.Rev = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Rev |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ 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 ErrIntOverflowV3Election
+ }
+ 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 := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *LeaderRequest) 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 ErrIntOverflowV3Election
+ }
+ 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: LeaderRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaderRequest: 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = append(m.Name[:0], dAtA[iNdEx:postIndex]...)
+ if m.Name == nil {
+ m.Name = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *LeaderResponse) 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 ErrIntOverflowV3Election
+ }
+ 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: LeaderResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaderResponse: 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &etcdserverpb.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 Kv", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Kv == nil {
+ m.Kv = &mvccpb.KeyValue{}
+ }
+ if err := m.Kv.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *ResignRequest) 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 ErrIntOverflowV3Election
+ }
+ 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: ResignRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ResignRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Leader", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Leader == nil {
+ m.Leader = &LeaderKey{}
+ }
+ if err := m.Leader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *ResignResponse) 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 ErrIntOverflowV3Election
+ }
+ 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: ResignResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ResignResponse: 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &etcdserverpb.ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *ProclaimRequest) 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 ErrIntOverflowV3Election
+ }
+ 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: ProclaimRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ProclaimRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Leader", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Leader == nil {
+ m.Leader = &LeaderKey{}
+ }
+ if err := m.Leader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
+ if m.Value == nil {
+ m.Value = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 *ProclaimResponse) 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 ErrIntOverflowV3Election
+ }
+ 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: ProclaimResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ProclaimResponse: 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 ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &etcdserverpb.ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Election(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Election
+ }
+ 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 skipV3Election(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowV3Election
+ }
+ 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, ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowV3Election
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthV3Election
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupV3Election
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthV3Election
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthV3Election = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowV3Election = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupV3Election = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.proto b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.proto
new file mode 100644
index 0000000000..24ccaf138d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.proto
@@ -0,0 +1,119 @@
+syntax = "proto3";
+package v3electionpb;
+
+import "gogoproto/gogo.proto";
+import "etcd/api/etcdserverpb/rpc.proto";
+import "etcd/api/mvccpb/kv.proto";
+
+// for grpc-gateway
+import "google/api/annotations.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+
+// The election service exposes client-side election facilities as a gRPC interface.
+service Election {
+ // Campaign waits to acquire leadership in an election, returning a LeaderKey
+ // representing the leadership if successful. The LeaderKey can then be used
+ // to issue new values on the election, transactionally guard API requests on
+ // leadership still being held, and resign from the election.
+ rpc Campaign(CampaignRequest) returns (CampaignResponse) {
+ option (google.api.http) = {
+ post: "/v3/election/campaign"
+ body: "*"
+ };
+ }
+ // Proclaim updates the leader's posted value with a new value.
+ rpc Proclaim(ProclaimRequest) returns (ProclaimResponse) {
+ option (google.api.http) = {
+ post: "/v3/election/proclaim"
+ body: "*"
+ };
+ }
+ // Leader returns the current election proclamation, if any.
+ rpc Leader(LeaderRequest) returns (LeaderResponse) {
+ option (google.api.http) = {
+ post: "/v3/election/leader"
+ body: "*"
+ };
+ }
+ // Observe streams election proclamations in-order as made by the election's
+ // elected leaders.
+ rpc Observe(LeaderRequest) returns (stream LeaderResponse) {
+ option (google.api.http) = {
+ post: "/v3/election/observe"
+ body: "*"
+ };
+ }
+ // Resign releases election leadership so other campaigners may acquire
+ // leadership on the election.
+ rpc Resign(ResignRequest) returns (ResignResponse) {
+ option (google.api.http) = {
+ post: "/v3/election/resign"
+ body: "*"
+ };
+ }
+}
+
+message CampaignRequest {
+ // name is the election's identifier for the campaign.
+ bytes name = 1;
+ // lease is the ID of the lease attached to leadership of the election. If the
+ // lease expires or is revoked before resigning leadership, then the
+ // leadership is transferred to the next campaigner, if any.
+ int64 lease = 2;
+ // value is the initial proclaimed value set when the campaigner wins the
+ // election.
+ bytes value = 3;
+}
+
+message CampaignResponse {
+ etcdserverpb.ResponseHeader header = 1;
+ // leader describes the resources used for holding leadereship of the election.
+ LeaderKey leader = 2;
+}
+
+message LeaderKey {
+ // name is the election identifier that correponds to the leadership key.
+ bytes name = 1;
+ // key is an opaque key representing the ownership of the election. If the key
+ // is deleted, then leadership is lost.
+ bytes key = 2;
+ // rev is the creation revision of the key. It can be used to test for ownership
+ // of an election during transactions by testing the key's creation revision
+ // matches rev.
+ int64 rev = 3;
+ // lease is the lease ID of the election leader.
+ int64 lease = 4;
+}
+
+message LeaderRequest {
+ // name is the election identifier for the leadership information.
+ bytes name = 1;
+}
+
+message LeaderResponse {
+ etcdserverpb.ResponseHeader header = 1;
+ // kv is the key-value pair representing the latest leader update.
+ mvccpb.KeyValue kv = 2;
+}
+
+message ResignRequest {
+ // leader is the leadership to relinquish by resignation.
+ LeaderKey leader = 1;
+}
+
+message ResignResponse {
+ etcdserverpb.ResponseHeader header = 1;
+}
+
+message ProclaimRequest {
+ // leader is the leadership hold on the election.
+ LeaderKey leader = 1;
+ // value is an update meant to overwrite the leader's current value.
+ bytes value = 2;
+}
+
+message ProclaimResponse {
+ etcdserverpb.ResponseHeader header = 1;
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/doc.go
new file mode 100644
index 0000000000..e0a1008abc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/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 v3lock provides a v3 locking service from an etcdserver.
+package v3lock
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/lock.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/lock.go
new file mode 100644
index 0000000000..8f9623361c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/lock.go
@@ -0,0 +1,56 @@
+// 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 v3lock
+
+import (
+ "context"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/client/v3/concurrency"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"
+)
+
+type lockServer struct {
+ c *clientv3.Client
+}
+
+func NewLockServer(c *clientv3.Client) v3lockpb.LockServer {
+ return &lockServer{c}
+}
+
+func (ls *lockServer) Lock(ctx context.Context, req *v3lockpb.LockRequest) (*v3lockpb.LockResponse, error) {
+ s, err := concurrency.NewSession(
+ ls.c,
+ concurrency.WithLease(clientv3.LeaseID(req.Lease)),
+ concurrency.WithContext(ctx),
+ )
+ if err != nil {
+ return nil, err
+ }
+ s.Orphan()
+ m := concurrency.NewMutex(s, string(req.Name))
+ if err = m.Lock(ctx); err != nil {
+ return nil, err
+ }
+ return &v3lockpb.LockResponse{Header: m.Header(), Key: []byte(m.Key())}, nil
+}
+
+func (ls *lockServer) Unlock(ctx context.Context, req *v3lockpb.UnlockRequest) (*v3lockpb.UnlockResponse, error) {
+ resp, err := ls.c.Delete(ctx, string(req.Key))
+ if err != nil {
+ return nil, err
+ }
+ return &v3lockpb.UnlockResponse{Header: resp.Header}, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go
new file mode 100644
index 0000000000..dc573d79cf
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go
@@ -0,0 +1,242 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: server/etcdserver/api/v3lock/v3lockpb/v3lock.proto
+
+/*
+Package v3lockpb is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package gw
+
+import (
+ "context"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/grpc-gateway/runtime"
+ "github.com/grpc-ecosystem/grpc-gateway/utilities"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/status"
+)
+
+// Suppress "imported and not used" errors
+var _ codes.Code
+var _ io.Reader
+var _ status.Status
+var _ = runtime.String
+var _ = utilities.NewDoubleArray
+var _ = descriptor.ForMessage
+
+func request_Lock_Lock_0(ctx context.Context, marshaler runtime.Marshaler, client v3lockpb.LockClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3lockpb.LockRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Lock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lock_Lock_0(ctx context.Context, marshaler runtime.Marshaler, server v3lockpb.LockServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3lockpb.LockRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Lock(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+func request_Lock_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, client v3lockpb.LockClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3lockpb.UnlockRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.Unlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Lock_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, server v3lockpb.LockServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq v3lockpb.UnlockRequest
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.Unlock(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+// v3lockpb.RegisterLockHandlerServer registers the http handlers for service Lock to "mux".
+// UnaryRPC :call v3lockpb.LockServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+func RegisterLockHandlerServer(ctx context.Context, mux *runtime.ServeMux, server v3lockpb.LockServer) error {
+
+ mux.Handle("POST", pattern_Lock_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lock_Lock_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lock_Lock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lock_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Lock_Unlock_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lock_Unlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+// RegisterLockHandlerFromEndpoint is same as RegisterLockHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterLockHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err != nil {
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ return
+ }
+ go func() {
+ <-ctx.Done()
+ if cerr := conn.Close(); cerr != nil {
+ grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
+ }
+ }()
+ }()
+
+ return RegisterLockHandler(ctx, mux, conn)
+}
+
+// RegisterLockHandler registers the http handlers for service Lock to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterLockHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+ return RegisterLockHandlerClient(ctx, mux, v3lockpb.NewLockClient(conn))
+}
+
+// v3lockpb.RegisterLockHandlerClient registers the http handlers for service Lock
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "LockClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "LockClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "LockClient" to call the correct interceptors.
+func RegisterLockHandlerClient(ctx context.Context, mux *runtime.ServeMux, client v3lockpb.LockClient) error {
+
+ mux.Handle("POST", pattern_Lock_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lock_Lock_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lock_Lock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("POST", pattern_Lock_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Lock_Unlock_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Lock_Unlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ return nil
+}
+
+var (
+ pattern_Lock_Lock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 1}, []string{"v3", "lock"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_Lock_Unlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lock", "unlock"}, "", runtime.AssumeColonVerbOpt(true)))
+)
+
+var (
+ forward_Lock_Lock_0 = runtime.ForwardResponseMessage
+
+ forward_Lock_Unlock_0 = runtime.ForwardResponseMessage
+)
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go
new file mode 100644
index 0000000000..4282ddc85e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go
@@ -0,0 +1,1141 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: v3lock.proto
+
+package v3lockpb
+
+import (
+ context "context"
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+ proto "github.com/golang/protobuf/proto"
+ etcdserverpb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ _ "google.golang.org/genproto/googleapis/api/annotations"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// 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.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type LockRequest struct {
+ // name is the identifier for the distributed shared lock to be acquired.
+ Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // lease is the ID of the lease that will be attached to ownership of the
+ // lock. If the lease expires or is revoked and currently holds the lock,
+ // the lock is automatically released. Calls to Lock with the same lease will
+ // be treated as a single acquisition; locking twice with the same lease is a
+ // no-op.
+ Lease int64 `protobuf:"varint,2,opt,name=lease,proto3" json:"lease,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LockRequest) Reset() { *m = LockRequest{} }
+func (m *LockRequest) String() string { return proto.CompactTextString(m) }
+func (*LockRequest) ProtoMessage() {}
+func (*LockRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_52389b3e2f253201, []int{0}
+}
+func (m *LockRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LockRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LockRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LockRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LockRequest.Merge(m, src)
+}
+func (m *LockRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *LockRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_LockRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LockRequest proto.InternalMessageInfo
+
+func (m *LockRequest) GetName() []byte {
+ if m != nil {
+ return m.Name
+ }
+ return nil
+}
+
+func (m *LockRequest) GetLease() int64 {
+ if m != nil {
+ return m.Lease
+ }
+ return 0
+}
+
+type LockResponse struct {
+ Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
+ // key is a key that will exist on etcd for the duration that the Lock caller
+ // owns the lock. Users should not modify this key or the lock may exhibit
+ // undefined behavior.
+ Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LockResponse) Reset() { *m = LockResponse{} }
+func (m *LockResponse) String() string { return proto.CompactTextString(m) }
+func (*LockResponse) ProtoMessage() {}
+func (*LockResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_52389b3e2f253201, []int{1}
+}
+func (m *LockResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LockResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LockResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LockResponse.Merge(m, src)
+}
+func (m *LockResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *LockResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_LockResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LockResponse proto.InternalMessageInfo
+
+func (m *LockResponse) GetHeader() *etcdserverpb.ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *LockResponse) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+type UnlockRequest struct {
+ // key is the lock ownership key granted by Lock.
+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *UnlockRequest) Reset() { *m = UnlockRequest{} }
+func (m *UnlockRequest) String() string { return proto.CompactTextString(m) }
+func (*UnlockRequest) ProtoMessage() {}
+func (*UnlockRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_52389b3e2f253201, []int{2}
+}
+func (m *UnlockRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *UnlockRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_UnlockRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *UnlockRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_UnlockRequest.Merge(m, src)
+}
+func (m *UnlockRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *UnlockRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_UnlockRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_UnlockRequest proto.InternalMessageInfo
+
+func (m *UnlockRequest) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+type UnlockResponse struct {
+ Header *etcdserverpb.ResponseHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *UnlockResponse) Reset() { *m = UnlockResponse{} }
+func (m *UnlockResponse) String() string { return proto.CompactTextString(m) }
+func (*UnlockResponse) ProtoMessage() {}
+func (*UnlockResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_52389b3e2f253201, []int{3}
+}
+func (m *UnlockResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *UnlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_UnlockResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *UnlockResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_UnlockResponse.Merge(m, src)
+}
+func (m *UnlockResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *UnlockResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_UnlockResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_UnlockResponse proto.InternalMessageInfo
+
+func (m *UnlockResponse) GetHeader() *etcdserverpb.ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*LockRequest)(nil), "v3lockpb.LockRequest")
+ proto.RegisterType((*LockResponse)(nil), "v3lockpb.LockResponse")
+ proto.RegisterType((*UnlockRequest)(nil), "v3lockpb.UnlockRequest")
+ proto.RegisterType((*UnlockResponse)(nil), "v3lockpb.UnlockResponse")
+}
+
+func init() { proto.RegisterFile("v3lock.proto", fileDescriptor_52389b3e2f253201) }
+
+var fileDescriptor_52389b3e2f253201 = []byte{
+ // 330 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x33, 0xce, 0xc9,
+ 0x4f, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0xf0, 0x0a, 0x92, 0xa4, 0x44,
+ 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x82, 0xfa, 0x20, 0x16, 0x44, 0x5e, 0x4a, 0x3e, 0xb5, 0x24, 0x39,
+ 0x45, 0x3f, 0xb1, 0x20, 0x53, 0x1f, 0xc4, 0x28, 0x4e, 0x2d, 0x2a, 0x4b, 0x2d, 0x2a, 0x48, 0xd2,
+ 0x2f, 0x2a, 0x48, 0x86, 0x2a, 0x90, 0x49, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0x05, 0x2b, 0x49, 0xcc,
+ 0xcb, 0xcb, 0x2f, 0x49, 0x2c, 0xc9, 0xcc, 0xcf, 0x2b, 0x86, 0xc8, 0x2a, 0x99, 0x73, 0x71, 0xfb,
+ 0xe4, 0x27, 0x67, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x09, 0x71, 0xb1, 0xe4, 0x25,
+ 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81, 0xd9, 0x42, 0x22, 0x5c, 0xac, 0x39,
+ 0xa9, 0x89, 0xc5, 0xa9, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x10, 0x8e, 0x52, 0x18, 0x17,
+ 0x0f, 0x44, 0x63, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0xaa, 0x90, 0x09, 0x17, 0x5b, 0x46, 0x6a, 0x62,
+ 0x4a, 0x6a, 0x11, 0x58, 0x2f, 0xb7, 0x91, 0x8c, 0x1e, 0xb2, 0x7b, 0xf4, 0x60, 0xea, 0x3c, 0xc0,
+ 0x6a, 0x82, 0xa0, 0x6a, 0x85, 0x04, 0xb8, 0x98, 0xb3, 0x53, 0x2b, 0xc1, 0x26, 0xf3, 0x04, 0x81,
+ 0x98, 0x4a, 0x8a, 0x5c, 0xbc, 0xa1, 0x79, 0x39, 0x48, 0x4e, 0x82, 0x2a, 0x61, 0x44, 0x28, 0x71,
+ 0xe3, 0xe2, 0x83, 0x29, 0xa1, 0xc4, 0x72, 0xa3, 0x0d, 0x8c, 0x5c, 0x2c, 0x20, 0x3f, 0x08, 0xf9,
+ 0x43, 0x69, 0x51, 0x3d, 0x58, 0x60, 0xeb, 0x21, 0x05, 0x8a, 0x94, 0x18, 0xba, 0x30, 0xc4, 0x34,
+ 0x25, 0x89, 0xa6, 0xcb, 0x4f, 0x26, 0x33, 0x09, 0x29, 0xf1, 0xea, 0x97, 0x19, 0xeb, 0x83, 0x14,
+ 0x80, 0x09, 0x2b, 0x46, 0x2d, 0xa1, 0x70, 0x2e, 0x36, 0x88, 0x0b, 0x85, 0xc4, 0x11, 0x7a, 0x51,
+ 0xbc, 0x25, 0x25, 0x81, 0x29, 0x01, 0x35, 0x56, 0x0a, 0x6c, 0xac, 0x88, 0x12, 0x3f, 0xdc, 0xd8,
+ 0xd2, 0x3c, 0xa8, 0xc1, 0x4e, 0x02, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0,
+ 0x91, 0x1c, 0xe3, 0x8c, 0xc7, 0x72, 0x0c, 0x49, 0x6c, 0xe0, 0x78, 0x34, 0x06, 0x04, 0x00, 0x00,
+ 0xff, 0xff, 0x4a, 0x4d, 0xca, 0xbb, 0x36, 0x02, 0x00, 0x00,
+}
+
+// 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
+
+// LockClient is the client API for Lock service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type LockClient interface {
+ // Lock acquires a distributed shared lock on a given named lock.
+ // On success, it will return a unique key that exists so long as the
+ // lock is held by the caller. This key can be used in conjunction with
+ // transactions to safely ensure updates to etcd only occur while holding
+ // lock ownership. The lock is held until Unlock is called on the key or the
+ // lease associate with the owner expires.
+ Lock(ctx context.Context, in *LockRequest, opts ...grpc.CallOption) (*LockResponse, error)
+ // Unlock takes a key returned by Lock and releases the hold on lock. The
+ // next Lock caller waiting for the lock will then be woken up and given
+ // ownership of the lock.
+ Unlock(ctx context.Context, in *UnlockRequest, opts ...grpc.CallOption) (*UnlockResponse, error)
+}
+
+type lockClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewLockClient(cc *grpc.ClientConn) LockClient {
+ return &lockClient{cc}
+}
+
+func (c *lockClient) Lock(ctx context.Context, in *LockRequest, opts ...grpc.CallOption) (*LockResponse, error) {
+ out := new(LockResponse)
+ err := c.cc.Invoke(ctx, "/v3lockpb.Lock/Lock", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *lockClient) Unlock(ctx context.Context, in *UnlockRequest, opts ...grpc.CallOption) (*UnlockResponse, error) {
+ out := new(UnlockResponse)
+ err := c.cc.Invoke(ctx, "/v3lockpb.Lock/Unlock", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// LockServer is the server API for Lock service.
+type LockServer interface {
+ // Lock acquires a distributed shared lock on a given named lock.
+ // On success, it will return a unique key that exists so long as the
+ // lock is held by the caller. This key can be used in conjunction with
+ // transactions to safely ensure updates to etcd only occur while holding
+ // lock ownership. The lock is held until Unlock is called on the key or the
+ // lease associate with the owner expires.
+ Lock(context.Context, *LockRequest) (*LockResponse, error)
+ // Unlock takes a key returned by Lock and releases the hold on lock. The
+ // next Lock caller waiting for the lock will then be woken up and given
+ // ownership of the lock.
+ Unlock(context.Context, *UnlockRequest) (*UnlockResponse, error)
+}
+
+// UnimplementedLockServer can be embedded to have forward compatible implementations.
+type UnimplementedLockServer struct {
+}
+
+func (*UnimplementedLockServer) Lock(ctx context.Context, req *LockRequest) (*LockResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Lock not implemented")
+}
+func (*UnimplementedLockServer) Unlock(ctx context.Context, req *UnlockRequest) (*UnlockResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Unlock not implemented")
+}
+
+func RegisterLockServer(s *grpc.Server, srv LockServer) {
+ s.RegisterService(&_Lock_serviceDesc, srv)
+}
+
+func _Lock_Lock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LockRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LockServer).Lock(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/v3lockpb.Lock/Lock",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LockServer).Lock(ctx, req.(*LockRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Lock_Unlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UnlockRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LockServer).Unlock(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/v3lockpb.Lock/Unlock",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LockServer).Unlock(ctx, req.(*UnlockRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Lock_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "v3lockpb.Lock",
+ HandlerType: (*LockServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Lock",
+ Handler: _Lock_Lock_Handler,
+ },
+ {
+ MethodName: "Unlock",
+ Handler: _Lock_Unlock_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "v3lock.proto",
+}
+
+func (m *LockRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LockRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Lease != 0 {
+ i = encodeVarintV3Lock(dAtA, i, uint64(m.Lease))
+ i--
+ dAtA[i] = 0x10
+ }
+ if len(m.Name) > 0 {
+ i -= len(m.Name)
+ copy(dAtA[i:], m.Name)
+ i = encodeVarintV3Lock(dAtA, i, uint64(len(m.Name)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *LockResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LockResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if len(m.Key) > 0 {
+ i -= len(m.Key)
+ copy(dAtA[i:], m.Key)
+ i = encodeVarintV3Lock(dAtA, i, uint64(len(m.Key)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if m.Header != nil {
+ {
+ size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Lock(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *UnlockRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *UnlockRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *UnlockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if len(m.Key) > 0 {
+ i -= len(m.Key)
+ copy(dAtA[i:], m.Key)
+ i = encodeVarintV3Lock(dAtA, i, uint64(len(m.Key)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *UnlockResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *UnlockResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *UnlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Header != nil {
+ {
+ size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintV3Lock(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintV3Lock(dAtA []byte, offset int, v uint64) int {
+ offset -= sovV3Lock(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *LockRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovV3Lock(uint64(l))
+ }
+ if m.Lease != 0 {
+ n += 1 + sovV3Lock(uint64(m.Lease))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *LockResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovV3Lock(uint64(l))
+ }
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovV3Lock(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *UnlockRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovV3Lock(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *UnlockResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovV3Lock(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovV3Lock(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozV3Lock(x uint64) (n int) {
+ return sovV3Lock(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *LockRequest) 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 ErrIntOverflowV3Lock
+ }
+ 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: LockRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LockRequest: 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 ErrIntOverflowV3Lock
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ 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 != 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 ErrIntOverflowV3Lock
+ }
+ 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 := skipV3Lock(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ 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 *LockResponse) 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 ErrIntOverflowV3Lock
+ }
+ 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: LockResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LockResponse: 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 ErrIntOverflowV3Lock
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &etcdserverpb.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 Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowV3Lock
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Lock(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ 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 *UnlockRequest) 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 ErrIntOverflowV3Lock
+ }
+ 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: UnlockRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: UnlockRequest: 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 ErrIntOverflowV3Lock
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Lock(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ 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 *UnlockResponse) 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 ErrIntOverflowV3Lock
+ }
+ 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: UnlockResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: UnlockResponse: 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 ErrIntOverflowV3Lock
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &etcdserverpb.ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipV3Lock(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthV3Lock
+ }
+ 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 skipV3Lock(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowV3Lock
+ }
+ 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, ErrIntOverflowV3Lock
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ case 1:
+ iNdEx += 8
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowV3Lock
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthV3Lock
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupV3Lock
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthV3Lock
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthV3Lock = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowV3Lock = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupV3Lock = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.proto b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.proto
new file mode 100644
index 0000000000..1b5c456ae2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.proto
@@ -0,0 +1,65 @@
+syntax = "proto3";
+package v3lockpb;
+
+import "gogoproto/gogo.proto";
+import "etcd/api/etcdserverpb/rpc.proto";
+
+// for grpc-gateway
+import "google/api/annotations.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+
+// The lock service exposes client-side locking facilities as a gRPC interface.
+service Lock {
+ // Lock acquires a distributed shared lock on a given named lock.
+ // On success, it will return a unique key that exists so long as the
+ // lock is held by the caller. This key can be used in conjunction with
+ // transactions to safely ensure updates to etcd only occur while holding
+ // lock ownership. The lock is held until Unlock is called on the key or the
+ // lease associate with the owner expires.
+ rpc Lock(LockRequest) returns (LockResponse) {
+ option (google.api.http) = {
+ post: "/v3/lock/lock"
+ body: "*"
+ };
+ }
+
+ // Unlock takes a key returned by Lock and releases the hold on lock. The
+ // next Lock caller waiting for the lock will then be woken up and given
+ // ownership of the lock.
+ rpc Unlock(UnlockRequest) returns (UnlockResponse) {
+ option (google.api.http) = {
+ post: "/v3/lock/unlock"
+ body: "*"
+ };
+ }
+}
+
+message LockRequest {
+ // name is the identifier for the distributed shared lock to be acquired.
+ bytes name = 1;
+ // lease is the ID of the lease that will be attached to ownership of the
+ // lock. If the lease expires or is revoked and currently holds the lock,
+ // the lock is automatically released. Calls to Lock with the same lease will
+ // be treated as a single acquisition; locking twice with the same lease is a
+ // no-op.
+ int64 lease = 2;
+}
+
+message LockResponse {
+ etcdserverpb.ResponseHeader header = 1;
+ // key is a key that will exist on etcd for the duration that the Lock caller
+ // owns the lock. Users should not modify this key or the lock may exhibit
+ // undefined behavior.
+ bytes key = 2;
+}
+
+message UnlockRequest {
+ // key is the lock ownership key granted by Lock.
+ bytes key = 1;
+}
+
+message UnlockResponse {
+ etcdserverpb.ResponseHeader header = 1;
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/auth.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/auth.go
new file mode 100644
index 0000000000..d986037a1b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/auth.go
@@ -0,0 +1,166 @@
+// 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 v3rpc
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+)
+
+type AuthServer struct {
+ authenticator etcdserver.Authenticator
+}
+
+func NewAuthServer(s *etcdserver.EtcdServer) *AuthServer {
+ return &AuthServer{authenticator: s}
+}
+
+func (as *AuthServer) AuthEnable(ctx context.Context, r *pb.AuthEnableRequest) (*pb.AuthEnableResponse, error) {
+ resp, err := as.authenticator.AuthEnable(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) AuthDisable(ctx context.Context, r *pb.AuthDisableRequest) (*pb.AuthDisableResponse, error) {
+ resp, err := as.authenticator.AuthDisable(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) AuthStatus(ctx context.Context, r *pb.AuthStatusRequest) (*pb.AuthStatusResponse, error) {
+ resp, err := as.authenticator.AuthStatus(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) {
+ resp, err := as.authenticator.Authenticate(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
+ resp, err := as.authenticator.RoleAdd(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) RoleDelete(ctx context.Context, r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) {
+ resp, err := as.authenticator.RoleDelete(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) RoleGet(ctx context.Context, r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
+ resp, err := as.authenticator.RoleGet(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) RoleList(ctx context.Context, r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) {
+ resp, err := as.authenticator.RoleList(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) RoleRevokePermission(ctx context.Context, r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) {
+ resp, err := as.authenticator.RoleRevokePermission(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) RoleGrantPermission(ctx context.Context, r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) {
+ resp, err := as.authenticator.RoleGrantPermission(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
+ resp, err := as.authenticator.UserAdd(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) {
+ resp, err := as.authenticator.UserDelete(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
+ resp, err := as.authenticator.UserGet(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) UserList(ctx context.Context, r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) {
+ resp, err := as.authenticator.UserList(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) UserGrantRole(ctx context.Context, r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) {
+ resp, err := as.authenticator.UserGrantRole(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) UserRevokeRole(ctx context.Context, r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) {
+ resp, err := as.authenticator.UserRevokeRole(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
+
+func (as *AuthServer) UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) {
+ resp, err := as.authenticator.UserChangePassword(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return resp, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/codec.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/codec.go
new file mode 100644
index 0000000000..d599ff63cc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/codec.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.
+
+package v3rpc
+
+import "github.com/golang/protobuf/proto"
+
+type codec struct{}
+
+func (c *codec) Marshal(v interface{}) ([]byte, error) {
+ b, err := proto.Marshal(v.(proto.Message))
+ sentBytes.Add(float64(len(b)))
+ return b, err
+}
+
+func (c *codec) Unmarshal(data []byte, v interface{}) error {
+ receivedBytes.Add(float64(len(data)))
+ return proto.Unmarshal(data, v.(proto.Message))
+}
+
+func (c *codec) String() string {
+ return "proto"
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/grpc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/grpc.go
new file mode 100644
index 0000000000..349ebea400
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/grpc.go
@@ -0,0 +1,92 @@
+// 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 v3rpc
+
+import (
+ "crypto/tls"
+ "math"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/v3/credentials"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+
+ grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
+ grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
+ "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/health"
+ healthpb "google.golang.org/grpc/health/grpc_health_v1"
+)
+
+const (
+ grpcOverheadBytes = 512 * 1024
+ maxSendBytes = math.MaxInt32
+)
+
+func Server(s *etcdserver.EtcdServer, tls *tls.Config, interceptor grpc.UnaryServerInterceptor, gopts ...grpc.ServerOption) *grpc.Server {
+ var opts []grpc.ServerOption
+ opts = append(opts, grpc.CustomCodec(&codec{}))
+ if tls != nil {
+ bundle := credentials.NewBundle(credentials.Config{TLSConfig: tls})
+ opts = append(opts, grpc.Creds(bundle.TransportCredentials()))
+ }
+ chainUnaryInterceptors := []grpc.UnaryServerInterceptor{
+ newLogUnaryInterceptor(s),
+ newUnaryInterceptor(s),
+ grpc_prometheus.UnaryServerInterceptor,
+ }
+ if interceptor != nil {
+ chainUnaryInterceptors = append(chainUnaryInterceptors, interceptor)
+ }
+
+ chainStreamInterceptors := []grpc.StreamServerInterceptor{
+ newStreamInterceptor(s),
+ grpc_prometheus.StreamServerInterceptor,
+ }
+
+ if s.Cfg.ExperimentalEnableDistributedTracing {
+ chainUnaryInterceptors = append(chainUnaryInterceptors, otelgrpc.UnaryServerInterceptor(s.Cfg.ExperimentalTracerOptions...))
+ chainStreamInterceptors = append(chainStreamInterceptors, otelgrpc.StreamServerInterceptor(s.Cfg.ExperimentalTracerOptions...))
+
+ }
+
+ opts = append(opts, grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(chainUnaryInterceptors...)))
+ opts = append(opts, grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(chainStreamInterceptors...)))
+
+ opts = append(opts, grpc.MaxRecvMsgSize(int(s.Cfg.MaxRequestBytes+grpcOverheadBytes)))
+ opts = append(opts, grpc.MaxSendMsgSize(maxSendBytes))
+ opts = append(opts, grpc.MaxConcurrentStreams(s.Cfg.MaxConcurrentStreams))
+
+ grpcServer := grpc.NewServer(append(opts, gopts...)...)
+
+ pb.RegisterKVServer(grpcServer, NewQuotaKVServer(s))
+ pb.RegisterWatchServer(grpcServer, NewWatchServer(s))
+ pb.RegisterLeaseServer(grpcServer, NewQuotaLeaseServer(s))
+ pb.RegisterClusterServer(grpcServer, NewClusterServer(s))
+ pb.RegisterAuthServer(grpcServer, NewAuthServer(s))
+ pb.RegisterMaintenanceServer(grpcServer, NewMaintenanceServer(s))
+
+ // server should register all the services manually
+ // use empty service name for all etcd services' health status,
+ // see https://github.com/grpc/grpc/blob/master/doc/health-checking.md for more
+ hsrv := health.NewServer()
+ hsrv.SetServingStatus("", healthpb.HealthCheckResponse_SERVING)
+ healthpb.RegisterHealthServer(grpcServer, hsrv)
+
+ // set zero values for metrics registered for this grpc server
+ grpc_prometheus.Register(grpcServer)
+
+ return grpcServer
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/header.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/header.go
new file mode 100644
index 0000000000..112cc922ea
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/header.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 v3rpc
+
+import (
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+)
+
+type header struct {
+ clusterID int64
+ memberID int64
+ sg etcdserver.RaftStatusGetter
+ rev func() int64
+}
+
+func newHeader(s *etcdserver.EtcdServer) header {
+ return header{
+ clusterID: int64(s.Cluster().ID()),
+ memberID: int64(s.ID()),
+ sg: s,
+ rev: func() int64 { return s.KV().Rev() },
+ }
+}
+
+// fill populates pb.ResponseHeader using etcdserver information
+func (h *header) fill(rh *pb.ResponseHeader) {
+ if rh == nil {
+ panic("unexpected nil resp.Header")
+ }
+ rh.ClusterId = uint64(h.clusterID)
+ rh.MemberId = uint64(h.memberID)
+ rh.RaftTerm = h.sg.Term()
+ if rh.Revision == 0 {
+ rh.Revision = h.rev()
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/interceptor.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/interceptor.go
new file mode 100644
index 0000000000..5c80fcf041
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/interceptor.go
@@ -0,0 +1,345 @@
+// 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 v3rpc
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.uber.org/zap"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+)
+
+const (
+ maxNoLeaderCnt = 3
+ warnUnaryRequestLatency = 300 * time.Millisecond
+ snapshotMethod = "/etcdserverpb.Maintenance/Snapshot"
+)
+
+type streamsMap struct {
+ mu sync.Mutex
+ streams map[grpc.ServerStream]struct{}
+}
+
+func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ if !api.IsCapabilityEnabled(api.V3rpcCapability) {
+ return nil, rpctypes.ErrGRPCNotCapable
+ }
+
+ if s.IsMemberExist(s.ID()) && s.IsLearner() && !isRPCSupportedForLearner(req) {
+ return nil, rpctypes.ErrGPRCNotSupportedForLearner
+ }
+
+ md, ok := metadata.FromIncomingContext(ctx)
+ if ok {
+ ver, vs := "unknown", md.Get(rpctypes.MetadataClientAPIVersionKey)
+ if len(vs) > 0 {
+ ver = vs[0]
+ }
+ clientRequests.WithLabelValues("unary", ver).Inc()
+
+ if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader {
+ if s.Leader() == types.ID(raft.None) {
+ return nil, rpctypes.ErrGRPCNoLeader
+ }
+ }
+ }
+
+ return handler(ctx, req)
+ }
+}
+
+func newLogUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ startTime := time.Now()
+ resp, err := handler(ctx, req)
+ lg := s.Logger()
+ if lg != nil { // acquire stats if debug level is enabled or request is expensive
+ defer logUnaryRequestStats(ctx, lg, info, startTime, req, resp)
+ }
+ return resp, err
+ }
+}
+
+func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryServerInfo, startTime time.Time, req interface{}, resp interface{}) {
+ duration := time.Since(startTime)
+ var enabledDebugLevel, expensiveRequest bool
+ if lg.Core().Enabled(zap.DebugLevel) {
+ enabledDebugLevel = true
+ }
+ if duration > warnUnaryRequestLatency {
+ expensiveRequest = true
+ }
+ if !enabledDebugLevel && !expensiveRequest {
+ return
+ }
+ remote := "No remote client info."
+ peerInfo, ok := peer.FromContext(ctx)
+ if ok {
+ remote = peerInfo.Addr.String()
+ }
+ responseType := info.FullMethod
+ var reqCount, respCount int64
+ var reqSize, respSize int
+ var reqContent string
+ switch _resp := resp.(type) {
+ case *pb.RangeResponse:
+ _req, ok := req.(*pb.RangeRequest)
+ if ok {
+ reqCount = 0
+ reqSize = _req.Size()
+ reqContent = _req.String()
+ }
+ if _resp != nil {
+ respCount = _resp.GetCount()
+ respSize = _resp.Size()
+ }
+ case *pb.PutResponse:
+ _req, ok := req.(*pb.PutRequest)
+ if ok {
+ reqCount = 1
+ reqSize = _req.Size()
+ reqContent = pb.NewLoggablePutRequest(_req).String()
+ // redact value field from request content, see PR #9821
+ }
+ if _resp != nil {
+ respCount = 0
+ respSize = _resp.Size()
+ }
+ case *pb.DeleteRangeResponse:
+ _req, ok := req.(*pb.DeleteRangeRequest)
+ if ok {
+ reqCount = 0
+ reqSize = _req.Size()
+ reqContent = _req.String()
+ }
+ if _resp != nil {
+ respCount = _resp.GetDeleted()
+ respSize = _resp.Size()
+ }
+ case *pb.TxnResponse:
+ _req, ok := req.(*pb.TxnRequest)
+ if ok && _resp != nil {
+ if _resp.GetSucceeded() { // determine the 'actual' count and size of request based on success or failure
+ reqCount = int64(len(_req.GetSuccess()))
+ reqSize = 0
+ for _, r := range _req.GetSuccess() {
+ reqSize += r.Size()
+ }
+ } else {
+ reqCount = int64(len(_req.GetFailure()))
+ reqSize = 0
+ for _, r := range _req.GetFailure() {
+ reqSize += r.Size()
+ }
+ }
+ reqContent = pb.NewLoggableTxnRequest(_req).String()
+ // redact value field from request content, see PR #9821
+ }
+ if _resp != nil {
+ respCount = 0
+ respSize = _resp.Size()
+ }
+ default:
+ reqCount = -1
+ reqSize = -1
+ respCount = -1
+ respSize = -1
+ }
+
+ if enabledDebugLevel {
+ logGenericRequestStats(lg, startTime, duration, remote, responseType, reqCount, reqSize, respCount, respSize, reqContent)
+ } else if expensiveRequest {
+ logExpensiveRequestStats(lg, startTime, duration, remote, responseType, reqCount, reqSize, respCount, respSize, reqContent)
+ }
+}
+
+func logGenericRequestStats(lg *zap.Logger, startTime time.Time, duration time.Duration, remote string, responseType string,
+ reqCount int64, reqSize int, respCount int64, respSize int, reqContent string) {
+ lg.Debug("request stats",
+ zap.Time("start time", startTime),
+ zap.Duration("time spent", duration),
+ zap.String("remote", remote),
+ zap.String("response type", responseType),
+ zap.Int64("request count", reqCount),
+ zap.Int("request size", reqSize),
+ zap.Int64("response count", respCount),
+ zap.Int("response size", respSize),
+ zap.String("request content", reqContent),
+ )
+}
+
+func logExpensiveRequestStats(lg *zap.Logger, startTime time.Time, duration time.Duration, remote string, responseType string,
+ reqCount int64, reqSize int, respCount int64, respSize int, reqContent string) {
+ lg.Warn("request stats",
+ zap.Time("start time", startTime),
+ zap.Duration("time spent", duration),
+ zap.String("remote", remote),
+ zap.String("response type", responseType),
+ zap.Int64("request count", reqCount),
+ zap.Int("request size", reqSize),
+ zap.Int64("response count", respCount),
+ zap.Int("response size", respSize),
+ zap.String("request content", reqContent),
+ )
+}
+
+func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor {
+ smap := monitorLeader(s)
+
+ return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ if !api.IsCapabilityEnabled(api.V3rpcCapability) {
+ return rpctypes.ErrGRPCNotCapable
+ }
+
+ if s.IsMemberExist(s.ID()) && s.IsLearner() && info.FullMethod != snapshotMethod { // learner does not support stream RPC except Snapshot
+ return rpctypes.ErrGPRCNotSupportedForLearner
+ }
+
+ md, ok := metadata.FromIncomingContext(ss.Context())
+ if ok {
+ ver, vs := "unknown", md.Get(rpctypes.MetadataClientAPIVersionKey)
+ if len(vs) > 0 {
+ ver = vs[0]
+ }
+ clientRequests.WithLabelValues("stream", ver).Inc()
+
+ if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader {
+ if s.Leader() == types.ID(raft.None) {
+ return rpctypes.ErrGRPCNoLeader
+ }
+
+ ctx := newCancellableContext(ss.Context())
+ ss = serverStreamWithCtx{ctx: ctx, ServerStream: ss}
+
+ smap.mu.Lock()
+ smap.streams[ss] = struct{}{}
+ smap.mu.Unlock()
+
+ defer func() {
+ smap.mu.Lock()
+ delete(smap.streams, ss)
+ smap.mu.Unlock()
+ // TODO: investigate whether the reason for cancellation here is useful to know
+ ctx.Cancel(nil)
+ }()
+ }
+ }
+
+ return handler(srv, ss)
+ }
+}
+
+// cancellableContext wraps a context with new cancellable context that allows a
+// specific cancellation error to be preserved and later retrieved using the
+// Context.Err() function. This is so downstream context users can disambiguate
+// the reason for the cancellation which could be from the client (for example)
+// or from this interceptor code.
+type cancellableContext struct {
+ context.Context
+
+ lock sync.RWMutex
+ cancel context.CancelFunc
+ cancelReason error
+}
+
+func newCancellableContext(parent context.Context) *cancellableContext {
+ ctx, cancel := context.WithCancel(parent)
+ return &cancellableContext{
+ Context: ctx,
+ cancel: cancel,
+ }
+}
+
+// Cancel stores the cancellation reason and then delegates to context.WithCancel
+// against the parent context.
+func (c *cancellableContext) Cancel(reason error) {
+ c.lock.Lock()
+ c.cancelReason = reason
+ c.lock.Unlock()
+ c.cancel()
+}
+
+// Err will return the preserved cancel reason error if present, and will
+// otherwise return the underlying error from the parent context.
+func (c *cancellableContext) Err() error {
+ c.lock.RLock()
+ defer c.lock.RUnlock()
+ if c.cancelReason != nil {
+ return c.cancelReason
+ }
+ return c.Context.Err()
+}
+
+type serverStreamWithCtx struct {
+ grpc.ServerStream
+
+ // ctx is used so that we can preserve a reason for cancellation.
+ ctx *cancellableContext
+}
+
+func (ssc serverStreamWithCtx) Context() context.Context { return ssc.ctx }
+
+func monitorLeader(s *etcdserver.EtcdServer) *streamsMap {
+ smap := &streamsMap{
+ streams: make(map[grpc.ServerStream]struct{}),
+ }
+
+ s.GoAttach(func() {
+ election := time.Duration(s.Cfg.TickMs) * time.Duration(s.Cfg.ElectionTicks) * time.Millisecond
+ noLeaderCnt := 0
+
+ for {
+ select {
+ case <-s.StoppingNotify():
+ return
+ case <-time.After(election):
+ if s.Leader() == types.ID(raft.None) {
+ noLeaderCnt++
+ } else {
+ noLeaderCnt = 0
+ }
+
+ // We are more conservative on canceling existing streams. Reconnecting streams
+ // cost much more than just rejecting new requests. So we wait until the member
+ // cannot find a leader for maxNoLeaderCnt election timeouts to cancel existing streams.
+ if noLeaderCnt >= maxNoLeaderCnt {
+ smap.mu.Lock()
+ for ss := range smap.streams {
+ if ssWithCtx, ok := ss.(serverStreamWithCtx); ok {
+ ssWithCtx.ctx.Cancel(rpctypes.ErrGRPCNoLeader)
+ <-ss.Context().Done()
+ }
+ }
+ smap.streams = make(map[grpc.ServerStream]struct{})
+ smap.mu.Unlock()
+ }
+ }
+ }
+ })
+
+ return smap
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/key.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/key.go
new file mode 100644
index 0000000000..d1a7ee6334
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/key.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 v3rpc implements etcd v3 RPC system based on gRPC.
+package v3rpc
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/pkg/v3/adt"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+)
+
+type kvServer struct {
+ hdr header
+ kv etcdserver.RaftKV
+ // maxTxnOps is the max operations per txn.
+ // e.g suppose maxTxnOps = 128.
+ // Txn.Success can have at most 128 operations,
+ // and Txn.Failure can have at most 128 operations.
+ maxTxnOps uint
+}
+
+func NewKVServer(s *etcdserver.EtcdServer) pb.KVServer {
+ return &kvServer{hdr: newHeader(s), kv: s, maxTxnOps: s.Cfg.MaxTxnOps}
+}
+
+func (s *kvServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
+ if err := checkRangeRequest(r); err != nil {
+ return nil, err
+ }
+
+ resp, err := s.kv.Range(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+
+ s.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (s *kvServer) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) {
+ if err := checkPutRequest(r); err != nil {
+ return nil, err
+ }
+
+ resp, err := s.kv.Put(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+
+ s.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (s *kvServer) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
+ if err := checkDeleteRequest(r); err != nil {
+ return nil, err
+ }
+
+ resp, err := s.kv.DeleteRange(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+
+ s.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (s *kvServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
+ if err := checkTxnRequest(r, int(s.maxTxnOps)); err != nil {
+ return nil, err
+ }
+ // check for forbidden put/del overlaps after checking request to avoid quadratic blowup
+ if _, _, err := checkIntervals(r.Success); err != nil {
+ return nil, err
+ }
+ if _, _, err := checkIntervals(r.Failure); err != nil {
+ return nil, err
+ }
+
+ resp, err := s.kv.Txn(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+
+ s.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (s *kvServer) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error) {
+ resp, err := s.kv.Compact(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+
+ s.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func checkRangeRequest(r *pb.RangeRequest) error {
+ if len(r.Key) == 0 {
+ return rpctypes.ErrGRPCEmptyKey
+ }
+ return nil
+}
+
+func checkPutRequest(r *pb.PutRequest) error {
+ if len(r.Key) == 0 {
+ return rpctypes.ErrGRPCEmptyKey
+ }
+ if r.IgnoreValue && len(r.Value) != 0 {
+ return rpctypes.ErrGRPCValueProvided
+ }
+ if r.IgnoreLease && r.Lease != 0 {
+ return rpctypes.ErrGRPCLeaseProvided
+ }
+ return nil
+}
+
+func checkDeleteRequest(r *pb.DeleteRangeRequest) error {
+ if len(r.Key) == 0 {
+ return rpctypes.ErrGRPCEmptyKey
+ }
+ return nil
+}
+
+func checkTxnRequest(r *pb.TxnRequest, maxTxnOps int) error {
+ opc := len(r.Compare)
+ if opc < len(r.Success) {
+ opc = len(r.Success)
+ }
+ if opc < len(r.Failure) {
+ opc = len(r.Failure)
+ }
+ if opc > maxTxnOps {
+ return rpctypes.ErrGRPCTooManyOps
+ }
+
+ for _, c := range r.Compare {
+ if len(c.Key) == 0 {
+ return rpctypes.ErrGRPCEmptyKey
+ }
+ }
+ for _, u := range r.Success {
+ if err := checkRequestOp(u, maxTxnOps-opc); err != nil {
+ return err
+ }
+ }
+ for _, u := range r.Failure {
+ if err := checkRequestOp(u, maxTxnOps-opc); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// checkIntervals tests whether puts and deletes overlap for a list of ops. If
+// there is an overlap, returns an error. If no overlap, return put and delete
+// sets for recursive evaluation.
+func checkIntervals(reqs []*pb.RequestOp) (map[string]struct{}, adt.IntervalTree, error) {
+ dels := adt.NewIntervalTree()
+
+ // collect deletes from this level; build first to check lower level overlapped puts
+ for _, req := range reqs {
+ tv, ok := req.Request.(*pb.RequestOp_RequestDeleteRange)
+ if !ok {
+ continue
+ }
+ dreq := tv.RequestDeleteRange
+ if dreq == nil {
+ continue
+ }
+ var iv adt.Interval
+ if len(dreq.RangeEnd) != 0 {
+ iv = adt.NewStringAffineInterval(string(dreq.Key), string(dreq.RangeEnd))
+ } else {
+ iv = adt.NewStringAffinePoint(string(dreq.Key))
+ }
+ dels.Insert(iv, struct{}{})
+ }
+
+ // collect children puts/deletes
+ puts := make(map[string]struct{})
+ for _, req := range reqs {
+ tv, ok := req.Request.(*pb.RequestOp_RequestTxn)
+ if !ok {
+ continue
+ }
+ putsThen, delsThen, err := checkIntervals(tv.RequestTxn.Success)
+ if err != nil {
+ return nil, dels, err
+ }
+ putsElse, delsElse, err := checkIntervals(tv.RequestTxn.Failure)
+ if err != nil {
+ return nil, dels, err
+ }
+ for k := range putsThen {
+ if _, ok := puts[k]; ok {
+ return nil, dels, rpctypes.ErrGRPCDuplicateKey
+ }
+ if dels.Intersects(adt.NewStringAffinePoint(k)) {
+ return nil, dels, rpctypes.ErrGRPCDuplicateKey
+ }
+ puts[k] = struct{}{}
+ }
+ for k := range putsElse {
+ if _, ok := puts[k]; ok {
+ // if key is from putsThen, overlap is OK since
+ // either then/else are mutually exclusive
+ if _, isSafe := putsThen[k]; !isSafe {
+ return nil, dels, rpctypes.ErrGRPCDuplicateKey
+ }
+ }
+ if dels.Intersects(adt.NewStringAffinePoint(k)) {
+ return nil, dels, rpctypes.ErrGRPCDuplicateKey
+ }
+ puts[k] = struct{}{}
+ }
+ dels.Union(delsThen, adt.NewStringAffineInterval("\x00", ""))
+ dels.Union(delsElse, adt.NewStringAffineInterval("\x00", ""))
+ }
+
+ // collect and check this level's puts
+ for _, req := range reqs {
+ tv, ok := req.Request.(*pb.RequestOp_RequestPut)
+ if !ok || tv.RequestPut == nil {
+ continue
+ }
+ k := string(tv.RequestPut.Key)
+ if _, ok := puts[k]; ok {
+ return nil, dels, rpctypes.ErrGRPCDuplicateKey
+ }
+ if dels.Intersects(adt.NewStringAffinePoint(k)) {
+ return nil, dels, rpctypes.ErrGRPCDuplicateKey
+ }
+ puts[k] = struct{}{}
+ }
+ return puts, dels, nil
+}
+
+func checkRequestOp(u *pb.RequestOp, maxTxnOps int) error {
+ // TODO: ensure only one of the field is set.
+ switch uv := u.Request.(type) {
+ case *pb.RequestOp_RequestRange:
+ return checkRangeRequest(uv.RequestRange)
+ case *pb.RequestOp_RequestPut:
+ return checkPutRequest(uv.RequestPut)
+ case *pb.RequestOp_RequestDeleteRange:
+ return checkDeleteRequest(uv.RequestDeleteRange)
+ case *pb.RequestOp_RequestTxn:
+ return checkTxnRequest(uv.RequestTxn, maxTxnOps)
+ default:
+ // empty op / nil entry
+ return rpctypes.ErrGRPCKeyNotFound
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/lease.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/lease.go
new file mode 100644
index 0000000000..e123dd2a37
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/lease.go
@@ -0,0 +1,157 @@
+// 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 v3rpc
+
+import (
+ "context"
+ "io"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/lease"
+
+ "go.uber.org/zap"
+)
+
+type LeaseServer struct {
+ lg *zap.Logger
+ hdr header
+ le etcdserver.Lessor
+}
+
+func NewLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer {
+ srv := &LeaseServer{lg: s.Cfg.Logger, le: s, hdr: newHeader(s)}
+ if srv.lg == nil {
+ srv.lg = zap.NewNop()
+ }
+ return srv
+}
+
+func (ls *LeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ resp, err := ls.le.LeaseGrant(ctx, cr)
+
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ ls.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (ls *LeaseServer) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) {
+ resp, err := ls.le.LeaseRevoke(ctx, rr)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ ls.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (ls *LeaseServer) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) {
+ resp, err := ls.le.LeaseTimeToLive(ctx, rr)
+ if err != nil && err != lease.ErrLeaseNotFound {
+ return nil, togRPCError(err)
+ }
+ if err == lease.ErrLeaseNotFound {
+ resp = &pb.LeaseTimeToLiveResponse{
+ Header: &pb.ResponseHeader{},
+ ID: rr.ID,
+ TTL: -1,
+ }
+ }
+ ls.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (ls *LeaseServer) LeaseLeases(ctx context.Context, rr *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) {
+ resp, err := ls.le.LeaseLeases(ctx, rr)
+ if err != nil && err != lease.ErrLeaseNotFound {
+ return nil, togRPCError(err)
+ }
+ if err == lease.ErrLeaseNotFound {
+ resp = &pb.LeaseLeasesResponse{
+ Header: &pb.ResponseHeader{},
+ Leases: []*pb.LeaseStatus{},
+ }
+ }
+ ls.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (ls *LeaseServer) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) (err error) {
+ errc := make(chan error, 1)
+ go func() {
+ errc <- ls.leaseKeepAlive(stream)
+ }()
+ select {
+ case err = <-errc:
+ case <-stream.Context().Done():
+ // the only server-side cancellation is noleader for now.
+ err = stream.Context().Err()
+ if err == context.Canceled {
+ err = rpctypes.ErrGRPCNoLeader
+ }
+ }
+ return err
+}
+
+func (ls *LeaseServer) leaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) error {
+ for {
+ req, err := stream.Recv()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ if isClientCtxErr(stream.Context().Err(), err) {
+ ls.lg.Debug("failed to receive lease keepalive request from gRPC stream", zap.Error(err))
+ } else {
+ ls.lg.Warn("failed to receive lease keepalive request from gRPC stream", zap.Error(err))
+ streamFailures.WithLabelValues("receive", "lease-keepalive").Inc()
+ }
+ return err
+ }
+
+ // Create header before we sent out the renew request.
+ // This can make sure that the revision is strictly smaller or equal to
+ // when the keepalive happened at the local server (when the local server is the leader)
+ // or remote leader.
+ // Without this, a lease might be revoked at rev 3 but client can see the keepalive succeeded
+ // at rev 4.
+ resp := &pb.LeaseKeepAliveResponse{ID: req.ID, Header: &pb.ResponseHeader{}}
+ ls.hdr.fill(resp.Header)
+
+ ttl, err := ls.le.LeaseRenew(stream.Context(), lease.LeaseID(req.ID))
+ if err == lease.ErrLeaseNotFound {
+ err = nil
+ ttl = 0
+ }
+
+ if err != nil {
+ return togRPCError(err)
+ }
+
+ resp.TTL = ttl
+ err = stream.Send(resp)
+ if err != nil {
+ if isClientCtxErr(stream.Context().Err(), err) {
+ ls.lg.Debug("failed to send lease keepalive response to gRPC stream", zap.Error(err))
+ } else {
+ ls.lg.Warn("failed to send lease keepalive response to gRPC stream", zap.Error(err))
+ streamFailures.WithLabelValues("send", "lease-keepalive").Inc()
+ }
+ return err
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/maintenance.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/maintenance.go
new file mode 100644
index 0000000000..42f8b0da2e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/maintenance.go
@@ -0,0 +1,315 @@
+// 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 v3rpc
+
+import (
+ "context"
+ "crypto/sha256"
+ "io"
+ "time"
+
+ "github.com/dustin/go-humanize"
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/mvcc"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+
+ "go.uber.org/zap"
+)
+
+type KVGetter interface {
+ KV() mvcc.WatchableKV
+}
+
+type BackendGetter interface {
+ Backend() backend.Backend
+}
+
+type Alarmer interface {
+ // Alarms is implemented in Server interface located in etcdserver/server.go
+ // It returns a list of alarms present in the AlarmStore
+ Alarms() []*pb.AlarmMember
+ Alarm(ctx context.Context, ar *pb.AlarmRequest) (*pb.AlarmResponse, error)
+}
+
+type Downgrader interface {
+ Downgrade(ctx context.Context, dr *pb.DowngradeRequest) (*pb.DowngradeResponse, error)
+}
+
+type LeaderTransferrer interface {
+ MoveLeader(ctx context.Context, lead, target uint64) error
+}
+
+type AuthGetter interface {
+ AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error)
+ AuthStore() auth.AuthStore
+}
+
+type ClusterStatusGetter interface {
+ IsLearner() bool
+}
+
+type maintenanceServer struct {
+ lg *zap.Logger
+ rg etcdserver.RaftStatusGetter
+ hasher mvcc.HashStorage
+ kg KVGetter
+ bg BackendGetter
+ a Alarmer
+ lt LeaderTransferrer
+ hdr header
+ cs ClusterStatusGetter
+ d Downgrader
+}
+
+func NewMaintenanceServer(s *etcdserver.EtcdServer) pb.MaintenanceServer {
+ srv := &maintenanceServer{lg: s.Cfg.Logger, rg: s, hasher: s.KV().HashStorage(), kg: s, bg: s, a: s, lt: s, hdr: newHeader(s), cs: s, d: s}
+ if srv.lg == nil {
+ srv.lg = zap.NewNop()
+ }
+ return &authMaintenanceServer{srv, s}
+}
+
+func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) {
+ ms.lg.Info("starting defragment")
+ err := ms.bg.Backend().Defrag()
+ if err != nil {
+ ms.lg.Warn("failed to defragment", zap.Error(err))
+ return nil, err
+ }
+ ms.lg.Info("finished defragment")
+ return &pb.DefragmentResponse{}, nil
+}
+
+// big enough size to hold >1 OS pages in the buffer
+const snapshotSendBufferSize = 32 * 1024
+
+func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error {
+ snap := ms.bg.Backend().Snapshot()
+ pr, pw := io.Pipe()
+
+ defer pr.Close()
+
+ go func() {
+ snap.WriteTo(pw)
+ if err := snap.Close(); err != nil {
+ ms.lg.Warn("failed to close snapshot", zap.Error(err))
+ }
+ pw.Close()
+ }()
+
+ // record SHA digest of snapshot data
+ // used for integrity checks during snapshot restore operation
+ h := sha256.New()
+
+ sent := int64(0)
+ total := snap.Size()
+ size := humanize.Bytes(uint64(total))
+
+ start := time.Now()
+ ms.lg.Info("sending database snapshot to client",
+ zap.Int64("total-bytes", total),
+ zap.String("size", size),
+ )
+ for total-sent > 0 {
+ // buffer just holds read bytes from stream
+ // response size is multiple of OS page size, fetched in boltdb
+ // e.g. 4*1024
+ // NOTE: srv.Send does not wait until the message is received by the client.
+ // Therefore the buffer can not be safely reused between Send operations
+ buf := make([]byte, snapshotSendBufferSize)
+
+ n, err := io.ReadFull(pr, buf)
+ if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
+ return togRPCError(err)
+ }
+ sent += int64(n)
+
+ // if total is x * snapshotSendBufferSize. it is possible that
+ // resp.RemainingBytes == 0
+ // resp.Blob == zero byte but not nil
+ // does this make server response sent to client nil in proto
+ // and client stops receiving from snapshot stream before
+ // server sends snapshot SHA?
+ // No, the client will still receive non-nil response
+ // until server closes the stream with EOF
+ resp := &pb.SnapshotResponse{
+ RemainingBytes: uint64(total - sent),
+ Blob: buf[:n],
+ }
+ if err = srv.Send(resp); err != nil {
+ return togRPCError(err)
+ }
+ h.Write(buf[:n])
+ }
+
+ // send SHA digest for integrity checks
+ // during snapshot restore operation
+ sha := h.Sum(nil)
+
+ ms.lg.Info("sending database sha256 checksum to client",
+ zap.Int64("total-bytes", total),
+ zap.Int("checksum-size", len(sha)),
+ )
+ hresp := &pb.SnapshotResponse{RemainingBytes: 0, Blob: sha}
+ if err := srv.Send(hresp); err != nil {
+ return togRPCError(err)
+ }
+
+ ms.lg.Info("successfully sent database snapshot to client",
+ zap.Int64("total-bytes", total),
+ zap.String("size", size),
+ zap.String("took", humanize.Time(start)),
+ )
+ return nil
+}
+
+func (ms *maintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) {
+ h, rev, err := ms.hasher.Hash()
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ resp := &pb.HashResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: h}
+ ms.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (ms *maintenanceServer) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) {
+ h, rev, err := ms.hasher.HashByRev(r.Revision)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+
+ resp := &pb.HashKVResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: h.Hash, CompactRevision: h.CompactRevision}
+ ms.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (ms *maintenanceServer) Alarm(ctx context.Context, ar *pb.AlarmRequest) (*pb.AlarmResponse, error) {
+ resp, err := ms.a.Alarm(ctx, ar)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ if resp.Header == nil {
+ resp.Header = &pb.ResponseHeader{}
+ }
+ ms.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+func (ms *maintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) {
+ hdr := &pb.ResponseHeader{}
+ ms.hdr.fill(hdr)
+ resp := &pb.StatusResponse{
+ Header: hdr,
+ Version: version.Version,
+ Leader: uint64(ms.rg.Leader()),
+ RaftIndex: ms.rg.CommittedIndex(),
+ RaftAppliedIndex: ms.rg.AppliedIndex(),
+ RaftTerm: ms.rg.Term(),
+ DbSize: ms.bg.Backend().Size(),
+ DbSizeInUse: ms.bg.Backend().SizeInUse(),
+ IsLearner: ms.cs.IsLearner(),
+ }
+ if resp.Leader == raft.None {
+ resp.Errors = append(resp.Errors, etcdserver.ErrNoLeader.Error())
+ }
+ for _, a := range ms.a.Alarms() {
+ resp.Errors = append(resp.Errors, a.String())
+ }
+ return resp, nil
+}
+
+func (ms *maintenanceServer) MoveLeader(ctx context.Context, tr *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) {
+ if ms.rg.ID() != ms.rg.Leader() {
+ return nil, rpctypes.ErrGRPCNotLeader
+ }
+
+ if err := ms.lt.MoveLeader(ctx, uint64(ms.rg.Leader()), tr.TargetID); err != nil {
+ return nil, togRPCError(err)
+ }
+ return &pb.MoveLeaderResponse{}, nil
+}
+
+func (ms *maintenanceServer) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) {
+ resp, err := ms.d.Downgrade(ctx, r)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ resp.Header = &pb.ResponseHeader{}
+ ms.hdr.fill(resp.Header)
+ return resp, nil
+}
+
+type authMaintenanceServer struct {
+ *maintenanceServer
+ ag AuthGetter
+}
+
+func (ams *authMaintenanceServer) isAuthenticated(ctx context.Context) error {
+ authInfo, err := ams.ag.AuthInfoFromCtx(ctx)
+ if err != nil {
+ return err
+ }
+
+ return ams.ag.AuthStore().IsAdminPermitted(authInfo)
+}
+
+func (ams *authMaintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) {
+ if err := ams.isAuthenticated(ctx); err != nil {
+ return nil, err
+ }
+
+ return ams.maintenanceServer.Defragment(ctx, sr)
+}
+
+func (ams *authMaintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error {
+ if err := ams.isAuthenticated(srv.Context()); err != nil {
+ return err
+ }
+
+ return ams.maintenanceServer.Snapshot(sr, srv)
+}
+
+func (ams *authMaintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) {
+ if err := ams.isAuthenticated(ctx); err != nil {
+ return nil, err
+ }
+
+ return ams.maintenanceServer.Hash(ctx, r)
+}
+
+func (ams *authMaintenanceServer) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) {
+ if err := ams.isAuthenticated(ctx); err != nil {
+ return nil, err
+ }
+ return ams.maintenanceServer.HashKV(ctx, r)
+}
+
+func (ams *authMaintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) {
+ return ams.maintenanceServer.Status(ctx, ar)
+}
+
+func (ams *authMaintenanceServer) MoveLeader(ctx context.Context, tr *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) {
+ return ams.maintenanceServer.MoveLeader(ctx, tr)
+}
+
+func (ams *authMaintenanceServer) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) {
+ return ams.maintenanceServer.Downgrade(ctx, r)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/member.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/member.go
new file mode 100644
index 0000000000..54fcc24843
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/member.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 v3rpc
+
+import (
+ "context"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+)
+
+type ClusterServer struct {
+ cluster api.Cluster
+ server *etcdserver.EtcdServer
+}
+
+func NewClusterServer(s *etcdserver.EtcdServer) *ClusterServer {
+ return &ClusterServer{
+ cluster: s.Cluster(),
+ server: s,
+ }
+}
+
+func (cs *ClusterServer) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) (*pb.MemberAddResponse, error) {
+ urls, err := types.NewURLs(r.PeerURLs)
+ if err != nil {
+ return nil, rpctypes.ErrGRPCMemberBadURLs
+ }
+
+ now := time.Now()
+ var m *membership.Member
+ if r.IsLearner {
+ m = membership.NewMemberAsLearner("", urls, "", &now)
+ } else {
+ m = membership.NewMember("", urls, "", &now)
+ }
+ membs, merr := cs.server.AddMember(ctx, *m)
+ if merr != nil {
+ return nil, togRPCError(merr)
+ }
+
+ return &pb.MemberAddResponse{
+ Header: cs.header(),
+ Member: &pb.Member{
+ ID: uint64(m.ID),
+ PeerURLs: m.PeerURLs,
+ IsLearner: m.IsLearner,
+ },
+ Members: membersToProtoMembers(membs),
+ }, nil
+}
+
+func (cs *ClusterServer) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest) (*pb.MemberRemoveResponse, error) {
+ membs, err := cs.server.RemoveMember(ctx, r.ID)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return &pb.MemberRemoveResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
+}
+
+func (cs *ClusterServer) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest) (*pb.MemberUpdateResponse, error) {
+ m := membership.Member{
+ ID: types.ID(r.ID),
+ RaftAttributes: membership.RaftAttributes{PeerURLs: r.PeerURLs},
+ }
+ membs, err := cs.server.UpdateMember(ctx, m)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return &pb.MemberUpdateResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
+}
+
+func (cs *ClusterServer) MemberList(ctx context.Context, r *pb.MemberListRequest) (*pb.MemberListResponse, error) {
+ if r.Linearizable {
+ if err := cs.server.LinearizableReadNotify(ctx); err != nil {
+ return nil, togRPCError(err)
+ }
+ }
+ membs := membersToProtoMembers(cs.cluster.Members())
+ return &pb.MemberListResponse{Header: cs.header(), Members: membs}, nil
+}
+
+func (cs *ClusterServer) MemberPromote(ctx context.Context, r *pb.MemberPromoteRequest) (*pb.MemberPromoteResponse, error) {
+ membs, err := cs.server.PromoteMember(ctx, r.ID)
+ if err != nil {
+ return nil, togRPCError(err)
+ }
+ return &pb.MemberPromoteResponse{Header: cs.header(), Members: membersToProtoMembers(membs)}, nil
+}
+
+func (cs *ClusterServer) header() *pb.ResponseHeader {
+ return &pb.ResponseHeader{ClusterId: uint64(cs.cluster.ID()), MemberId: uint64(cs.server.ID()), RaftTerm: cs.server.Term()}
+}
+
+func membersToProtoMembers(membs []*membership.Member) []*pb.Member {
+ protoMembs := make([]*pb.Member, len(membs))
+ for i := range membs {
+ protoMembs[i] = &pb.Member{
+ Name: membs[i].Name,
+ ID: uint64(membs[i].ID),
+ PeerURLs: membs[i].PeerURLs,
+ ClientURLs: membs[i].ClientURLs,
+ IsLearner: membs[i].IsLearner,
+ }
+ }
+ return protoMembs
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/metrics.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/metrics.go
new file mode 100644
index 0000000000..a4ee723c52
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/metrics.go
@@ -0,0 +1,58 @@
+// 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 v3rpc
+
+import "github.com/prometheus/client_golang/prometheus"
+
+var (
+ sentBytes = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "client_grpc_sent_bytes_total",
+ Help: "The total number of bytes sent to grpc clients.",
+ })
+
+ receivedBytes = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "client_grpc_received_bytes_total",
+ Help: "The total number of bytes received from grpc clients.",
+ })
+
+ streamFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "server_stream_failures_total",
+ Help: "The total number of stream failures from the local server.",
+ },
+ []string{"Type", "API"},
+ )
+
+ clientRequests = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "client_requests_total",
+ Help: "The total number of client requests per client version.",
+ },
+ []string{"type", "client_api_version"},
+ )
+)
+
+func init() {
+ prometheus.MustRegister(sentBytes)
+ prometheus.MustRegister(receivedBytes)
+ prometheus.MustRegister(streamFailures)
+ prometheus.MustRegister(clientRequests)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/quota.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/quota.go
new file mode 100644
index 0000000000..7f53bd966b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/quota.go
@@ -0,0 +1,90 @@
+// 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 v3rpc
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+)
+
+type quotaKVServer struct {
+ pb.KVServer
+ qa quotaAlarmer
+}
+
+type quotaAlarmer struct {
+ q etcdserver.Quota
+ a Alarmer
+ id types.ID
+}
+
+// check whether request satisfies the quota. If there is not enough space,
+// ignore request and raise the free space alarm.
+func (qa *quotaAlarmer) check(ctx context.Context, r interface{}) error {
+ if qa.q.Available(r) {
+ return nil
+ }
+ req := &pb.AlarmRequest{
+ MemberID: uint64(qa.id),
+ Action: pb.AlarmRequest_ACTIVATE,
+ Alarm: pb.AlarmType_NOSPACE,
+ }
+ qa.a.Alarm(ctx, req)
+ return rpctypes.ErrGRPCNoSpace
+}
+
+func NewQuotaKVServer(s *etcdserver.EtcdServer) pb.KVServer {
+ return "aKVServer{
+ NewKVServer(s),
+ quotaAlarmer{etcdserver.NewBackendQuota(s, "kv"), s, s.ID()},
+ }
+}
+
+func (s *quotaKVServer) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) {
+ if err := s.qa.check(ctx, r); err != nil {
+ return nil, err
+ }
+ return s.KVServer.Put(ctx, r)
+}
+
+func (s *quotaKVServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
+ if err := s.qa.check(ctx, r); err != nil {
+ return nil, err
+ }
+ return s.KVServer.Txn(ctx, r)
+}
+
+type quotaLeaseServer struct {
+ pb.LeaseServer
+ qa quotaAlarmer
+}
+
+func (s *quotaLeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ if err := s.qa.check(ctx, cr); err != nil {
+ return nil, err
+ }
+ return s.LeaseServer.LeaseGrant(ctx, cr)
+}
+
+func NewQuotaLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer {
+ return "aLeaseServer{
+ NewLeaseServer(s),
+ quotaAlarmer{etcdserver.NewBackendQuota(s, "lease"), s, s.ID()},
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/util.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/util.go
new file mode 100644
index 0000000000..b238934268
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/util.go
@@ -0,0 +1,149 @@
+// 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 v3rpc
+
+import (
+ "context"
+ "strings"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/mvcc"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+var toGRPCErrorMap = map[error]error{
+ membership.ErrIDRemoved: rpctypes.ErrGRPCMemberNotFound,
+ membership.ErrIDNotFound: rpctypes.ErrGRPCMemberNotFound,
+ membership.ErrIDExists: rpctypes.ErrGRPCMemberExist,
+ membership.ErrPeerURLexists: rpctypes.ErrGRPCPeerURLExist,
+ membership.ErrMemberNotLearner: rpctypes.ErrGRPCMemberNotLearner,
+ membership.ErrTooManyLearners: rpctypes.ErrGRPCTooManyLearners,
+ etcdserver.ErrNotEnoughStartedMembers: rpctypes.ErrMemberNotEnoughStarted,
+ etcdserver.ErrLearnerNotReady: rpctypes.ErrGRPCLearnerNotReady,
+
+ mvcc.ErrCompacted: rpctypes.ErrGRPCCompacted,
+ mvcc.ErrFutureRev: rpctypes.ErrGRPCFutureRev,
+ etcdserver.ErrRequestTooLarge: rpctypes.ErrGRPCRequestTooLarge,
+ etcdserver.ErrNoSpace: rpctypes.ErrGRPCNoSpace,
+ etcdserver.ErrTooManyRequests: rpctypes.ErrTooManyRequests,
+
+ etcdserver.ErrNoLeader: rpctypes.ErrGRPCNoLeader,
+ etcdserver.ErrNotLeader: rpctypes.ErrGRPCNotLeader,
+ etcdserver.ErrLeaderChanged: rpctypes.ErrGRPCLeaderChanged,
+ etcdserver.ErrStopped: rpctypes.ErrGRPCStopped,
+ etcdserver.ErrTimeout: rpctypes.ErrGRPCTimeout,
+ etcdserver.ErrTimeoutDueToLeaderFail: rpctypes.ErrGRPCTimeoutDueToLeaderFail,
+ etcdserver.ErrTimeoutDueToConnectionLost: rpctypes.ErrGRPCTimeoutDueToConnectionLost,
+ etcdserver.ErrTimeoutWaitAppliedIndex: rpctypes.ErrGRPCTimeoutWaitAppliedIndex,
+ etcdserver.ErrUnhealthy: rpctypes.ErrGRPCUnhealthy,
+ etcdserver.ErrKeyNotFound: rpctypes.ErrGRPCKeyNotFound,
+ etcdserver.ErrCorrupt: rpctypes.ErrGRPCCorrupt,
+ etcdserver.ErrBadLeaderTransferee: rpctypes.ErrGRPCBadLeaderTransferee,
+
+ etcdserver.ErrClusterVersionUnavailable: rpctypes.ErrGRPCClusterVersionUnavailable,
+ etcdserver.ErrWrongDowngradeVersionFormat: rpctypes.ErrGRPCWrongDowngradeVersionFormat,
+ etcdserver.ErrInvalidDowngradeTargetVersion: rpctypes.ErrGRPCInvalidDowngradeTargetVersion,
+ etcdserver.ErrDowngradeInProcess: rpctypes.ErrGRPCDowngradeInProcess,
+ etcdserver.ErrNoInflightDowngrade: rpctypes.ErrGRPCNoInflightDowngrade,
+
+ lease.ErrLeaseNotFound: rpctypes.ErrGRPCLeaseNotFound,
+ lease.ErrLeaseExists: rpctypes.ErrGRPCLeaseExist,
+ lease.ErrLeaseTTLTooLarge: rpctypes.ErrGRPCLeaseTTLTooLarge,
+
+ auth.ErrRootUserNotExist: rpctypes.ErrGRPCRootUserNotExist,
+ auth.ErrRootRoleNotExist: rpctypes.ErrGRPCRootRoleNotExist,
+ auth.ErrUserAlreadyExist: rpctypes.ErrGRPCUserAlreadyExist,
+ auth.ErrUserEmpty: rpctypes.ErrGRPCUserEmpty,
+ auth.ErrUserNotFound: rpctypes.ErrGRPCUserNotFound,
+ auth.ErrRoleAlreadyExist: rpctypes.ErrGRPCRoleAlreadyExist,
+ auth.ErrRoleNotFound: rpctypes.ErrGRPCRoleNotFound,
+ auth.ErrRoleEmpty: rpctypes.ErrGRPCRoleEmpty,
+ auth.ErrAuthFailed: rpctypes.ErrGRPCAuthFailed,
+ auth.ErrPermissionNotGiven: rpctypes.ErrGRPCPermissionNotGiven,
+ auth.ErrPermissionDenied: rpctypes.ErrGRPCPermissionDenied,
+ auth.ErrRoleNotGranted: rpctypes.ErrGRPCRoleNotGranted,
+ auth.ErrPermissionNotGranted: rpctypes.ErrGRPCPermissionNotGranted,
+ auth.ErrAuthNotEnabled: rpctypes.ErrGRPCAuthNotEnabled,
+ auth.ErrInvalidAuthToken: rpctypes.ErrGRPCInvalidAuthToken,
+ auth.ErrInvalidAuthMgmt: rpctypes.ErrGRPCInvalidAuthMgmt,
+ auth.ErrAuthOldRevision: rpctypes.ErrGRPCAuthOldRevision,
+
+ // In sync with status.FromContextError
+ context.Canceled: rpctypes.ErrGRPCCanceled,
+ context.DeadlineExceeded: rpctypes.ErrGRPCDeadlineExceeded,
+}
+
+func togRPCError(err error) error {
+ // let gRPC server convert to codes.Canceled, codes.DeadlineExceeded
+ if err == context.Canceled || err == context.DeadlineExceeded {
+ return err
+ }
+ grpcErr, ok := toGRPCErrorMap[err]
+ if !ok {
+ return status.Error(codes.Unknown, err.Error())
+ }
+ return grpcErr
+}
+
+func isClientCtxErr(ctxErr error, err error) bool {
+ if ctxErr != nil {
+ return true
+ }
+
+ ev, ok := status.FromError(err)
+ if !ok {
+ return false
+ }
+
+ switch ev.Code() {
+ case codes.Canceled, codes.DeadlineExceeded:
+ // client-side context cancel or deadline exceeded
+ // "rpc error: code = Canceled desc = context canceled"
+ // "rpc error: code = DeadlineExceeded desc = context deadline exceeded"
+ return true
+ case codes.Unavailable:
+ msg := ev.Message()
+ // client-side context cancel or deadline exceeded with TLS ("http2.errClientDisconnected")
+ // "rpc error: code = Unavailable desc = client disconnected"
+ if msg == "client disconnected" {
+ return true
+ }
+ // "grpc/transport.ClientTransport.CloseStream" on canceled streams
+ // "rpc error: code = Unavailable desc = stream error: stream ID 21; CANCEL")
+ if strings.HasPrefix(msg, "stream error: ") && strings.HasSuffix(msg, "; CANCEL") {
+ return true
+ }
+ }
+ return false
+}
+
+// in v3.4, learner is allowed to serve serializable read and endpoint status
+func isRPCSupportedForLearner(req interface{}) bool {
+ switch r := req.(type) {
+ case *pb.StatusRequest:
+ return true
+ case *pb.RangeRequest:
+ return r.Serializable
+ default:
+ return false
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/watch.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/watch.go
new file mode 100644
index 0000000000..cd834aa3e8
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/watch.go
@@ -0,0 +1,630 @@
+// 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 v3rpc
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "math/rand"
+ "sync"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ clientv3 "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/mvcc"
+
+ "go.uber.org/zap"
+)
+
+const minWatchProgressInterval = 100 * time.Millisecond
+
+type watchServer struct {
+ lg *zap.Logger
+
+ clusterID int64
+ memberID int64
+
+ maxRequestBytes int
+
+ sg etcdserver.RaftStatusGetter
+ watchable mvcc.WatchableKV
+ ag AuthGetter
+}
+
+// NewWatchServer returns a new watch server.
+func NewWatchServer(s *etcdserver.EtcdServer) pb.WatchServer {
+ srv := &watchServer{
+ lg: s.Cfg.Logger,
+
+ clusterID: int64(s.Cluster().ID()),
+ memberID: int64(s.ID()),
+
+ maxRequestBytes: int(s.Cfg.MaxRequestBytes + grpcOverheadBytes),
+
+ sg: s,
+ watchable: s.Watchable(),
+ ag: s,
+ }
+ if srv.lg == nil {
+ srv.lg = zap.NewNop()
+ }
+ if s.Cfg.WatchProgressNotifyInterval > 0 {
+ if s.Cfg.WatchProgressNotifyInterval < minWatchProgressInterval {
+ srv.lg.Warn(
+ "adjusting watch progress notify interval to minimum period",
+ zap.Duration("min-watch-progress-notify-interval", minWatchProgressInterval),
+ )
+ s.Cfg.WatchProgressNotifyInterval = minWatchProgressInterval
+ }
+ SetProgressReportInterval(s.Cfg.WatchProgressNotifyInterval)
+ }
+ return srv
+}
+
+var (
+ // External test can read this with GetProgressReportInterval()
+ // and change this to a small value to finish fast with
+ // SetProgressReportInterval().
+ progressReportInterval = 10 * time.Minute
+ progressReportIntervalMu sync.RWMutex
+)
+
+// GetProgressReportInterval returns the current progress report interval (for testing).
+func GetProgressReportInterval() time.Duration {
+ progressReportIntervalMu.RLock()
+ interval := progressReportInterval
+ progressReportIntervalMu.RUnlock()
+
+ // add rand(1/10*progressReportInterval) as jitter so that etcdserver will not
+ // send progress notifications to watchers around the same time even when watchers
+ // are created around the same time (which is common when a client restarts itself).
+ jitter := time.Duration(rand.Int63n(int64(interval) / 10))
+
+ return interval + jitter
+}
+
+// SetProgressReportInterval updates the current progress report interval (for testing).
+func SetProgressReportInterval(newTimeout time.Duration) {
+ progressReportIntervalMu.Lock()
+ progressReportInterval = newTimeout
+ progressReportIntervalMu.Unlock()
+}
+
+// We send ctrl response inside the read loop. We do not want
+// send to block read, but we still want ctrl response we sent to
+// be serialized. Thus we use a buffered chan to solve the problem.
+// A small buffer should be OK for most cases, since we expect the
+// ctrl requests are infrequent.
+const ctrlStreamBufLen = 16
+
+// serverWatchStream is an etcd server side stream. It receives requests
+// from client side gRPC stream. It receives watch events from mvcc.WatchStream,
+// and creates responses that forwarded to gRPC stream.
+// It also forwards control message like watch created and canceled.
+type serverWatchStream struct {
+ lg *zap.Logger
+
+ clusterID int64
+ memberID int64
+
+ maxRequestBytes int
+
+ sg etcdserver.RaftStatusGetter
+ watchable mvcc.WatchableKV
+ ag AuthGetter
+
+ gRPCStream pb.Watch_WatchServer
+ watchStream mvcc.WatchStream
+ ctrlStream chan *pb.WatchResponse
+
+ // mu protects progress, prevKV, fragment
+ mu sync.RWMutex
+ // tracks the watchID that stream might need to send progress to
+ // TODO: combine progress and prevKV into a single struct?
+ progress map[mvcc.WatchID]bool
+ // record watch IDs that need return previous key-value pair
+ prevKV map[mvcc.WatchID]bool
+ // records fragmented watch IDs
+ fragment map[mvcc.WatchID]bool
+
+ // indicates whether we have an outstanding global progress
+ // notification to send
+ deferredProgress bool
+
+ // closec indicates the stream is closed.
+ closec chan struct{}
+
+ // wg waits for the send loop to complete
+ wg sync.WaitGroup
+}
+
+func (ws *watchServer) Watch(stream pb.Watch_WatchServer) (err error) {
+ sws := serverWatchStream{
+ lg: ws.lg,
+
+ clusterID: ws.clusterID,
+ memberID: ws.memberID,
+
+ maxRequestBytes: ws.maxRequestBytes,
+
+ sg: ws.sg,
+ watchable: ws.watchable,
+ ag: ws.ag,
+
+ gRPCStream: stream,
+ watchStream: ws.watchable.NewWatchStream(),
+ // chan for sending control response like watcher created and canceled.
+ ctrlStream: make(chan *pb.WatchResponse, ctrlStreamBufLen),
+
+ progress: make(map[mvcc.WatchID]bool),
+ prevKV: make(map[mvcc.WatchID]bool),
+ fragment: make(map[mvcc.WatchID]bool),
+
+ deferredProgress: false,
+
+ closec: make(chan struct{}),
+ }
+
+ sws.wg.Add(1)
+ go func() {
+ sws.sendLoop()
+ sws.wg.Done()
+ }()
+
+ errc := make(chan error, 1)
+ // Ideally recvLoop would also use sws.wg to signal its completion
+ // but when stream.Context().Done() is closed, the stream's recv
+ // may continue to block since it uses a different context, leading to
+ // deadlock when calling sws.close().
+ go func() {
+ if rerr := sws.recvLoop(); rerr != nil {
+ if isClientCtxErr(stream.Context().Err(), rerr) {
+ sws.lg.Debug("failed to receive watch request from gRPC stream", zap.Error(rerr))
+ } else {
+ sws.lg.Warn("failed to receive watch request from gRPC stream", zap.Error(rerr))
+ streamFailures.WithLabelValues("receive", "watch").Inc()
+ }
+ errc <- rerr
+ }
+ }()
+
+ // TODO: There's a race here. When a stream is closed (e.g. due to a cancellation),
+ // the underlying error (e.g. a gRPC stream error) may be returned and handled
+ // through errc if the recv goroutine finishes before the send goroutine.
+ // When the recv goroutine wins, the stream error is retained. When recv loses
+ // the race, the underlying error is lost (unless the root error is propagated
+ // through Context.Err() which is not always the case (as callers have to decide
+ // to implement a custom context to do so). The stdlib context package builtins
+ // may be insufficient to carry semantically useful errors around and should be
+ // revisited.
+ select {
+ case err = <-errc:
+ if err == context.Canceled {
+ err = rpctypes.ErrGRPCWatchCanceled
+ }
+ close(sws.ctrlStream)
+ case <-stream.Context().Done():
+ err = stream.Context().Err()
+ if err == context.Canceled {
+ err = rpctypes.ErrGRPCWatchCanceled
+ }
+ }
+
+ sws.close()
+ return err
+}
+
+func (sws *serverWatchStream) isWatchPermitted(wcr *pb.WatchCreateRequest) error {
+ authInfo, err := sws.ag.AuthInfoFromCtx(sws.gRPCStream.Context())
+ if err != nil {
+ return err
+ }
+ if authInfo == nil {
+ // if auth is enabled, IsRangePermitted() can cause an error
+ authInfo = &auth.AuthInfo{}
+ }
+ return sws.ag.AuthStore().IsRangePermitted(authInfo, wcr.Key, wcr.RangeEnd)
+}
+
+func (sws *serverWatchStream) recvLoop() error {
+ for {
+ req, err := sws.gRPCStream.Recv()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+
+ switch uv := req.RequestUnion.(type) {
+ case *pb.WatchRequest_CreateRequest:
+ if uv.CreateRequest == nil {
+ break
+ }
+
+ creq := uv.CreateRequest
+ if len(creq.Key) == 0 {
+ // \x00 is the smallest key
+ creq.Key = []byte{0}
+ }
+ if len(creq.RangeEnd) == 0 {
+ // force nil since watchstream.Watch distinguishes
+ // between nil and []byte{} for single key / >=
+ creq.RangeEnd = nil
+ }
+ if len(creq.RangeEnd) == 1 && creq.RangeEnd[0] == 0 {
+ // support >= key queries
+ creq.RangeEnd = []byte{}
+ }
+
+ err := sws.isWatchPermitted(creq)
+ if err != nil {
+ var cancelReason string
+ switch err {
+ case auth.ErrInvalidAuthToken:
+ cancelReason = rpctypes.ErrGRPCInvalidAuthToken.Error()
+ case auth.ErrAuthOldRevision:
+ cancelReason = rpctypes.ErrGRPCAuthOldRevision.Error()
+ case auth.ErrUserEmpty:
+ cancelReason = rpctypes.ErrGRPCUserEmpty.Error()
+ default:
+ if err != auth.ErrPermissionDenied {
+ sws.lg.Error("unexpected error code", zap.Error(err))
+ }
+ cancelReason = rpctypes.ErrGRPCPermissionDenied.Error()
+ }
+
+ wr := &pb.WatchResponse{
+ Header: sws.newResponseHeader(sws.watchStream.Rev()),
+ WatchId: clientv3.InvalidWatchID,
+ Canceled: true,
+ Created: true,
+ CancelReason: cancelReason,
+ }
+
+ select {
+ case sws.ctrlStream <- wr:
+ continue
+ case <-sws.closec:
+ return nil
+ }
+ }
+
+ filters := FiltersFromRequest(creq)
+
+ wsrev := sws.watchStream.Rev()
+ rev := creq.StartRevision
+ if rev == 0 {
+ rev = wsrev + 1
+ }
+ id, err := sws.watchStream.Watch(mvcc.WatchID(creq.WatchId), creq.Key, creq.RangeEnd, rev, filters...)
+ if err == nil {
+ sws.mu.Lock()
+ if creq.ProgressNotify {
+ sws.progress[id] = true
+ }
+ if creq.PrevKv {
+ sws.prevKV[id] = true
+ }
+ if creq.Fragment {
+ sws.fragment[id] = true
+ }
+ sws.mu.Unlock()
+ } else {
+ id = clientv3.InvalidWatchID
+ }
+
+ wr := &pb.WatchResponse{
+ Header: sws.newResponseHeader(wsrev),
+ WatchId: int64(id),
+ Created: true,
+ Canceled: err != nil,
+ }
+ if err != nil {
+ wr.CancelReason = err.Error()
+ }
+ select {
+ case sws.ctrlStream <- wr:
+ case <-sws.closec:
+ return nil
+ }
+
+ case *pb.WatchRequest_CancelRequest:
+ if uv.CancelRequest != nil {
+ id := uv.CancelRequest.WatchId
+ err := sws.watchStream.Cancel(mvcc.WatchID(id))
+ if err == nil {
+ sws.ctrlStream <- &pb.WatchResponse{
+ Header: sws.newResponseHeader(sws.watchStream.Rev()),
+ WatchId: id,
+ Canceled: true,
+ }
+ sws.mu.Lock()
+ delete(sws.progress, mvcc.WatchID(id))
+ delete(sws.prevKV, mvcc.WatchID(id))
+ delete(sws.fragment, mvcc.WatchID(id))
+ sws.mu.Unlock()
+ }
+ }
+ case *pb.WatchRequest_ProgressRequest:
+ if uv.ProgressRequest != nil {
+ sws.mu.Lock()
+ // Ignore if deferred progress notification is already in progress
+ if !sws.deferredProgress {
+ // Request progress for all watchers,
+ // force generation of a response
+ if !sws.watchStream.RequestProgressAll() {
+ sws.deferredProgress = true
+ }
+ }
+ sws.mu.Unlock()
+ }
+ default:
+ // we probably should not shutdown the entire stream when
+ // receive an valid command.
+ // so just do nothing instead.
+ continue
+ }
+ }
+}
+
+func (sws *serverWatchStream) sendLoop() {
+ // watch ids that are currently active
+ ids := make(map[mvcc.WatchID]struct{})
+ // watch responses pending on a watch id creation message
+ pending := make(map[mvcc.WatchID][]*pb.WatchResponse)
+
+ interval := GetProgressReportInterval()
+ progressTicker := time.NewTicker(interval)
+
+ defer func() {
+ progressTicker.Stop()
+ // drain the chan to clean up pending events
+ for ws := range sws.watchStream.Chan() {
+ mvcc.ReportEventReceived(len(ws.Events))
+ }
+ for _, wrs := range pending {
+ for _, ws := range wrs {
+ mvcc.ReportEventReceived(len(ws.Events))
+ }
+ }
+ }()
+
+ for {
+ select {
+ case wresp, ok := <-sws.watchStream.Chan():
+ if !ok {
+ return
+ }
+
+ // TODO: evs is []mvccpb.Event type
+ // either return []*mvccpb.Event from the mvcc package
+ // or define protocol buffer with []mvccpb.Event.
+ evs := wresp.Events
+ events := make([]*mvccpb.Event, len(evs))
+ sws.mu.RLock()
+ needPrevKV := sws.prevKV[wresp.WatchID]
+ sws.mu.RUnlock()
+ for i := range evs {
+ events[i] = &evs[i]
+ if needPrevKV && !IsCreateEvent(evs[i]) {
+ opt := mvcc.RangeOptions{Rev: evs[i].Kv.ModRevision - 1}
+ r, err := sws.watchable.Range(context.TODO(), evs[i].Kv.Key, nil, opt)
+ if err == nil && len(r.KVs) != 0 {
+ events[i].PrevKv = &(r.KVs[0])
+ }
+ }
+ }
+
+ canceled := wresp.CompactRevision != 0
+ wr := &pb.WatchResponse{
+ Header: sws.newResponseHeader(wresp.Revision),
+ WatchId: int64(wresp.WatchID),
+ Events: events,
+ CompactRevision: wresp.CompactRevision,
+ Canceled: canceled,
+ }
+
+ // Progress notifications can have WatchID -1
+ // if they announce on behalf of multiple watchers
+ if wresp.WatchID != clientv3.InvalidWatchID {
+ if _, okID := ids[wresp.WatchID]; !okID {
+ // buffer if id not yet announced
+ wrs := append(pending[wresp.WatchID], wr)
+ pending[wresp.WatchID] = wrs
+ continue
+ }
+ }
+
+ mvcc.ReportEventReceived(len(evs))
+
+ sws.mu.RLock()
+ fragmented, ok := sws.fragment[wresp.WatchID]
+ sws.mu.RUnlock()
+
+ var serr error
+ if !fragmented && !ok {
+ serr = sws.gRPCStream.Send(wr)
+ } else {
+ serr = sendFragments(wr, sws.maxRequestBytes, sws.gRPCStream.Send)
+ }
+
+ if serr != nil {
+ if isClientCtxErr(sws.gRPCStream.Context().Err(), serr) {
+ sws.lg.Debug("failed to send watch response to gRPC stream", zap.Error(serr))
+ } else {
+ sws.lg.Warn("failed to send watch response to gRPC stream", zap.Error(serr))
+ streamFailures.WithLabelValues("send", "watch").Inc()
+ }
+ return
+ }
+
+ sws.mu.Lock()
+ if len(evs) > 0 && sws.progress[wresp.WatchID] {
+ // elide next progress update if sent a key update
+ sws.progress[wresp.WatchID] = false
+ }
+ if sws.deferredProgress {
+ if sws.watchStream.RequestProgressAll() {
+ sws.deferredProgress = false
+ }
+ }
+ sws.mu.Unlock()
+
+ case c, ok := <-sws.ctrlStream:
+ if !ok {
+ return
+ }
+
+ if err := sws.gRPCStream.Send(c); err != nil {
+ if isClientCtxErr(sws.gRPCStream.Context().Err(), err) {
+ sws.lg.Debug("failed to send watch control response to gRPC stream", zap.Error(err))
+ } else {
+ sws.lg.Warn("failed to send watch control response to gRPC stream", zap.Error(err))
+ streamFailures.WithLabelValues("send", "watch").Inc()
+ }
+ return
+ }
+
+ // track id creation
+ wid := mvcc.WatchID(c.WatchId)
+
+ if !(!(c.Canceled && c.Created) || wid == clientv3.InvalidWatchID) {
+ panic(fmt.Sprintf("unexpected watchId: %d, wanted: %d, since both 'Canceled' and 'Created' are true", wid, clientv3.InvalidWatchID))
+ }
+
+ if c.Canceled && wid != clientv3.InvalidWatchID {
+ delete(ids, wid)
+ continue
+ }
+ if c.Created {
+ // flush buffered events
+ ids[wid] = struct{}{}
+ for _, v := range pending[wid] {
+ mvcc.ReportEventReceived(len(v.Events))
+ if err := sws.gRPCStream.Send(v); err != nil {
+ if isClientCtxErr(sws.gRPCStream.Context().Err(), err) {
+ sws.lg.Debug("failed to send pending watch response to gRPC stream", zap.Error(err))
+ } else {
+ sws.lg.Warn("failed to send pending watch response to gRPC stream", zap.Error(err))
+ streamFailures.WithLabelValues("send", "watch").Inc()
+ }
+ return
+ }
+ }
+ delete(pending, wid)
+ }
+
+ case <-progressTicker.C:
+ sws.mu.Lock()
+ for id, ok := range sws.progress {
+ if ok {
+ sws.watchStream.RequestProgress(id)
+ }
+ sws.progress[id] = true
+ }
+ sws.mu.Unlock()
+
+ case <-sws.closec:
+ return
+ }
+ }
+}
+
+func IsCreateEvent(e mvccpb.Event) bool {
+ return e.Type == mvccpb.PUT && e.Kv.CreateRevision == e.Kv.ModRevision
+}
+
+func sendFragments(
+ wr *pb.WatchResponse,
+ maxRequestBytes int,
+ sendFunc func(*pb.WatchResponse) error) error {
+ // no need to fragment if total request size is smaller
+ // than max request limit or response contains only one event
+ if wr.Size() < maxRequestBytes || len(wr.Events) < 2 {
+ return sendFunc(wr)
+ }
+
+ ow := *wr
+ ow.Events = make([]*mvccpb.Event, 0)
+ ow.Fragment = true
+
+ var idx int
+ for {
+ cur := ow
+ for _, ev := range wr.Events[idx:] {
+ cur.Events = append(cur.Events, ev)
+ if len(cur.Events) > 1 && cur.Size() >= maxRequestBytes {
+ cur.Events = cur.Events[:len(cur.Events)-1]
+ break
+ }
+ idx++
+ }
+ if idx == len(wr.Events) {
+ // last response has no more fragment
+ cur.Fragment = false
+ }
+ if err := sendFunc(&cur); err != nil {
+ return err
+ }
+ if !cur.Fragment {
+ break
+ }
+ }
+ return nil
+}
+
+func (sws *serverWatchStream) close() {
+ sws.watchStream.Close()
+ close(sws.closec)
+ sws.wg.Wait()
+}
+
+func (sws *serverWatchStream) newResponseHeader(rev int64) *pb.ResponseHeader {
+ return &pb.ResponseHeader{
+ ClusterId: uint64(sws.clusterID),
+ MemberId: uint64(sws.memberID),
+ Revision: rev,
+ RaftTerm: sws.sg.Term(),
+ }
+}
+
+func filterNoDelete(e mvccpb.Event) bool {
+ return e.Type == mvccpb.DELETE
+}
+
+func filterNoPut(e mvccpb.Event) bool {
+ return e.Type == mvccpb.PUT
+}
+
+// FiltersFromRequest returns "mvcc.FilterFunc" from a given watch create request.
+func FiltersFromRequest(creq *pb.WatchCreateRequest) []mvcc.FilterFunc {
+ filters := make([]mvcc.FilterFunc, 0, len(creq.Filters))
+ for _, ft := range creq.Filters {
+ switch ft {
+ case pb.WatchCreateRequest_NOPUT:
+ filters = append(filters, filterNoPut)
+ case pb.WatchCreateRequest_NODELETE:
+ filters = append(filters, filterNoDelete)
+ default:
+ }
+ }
+ return filters
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply.go
new file mode 100644
index 0000000000..2ef151259c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply.go
@@ -0,0 +1,1166 @@
+// 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"
+ "fmt"
+ "sort"
+ "strconv"
+ "time"
+
+ "github.com/coreos/go-semver/semver"
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/membershippb"
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/mvcc"
+
+ "github.com/gogo/protobuf/proto"
+ "go.uber.org/zap"
+)
+
+const (
+ v3Version = "v3"
+)
+
+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{}
+ trace *traceutil.Trace
+}
+
+// applierV3Internal is the interface for processing internal V3 raft request
+type applierV3Internal interface {
+ ClusterVersionSet(r *membershippb.ClusterVersionSetRequest, shouldApplyV3 membership.ShouldApplyV3)
+ ClusterMemberAttrSet(r *membershippb.ClusterMemberAttrSetRequest, shouldApplyV3 membership.ShouldApplyV3)
+ DowngradeInfoSet(r *membershippb.DowngradeInfoSetRequest, shouldApplyV3 membership.ShouldApplyV3)
+}
+
+// applierV3 is the interface for processing V3 raft messages
+type applierV3 interface {
+ Apply(r *pb.InternalRaftRequest, shouldApplyV3 membership.ShouldApplyV3) *applyResult
+
+ Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error)
+ Range(ctx context.Context, txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error)
+ DeleteRange(txn mvcc.TxnWrite, dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error)
+ Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error)
+ Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error)
+
+ LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error)
+ LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error)
+
+ LeaseCheckpoint(lc *pb.LeaseCheckpointRequest) (*pb.LeaseCheckpointResponse, error)
+
+ Alarm(*pb.AlarmRequest) (*pb.AlarmResponse, error)
+
+ Authenticate(r *pb.InternalAuthenticateRequest) (*pb.AuthenticateResponse, error)
+
+ AuthEnable() (*pb.AuthEnableResponse, error)
+ AuthDisable() (*pb.AuthDisableResponse, error)
+ AuthStatus() (*pb.AuthStatusResponse, 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) newApplierV3Internal() applierV3Internal {
+ base := &applierV3backend{s: s}
+ return base
+}
+
+func (s *EtcdServer) newApplierV3() applierV3 {
+ return newAuthApplierV3(
+ s.AuthStore(),
+ newQuotaApplierV3(s, s.newApplierV3Backend()),
+ s.lessor,
+ )
+}
+
+func (a *applierV3backend) Apply(r *pb.InternalRaftRequest, shouldApplyV3 membership.ShouldApplyV3) *applyResult {
+ op := "unknown"
+ ar := &applyResult{}
+ defer func(start time.Time) {
+ success := ar.err == nil || ar.err == mvcc.ErrCompacted
+ applySec.WithLabelValues(v3Version, op, strconv.FormatBool(success)).Observe(time.Since(start).Seconds())
+ warnOfExpensiveRequest(a.s.Logger(), a.s.Cfg.WarningApplyDuration, start, &pb.InternalRaftStringer{Request: r}, ar.resp, ar.err)
+ if !success {
+ warnOfFailedRequest(a.s.Logger(), start, &pb.InternalRaftStringer{Request: r}, ar.resp, ar.err)
+ }
+ }(time.Now())
+
+ switch {
+ case r.ClusterVersionSet != nil: // Implemented in 3.5.x
+ op = "ClusterVersionSet"
+ a.s.applyV3Internal.ClusterVersionSet(r.ClusterVersionSet, shouldApplyV3)
+ return nil
+ case r.ClusterMemberAttrSet != nil:
+ op = "ClusterMemberAttrSet" // Implemented in 3.5.x
+ a.s.applyV3Internal.ClusterMemberAttrSet(r.ClusterMemberAttrSet, shouldApplyV3)
+ return nil
+ case r.DowngradeInfoSet != nil:
+ op = "DowngradeInfoSet" // Implemented in 3.5.x
+ a.s.applyV3Internal.DowngradeInfoSet(r.DowngradeInfoSet, shouldApplyV3)
+ return nil
+ }
+
+ if !shouldApplyV3 {
+ return nil
+ }
+
+ // call into a.s.applyV3.F instead of a.F so upper appliers can check individual calls
+ switch {
+ case r.Range != nil:
+ op = "Range"
+ ar.resp, ar.err = a.s.applyV3.Range(context.TODO(), nil, r.Range)
+ case r.Put != nil:
+ op = "Put"
+ ar.resp, ar.trace, ar.err = a.s.applyV3.Put(context.TODO(), nil, r.Put)
+ case r.DeleteRange != nil:
+ op = "DeleteRange"
+ ar.resp, ar.err = a.s.applyV3.DeleteRange(nil, r.DeleteRange)
+ case r.Txn != nil:
+ op = "Txn"
+ ar.resp, ar.trace, ar.err = a.s.applyV3.Txn(context.TODO(), r.Txn)
+ case r.Compaction != nil:
+ op = "Compaction"
+ ar.resp, ar.physc, ar.trace, ar.err = a.s.applyV3.Compaction(r.Compaction)
+ case r.LeaseGrant != nil:
+ op = "LeaseGrant"
+ ar.resp, ar.err = a.s.applyV3.LeaseGrant(r.LeaseGrant)
+ case r.LeaseRevoke != nil:
+ op = "LeaseRevoke"
+ ar.resp, ar.err = a.s.applyV3.LeaseRevoke(r.LeaseRevoke)
+ case r.LeaseCheckpoint != nil:
+ op = "LeaseCheckpoint"
+ ar.resp, ar.err = a.s.applyV3.LeaseCheckpoint(r.LeaseCheckpoint)
+ case r.Alarm != nil:
+ op = "Alarm"
+ ar.resp, ar.err = a.s.applyV3.Alarm(r.Alarm)
+ case r.Authenticate != nil:
+ op = "Authenticate"
+ ar.resp, ar.err = a.s.applyV3.Authenticate(r.Authenticate)
+ case r.AuthEnable != nil:
+ op = "AuthEnable"
+ ar.resp, ar.err = a.s.applyV3.AuthEnable()
+ case r.AuthDisable != nil:
+ op = "AuthDisable"
+ ar.resp, ar.err = a.s.applyV3.AuthDisable()
+ case r.AuthStatus != nil:
+ ar.resp, ar.err = a.s.applyV3.AuthStatus()
+ case r.AuthUserAdd != nil:
+ op = "AuthUserAdd"
+ ar.resp, ar.err = a.s.applyV3.UserAdd(r.AuthUserAdd)
+ case r.AuthUserDelete != nil:
+ op = "AuthUserDelete"
+ ar.resp, ar.err = a.s.applyV3.UserDelete(r.AuthUserDelete)
+ case r.AuthUserChangePassword != nil:
+ op = "AuthUserChangePassword"
+ ar.resp, ar.err = a.s.applyV3.UserChangePassword(r.AuthUserChangePassword)
+ case r.AuthUserGrantRole != nil:
+ op = "AuthUserGrantRole"
+ ar.resp, ar.err = a.s.applyV3.UserGrantRole(r.AuthUserGrantRole)
+ case r.AuthUserGet != nil:
+ op = "AuthUserGet"
+ ar.resp, ar.err = a.s.applyV3.UserGet(r.AuthUserGet)
+ case r.AuthUserRevokeRole != nil:
+ op = "AuthUserRevokeRole"
+ ar.resp, ar.err = a.s.applyV3.UserRevokeRole(r.AuthUserRevokeRole)
+ case r.AuthRoleAdd != nil:
+ op = "AuthRoleAdd"
+ ar.resp, ar.err = a.s.applyV3.RoleAdd(r.AuthRoleAdd)
+ case r.AuthRoleGrantPermission != nil:
+ op = "AuthRoleGrantPermission"
+ ar.resp, ar.err = a.s.applyV3.RoleGrantPermission(r.AuthRoleGrantPermission)
+ case r.AuthRoleGet != nil:
+ op = "AuthRoleGet"
+ ar.resp, ar.err = a.s.applyV3.RoleGet(r.AuthRoleGet)
+ case r.AuthRoleRevokePermission != nil:
+ op = "AuthRoleRevokePermission"
+ ar.resp, ar.err = a.s.applyV3.RoleRevokePermission(r.AuthRoleRevokePermission)
+ case r.AuthRoleDelete != nil:
+ op = "AuthRoleDelete"
+ ar.resp, ar.err = a.s.applyV3.RoleDelete(r.AuthRoleDelete)
+ case r.AuthUserList != nil:
+ op = "AuthUserList"
+ ar.resp, ar.err = a.s.applyV3.UserList(r.AuthUserList)
+ case r.AuthRoleList != nil:
+ op = "AuthRoleList"
+ ar.resp, ar.err = a.s.applyV3.RoleList(r.AuthRoleList)
+ default:
+ a.s.lg.Panic("not implemented apply", zap.Stringer("raft-request", r))
+ }
+ return ar
+}
+
+func (a *applierV3backend) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (resp *pb.PutResponse, trace *traceutil.Trace, err error) {
+ resp = &pb.PutResponse{}
+ resp.Header = &pb.ResponseHeader{}
+ trace = traceutil.Get(ctx)
+ // create put tracing if the trace in context is empty
+ if trace.IsEmpty() {
+ trace = traceutil.New("put",
+ a.s.Logger(),
+ traceutil.Field{Key: "key", Value: string(p.Key)},
+ traceutil.Field{Key: "req_size", Value: p.Size()},
+ )
+ }
+ 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, nil, lease.ErrLeaseNotFound
+ }
+ }
+ txn = a.s.KV().Write(trace)
+ defer txn.End()
+ }
+
+ var rr *mvcc.RangeResult
+ if p.IgnoreValue || p.IgnoreLease || p.PrevKv {
+ trace.StepWithFunction(func() {
+ rr, err = txn.Range(context.TODO(), p.Key, nil, mvcc.RangeOptions{})
+ }, "get previous kv pair")
+
+ if err != nil {
+ return nil, 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, 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)
+ trace.AddField(traceutil.Field{Key: "response_revision", Value: resp.Header.Revision})
+ return resp, trace, 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(traceutil.TODO())
+ defer txn.End()
+ }
+
+ if dr.PrevKv {
+ rr, err := txn.Range(context.TODO(), 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(ctx context.Context, txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error) {
+ trace := traceutil.Get(ctx)
+
+ resp := &pb.RangeResponse{}
+ resp.Header = &pb.ResponseHeader{}
+
+ if txn == nil {
+ txn = a.s.kv.Read(mvcc.ConcurrentReadTxMode, trace)
+ 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(ctx, 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
+ }
+ trace.Step("filter and sort the key-value pairs")
+ 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]
+ }
+ trace.Step("assemble the response")
+ return resp, nil
+}
+
+func (a *applierV3backend) Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) {
+ lg := a.s.Logger()
+ trace := traceutil.Get(ctx)
+ if trace.IsEmpty() {
+ trace = traceutil.New("transaction", a.s.Logger())
+ ctx = context.WithValue(ctx, traceutil.TraceKey, trace)
+ }
+ isWrite := !isTxnReadonly(rt)
+
+ // When the transaction contains write operations, we use ReadTx instead of
+ // ConcurrentReadTx to avoid extra overhead of copying buffer.
+ var txn mvcc.TxnWrite
+ if isWrite && a.s.Cfg.ExperimentalTxnModeWriteWithSharedBuffer {
+ txn = mvcc.NewReadOnlyTxnWrite(a.s.KV().Read(mvcc.SharedBufReadTxMode, trace))
+ } else {
+ txn = mvcc.NewReadOnlyTxnWrite(a.s.KV().Read(mvcc.ConcurrentReadTxMode, trace))
+ }
+
+ var txnPath []bool
+ trace.StepWithFunction(
+ func() {
+ txnPath = compareToPath(txn, rt)
+ },
+ "compare",
+ )
+
+ if isWrite {
+ trace.AddField(traceutil.Field{Key: "read_only", Value: false})
+ if _, err := checkRequests(txn, rt, txnPath, a.checkPut); err != nil {
+ txn.End()
+ return nil, nil, err
+ }
+ }
+ if _, err := checkRequests(txn, rt, txnPath, a.checkRange); err != nil {
+ txn.End()
+ return nil, nil, err
+ }
+ trace.Step("check requests")
+ 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(trace)
+ }
+ _, err := a.applyTxn(ctx, txn, rt, txnPath, txnResp)
+ if err != nil {
+ if isWrite {
+ // end txn to release locks before panic
+ txn.End()
+ // When txn with write operations starts it has to be successful
+ // We don't have a way to recover state in case of write failure
+ lg.Panic("unexpected error during txn with writes", zap.Error(err))
+ } else {
+ lg.Error("unexpected error during readonly txn", zap.Error(err))
+ }
+ }
+ rev := txn.Rev()
+ if len(txn.Changes()) != 0 {
+ rev++
+ }
+ txn.End()
+
+ txnResp.Header.Revision = rev
+ trace.AddField(
+ traceutil.Field{Key: "number_of_response", Value: len(txnResp.Responses)},
+ traceutil.Field{Key: "response_revision", Value: txnResp.Header.Revision},
+ )
+ return txnResp, trace, err
+}
+
+// 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(context.TODO(), 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(ctx context.Context, txn mvcc.TxnWrite, rt *pb.TxnRequest, txnPath []bool, tresp *pb.TxnResponse) (txns int, err error) {
+ trace := traceutil.Get(ctx)
+ 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:
+ trace.StartSubTrace(
+ traceutil.Field{Key: "req_type", Value: "range"},
+ traceutil.Field{Key: "range_begin", Value: string(tv.RequestRange.Key)},
+ traceutil.Field{Key: "range_end", Value: string(tv.RequestRange.RangeEnd)})
+ resp, err := a.Range(ctx, txn, tv.RequestRange)
+ if err != nil {
+ return 0, fmt.Errorf("applyTxn: failed Range: %w", err)
+ }
+ respi.(*pb.ResponseOp_ResponseRange).ResponseRange = resp
+ trace.StopSubTrace()
+ case *pb.RequestOp_RequestPut:
+ trace.StartSubTrace(
+ traceutil.Field{Key: "req_type", Value: "put"},
+ traceutil.Field{Key: "key", Value: string(tv.RequestPut.Key)},
+ traceutil.Field{Key: "req_size", Value: tv.RequestPut.Size()})
+ resp, _, err := a.Put(ctx, txn, tv.RequestPut)
+ if err != nil {
+ return 0, fmt.Errorf("applyTxn: failed Put: %w", err)
+ }
+ respi.(*pb.ResponseOp_ResponsePut).ResponsePut = resp
+ trace.StopSubTrace()
+ case *pb.RequestOp_RequestDeleteRange:
+ resp, err := a.DeleteRange(txn, tv.RequestDeleteRange)
+ if err != nil {
+ return 0, fmt.Errorf("applyTxn: failed DeleteRange: %w", err)
+ }
+ respi.(*pb.ResponseOp_ResponseDeleteRange).ResponseDeleteRange = resp
+ case *pb.RequestOp_RequestTxn:
+ resp := respi.(*pb.ResponseOp_ResponseTxn).ResponseTxn
+ applyTxns, err := a.applyTxn(ctx, txn, tv.RequestTxn, txnPath[1:], resp)
+ if err != nil {
+ // don't wrap the error. It's a recursive call and err should be already wrapped
+ return 0, err
+ }
+ txns += applyTxns + 1
+ txnPath = txnPath[applyTxns+1:]
+ default:
+ // empty union
+ }
+ }
+ return txns, nil
+}
+
+func (a *applierV3backend) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) {
+ resp := &pb.CompactionResponse{}
+ resp.Header = &pb.ResponseHeader{}
+ trace := traceutil.New("compact",
+ a.s.Logger(),
+ traceutil.Field{Key: "revision", Value: compaction.Revision},
+ )
+
+ ch, err := a.s.KV().Compact(trace, compaction.Revision)
+ if err != nil {
+ return nil, ch, nil, err
+ }
+ // get the current revision. which key to get is not important.
+ rr, _ := a.s.KV().Range(context.TODO(), []byte("compaction"), nil, mvcc.RangeOptions{})
+ resp.Header.Revision = rr.Rev
+ return resp, ch, trace, 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) LeaseCheckpoint(lc *pb.LeaseCheckpointRequest) (*pb.LeaseCheckpointResponse, error) {
+ for _, c := range lc.Checkpoints {
+ err := a.s.lessor.Checkpoint(lease.LeaseID(c.ID), c.Remaining_TTL)
+ if err != nil {
+ return &pb.LeaseCheckpointResponse{Header: newHeader(a.s)}, err
+ }
+ }
+ return &pb.LeaseCheckpointResponse{Header: newHeader(a.s)}, nil
+}
+
+func (a *applierV3backend) Alarm(ar *pb.AlarmRequest) (*pb.AlarmResponse, error) {
+ resp := &pb.AlarmResponse{}
+ oldCount := len(a.s.alarmStore.Get(ar.Alarm))
+
+ lg := a.s.Logger()
+ switch ar.Action {
+ case pb.AlarmRequest_GET:
+ resp.Alarms = a.s.alarmStore.Get(ar.Alarm)
+ case pb.AlarmRequest_ACTIVATE:
+ if ar.Alarm == pb.AlarmType_NONE {
+ break
+ }
+ 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
+ }
+
+ lg.Warn("alarm raised", zap.String("alarm", m.Alarm.String()), zap.String("from", types.ID(m.MemberID).String()))
+ switch m.Alarm {
+ case pb.AlarmType_CORRUPT:
+ a.s.applyV3 = newApplierV3Corrupt(a)
+ case pb.AlarmType_NOSPACE:
+ a.s.applyV3 = newApplierV3Capped(a)
+ default:
+ lg.Panic("unimplemented alarm activation", zap.String("alarm", fmt.Sprintf("%+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?
+ lg.Warn("alarm disarmed", zap.String("alarm", m.Alarm.String()), zap.String("from", types.ID(m.MemberID).String()))
+ a.s.applyV3 = a.s.newApplierV3()
+ default:
+ lg.Warn("unimplemented alarm deactivation", zap.String("alarm", fmt.Sprintf("%+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(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) {
+ return nil, nil, ErrNoSpace
+}
+
+func (a *applierV3Capped) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) {
+ if a.q.Cost(r) > 0 {
+ return nil, nil, ErrNoSpace
+ }
+ return a.applierV3.Txn(ctx, 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) AuthStatus() (*pb.AuthStatusResponse, error) {
+ enabled := a.s.AuthStore().IsAuthEnabled()
+ authRevision := a.s.AuthStore().Revision()
+ return &pb.AuthStatusResponse{Header: newHeader(a.s), Enabled: enabled, AuthRevision: authRevision}, 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
+}
+
+func (a *applierV3backend) ClusterVersionSet(r *membershippb.ClusterVersionSetRequest, shouldApplyV3 membership.ShouldApplyV3) {
+ a.s.cluster.SetVersion(semver.Must(semver.NewVersion(r.Ver)), api.UpdateCapability, shouldApplyV3)
+}
+
+func (a *applierV3backend) ClusterMemberAttrSet(r *membershippb.ClusterMemberAttrSetRequest, shouldApplyV3 membership.ShouldApplyV3) {
+ a.s.cluster.UpdateAttributes(
+ types.ID(r.Member_ID),
+ membership.Attributes{
+ Name: r.MemberAttributes.Name,
+ ClientURLs: r.MemberAttributes.ClientUrls,
+ },
+ shouldApplyV3,
+ )
+}
+
+func (a *applierV3backend) DowngradeInfoSet(r *membershippb.DowngradeInfoSetRequest, shouldApplyV3 membership.ShouldApplyV3) {
+ d := membership.DowngradeInfo{Enabled: false}
+ if r.Enabled {
+ d = membership.DowngradeInfo{Enabled: true, TargetVersion: r.Ver}
+ }
+ a.s.cluster.SetDowngradeInfo(&d, shouldApplyV3)
+}
+
+type quotaApplierV3 struct {
+ applierV3
+ q Quota
+}
+
+func newQuotaApplierV3(s *EtcdServer, app applierV3) applierV3 {
+ return "aApplierV3{app, NewBackendQuota(s, "v3-applier")}
+}
+
+func (a *quotaApplierV3) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) {
+ ok := a.q.Available(p)
+ resp, trace, err := a.applierV3.Put(ctx, txn, p)
+ if err == nil && !ok {
+ err = ErrNoSpace
+ }
+ return resp, trace, err
+}
+
+func (a *quotaApplierV3) Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) {
+ ok := a.q.Available(rt)
+ resp, trace, err := a.applierV3.Txn(ctx, rt)
+ if err == nil && !ok {
+ err = ErrNoSpace
+ }
+ return resp, trace, 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(context.TODO(), 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 || r.AuthStatus != 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/go.etcd.io/etcd/server/v3/etcdserver/apply_auth.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_auth.go
new file mode 100644
index 0000000000..beafa967ba
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_auth.go
@@ -0,0 +1,258 @@
+// 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"
+ "sync"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/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, shouldApplyV3 membership.ShouldApplyV3) *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, shouldApplyV3)
+ aa.authInfo.Username = ""
+ aa.authInfo.Revision = 0
+ return ret
+}
+
+func (aa *authApplierV3) Put(ctx context.Context, txn mvcc.TxnWrite, r *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) {
+ if err := aa.as.IsPutPermitted(&aa.authInfo, r.Key); err != nil {
+ return nil, 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, nil, err
+ }
+
+ if r.PrevKv {
+ err := aa.as.IsRangePermitted(&aa.authInfo, r.Key, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+ return aa.applierV3.Put(ctx, txn, r)
+}
+
+func (aa *authApplierV3) Range(ctx context.Context, 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(ctx, 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
+ }
+ return checkTxnReqsPermission(as, ai, rt.Failure)
+}
+
+func (aa *authApplierV3) Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) {
+ if err := checkTxnAuth(aa.as, &aa.authInfo, rt); err != nil {
+ return nil, nil, err
+ }
+ return aa.applierV3.Txn(ctx, 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 {
+ l := aa.lessor.Lookup(leaseID)
+ if l != nil {
+ return aa.checkLeasePutsKeys(l)
+ }
+
+ return nil
+}
+
+func (aa *authApplierV3) checkLeasePutsKeys(l *lease.Lease) error {
+ // early return for most-common scenario of either disabled auth or admin user.
+ // IsAdminPermitted also checks whether auth is enabled
+ if err := aa.as.IsAdminPermitted(&aa.authInfo); err == nil {
+ return nil
+ }
+
+ for _, key := range l.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.AuthStatus != 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/go.etcd.io/etcd/server/v3/etcdserver/apply_v2.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_v2.go
new file mode 100644
index 0000000000..2f5913f18c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_v2.go
@@ -0,0 +1,159 @@
+// 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"
+ "fmt"
+ "path"
+ "strconv"
+ "time"
+
+ "github.com/coreos/go-semver/semver"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+
+ "go.uber.org/zap"
+)
+
+const v2Version = "v2"
+
+// ApplierV2 is the interface for processing V2 raft messages
+type ApplierV2 interface {
+ Delete(r *RequestV2) Response
+ Post(r *RequestV2) Response
+ Put(r *RequestV2, shouldApplyV3 membership.ShouldApplyV3) Response
+ QGet(r *RequestV2) Response
+ Sync(r *RequestV2) Response
+}
+
+func NewApplierV2(lg *zap.Logger, s v2store.Store, c *membership.RaftCluster) ApplierV2 {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ return &applierV2store{lg: lg, store: s, cluster: c}
+}
+
+type applierV2store struct {
+ lg *zap.Logger
+ store v2store.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, shouldApplyV3 membership.ShouldApplyV3) 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(a.lg, path.Dir(r.Path))
+ var attr membership.Attributes
+ if err := json.Unmarshal([]byte(r.Val), &attr); err != nil {
+ a.lg.Panic("failed to unmarshal", zap.String("value", r.Val), zap.Error(err))
+ }
+ if a.cluster != nil {
+ a.cluster.UpdateAttributes(id, attr, shouldApplyV3)
+ }
+ // return an empty response since there is no consumer.
+ return Response{}
+ }
+ // TODO remove v2 version set to avoid the conflict between v2 and v3 in etcd 3.6
+ if r.Path == membership.StoreClusterVersionKey() {
+ if a.cluster != nil {
+ // persist to backend given v2store can be very stale
+ a.cluster.SetVersion(semver.Must(semver.NewVersion(r.Val)), api.UpdateCapability, shouldApplyV3)
+ }
+ 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 v2store.X
+// and returns a Response interpreted from v2store.Event
+func (s *EtcdServer) applyV2Request(r *RequestV2, shouldApplyV3 membership.ShouldApplyV3) (resp Response) {
+ stringer := panicAlternativeStringer{
+ stringer: r,
+ alternative: func() string { return fmt.Sprintf("id:%d,method:%s,path:%s", r.ID, r.Method, r.Path) },
+ }
+ defer func(start time.Time) {
+ success := resp.Err == nil
+ applySec.WithLabelValues(v2Version, r.Method, strconv.FormatBool(success)).Observe(time.Since(start).Seconds())
+ warnOfExpensiveRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, stringer, nil, nil)
+ }(time.Now())
+
+ switch r.Method {
+ case "POST":
+ return s.applyV2.Post(r)
+ case "PUT":
+ return s.applyV2.Put(r, shouldApplyV3)
+ 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() v2store.TTLOptionSet {
+ refresh, _ := pbutil.GetBool(r.Refresh)
+ ttlOptions := v2store.TTLOptionSet{Refresh: refresh}
+ if r.Expiration != 0 {
+ ttlOptions.ExpireTime = time.Unix(0, r.Expiration)
+ }
+ return ttlOptions
+}
+
+func toResponse(ev *v2store.Event, err error) Response {
+ return Response{Event: ev, Err: err}
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/backend.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/backend.go
new file mode 100644
index 0000000000..2beef57634
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/backend.go
@@ -0,0 +1,109 @@
+// 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"
+
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/config"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+ "go.etcd.io/etcd/server/v3/etcdserver/cindex"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+
+ "go.uber.org/zap"
+)
+
+func newBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend {
+ bcfg := backend.DefaultBackendConfig()
+ bcfg.Path = cfg.BackendPath()
+ bcfg.UnsafeNoFsync = cfg.UnsafeNoFsync
+ if cfg.BackendBatchLimit != 0 {
+ bcfg.BatchLimit = cfg.BackendBatchLimit
+ if cfg.Logger != nil {
+ cfg.Logger.Info("setting backend batch limit", zap.Int("batch limit", cfg.BackendBatchLimit))
+ }
+ }
+ if cfg.BackendBatchInterval != 0 {
+ bcfg.BatchInterval = cfg.BackendBatchInterval
+ if cfg.Logger != nil {
+ cfg.Logger.Info("setting backend batch interval", zap.Duration("batch interval", cfg.BackendBatchInterval))
+ }
+ }
+ bcfg.BackendFreelistType = cfg.BackendFreelistType
+ bcfg.Logger = cfg.Logger
+ if cfg.QuotaBackendBytes > 0 && cfg.QuotaBackendBytes != DefaultQuotaBytes {
+ // permit 10% excess over quota for disarm
+ bcfg.MmapSize = uint64(cfg.QuotaBackendBytes + cfg.QuotaBackendBytes/10)
+ }
+ bcfg.Mlock = cfg.ExperimentalMemoryMlock
+ bcfg.Hooks = hooks
+ return backend.New(bcfg)
+}
+
+// openSnapshotBackend renames a snapshot db to the current etcd db and opens it.
+func openSnapshotBackend(cfg config.ServerConfig, ss *snap.Snapshotter, snapshot raftpb.Snapshot, hooks backend.Hooks) (backend.Backend, error) {
+ snapPath, err := ss.DBFilePath(snapshot.Metadata.Index)
+ if err != nil {
+ return nil, fmt.Errorf("failed to find database snapshot file (%v)", err)
+ }
+ if err := os.Rename(snapPath, cfg.BackendPath()); err != nil {
+ return nil, fmt.Errorf("failed to rename database snapshot file (%v)", err)
+ }
+ return openBackend(cfg, hooks), nil
+}
+
+// openBackend returns a backend using the current etcd db.
+func openBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend {
+ fn := cfg.BackendPath()
+
+ now, beOpened := time.Now(), make(chan backend.Backend)
+ go func() {
+ beOpened <- newBackend(cfg, hooks)
+ }()
+
+ select {
+ case be := <-beOpened:
+ cfg.Logger.Info("opened backend db", zap.String("path", fn), zap.Duration("took", time.Since(now)))
+ return be
+
+ case <-time.After(10 * time.Second):
+ cfg.Logger.Info(
+ "db file is flocked by another process, or taking too long",
+ zap.String("path", fn),
+ zap.Duration("took", time.Since(now)),
+ )
+ }
+
+ 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 config.ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot, beExist bool, hooks backend.Hooks) (backend.Backend, error) {
+ consistentIndex := uint64(0)
+ if beExist {
+ consistentIndex, _ = cindex.ReadConsistentIndex(oldbe.ReadTx())
+ }
+ if snapshot.Metadata.Index <= consistentIndex {
+ return oldbe, nil
+ }
+ oldbe.Close()
+ return openSnapshotBackend(cfg, snap.New(cfg.Logger, cfg.SnapDir()), snapshot, hooks)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/cindex.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/cindex.go
new file mode 100644
index 0000000000..ac6ae63742
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/cindex.go
@@ -0,0 +1,226 @@
+// 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 cindex
+
+import (
+ "encoding/binary"
+ "sync"
+ "sync/atomic"
+
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+)
+
+type Backend interface {
+ BatchTx() backend.BatchTx
+ ReadTx() backend.ReadTx
+}
+
+// ConsistentIndexer is an interface that wraps the Get/Set/Save method for consistentIndex.
+type ConsistentIndexer interface {
+
+ // ConsistentIndex returns the consistent index of current executing entry.
+ ConsistentIndex() uint64
+
+ // ConsistentApplyingIndex returns the consistent applying index of current executing entry.
+ ConsistentApplyingIndex() (uint64, uint64)
+
+ // UnsafeConsistentIndex is similar to ConsistentIndex, but it doesn't lock the transaction.
+ UnsafeConsistentIndex() uint64
+
+ // SetConsistentIndex set the consistent index of current executing entry.
+ SetConsistentIndex(v uint64, term uint64)
+
+ // SetConsistentApplyingIndex set the consistent applying index of current executing entry.
+ SetConsistentApplyingIndex(v uint64, term uint64)
+
+ // UnsafeSave must be called holding the lock on the tx.
+ // It saves consistentIndex to the underlying stable storage.
+ UnsafeSave(tx backend.BatchTx)
+
+ // SetBackend set the available backend.BatchTx for ConsistentIndexer.
+ SetBackend(be Backend)
+}
+
+// consistentIndex implements the ConsistentIndexer interface.
+type consistentIndex struct {
+ // consistentIndex represents the offset of an entry in a consistent replica log.
+ // It caches the "consistent_index" key's value.
+ // Accessed through atomics so must be 64-bit aligned.
+ consistentIndex uint64
+ // term represents the RAFT term of committed entry in a consistent replica log.
+ // Accessed through atomics so must be 64-bit aligned.
+ // The value is being persisted in the backend since v3.5.
+ term uint64
+
+ // applyingIndex and applyingTerm are just temporary cache of the raftpb.Entry.Index
+ // and raftpb.Entry.Term, and they are not ready to be persisted yet. They will be
+ // saved to consistentIndex and term above in the txPostLockInsideApplyHook.
+ applyingIndex uint64
+ applyingTerm uint64
+
+ // be is used for initial read consistentIndex
+ be Backend
+ // mutex is protecting be.
+ mutex sync.Mutex
+}
+
+// NewConsistentIndex creates a new consistent index.
+// If `be` is nil, it must be set (SetBackend) before first access using `ConsistentIndex()`.
+func NewConsistentIndex(be Backend) ConsistentIndexer {
+ return &consistentIndex{be: be}
+}
+
+func (ci *consistentIndex) ConsistentIndex() uint64 {
+ if index := atomic.LoadUint64(&ci.consistentIndex); index > 0 {
+ return index
+ }
+ ci.mutex.Lock()
+ defer ci.mutex.Unlock()
+
+ v, term := ReadConsistentIndex(ci.be.ReadTx())
+ ci.SetConsistentIndex(v, term)
+ return v
+}
+
+func (ci *consistentIndex) UnsafeConsistentIndex() uint64 {
+ if index := atomic.LoadUint64(&ci.consistentIndex); index > 0 {
+ return index
+ }
+
+ v, term := unsafeReadConsistentIndex(ci.be.ReadTx())
+ ci.SetConsistentIndex(v, term)
+ return v
+}
+
+func (ci *consistentIndex) SetConsistentIndex(v uint64, term uint64) {
+ atomic.StoreUint64(&ci.consistentIndex, v)
+ atomic.StoreUint64(&ci.term, term)
+}
+
+func (ci *consistentIndex) UnsafeSave(tx backend.BatchTx) {
+ index := atomic.LoadUint64(&ci.consistentIndex)
+ term := atomic.LoadUint64(&ci.term)
+ UnsafeUpdateConsistentIndex(tx, index, term)
+}
+
+func (ci *consistentIndex) SetBackend(be Backend) {
+ ci.mutex.Lock()
+ defer ci.mutex.Unlock()
+ ci.be = be
+ // After the backend is changed, the first access should re-read it.
+ ci.SetConsistentIndex(0, 0)
+}
+
+func (ci *consistentIndex) ConsistentApplyingIndex() (uint64, uint64) {
+ return atomic.LoadUint64(&ci.applyingIndex), atomic.LoadUint64(&ci.applyingTerm)
+}
+
+func (ci *consistentIndex) SetConsistentApplyingIndex(v uint64, term uint64) {
+ atomic.StoreUint64(&ci.applyingIndex, v)
+ atomic.StoreUint64(&ci.applyingTerm, term)
+}
+
+func NewFakeConsistentIndex(index uint64) ConsistentIndexer {
+ return &fakeConsistentIndex{index: index}
+}
+
+type fakeConsistentIndex struct {
+ index uint64
+ term uint64
+}
+
+func (f *fakeConsistentIndex) ConsistentIndex() uint64 {
+ return atomic.LoadUint64(&f.index)
+}
+func (f *fakeConsistentIndex) ConsistentApplyingIndex() (uint64, uint64) {
+ return atomic.LoadUint64(&f.index), atomic.LoadUint64(&f.term)
+}
+func (f *fakeConsistentIndex) UnsafeConsistentIndex() uint64 {
+ return atomic.LoadUint64(&f.index)
+}
+
+func (f *fakeConsistentIndex) SetConsistentIndex(index uint64, term uint64) {
+ atomic.StoreUint64(&f.index, index)
+ atomic.StoreUint64(&f.term, term)
+}
+func (f *fakeConsistentIndex) SetConsistentApplyingIndex(index uint64, term uint64) {
+ atomic.StoreUint64(&f.index, index)
+ atomic.StoreUint64(&f.term, term)
+}
+
+func (f *fakeConsistentIndex) UnsafeSave(_ backend.BatchTx) {}
+func (f *fakeConsistentIndex) SetBackend(_ Backend) {}
+
+// UnsafeCreateMetaBucket creates the `meta` bucket (if it does not exists yet).
+func UnsafeCreateMetaBucket(tx backend.BatchTx) {
+ tx.UnsafeCreateBucket(buckets.Meta)
+}
+
+// CreateMetaBucket creates the `meta` bucket (if it does not exists yet).
+func CreateMetaBucket(tx backend.BatchTx) {
+ tx.LockOutsideApply()
+ defer tx.Unlock()
+ tx.UnsafeCreateBucket(buckets.Meta)
+}
+
+// unsafeGetConsistentIndex loads consistent index & term from given transaction.
+// returns 0,0 if the data are not found.
+// Term is persisted since v3.5.
+func unsafeReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) {
+ _, vs := tx.UnsafeRange(buckets.Meta, buckets.MetaConsistentIndexKeyName, nil, 0)
+ if len(vs) == 0 {
+ return 0, 0
+ }
+ v := binary.BigEndian.Uint64(vs[0])
+ _, ts := tx.UnsafeRange(buckets.Meta, buckets.MetaTermKeyName, nil, 0)
+ if len(ts) == 0 {
+ return v, 0
+ }
+ t := binary.BigEndian.Uint64(ts[0])
+ return v, t
+}
+
+// ReadConsistentIndex loads consistent index and term from given transaction.
+// returns 0 if the data are not found.
+func ReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) {
+ tx.Lock()
+ defer tx.Unlock()
+ return unsafeReadConsistentIndex(tx)
+}
+
+func UnsafeUpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64) {
+ if index == 0 {
+ // Never save 0 as it means that we didn't loaded the real index yet.
+ return
+ }
+
+ bs1 := make([]byte, 8)
+ binary.BigEndian.PutUint64(bs1, index)
+ // put the index into the underlying backend
+ // tx has been locked in TxnBegin, so there is no need to lock it again
+ tx.UnsafePut(buckets.Meta, buckets.MetaConsistentIndexKeyName, bs1)
+ if term > 0 {
+ bs2 := make([]byte, 8)
+ binary.BigEndian.PutUint64(bs2, term)
+ tx.UnsafePut(buckets.Meta, buckets.MetaTermKeyName, bs2)
+ }
+}
+
+func UpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64) {
+ tx.LockOutsideApply()
+ defer tx.Unlock()
+ UnsafeUpdateConsistentIndex(tx, index, term)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/doc.go
new file mode 100644
index 0000000000..7d3e4b774e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/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 cindex provides an interface and implementation for getting/saving consistentIndex.
+package cindex
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/cluster_util.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/cluster_util.go
new file mode 100644
index 0000000000..595586e201
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/cluster_util.go
@@ -0,0 +1,482 @@
+// 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"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+
+ "github.com/coreos/go-semver/semver"
+ "go.uber.org/zap"
+)
+
+// isMemberBootstrapped tries to check if the given member has been bootstrapped
+// in the given cluster.
+func isMemberBootstrapped(lg *zap.Logger, cl *membership.RaftCluster, member string, rt http.RoundTripper, timeout time.Duration) bool {
+ rcl, err := getClusterFromRemotePeers(lg, 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(lg *zap.Logger, urls []string, rt http.RoundTripper) (*membership.RaftCluster, error) {
+ return getClusterFromRemotePeers(lg, urls, 10*time.Second, true, rt)
+}
+
+// If logerr is true, it prints out more error messages.
+func getClusterFromRemotePeers(lg *zap.Logger, urls []string, timeout time.Duration, logerr bool, rt http.RoundTripper) (*membership.RaftCluster, error) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ cc := &http.Client{
+ Transport: rt,
+ Timeout: timeout,
+ }
+ for _, u := range urls {
+ addr := u + "/members"
+ resp, err := cc.Get(addr)
+ if err != nil {
+ if logerr {
+ lg.Warn("failed to get cluster response", zap.String("address", addr), zap.Error(err))
+ }
+ continue
+ }
+ b, err := ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ if err != nil {
+ if logerr {
+ lg.Warn("failed to read body of cluster response", zap.String("address", addr), zap.Error(err))
+ }
+ continue
+ }
+ var membs []*membership.Member
+ if err = json.Unmarshal(b, &membs); err != nil {
+ if logerr {
+ lg.Warn("failed to unmarshal cluster response", zap.String("address", addr), zap.Error(err))
+ }
+ continue
+ }
+ id, err := types.IDFromString(resp.Header.Get("X-Etcd-Cluster-ID"))
+ if err != nil {
+ if logerr {
+ lg.Warn(
+ "failed to parse cluster ID",
+ zap.String("address", addr),
+ zap.String("header", resp.Header.Get("X-Etcd-Cluster-ID")),
+ zap.Error(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(lg, 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(lg *zap.Logger, 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(lg, m, rt)
+ if err != nil {
+ lg.Warn("failed to get version", zap.String("remote-member-id", m.ID.String()), zap.Error(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(lg *zap.Logger, 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 {
+ lg.Warn(
+ "failed to parse server version of remote member",
+ zap.String("remote-member-id", mid),
+ zap.String("remote-member-version", ver.Server),
+ zap.Error(err),
+ )
+ return nil
+ }
+ if lv.LessThan(*v) {
+ lg.Warn(
+ "leader found higher-versioned member",
+ zap.String("local-member-version", lv.String()),
+ zap.String("remote-member-id", mid),
+ zap.String("remote-member-version", ver.Server),
+ )
+ }
+ if cv == nil {
+ cv = v
+ } else if v.LessThan(*cv) {
+ cv = v
+ }
+ }
+ return cv
+}
+
+// allowedVersionRange decides the available version range of the cluster that local server can join in;
+// if the downgrade enabled status is true, the version window is [oneMinorHigher, oneMinorHigher]
+// if the downgrade is not enabled, the version window is [MinClusterVersion, localVersion]
+func allowedVersionRange(downgradeEnabled bool) (minV *semver.Version, maxV *semver.Version) {
+ minV = semver.Must(semver.NewVersion(version.MinClusterVersion))
+ maxV = semver.Must(semver.NewVersion(version.Version))
+ maxV = &semver.Version{Major: maxV.Major, Minor: maxV.Minor}
+
+ if downgradeEnabled {
+ // Todo: handle the case that downgrading from higher major version(e.g. downgrade from v4.0 to v3.x)
+ maxV.Minor = maxV.Minor + 1
+ minV = &semver.Version{Major: maxV.Major, Minor: maxV.Minor}
+ }
+ return minV, maxV
+}
+
+// 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 [MinV, MaxV] 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(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) bool {
+ vers := getVersions(lg, cl, local, rt)
+ minV, maxV := allowedVersionRange(getDowngradeEnabledFromRemotePeers(lg, cl, local, rt))
+ return isCompatibleWithVers(lg, vers, local, minV, maxV)
+}
+
+func isCompatibleWithVers(lg *zap.Logger, 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 {
+ lg.Warn(
+ "failed to parse cluster version of remote member",
+ zap.String("remote-member-id", id),
+ zap.String("remote-member-cluster-version", v.Cluster),
+ zap.Error(err),
+ )
+ continue
+ }
+ if clusterv.LessThan(*minV) {
+ lg.Warn(
+ "cluster version of remote member is not compatible; too low",
+ zap.String("remote-member-id", id),
+ zap.String("remote-member-cluster-version", clusterv.String()),
+ zap.String("minimum-cluster-version-supported", minV.String()),
+ )
+ return false
+ }
+ if maxV.LessThan(*clusterv) {
+ lg.Warn(
+ "cluster version of remote member is not compatible; too high",
+ zap.String("remote-member-id", id),
+ zap.String("remote-member-cluster-version", clusterv.String()),
+ zap.String("minimum-cluster-version-supported", minV.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(lg *zap.Logger, 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 {
+ addr := u + "/version"
+ resp, err = cc.Get(addr)
+ if err != nil {
+ lg.Warn(
+ "failed to reach the peer URL",
+ zap.String("address", addr),
+ zap.String("remote-member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ continue
+ }
+ var b []byte
+ b, err = ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ if err != nil {
+ lg.Warn(
+ "failed to read body of response",
+ zap.String("address", addr),
+ zap.String("remote-member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ continue
+ }
+ var vers version.Versions
+ if err = json.Unmarshal(b, &vers); err != nil {
+ lg.Warn(
+ "failed to unmarshal response",
+ zap.String("address", addr),
+ zap.String("remote-member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ continue
+ }
+ return &vers, nil
+ }
+ return nil, err
+}
+
+func promoteMemberHTTP(ctx context.Context, url string, id uint64, peerRt http.RoundTripper) ([]*membership.Member, error) {
+ cc := &http.Client{Transport: peerRt}
+ // TODO: refactor member http handler code
+ // cannot import etcdhttp, so manually construct url
+ requestUrl := url + "/members/promote/" + fmt.Sprintf("%d", id)
+ req, err := http.NewRequest("POST", requestUrl, nil)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ resp, err := cc.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ if resp.StatusCode == http.StatusRequestTimeout {
+ return nil, ErrTimeout
+ }
+ if resp.StatusCode == http.StatusPreconditionFailed {
+ // both ErrMemberNotLearner and ErrLearnerNotReady have same http status code
+ if strings.Contains(string(b), ErrLearnerNotReady.Error()) {
+ return nil, ErrLearnerNotReady
+ }
+ if strings.Contains(string(b), membership.ErrMemberNotLearner.Error()) {
+ return nil, membership.ErrMemberNotLearner
+ }
+ return nil, fmt.Errorf("member promote: unknown error(%s)", string(b))
+ }
+ if resp.StatusCode == http.StatusNotFound {
+ return nil, membership.ErrIDNotFound
+ }
+
+ if resp.StatusCode != http.StatusOK { // all other types of errors
+ return nil, fmt.Errorf("member promote: unknown error(%s)", string(b))
+ }
+
+ var membs []*membership.Member
+ if err := json.Unmarshal(b, &membs); err != nil {
+ return nil, err
+ }
+ return membs, nil
+}
+
+// getDowngradeEnabledFromRemotePeers will get the downgrade enabled status of the cluster.
+func getDowngradeEnabledFromRemotePeers(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) bool {
+ members := cl.Members()
+
+ for _, m := range members {
+ if m.ID == local {
+ continue
+ }
+ enable, err := getDowngradeEnabled(lg, m, rt)
+ if err != nil {
+ lg.Warn("failed to get downgrade enabled status", zap.String("remote-member-id", m.ID.String()), zap.Error(err))
+ } else {
+ // Since the "/downgrade/enabled" serves linearized data,
+ // this function can return once it gets a non-error response from the endpoint.
+ return enable
+ }
+ }
+ return false
+}
+
+// getDowngradeEnabled returns the downgrade enabled status of the given member
+// via its peerURLs. Returns the last error if it fails to get it.
+func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTripper) (bool, error) {
+ cc := &http.Client{
+ Transport: rt,
+ }
+ var (
+ err error
+ resp *http.Response
+ )
+
+ for _, u := range m.PeerURLs {
+ addr := u + DowngradeEnabledPath
+ resp, err = cc.Get(addr)
+ if err != nil {
+ lg.Warn(
+ "failed to reach the peer URL",
+ zap.String("address", addr),
+ zap.String("remote-member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ continue
+ }
+ var b []byte
+ b, err = ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ if err != nil {
+ lg.Warn(
+ "failed to read body of response",
+ zap.String("address", addr),
+ zap.String("remote-member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ continue
+ }
+ var enable bool
+ if enable, err = strconv.ParseBool(string(b)); err != nil {
+ lg.Warn(
+ "failed to convert response",
+ zap.String("address", addr),
+ zap.String("remote-member-id", m.ID.String()),
+ zap.Error(err),
+ )
+ continue
+ }
+ return enable, nil
+ }
+ return false, err
+}
+
+// isMatchedVersions returns true if all server versions are equal to target version, otherwise return false.
+// It can be used to decide the whether the cluster finishes downgrading to target version.
+func isMatchedVersions(lg *zap.Logger, targetVersion *semver.Version, vers map[string]*version.Versions) bool {
+ for mid, ver := range vers {
+ if ver == nil {
+ return false
+ }
+ v, err := semver.NewVersion(ver.Cluster)
+ if err != nil {
+ lg.Warn(
+ "failed to parse server version of remote member",
+ zap.String("remote-member-id", mid),
+ zap.String("remote-member-version", ver.Server),
+ zap.Error(err),
+ )
+ return false
+ }
+ if !targetVersion.Equal(*v) {
+ lg.Warn("remotes server has mismatching etcd version",
+ zap.String("remote-member-id", mid),
+ zap.String("current-server-version", v.String()),
+ zap.String("target-version", targetVersion.String()),
+ )
+ return false
+ }
+ }
+ return true
+}
+
+func convertToClusterVersion(v string) (*semver.Version, error) {
+ ver, err := semver.NewVersion(v)
+ if err != nil {
+ // allow input version format Major.Minor
+ ver, err = semver.NewVersion(v + ".0")
+ if err != nil {
+ return nil, ErrWrongDowngradeVersionFormat
+ }
+ }
+ // cluster version only keeps major.minor, remove patch version
+ ver = &semver.Version{Major: ver.Major, Minor: ver.Minor}
+ return ver, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/corrupt.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/corrupt.go
new file mode 100644
index 0000000000..6b465125a6
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/corrupt.go
@@ -0,0 +1,571 @@
+// 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 (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
+ "go.etcd.io/etcd/server/v3/mvcc"
+
+ "go.uber.org/zap"
+)
+
+type CorruptionChecker interface {
+ InitialCheck() error
+ PeriodicCheck() error
+ CompactHashCheck()
+}
+
+type corruptionChecker struct {
+ lg *zap.Logger
+
+ hasher Hasher
+
+ mux sync.RWMutex
+ latestRevisionChecked int64
+}
+
+type Hasher interface {
+ mvcc.HashStorage
+ ReqTimeout() time.Duration
+ MemberId() types.ID
+ PeerHashByRev(int64) []*peerHashKVResp
+ LinearizableReadNotify(context.Context) error
+ TriggerCorruptAlarm(types.ID)
+}
+
+func newCorruptionChecker(lg *zap.Logger, s *EtcdServer, storage mvcc.HashStorage) *corruptionChecker {
+ return &corruptionChecker{
+ lg: lg,
+ hasher: hasherAdapter{s, storage},
+ }
+}
+
+type hasherAdapter struct {
+ *EtcdServer
+ mvcc.HashStorage
+}
+
+func (h hasherAdapter) MemberId() types.ID {
+ return h.EtcdServer.ID()
+}
+
+func (h hasherAdapter) ReqTimeout() time.Duration {
+ return h.EtcdServer.Cfg.ReqTimeout()
+}
+
+func (h hasherAdapter) PeerHashByRev(rev int64) []*peerHashKVResp {
+ return h.EtcdServer.getPeerHashKVs(rev)
+}
+
+func (h hasherAdapter) TriggerCorruptAlarm(memberID types.ID) {
+ h.EtcdServer.triggerCorruptAlarm(memberID)
+}
+
+// InitialCheck 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 (cm *corruptionChecker) InitialCheck() error {
+
+ cm.lg.Info(
+ "starting initial corruption check",
+ zap.String("local-member-id", cm.hasher.MemberId().String()),
+ zap.Duration("timeout", cm.hasher.ReqTimeout()),
+ )
+
+ h, rev, err := cm.hasher.HashByRev(0)
+ if err != nil {
+ return fmt.Errorf("%s failed to fetch hash (%v)", cm.hasher.MemberId(), err)
+ }
+ peers := cm.hasher.PeerHashByRev(rev)
+ mismatch := 0
+ for _, p := range peers {
+ if p.resp != nil {
+ peerID := types.ID(p.resp.Header.MemberId)
+ fields := []zap.Field{
+ zap.String("local-member-id", cm.hasher.MemberId().String()),
+ zap.Int64("local-member-revision", rev),
+ zap.Int64("local-member-compact-revision", h.CompactRevision),
+ zap.Uint32("local-member-hash", h.Hash),
+ zap.String("remote-peer-id", peerID.String()),
+ zap.Strings("remote-peer-endpoints", p.eps),
+ zap.Int64("remote-peer-revision", p.resp.Header.Revision),
+ zap.Int64("remote-peer-compact-revision", p.resp.CompactRevision),
+ zap.Uint32("remote-peer-hash", p.resp.Hash),
+ }
+
+ if h.Hash != p.resp.Hash {
+ if h.CompactRevision == p.resp.CompactRevision {
+ cm.lg.Warn("found different hash values from remote peer", fields...)
+ mismatch++
+ } else {
+ cm.lg.Warn("found different compact revision values from remote peer", fields...)
+ }
+ }
+
+ continue
+ }
+
+ if p.err != nil {
+ switch p.err {
+ case rpctypes.ErrFutureRev:
+ cm.lg.Warn(
+ "cannot fetch hash from slow remote peer",
+ zap.String("local-member-id", cm.hasher.MemberId().String()),
+ zap.Int64("local-member-revision", rev),
+ zap.Int64("local-member-compact-revision", h.CompactRevision),
+ zap.Uint32("local-member-hash", h.Hash),
+ zap.String("remote-peer-id", p.id.String()),
+ zap.Strings("remote-peer-endpoints", p.eps),
+ zap.Error(err),
+ )
+ case rpctypes.ErrCompacted:
+ cm.lg.Warn(
+ "cannot fetch hash from remote peer; local member is behind",
+ zap.String("local-member-id", cm.hasher.MemberId().String()),
+ zap.Int64("local-member-revision", rev),
+ zap.Int64("local-member-compact-revision", h.CompactRevision),
+ zap.Uint32("local-member-hash", h.Hash),
+ zap.String("remote-peer-id", p.id.String()),
+ zap.Strings("remote-peer-endpoints", p.eps),
+ zap.Error(err),
+ )
+ case rpctypes.ErrClusterIdMismatch:
+ cm.lg.Warn(
+ "cluster ID mismatch",
+ zap.String("local-member-id", cm.hasher.MemberId().String()),
+ zap.Int64("local-member-revision", h.Revision),
+ zap.Int64("local-member-compact-revision", h.CompactRevision),
+ zap.Uint32("local-member-hash", h.Hash),
+ zap.String("remote-peer-id", p.id.String()),
+ zap.Strings("remote-peer-endpoints", p.eps),
+ zap.Error(err),
+ )
+ }
+ }
+ }
+ if mismatch > 0 {
+ return fmt.Errorf("%s found data inconsistency with peers", cm.hasher.MemberId())
+ }
+
+ cm.lg.Info(
+ "initial corruption checking passed; no corruption",
+ zap.String("local-member-id", cm.hasher.MemberId().String()),
+ )
+ return nil
+}
+
+func (cm *corruptionChecker) PeriodicCheck() error {
+ h, rev, err := cm.hasher.HashByRev(0)
+ if err != nil {
+ return err
+ }
+ peers := cm.hasher.PeerHashByRev(rev)
+
+ ctx, cancel := context.WithTimeout(context.Background(), cm.hasher.ReqTimeout())
+ err = cm.hasher.LinearizableReadNotify(ctx)
+ cancel()
+ if err != nil {
+ return err
+ }
+
+ h2, rev2, err := cm.hasher.HashByRev(0)
+ if err != nil {
+ return err
+ }
+
+ alarmed := false
+ mismatch := func(id types.ID) {
+ if alarmed {
+ return
+ }
+ alarmed = true
+ // It isn't clear which member's data is corrupted, so we
+ // intentionally set the memberID as 0. We will identify
+ // the corrupted members using quorum in 3.6. Please see
+ // discussion in https://github.com/etcd-io/etcd/pull/14828.
+ cm.hasher.TriggerCorruptAlarm(types.ID(0))
+ }
+
+ if h2.Hash != h.Hash && rev2 == rev && h.CompactRevision == h2.CompactRevision {
+ cm.lg.Warn(
+ "found hash mismatch",
+ zap.Int64("revision-1", rev),
+ zap.Int64("compact-revision-1", h.CompactRevision),
+ zap.Uint32("hash-1", h.Hash),
+ zap.Int64("revision-2", rev2),
+ zap.Int64("compact-revision-2", h2.CompactRevision),
+ zap.Uint32("hash-2", h2.Hash),
+ )
+ mismatch(cm.hasher.MemberId())
+ }
+
+ checkedCount := 0
+ for _, p := range peers {
+ if p.resp == nil {
+ continue
+ }
+ checkedCount++
+
+ // leader expects follower's latest revision less than or equal to leader's
+ if p.resp.Header.Revision > rev2 {
+ cm.lg.Warn(
+ "revision from follower must be less than or equal to leader's",
+ zap.Int64("leader-revision", rev2),
+ zap.Int64("follower-revision", p.resp.Header.Revision),
+ zap.String("follower-peer-id", p.id.String()),
+ )
+ mismatch(p.id)
+ }
+
+ // leader expects follower's latest compact revision less than or equal to leader's
+ if p.resp.CompactRevision > h2.CompactRevision {
+ cm.lg.Warn(
+ "compact revision from follower must be less than or equal to leader's",
+ zap.Int64("leader-compact-revision", h2.CompactRevision),
+ zap.Int64("follower-compact-revision", p.resp.CompactRevision),
+ zap.String("follower-peer-id", p.id.String()),
+ )
+ mismatch(p.id)
+ }
+
+ // follower's compact revision is leader's old one, then hashes must match
+ if p.resp.CompactRevision == h.CompactRevision && p.resp.Hash != h.Hash {
+ cm.lg.Warn(
+ "same compact revision then hashes must match",
+ zap.Int64("leader-compact-revision", h2.CompactRevision),
+ zap.Uint32("leader-hash", h.Hash),
+ zap.Int64("follower-compact-revision", p.resp.CompactRevision),
+ zap.Uint32("follower-hash", p.resp.Hash),
+ zap.String("follower-peer-id", p.id.String()),
+ )
+ mismatch(p.id)
+ }
+ }
+ cm.lg.Info("finished peer corruption check", zap.Int("number-of-peers-checked", checkedCount))
+ return nil
+}
+
+func (cm *corruptionChecker) CompactHashCheck() {
+ cm.lg.Info("starting compact hash check",
+ zap.String("local-member-id", cm.hasher.MemberId().String()),
+ zap.Duration("timeout", cm.hasher.ReqTimeout()),
+ )
+ hashes := cm.uncheckedRevisions()
+ // Assume that revisions are ordered from largest to smallest
+ for i, hash := range hashes {
+ peers := cm.hasher.PeerHashByRev(hash.Revision)
+ if len(peers) == 0 {
+ continue
+ }
+ peersChecked := 0
+ for _, p := range peers {
+ if p.resp == nil || p.resp.CompactRevision != hash.CompactRevision {
+ continue
+ }
+
+ // follower's compact revision is leader's old one, then hashes must match
+ if p.resp.Hash != hash.Hash {
+ // It isn't clear which member's data is corrupted, so we
+ // intentionally set the memberID as 0. We will identify
+ // the corrupted members using quorum in 3.6. Please see
+ // discussion in https://github.com/etcd-io/etcd/pull/14828.
+ cm.hasher.TriggerCorruptAlarm(types.ID(0))
+ cm.lg.Error("failed compaction hash check",
+ zap.Int64("revision", hash.Revision),
+ zap.Int64("leader-compact-revision", hash.CompactRevision),
+ zap.Uint32("leader-hash", hash.Hash),
+ zap.Int64("follower-compact-revision", p.resp.CompactRevision),
+ zap.Uint32("follower-hash", p.resp.Hash),
+ zap.String("follower-peer-id", p.id.String()),
+ )
+ return
+ }
+ peersChecked++
+ cm.lg.Info("successfully checked hash on follower",
+ zap.Int64("revision", hash.Revision),
+ zap.String("peer-id", p.id.String()),
+ )
+ }
+ if len(peers) == peersChecked {
+ cm.lg.Info("successfully checked hash on whole cluster",
+ zap.Int("number-of-peers-checked", peersChecked),
+ zap.Int64("revision", hash.Revision),
+ )
+ cm.mux.Lock()
+ if hash.Revision > cm.latestRevisionChecked {
+ cm.latestRevisionChecked = hash.Revision
+ }
+ cm.mux.Unlock()
+ cm.lg.Info("finished compaction hash check", zap.Int("number-of-hashes-checked", i+1))
+ return
+ }
+ cm.lg.Warn("skipped revision in compaction hash check; was not able to check all peers",
+ zap.Int("number-of-peers-checked", peersChecked),
+ zap.Int("number-of-peers", len(peers)),
+ zap.Int64("revision", hash.Revision),
+ )
+ }
+ cm.lg.Info("finished compaction hash check", zap.Int("number-of-hashes-checked", len(hashes)))
+ return
+}
+
+func (cm *corruptionChecker) uncheckedRevisions() []mvcc.KeyValueHash {
+ cm.mux.RLock()
+ lastRevisionChecked := cm.latestRevisionChecked
+ cm.mux.RUnlock()
+
+ hashes := cm.hasher.Hashes()
+ // Sort in descending order
+ sort.Slice(hashes, func(i, j int) bool {
+ return hashes[i].Revision > hashes[j].Revision
+ })
+ for i, hash := range hashes {
+ if hash.Revision <= lastRevisionChecked {
+ return hashes[:i]
+ }
+ }
+ return hashes
+}
+
+func (s *EtcdServer) triggerCorruptAlarm(id types.ID) {
+ 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})
+ })
+}
+
+type peerInfo struct {
+ id types.ID
+ eps []string
+}
+
+type peerHashKVResp struct {
+ peerInfo
+ resp *pb.HashKVResponse
+ err error
+}
+
+func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp {
+ // TODO: handle the case when "s.cluster.Members" have not
+ // been populated (e.g. no snapshot to load from disk)
+ members := s.cluster.Members()
+ peers := make([]peerInfo, 0, len(members))
+ for _, m := range members {
+ if m.ID == s.ID() {
+ continue
+ }
+ peers = append(peers, peerInfo{id: m.ID, eps: m.PeerURLs})
+ }
+
+ lg := s.Logger()
+
+ cc := &http.Client{Transport: s.peerRt}
+ var resps []*peerHashKVResp
+ for _, p := range peers {
+ if len(p.eps) == 0 {
+ continue
+ }
+
+ respsLen := len(resps)
+ var lastErr error
+ for _, ep := range p.eps {
+ ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout())
+ resp, lastErr := HashByRev(ctx, s.cluster.ID(), cc, ep, rev)
+ cancel()
+ if lastErr == nil {
+ resps = append(resps, &peerHashKVResp{peerInfo: p, resp: resp, err: nil})
+ break
+ }
+ lg.Warn(
+ "failed hash kv request",
+ zap.String("local-member-id", s.ID().String()),
+ zap.Int64("requested-revision", rev),
+ zap.String("remote-peer-endpoint", ep),
+ zap.Error(lastErr),
+ )
+ }
+
+ // failed to get hashKV from all endpoints of this peer
+ if respsLen == len(resps) {
+ resps = append(resps, &peerHashKVResp{peerInfo: p, resp: nil, err: lastErr})
+ }
+ }
+ return resps
+}
+
+type applierV3Corrupt struct {
+ applierV3
+}
+
+func newApplierV3Corrupt(a applierV3) *applierV3Corrupt { return &applierV3Corrupt{a} }
+
+func (a *applierV3Corrupt) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) {
+ return nil, nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) Range(ctx context.Context, 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(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) {
+ return nil, nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) {
+ return nil, 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
+}
+
+const PeerHashKVPath = "/members/hashkv"
+
+type hashKVHandler struct {
+ lg *zap.Logger
+ server *EtcdServer
+}
+
+func (s *EtcdServer) HashKVHandler() http.Handler {
+ return &hashKVHandler{lg: s.Logger(), server: s}
+}
+
+func (h *hashKVHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodGet {
+ w.Header().Set("Allow", http.MethodGet)
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return
+ }
+ if r.URL.Path != PeerHashKVPath {
+ http.Error(w, "bad path", http.StatusBadRequest)
+ return
+ }
+ if gcid := r.Header.Get("X-Etcd-Cluster-ID"); gcid != "" && gcid != h.server.cluster.ID().String() {
+ http.Error(w, rafthttp.ErrClusterIDMismatch.Error(), http.StatusPreconditionFailed)
+ return
+ }
+
+ defer r.Body.Close()
+ b, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ http.Error(w, "error reading body", http.StatusBadRequest)
+ return
+ }
+
+ req := &pb.HashKVRequest{}
+ if err := json.Unmarshal(b, req); err != nil {
+ h.lg.Warn("failed to unmarshal request", zap.Error(err))
+ http.Error(w, "error unmarshalling request", http.StatusBadRequest)
+ return
+ }
+ hash, rev, err := h.server.KV().HashStorage().HashByRev(req.Revision)
+ if err != nil {
+ h.lg.Warn(
+ "failed to get hashKV",
+ zap.Int64("requested-revision", req.Revision),
+ zap.Error(err),
+ )
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ resp := &pb.HashKVResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: hash.Hash, CompactRevision: hash.CompactRevision}
+ respBytes, err := json.Marshal(resp)
+ if err != nil {
+ h.lg.Warn("failed to marshal hashKV response", zap.Error(err))
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("X-Etcd-Cluster-ID", h.server.Cluster().ID().String())
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(respBytes)
+}
+
+// HashByRev fetch hash of kv store at the given rev via http call to the given url
+func HashByRev(ctx context.Context, cid types.ID, cc *http.Client, url string, rev int64) (*pb.HashKVResponse, error) {
+ hashReq := &pb.HashKVRequest{Revision: rev}
+ hashReqBytes, err := json.Marshal(hashReq)
+ if err != nil {
+ return nil, err
+ }
+ requestUrl := url + PeerHashKVPath
+ req, err := http.NewRequest(http.MethodGet, requestUrl, bytes.NewReader(hashReqBytes))
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("X-Etcd-Cluster-ID", cid.String())
+ req.Cancel = ctx.Done()
+
+ resp, err := cc.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ if resp.StatusCode == http.StatusBadRequest {
+ if strings.Contains(string(b), mvcc.ErrCompacted.Error()) {
+ return nil, rpctypes.ErrCompacted
+ }
+ if strings.Contains(string(b), mvcc.ErrFutureRev.Error()) {
+ return nil, rpctypes.ErrFutureRev
+ }
+ } else if resp.StatusCode == http.StatusPreconditionFailed {
+ if strings.Contains(string(b), rafthttp.ErrClusterIDMismatch.Error()) {
+ return nil, rpctypes.ErrClusterIdMismatch
+ }
+ }
+ if resp.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("unknown error: %s", string(b))
+ }
+
+ hashResp := &pb.HashKVResponse{}
+ if err := json.Unmarshal(b, hashResp); err != nil {
+ return nil, err
+ }
+ return hashResp, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/doc.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/doc.go
new file mode 100644
index 0000000000..b195d2d167
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/etcdserver/errors.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors.go
new file mode 100644
index 0000000000..f6d77fe72a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors.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 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")
+ ErrTimeoutWaitAppliedIndex = errors.New("etcdserver: request timed out, waiting for the applied index took too long")
+ ErrLeaderChanged = errors.New("etcdserver: leader changed")
+ ErrNotEnoughStartedMembers = errors.New("etcdserver: re-configuration failed due to not enough started members")
+ ErrLearnerNotReady = errors.New("etcdserver: can only promote a learner member which is in sync with leader")
+ 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")
+ ErrBadLeaderTransferee = errors.New("etcdserver: bad leader transferee")
+ ErrClusterVersionUnavailable = errors.New("etcdserver: cluster version not found during downgrade")
+ ErrWrongDowngradeVersionFormat = errors.New("etcdserver: wrong downgrade target version format")
+ ErrInvalidDowngradeTargetVersion = errors.New("etcdserver: invalid downgrade target version")
+ ErrDowngradeInProcess = errors.New("etcdserver: cluster has a downgrade job in progress")
+ ErrNoInflightDowngrade = errors.New("etcdserver: no inflight downgrade job")
+)
+
+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/go.etcd.io/etcd/server/v3/etcdserver/metrics.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/metrics.go
new file mode 100644
index 0000000000..06263a9cd2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/metrics.go
@@ -0,0 +1,243 @@
+// 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"
+
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/pkg/v3/runtime"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "go.uber.org/zap"
+)
+
+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.",
+ })
+ isLearner = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "is_learner",
+ Help: "Whether or not this member is a learner. 1 if is, 0 otherwise.",
+ })
+ learnerPromoteFailed = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "learner_promote_failures",
+ Help: "The total number of failed learner promotions (likely learner not ready) while this member is leader.",
+ },
+ []string{"Reason"},
+ )
+ learnerPromoteSucceed = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "learner_promote_successes",
+ Help: "The total number of successful learner promotions while this member is leader.",
+ })
+ 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).",
+ })
+ applySnapshotInProgress = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "snapshot_apply_in_progress_total",
+ Help: "1 if the server is applying the incoming snapshot. 0 if none.",
+ })
+ 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.",
+ })
+ 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.",
+ })
+ readIndexFailed = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "read_indexes_failed_total",
+ Help: "The total number of failed read indexes seen.",
+ })
+ leaseExpired = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "server",
+ Name: "lease_expired_total",
+ Help: "The total number of expired leases.",
+ })
+ 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"})
+ serverID = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "id",
+ Help: "Server or member ID in hexadecimal format. 1 for 'server_id' label with current ID.",
+ },
+ []string{"server_id"})
+
+ fdUsed = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "os",
+ Subsystem: "fd",
+ Name: "used",
+ Help: "The number of used file descriptors.",
+ })
+ fdLimit = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "os",
+ Subsystem: "fd",
+ Name: "limit",
+ Help: "The file descriptor limit.",
+ })
+ applySec = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "apply_duration_seconds",
+ Help: "The latency distributions of v2 apply called by backend.",
+
+ // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2
+ // highest bucket start of 0.0001 sec * 2^19 == 52.4288 sec
+ Buckets: prometheus.ExponentialBuckets(0.0001, 2, 20),
+ },
+ []string{"version", "op", "success"})
+)
+
+func init() {
+ prometheus.MustRegister(hasLeader)
+ prometheus.MustRegister(isLeader)
+ prometheus.MustRegister(leaderChanges)
+ prometheus.MustRegister(heartbeatSendFailures)
+ prometheus.MustRegister(slowApplies)
+ prometheus.MustRegister(applySnapshotInProgress)
+ prometheus.MustRegister(proposalsCommitted)
+ prometheus.MustRegister(proposalsApplied)
+ prometheus.MustRegister(proposalsPending)
+ prometheus.MustRegister(proposalsFailed)
+ prometheus.MustRegister(slowReadIndex)
+ prometheus.MustRegister(readIndexFailed)
+ prometheus.MustRegister(leaseExpired)
+ prometheus.MustRegister(quotaBackendBytes)
+ prometheus.MustRegister(currentVersion)
+ prometheus.MustRegister(currentGoVersion)
+ prometheus.MustRegister(serverID)
+ prometheus.MustRegister(isLearner)
+ prometheus.MustRegister(learnerPromoteSucceed)
+ prometheus.MustRegister(learnerPromoteFailed)
+ prometheus.MustRegister(fdUsed)
+ prometheus.MustRegister(fdLimit)
+ prometheus.MustRegister(applySec)
+
+ currentVersion.With(prometheus.Labels{
+ "server_version": version.Version,
+ }).Set(1)
+ currentGoVersion.With(prometheus.Labels{
+ "server_go_version": goruntime.Version(),
+ }).Set(1)
+}
+
+func monitorFileDescriptor(lg *zap.Logger, done <-chan struct{}) {
+ // This ticker will check File Descriptor Requirements ,and count all fds in used.
+ // And recorded some logs when in used >= limit/5*4. Just recorded message.
+ // If fds was more than 10K,It's low performance due to FDUsage() works.
+ // So need to increase it.
+ // See https://github.com/etcd-io/etcd/issues/11969 for more detail.
+ ticker := time.NewTicker(10 * time.Minute)
+ defer ticker.Stop()
+ for {
+ used, err := runtime.FDUsage()
+ if err != nil {
+ lg.Warn("failed to get file descriptor usage", zap.Error(err))
+ return
+ }
+ fdUsed.Set(float64(used))
+ limit, err := runtime.FDLimit()
+ if err != nil {
+ lg.Warn("failed to get file descriptor limit", zap.Error(err))
+ return
+ }
+ fdLimit.Set(float64(limit))
+ if used >= limit/5*4 {
+ lg.Warn("80% of file descriptors are used", zap.Uint64("used", used), zap.Uint64("limit", limit))
+ }
+ select {
+ case <-ticker.C:
+ case <-done:
+ return
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/quota.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/quota.go
new file mode 100644
index 0000000000..c5fadc4b1e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/quota.go
@@ -0,0 +1,177 @@
+// 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"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+
+ humanize "github.com/dustin/go-humanize"
+ "go.uber.org/zap"
+)
+
+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
+)
+
+var (
+ // only log once
+ quotaLogOnce sync.Once
+
+ DefaultQuotaSize = humanize.Bytes(uint64(DefaultQuotaBytes))
+ maxQuotaSize = humanize.Bytes(uint64(MaxQuotaBytes))
+)
+
+// NewBackendQuota creates a quota layer with the given storage limit.
+func NewBackendQuota(s *EtcdServer, name string) Quota {
+ lg := s.Logger()
+ quotaBackendBytes.Set(float64(s.Cfg.QuotaBackendBytes))
+
+ if s.Cfg.QuotaBackendBytes < 0 {
+ // disable quotas if negative
+ quotaLogOnce.Do(func() {
+ lg.Info(
+ "disabled backend quota",
+ zap.String("quota-name", name),
+ zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes),
+ )
+ })
+ return &passthroughQuota{}
+ }
+
+ if s.Cfg.QuotaBackendBytes == 0 {
+ // use default size if no quota size given
+ quotaLogOnce.Do(func() {
+ if lg != nil {
+ lg.Info(
+ "enabled backend quota with default value",
+ zap.String("quota-name", name),
+ zap.Int64("quota-size-bytes", DefaultQuotaBytes),
+ zap.String("quota-size", DefaultQuotaSize),
+ )
+ }
+ })
+ quotaBackendBytes.Set(float64(DefaultQuotaBytes))
+ return &backendQuota{s, DefaultQuotaBytes}
+ }
+
+ quotaLogOnce.Do(func() {
+ if s.Cfg.QuotaBackendBytes > MaxQuotaBytes {
+ lg.Warn(
+ "quota exceeds the maximum value",
+ zap.String("quota-name", name),
+ zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes),
+ zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))),
+ zap.Int64("quota-maximum-size-bytes", MaxQuotaBytes),
+ zap.String("quota-maximum-size", maxQuotaSize),
+ )
+ }
+ lg.Info(
+ "enabled backend quota",
+ zap.String("quota-name", name),
+ zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes),
+ zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))),
+ )
+ })
+ return &backendQuota{s, s.Cfg.QuotaBackendBytes}
+}
+
+func (b *backendQuota) Available(v interface{}) bool {
+ cost := b.Cost(v)
+ // if there are no mutating requests, it's safe to pass through
+ if cost == 0 {
+ return true
+ }
+ // TODO: maybe optimize backend.Size()
+ return b.s.Backend().Size()+int64(cost) < 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/go.etcd.io/etcd/server/v3/etcdserver/raft.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/raft.go
new file mode 100644
index 0000000000..949d443c4a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/raft.go
@@ -0,0 +1,736 @@
+// 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"
+ "fmt"
+ "log"
+ "sort"
+ "sync"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/logutil"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/contention"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/config"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
+ "go.etcd.io/etcd/server/v3/wal"
+ "go.etcd.io/etcd/server/v3/wal/walpb"
+ "go.uber.org/zap"
+)
+
+const (
+ // 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() {
+ expvar.Publish("raft.status", expvar.Func(func() interface{} {
+ raftStatusMu.Lock()
+ defer raftStatusMu.Unlock()
+ if raftStatus == nil {
+ return nil
+ }
+ return raftStatus()
+ }))
+}
+
+// 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 {
+ lg *zap.Logger
+
+ 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 {
+ lg *zap.Logger
+
+ // 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 {
+ var lg raft.Logger
+ if cfg.lg != nil {
+ lg = NewRaftLoggerZap(cfg.lg)
+ } else {
+ lcfg := logutil.DefaultZapLoggerConfig
+ var err error
+ lg, err = NewRaftLogger(&lcfg)
+ if err != nil {
+ log.Fatalf("cannot create raft logger %v", err)
+ }
+ }
+ raft.SetLogger(lg)
+ r := &raftNode{
+ lg: cfg.lg,
+ 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 && rh.getLead() != rd.SoftState.Lead
+ if newLeader {
+ leaderChanges.Inc()
+ }
+
+ if rd.SoftState.Lead == raft.None {
+ hasLeader.Set(0)
+ } else {
+ hasLeader.Set(1)
+ }
+
+ rh.updateLead(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):
+ r.lg.Warn("timed out sending read state", zap.Duration("timeout", internalTimeout))
+ case <-r.stopped:
+ return
+ }
+ }
+
+ notifyc := make(chan struct{}, 1)
+ ap := apply{
+ entries: rd.CommittedEntries,
+ snapshot: rd.Snapshot,
+ notifyc: notifyc,
+ }
+
+ updateCommittedIndex(&ap, rh)
+
+ waitWALSync := shouldWaitWALSync(rd)
+ if waitWALSync {
+ // gofail: var raftBeforeSaveWaitWalSync struct{}
+ if err := r.storage.Save(rd.HardState, rd.Entries); err != nil {
+ r.lg.Fatal("failed to save Raft hard state and entries", zap.Error(err))
+ }
+ }
+
+ 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))
+ }
+
+ // Must save the snapshot file and WAL snapshot entry before saving any other entries or hardstate to
+ // ensure that recovery after a snapshot restore is possible.
+ if !raft.IsEmptySnap(rd.Snapshot) {
+ // gofail: var raftBeforeSaveSnap struct{}
+ if err := r.storage.SaveSnap(rd.Snapshot); err != nil {
+ r.lg.Fatal("failed to save Raft snapshot", zap.Error(err))
+ }
+ // gofail: var raftAfterSaveSnap struct{}
+ }
+
+ if !waitWALSync {
+ // gofail: var raftBeforeSave struct{}
+ if err := r.storage.Save(rd.HardState, rd.Entries); err != nil {
+ r.lg.Fatal("failed to save Raft hard state and entries", zap.Error(err))
+ }
+ }
+ if !raft.IsEmptyHardState(rd.HardState) {
+ proposalsCommitted.Set(float64(rd.HardState.Commit))
+ }
+ // gofail: var raftAfterSave struct{}
+
+ if !raft.IsEmptySnap(rd.Snapshot) {
+ // Force WAL to fsync its hard state before Release() releases
+ // old data from the WAL. Otherwise could get an error like:
+ // panic: tocommit(107) is out of range [lastIndex(84)]. Was the raft log corrupted, truncated, or lost?
+ // See https://github.com/etcd-io/etcd/issues/10219 for more details.
+ if err := r.storage.Sync(); err != nil {
+ r.lg.Fatal("failed to sync Raft snapshot", zap.Error(err))
+ }
+
+ // etcdserver now claim the snapshot has been persisted onto the disk
+ notifyc <- struct{}{}
+
+ // gofail: var raftBeforeApplySnap struct{}
+ r.raftStorage.ApplySnapshot(rd.Snapshot)
+ r.lg.Info("applied incoming Raft snapshot", zap.Uint64("snapshot-index", rd.Snapshot.Metadata.Index))
+ // gofail: var raftAfterApplySnap struct{}
+
+ if err := r.storage.Release(rd.Snapshot); err != nil {
+ r.lg.Fatal("failed to release Raft wal", zap.Error(err))
+ }
+ // gofail: var raftAfterWALRelease 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
+ }
+ }
+ }()
+}
+
+// For a cluster with only one member, the raft may send both the
+// unstable entries and committed entries to etcdserver, and there
+// may have overlapped log entries between them.
+//
+// etcd responds to the client once it finishes (actually partially)
+// the applying workflow. But when the client receives the response,
+// it doesn't mean etcd has already successfully saved the data,
+// including BoltDB and WAL, because:
+// 1. etcd commits the boltDB transaction periodically instead of on each request;
+// 2. etcd saves WAL entries in parallel with applying the committed entries.
+//
+// Accordingly, it might run into a situation of data loss when the etcd crashes
+// immediately after responding to the client and before the boltDB and WAL
+// successfully save the data to disk.
+// Note that this issue can only happen for clusters with only one member.
+//
+// For clusters with multiple members, it isn't an issue, because etcd will
+// not commit & apply the data before it being replicated to majority members.
+// When the client receives the response, it means the data must have been applied.
+// It further means the data must have been committed.
+// Note: for clusters with multiple members, the raft will never send identical
+// unstable entries and committed entries to etcdserver.
+//
+// Refer to https://github.com/etcd-io/etcd/issues/14370.
+func shouldWaitWALSync(rd raft.Ready) bool {
+ if len(rd.CommittedEntries) == 0 || len(rd.Entries) == 0 {
+ return false
+ }
+
+ // Check if there is overlap between unstable and committed entries
+ // assuming that their index and term are only incrementing.
+ lastCommittedEntry := rd.CommittedEntries[len(rd.CommittedEntries)-1]
+ firstUnstableEntry := rd.Entries[0]
+ return lastCommittedEntry.Term > firstUnstableEntry.Term ||
+ (lastCommittedEntry.Term == firstUnstableEntry.Term && lastCommittedEntry.Index >= firstUnstableEntry.Index)
+}
+
+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.
+ r.lg.Warn(
+ "leader failed to send out heartbeat on time; took too long, leader is overloaded likely from slow disk",
+ zap.String("to", fmt.Sprintf("%x", ms[i].To)),
+ zap.Duration("heartbeat-interval", r.heartbeat),
+ zap.Duration("expected-duration", 2*r.heartbeat),
+ zap.Duration("exceeded-duration", exceed),
+ )
+ 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 {
+ r.lg.Panic("failed to close Raft storage", zap.Error(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 config.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.Logger, cfg.WALDir(), metadata); err != nil {
+ cfg.Logger.Panic("failed to create WAL", zap.Error(err))
+ }
+ if cfg.UnsafeNoFsync {
+ w.SetUnsafeNoFsync()
+ }
+ peers := make([]raft.Peer, len(ids))
+ for i, id := range ids {
+ var ctx []byte
+ ctx, err = json.Marshal((*cl).Member(id))
+ if err != nil {
+ cfg.Logger.Panic("failed to marshal member", zap.Error(err))
+ }
+ peers[i] = raft.Peer{ID: uint64(id), Context: ctx}
+ }
+ id = member.ID
+ cfg.Logger.Info(
+ "starting local member",
+ zap.String("local-member-id", id.String()),
+ zap.String("cluster-id", cl.ID().String()),
+ )
+ s = raft.NewMemoryStorage()
+ c := &raft.Config{
+ ID: uint64(id),
+ ElectionTick: cfg.ElectionTicks,
+ HeartbeatTick: 1,
+ Storage: s,
+ MaxSizePerMsg: maxSizePerMsg,
+ MaxInflightMsgs: maxInflightMsgs,
+ CheckQuorum: true,
+ PreVote: cfg.PreVote,
+ Logger: NewRaftLoggerZap(cfg.Logger.Named("raft")),
+ }
+ if len(peers) == 0 {
+ n = raft.RestartNode(c)
+ } else {
+ n = raft.StartNode(c, peers)
+ }
+ raftStatusMu.Lock()
+ raftStatus = n.Status
+ raftStatusMu.Unlock()
+ return id, n, s, w
+}
+
+func restartNode(cfg config.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.Logger, cfg.WALDir(), walsnap, cfg.UnsafeNoFsync)
+
+ cfg.Logger.Info(
+ "restarting local member",
+ zap.String("cluster-id", cid.String()),
+ zap.String("local-member-id", id.String()),
+ zap.Uint64("commit-index", st.Commit),
+ )
+ cl := membership.NewCluster(cfg.Logger)
+ cl.SetID(id, 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,
+ PreVote: cfg.PreVote,
+ Logger: NewRaftLoggerZap(cfg.Logger.Named("raft")),
+ }
+
+ n := raft.RestartNode(c)
+ raftStatusMu.Lock()
+ raftStatus = n.Status
+ raftStatusMu.Unlock()
+ return id, cl, n, s, w
+}
+
+func restartAsStandaloneNode(cfg config.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.Logger, cfg.WALDir(), walsnap, cfg.UnsafeNoFsync)
+
+ // discard the previously uncommitted entries
+ for i, ent := range ents {
+ if ent.Index > st.Commit {
+ cfg.Logger.Info(
+ "discarding uncommitted WAL entries",
+ zap.Uint64("entry-index", ent.Index),
+ zap.Uint64("commit-index-from-wal", st.Commit),
+ zap.Int("number-of-discarded-entries", len(ents)-i),
+ )
+ ents = ents[:i]
+ break
+ }
+ }
+
+ // force append the configuration change entries
+ toAppEnts := createConfigChangeEnts(
+ cfg.Logger,
+ getIDs(cfg.Logger, 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 {
+ cfg.Logger.Fatal("failed to save hard state and entries", zap.Error(err))
+ }
+ if len(ents) != 0 {
+ st.Commit = ents[len(ents)-1].Index
+ }
+
+ cfg.Logger.Info(
+ "forcing restart member",
+ zap.String("cluster-id", cid.String()),
+ zap.String("local-member-id", id.String()),
+ zap.Uint64("commit-index", st.Commit),
+ )
+
+ cl := membership.NewCluster(cfg.Logger)
+ cl.SetID(id, 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,
+ PreVote: cfg.PreVote,
+ Logger: NewRaftLoggerZap(cfg.Logger.Named("raft")),
+ }
+
+ 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 three 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.
+// - ConfChangeAddLearnerNode, in which the contained ID will be added into the set.
+func getIDs(lg *zap.Logger, snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 {
+ ids := make(map[uint64]bool)
+ if snap != nil {
+ for _, id := range snap.Metadata.ConfState.Voters {
+ 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.ConfChangeAddLearnerNode:
+ ids[cc.NodeID] = true
+ case raftpb.ConfChangeAddNode:
+ ids[cc.NodeID] = true
+ case raftpb.ConfChangeRemoveNode:
+ delete(ids, cc.NodeID)
+ case raftpb.ConfChangeUpdateNode:
+ // do nothing
+ default:
+ lg.Panic("unknown ConfChange Type", zap.String("type", cc.Type.String()))
+ }
+ }
+ 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(lg *zap.Logger, ids []uint64, self uint64, term, index uint64) []raftpb.Entry {
+ found := false
+ for _, id := range ids {
+ if id == self {
+ found = true
+ }
+ }
+
+ var ents []raftpb.Entry
+ next := index + 1
+
+ // NB: always add self first, then remove other nodes. Raft will panic if the
+ // set of voters ever becomes empty.
+ 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 {
+ lg.Panic("failed to marshal member", zap.Error(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)
+ next++
+ }
+
+ for _, id := range ids {
+ if id == self {
+ 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++
+ }
+
+ return ents
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/server.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/server.go
new file mode 100644
index 0000000000..4e1c2c041a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/server.go
@@ -0,0 +1,2807 @@
+// 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"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/coreos/go-semver/semver"
+ humanize "github.com/dustin/go-humanize"
+ "github.com/prometheus/client_golang/prometheus"
+ "go.etcd.io/etcd/server/v3/config"
+ "go.uber.org/zap"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/membershippb"
+ "go.etcd.io/etcd/api/v3/version"
+ "go.etcd.io/etcd/client/pkg/v3/fileutil"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/idutil"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/pkg/v3/runtime"
+ "go.etcd.io/etcd/pkg/v3/schedule"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/pkg/v3/wait"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver/api"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes"
+ stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor"
+ "go.etcd.io/etcd/server/v3/etcdserver/cindex"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/lease/leasehttp"
+ "go.etcd.io/etcd/server/v3/mvcc"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/wal"
+)
+
+const (
+ DefaultSnapshotCount = 100000
+
+ // DefaultSnapshotCatchUpEntries is the number of entries for a 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.
+ DefaultSnapshotCatchUpEntries uint64 = 5000
+
+ 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
+
+ // 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
+
+ readyPercent = 0.9
+
+ DowngradeEnabledPath = "/downgrade/enabled"
+)
+
+var (
+ // 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
+
+ recommendedMaxRequestBytesString = humanize.Bytes(uint64(recommendedMaxRequestBytes))
+ 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 *v2store.Event
+ Watcher v2store.Watcher
+ Err error
+}
+
+type ServerV2 interface {
+ Server
+ Leader() types.ID
+
+ // 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
+ RaftStatusGetter
+}
+
+func (s *EtcdServer) ClientCertAuthEnabled() bool { return s.Cfg.ClientCertAuthEnabled }
+
+type Server interface {
+ // 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)
+ // PromoteMember attempts to promote a non-voting node to a voting node. It will
+ // return ErrIDNotFound if the member ID does not exist.
+ // return ErrLearnerNotReady if the member are not ready.
+ // return ErrMemberNotLearner if the member is not a learner.
+ PromoteMember(ctx context.Context, id uint64) ([]*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
+
+ // LeaderChangedNotify returns a channel for application level code to be notified
+ // when etcd leader changes, this function is intend to be used only in application
+ // which embed etcd.
+ // Caution:
+ // 1. the returned channel is being closed when the leadership changes.
+ // 2. so the new channel needs to be obtained for each raft term.
+ // 3. user can loose some consecutive channel changes using this API.
+ LeaderChangedNotify() <-chan struct{}
+}
+
+// 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.
+ term uint64 // must use atomic operations to access; keep 64-bit aligned.
+ lead uint64 // must use atomic operations to access; keep 64-bit aligned.
+
+ consistIndex cindex.ConsistentIndexer // consistIndex is used to get/set/save consistentIndex
+ r raftNode // uses 64-bit atomics; keep 64-bit aligned.
+
+ readych chan struct{}
+ Cfg config.ServerConfig
+
+ lgMu *sync.RWMutex
+ lg *zap.Logger
+
+ 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{}
+ // leaderChanged is used to notify the linearizable read loop to drop the old read requests.
+ leaderChanged chan struct{}
+ leaderChangedMu sync.RWMutex
+
+ errorc chan error
+ id types.ID
+ attributes membership.Attributes
+
+ cluster *membership.RaftCluster
+
+ v2store v2store.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
+ // applyV3Internal is the applier for internal request
+ applyV3Internal applierV3Internal
+ applyWait wait.WaitTime
+
+ kv mvcc.WatchableKV
+ lessor lease.Lessor
+ bemu sync.Mutex
+ be backend.Backend
+ beHooks *backendHooks
+ authStore auth.AuthStore
+ alarmStore *v3alarm.AlarmStore
+
+ stats *stats.ServerStats
+ lstats *stats.LeaderStats
+
+ SyncTicker *time.Ticker
+ // compactor is used to auto-compact the KV.
+ compactor v3compactor.Compactor
+
+ // peerRt used to send requests (version, lease) to peers.
+ peerRt http.RoundTripper
+ reqIDGen *idutil.Generator
+
+ // wgMu blocks concurrent waitgroup mutation while server stopping
+ wgMu sync.RWMutex
+ // wg is used to wait for the goroutines 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
+
+ firstCommitInTermMu sync.RWMutex
+ firstCommitInTermC chan struct{}
+
+ *AccessController
+ corruptionChecker CorruptionChecker
+}
+
+type backendHooks struct {
+ indexer cindex.ConsistentIndexer
+ lg *zap.Logger
+
+ // confState to be written in the next submitted backend transaction (if dirty)
+ confState raftpb.ConfState
+ // first write changes it to 'dirty'. false by default, so
+ // not initialized `confState` is meaningless.
+ confStateDirty bool
+ confStateLock sync.Mutex
+}
+
+func (bh *backendHooks) OnPreCommitUnsafe(tx backend.BatchTx) {
+ bh.indexer.UnsafeSave(tx)
+ bh.confStateLock.Lock()
+ defer bh.confStateLock.Unlock()
+ if bh.confStateDirty {
+ membership.MustUnsafeSaveConfStateToBackend(bh.lg, tx, &bh.confState)
+ // save bh.confState
+ bh.confStateDirty = false
+ }
+}
+
+func (bh *backendHooks) SetConfState(confState *raftpb.ConfState) {
+ bh.confStateLock.Lock()
+ defer bh.confStateLock.Unlock()
+ bh.confState = *confState
+ bh.confStateDirty = true
+}
+
+// NewServer creates a new EtcdServer from the supplied configuration. The
+// configuration is considered static for the lifetime of the EtcdServer.
+func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) {
+ st := v2store.New(StoreClusterPrefix, StoreKeysPrefix)
+
+ var (
+ w *wal.WAL
+ n raft.Node
+ s *raft.MemoryStorage
+ id types.ID
+ cl *membership.RaftCluster
+ )
+
+ if cfg.MaxRequestBytes > recommendedMaxRequestBytes {
+ cfg.Logger.Warn(
+ "exceeded recommended request limit",
+ zap.Uint("max-request-bytes", cfg.MaxRequestBytes),
+ zap.String("max-request-size", humanize.Bytes(uint64(cfg.MaxRequestBytes))),
+ zap.Int("recommended-request-bytes", recommendedMaxRequestBytes),
+ zap.String("recommended-request-size", recommendedMaxRequestBytesString),
+ )
+ }
+
+ if terr := fileutil.TouchDirAll(cfg.Logger, cfg.DataDir); terr != nil {
+ return nil, fmt.Errorf("cannot access data directory: %v", terr)
+ }
+
+ haveWAL := wal.Exist(cfg.WALDir())
+
+ if err = fileutil.TouchDirAll(cfg.Logger, cfg.SnapDir()); err != nil {
+ cfg.Logger.Fatal(
+ "failed to create snapshot directory",
+ zap.String("path", cfg.SnapDir()),
+ zap.Error(err),
+ )
+ }
+
+ if err = fileutil.RemoveMatchFile(cfg.Logger, cfg.SnapDir(), func(fileName string) bool {
+ return strings.HasPrefix(fileName, "tmp")
+ }); err != nil {
+ cfg.Logger.Error(
+ "failed to remove temp file(s) in snapshot directory",
+ zap.String("path", cfg.SnapDir()),
+ zap.Error(err),
+ )
+ }
+
+ ss := snap.New(cfg.Logger, cfg.SnapDir())
+
+ bepath := cfg.BackendPath()
+ beExist := fileutil.Exist(bepath)
+
+ ci := cindex.NewConsistentIndex(nil)
+ beHooks := &backendHooks{lg: cfg.Logger, indexer: ci}
+ be := openBackend(cfg, beHooks)
+ ci.SetBackend(be)
+ cindex.CreateMetaBucket(be.BatchTx())
+
+ if cfg.ExperimentalBootstrapDefragThresholdMegabytes != 0 {
+ err := maybeDefragBackend(cfg, be)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ 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.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap)
+ if err != nil {
+ return nil, err
+ }
+ existingCluster, gerr := GetClusterFromRemotePeers(cfg.Logger, 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(cfg.Logger, cl, existingCluster); err != nil {
+ return nil, fmt.Errorf("error validating peerURLs %s: %v", existingCluster, err)
+ }
+ if !isCompatibleWithCluster(cfg.Logger, cl, cl.MemberByName(cfg.Name).ID, prt) {
+ return nil, fmt.Errorf("incompatible with current running cluster")
+ }
+
+ remotes = existingCluster.Members()
+ cl.SetID(types.ID(0), existingCluster.ID())
+ cl.SetStore(st)
+ cl.SetBackend(be)
+ id, n, s, w = startNode(cfg, cl, nil)
+ cl.SetID(id, existingCluster.ID())
+
+ case !haveWAL && cfg.NewCluster:
+ if err = cfg.VerifyBootstrap(); err != nil {
+ return nil, err
+ }
+ cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap)
+ if err != nil {
+ return nil, err
+ }
+ m := cl.MemberByName(cfg.Name)
+ if isMemberBootstrapped(cfg.Logger, cl, cfg.Name, prt, cfg.BootstrapTimeoutEffective()) {
+ return nil, fmt.Errorf("member %s has already been bootstrapped", m.ID)
+ }
+ if cfg.ShouldDiscover() {
+ var str string
+ str, err = v2discovery.JoinCluster(cfg.Logger, 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 config.CheckDuplicateURL(urlsmap) {
+ return nil, fmt.Errorf("discovery cluster %s has duplicate url", urlsmap)
+ }
+ if cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, urlsmap); err != nil {
+ return nil, err
+ }
+ }
+ cl.SetStore(st)
+ cl.SetBackend(be)
+ id, n, s, w = startNode(cfg, cl, cl.MemberIDs())
+ cl.SetID(id, cl.ID())
+
+ 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() {
+ cfg.Logger.Warn(
+ "discovery token is ignored since cluster already initialized; valid logs are found",
+ zap.String("wal-dir", cfg.WALDir()),
+ )
+ }
+
+ // Find a snapshot to start/restart a raft node
+ walSnaps, err := wal.ValidSnapshotEntries(cfg.Logger, cfg.WALDir())
+ if err != nil {
+ return nil, err
+ }
+ // snapshot files can be orphaned if etcd crashes after writing them but before writing the corresponding
+ // wal log entries
+ snapshot, err := ss.LoadNewestAvailable(walSnaps)
+ if err != nil && err != snap.ErrNoSnapshot {
+ return nil, err
+ }
+
+ if snapshot != nil {
+ if err = st.Recovery(snapshot.Data); err != nil {
+ cfg.Logger.Panic("failed to recover from snapshot", zap.Error(err))
+ }
+
+ if err = assertNoV2StoreContent(cfg.Logger, st, cfg.V2Deprecation); err != nil {
+ cfg.Logger.Error("illegal v2store content", zap.Error(err))
+ return nil, err
+ }
+
+ cfg.Logger.Info(
+ "recovered v2 store from snapshot",
+ zap.Uint64("snapshot-index", snapshot.Metadata.Index),
+ zap.String("snapshot-size", humanize.Bytes(uint64(snapshot.Size()))),
+ )
+
+ if be, err = recoverSnapshotBackend(cfg, be, *snapshot, beExist, beHooks); err != nil {
+ cfg.Logger.Panic("failed to recover v3 backend from snapshot", zap.Error(err))
+ }
+ // A snapshot db may have already been recovered, and the old db should have
+ // already been closed in this case, so we should set the backend again.
+ ci.SetBackend(be)
+ s1, s2 := be.Size(), be.SizeInUse()
+ cfg.Logger.Info(
+ "recovered v3 backend from snapshot",
+ zap.Int64("backend-size-bytes", s1),
+ zap.String("backend-size", humanize.Bytes(uint64(s1))),
+ zap.Int64("backend-size-in-use-bytes", s2),
+ zap.String("backend-size-in-use", humanize.Bytes(uint64(s2))),
+ )
+ } else {
+ cfg.Logger.Info("No snapshot found. Recovering WAL from scratch!")
+ }
+
+ 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.Logger, cfg.MemberDir()); terr != nil {
+ return nil, fmt.Errorf("cannot access member directory: %v", terr)
+ }
+
+ sstats := stats.NewServerStats(cfg.Name, id.String())
+ lstats := stats.NewLeaderStats(cfg.Logger, id.String())
+
+ heartbeat := time.Duration(cfg.TickMs) * time.Millisecond
+ srv = &EtcdServer{
+ readych: make(chan struct{}),
+ Cfg: cfg,
+ lgMu: new(sync.RWMutex),
+ lg: cfg.Logger,
+ errorc: make(chan error, 1),
+ v2store: st,
+ snapshotter: ss,
+ r: *newRaftNode(
+ raftNodeConfig{
+ lg: cfg.Logger,
+ 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()),
+ AccessController: &AccessController{CORS: cfg.CORS, HostWhitelist: cfg.HostWhitelist},
+ consistIndex: ci,
+ firstCommitInTermC: make(chan struct{}),
+ }
+ serverID.With(prometheus.Labels{"server_id": id.String()}).Set(1)
+
+ srv.applyV2 = NewApplierV2(cfg.Logger, srv.v2store, srv.cluster)
+
+ srv.be = be
+ srv.beHooks = beHooks
+ 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.Logger(), srv.be, srv.cluster, lease.LessorConfig{
+ MinLeaseTTL: int64(math.Ceil(minTTL.Seconds())),
+ CheckpointInterval: cfg.LeaseCheckpointInterval,
+ CheckpointPersist: cfg.LeaseCheckpointPersist,
+ ExpiredLeasesRetryInterval: srv.Cfg.ReqTimeout(),
+ })
+
+ tp, err := auth.NewTokenProvider(cfg.Logger, cfg.AuthToken,
+ func(index uint64) <-chan struct{} {
+ return srv.applyWait.Wait(index)
+ },
+ time.Duration(cfg.TokenTTL)*time.Second,
+ )
+ if err != nil {
+ cfg.Logger.Warn("failed to create token provider", zap.Error(err))
+ return nil, err
+ }
+ srv.kv = mvcc.New(srv.Logger(), srv.be, srv.lessor, mvcc.StoreConfig{CompactionBatchLimit: cfg.CompactionBatchLimit})
+
+ kvindex := ci.ConsistentIndex()
+ srv.lg.Debug("restore consistentIndex", zap.Uint64("index", kvindex))
+ if beExist {
+ // 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)
+ }
+ cfg.Logger.Warn(
+ "consistent index was never saved",
+ zap.Uint64("snapshot-index", snapshot.Metadata.Index),
+ )
+ }
+ }
+ srv.corruptionChecker = newCorruptionChecker(cfg.Logger, srv, srv.kv.HashStorage())
+
+ srv.authStore = auth.NewAuthStore(srv.Logger(), srv.be, tp, int(cfg.BcryptCost))
+
+ 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()
+ }
+ }()
+ if num := cfg.AutoCompactionRetention; num != 0 {
+ srv.compactor, err = v3compactor.New(cfg.Logger, cfg.AutoCompactionMode, num, srv.kv, srv)
+ if err != nil {
+ return nil, err
+ }
+ srv.compactor.Run()
+ }
+
+ srv.applyV3Base = srv.newApplierV3Backend()
+ srv.applyV3Internal = srv.newApplierV3Internal()
+ if err = srv.restoreAlarms(); err != nil {
+ return nil, err
+ }
+
+ if srv.Cfg.EnableLeaseCheckpoint {
+ // setting checkpointer enables lease checkpoint feature.
+ srv.lessor.SetCheckpointer(func(ctx context.Context, cp *pb.LeaseCheckpointRequest) {
+ srv.raftRequestOnce(ctx, pb.InternalRaftRequest{LeaseCheckpoint: cp})
+ })
+ }
+
+ // Set the hook after EtcdServer finishes the initialization to avoid
+ // the hook being called during the initialization process.
+ srv.be.SetTxPostLockInsideApplyHook(srv.getTxPostLockInsideApplyHook())
+
+ // TODO: move transport initialization near the definition of remote
+ tr := &rafthttp.Transport{
+ Logger: cfg.Logger,
+ 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
+}
+
+// assertNoV2StoreContent -> depending on the deprecation stage, warns or report an error
+// if the v2store contains custom content.
+func assertNoV2StoreContent(lg *zap.Logger, st v2store.Store, deprecationStage config.V2DeprecationEnum) error {
+ metaOnly, err := membership.IsMetaStoreOnly(st)
+ if err != nil {
+ return err
+ }
+ if metaOnly {
+ return nil
+ }
+ if deprecationStage.IsAtLeast(config.V2_DEPR_1_WRITE_ONLY) {
+ return fmt.Errorf("detected disallowed custom content in v2store for stage --v2-deprecation=%s", deprecationStage)
+ }
+ lg.Warn("detected custom v2store content. Etcd v3.5 is the last version allowing to access it using API v2. Please remove the content.")
+ return nil
+}
+
+func (s *EtcdServer) Logger() *zap.Logger {
+ s.lgMu.RLock()
+ l := s.lg
+ s.lgMu.RUnlock()
+ return l
+}
+
+func tickToDur(ticks int, tickMs uint) string {
+ return fmt.Sprintf("%v", time.Duration(ticks)*time.Duration(tickMs)*time.Millisecond)
+}
+
+func (s *EtcdServer) adjustTicks() {
+ lg := s.Logger()
+ clusterN := len(s.cluster.Members())
+
+ // single-node fresh start, or single-node recovers from snapshot
+ if clusterN == 1 {
+ ticks := s.Cfg.ElectionTicks - 1
+ lg.Info(
+ "started as single-node; fast-forwarding election ticks",
+ zap.String("local-member-id", s.ID().String()),
+ zap.Int("forward-ticks", ticks),
+ zap.String("forward-duration", tickToDur(ticks, s.Cfg.TickMs)),
+ zap.Int("election-ticks", s.Cfg.ElectionTicks),
+ zap.String("election-timeout", tickToDur(s.Cfg.ElectionTicks, s.Cfg.TickMs)),
+ )
+ s.r.advanceTicks(ticks)
+ return
+ }
+
+ if !s.Cfg.InitialElectionTickAdvance {
+ lg.Info("skipping initial election tick advance", zap.Int("election-ticks", s.Cfg.ElectionTicks))
+ return
+ }
+ lg.Info("starting initial election tick advance", zap.Int("election-ticks", s.Cfg.ElectionTicks))
+
+ // 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
+
+ lg.Info(
+ "initialized peer connections; fast-forwarding election ticks",
+ zap.String("local-member-id", s.ID().String()),
+ zap.Int("forward-ticks", ticks),
+ zap.String("forward-duration", tickToDur(ticks, s.Cfg.TickMs)),
+ zap.Int("election-ticks", s.Cfg.ElectionTicks),
+ zap.String("election-timeout", tickToDur(s.Cfg.ElectionTicks, s.Cfg.TickMs)),
+ zap.Int("active-remote-members", 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() })
+ // TODO: Switch to publishV3 in 3.6.
+ // Support for cluster_member_set_attr was added in 3.5.
+ s.GoAttach(func() { s.publish(s.Cfg.ReqTimeout()) })
+ s.GoAttach(s.purgeFile)
+ s.GoAttach(func() { monitorFileDescriptor(s.Logger(), s.stopping) })
+ s.GoAttach(s.monitorVersions)
+ s.GoAttach(s.linearizableReadLoop)
+ s.GoAttach(s.monitorKVHash)
+ s.GoAttach(s.monitorCompactHash)
+ s.GoAttach(s.monitorDowngrade)
+}
+
+// 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() {
+ lg := s.Logger()
+
+ if s.Cfg.SnapshotCount == 0 {
+ lg.Info(
+ "updating snapshot-count to default",
+ zap.Uint64("given-snapshot-count", s.Cfg.SnapshotCount),
+ zap.Uint64("updated-snapshot-count", DefaultSnapshotCount),
+ )
+ s.Cfg.SnapshotCount = DefaultSnapshotCount
+ }
+ if s.Cfg.SnapshotCatchUpEntries == 0 {
+ lg.Info(
+ "updating snapshot catch-up entries to default",
+ zap.Uint64("given-snapshot-catchup-entries", s.Cfg.SnapshotCatchUpEntries),
+ zap.Uint64("updated-snapshot-catchup-entries", DefaultSnapshotCatchUpEntries),
+ )
+ s.Cfg.SnapshotCatchUpEntries = DefaultSnapshotCatchUpEntries
+ }
+
+ s.w = wait.New()
+ s.applyWait = wait.NewTimeList()
+ s.done = make(chan struct{})
+ s.stop = make(chan struct{})
+ s.stopping = make(chan struct{}, 1)
+ s.ctx, s.cancel = context.WithCancel(context.Background())
+ s.readwaitc = make(chan struct{}, 1)
+ s.readNotifier = newNotifier()
+ s.leaderChanged = make(chan struct{})
+ if s.ClusterVersion() != nil {
+ lg.Info(
+ "starting etcd server",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-server-version", version.Version),
+ zap.String("cluster-id", s.Cluster().ID().String()),
+ zap.String("cluster-version", version.Cluster(s.ClusterVersion().String())),
+ )
+ membership.ClusterVersionMetrics.With(prometheus.Labels{"cluster_version": version.Cluster(s.ClusterVersion().String())}).Set(1)
+ } else {
+ lg.Info(
+ "starting etcd server",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-server-version", version.Version),
+ zap.String("cluster-version", "to_be_decided"),
+ )
+ }
+
+ // TODO: if this is an empty log, writes all peer infos
+ // into the first entry
+ go s.run()
+}
+
+func (s *EtcdServer) purgeFile() {
+ lg := s.Logger()
+ var dberrc, serrc, werrc <-chan error
+ var dbdonec, sdonec, wdonec <-chan struct{}
+ if s.Cfg.MaxSnapFiles > 0 {
+ dbdonec, dberrc = fileutil.PurgeFileWithDoneNotify(lg, s.Cfg.SnapDir(), "snap.db", s.Cfg.MaxSnapFiles, purgeFileInterval, s.stopping)
+ sdonec, serrc = fileutil.PurgeFileWithDoneNotify(lg, s.Cfg.SnapDir(), "snap", s.Cfg.MaxSnapFiles, purgeFileInterval, s.stopping)
+ }
+ if s.Cfg.MaxWALFiles > 0 {
+ wdonec, werrc = fileutil.PurgeFileWithDoneNotify(lg, s.Cfg.WALDir(), "wal", s.Cfg.MaxWALFiles, purgeFileInterval, s.stopping)
+ }
+
+ select {
+ case e := <-dberrc:
+ lg.Fatal("failed to purge snap db file", zap.Error(e))
+ case e := <-serrc:
+ lg.Fatal("failed to purge snap file", zap.Error(e))
+ case e := <-werrc:
+ lg.Fatal("failed to purge wal file", zap.Error(e))
+ case <-s.stopping:
+ if dbdonec != nil {
+ <-dbdonec
+ }
+ if sdonec != nil {
+ <-sdonec
+ }
+ if wdonec != nil {
+ <-wdonec
+ }
+ return
+ }
+}
+
+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() }
+
+type ServerPeerV2 interface {
+ ServerPeer
+ HashKVHandler() http.Handler
+ DowngradeEnabledHandler() http.Handler
+}
+
+func (s *EtcdServer) DowngradeInfo() *membership.DowngradeInfo { return s.cluster.DowngradeInfo() }
+
+type downgradeEnabledHandler struct {
+ lg *zap.Logger
+ cluster api.Cluster
+ server *EtcdServer
+}
+
+func (s *EtcdServer) DowngradeEnabledHandler() http.Handler {
+ return &downgradeEnabledHandler{
+ lg: s.Logger(),
+ cluster: s.cluster,
+ server: s,
+ }
+}
+
+func (h *downgradeEnabledHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodGet {
+ w.Header().Set("Allow", http.MethodGet)
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String())
+
+ if r.URL.Path != DowngradeEnabledPath {
+ http.Error(w, "bad path", http.StatusBadRequest)
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), h.server.Cfg.ReqTimeout())
+ defer cancel()
+
+ // serve with linearized downgrade info
+ if err := h.server.linearizableReadNotify(ctx); err != nil {
+ http.Error(w, fmt.Sprintf("failed linearized read: %v", err),
+ http.StatusInternalServerError)
+ return
+ }
+ enabled := h.server.DowngradeInfo().Enabled
+ w.Header().Set("Content-Type", "text/plain")
+ w.Write([]byte(strconv.FormatBool(enabled)))
+}
+
+// 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 {
+ lg := s.Logger()
+ if s.cluster.IsIDRemoved(types.ID(m.From)) {
+ lg.Warn(
+ "rejected Raft message from removed member",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("removed-member-id", 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 {
+ getLead func() (lead uint64)
+ updateLead func(lead uint64)
+ updateLeadership func(newLeader bool)
+ updateCommittedIndex func(uint64)
+}
+
+func (s *EtcdServer) run() {
+ lg := s.Logger()
+
+ sn, err := s.r.raftStorage.Snapshot()
+ if err != nil {
+ lg.Panic("failed to get snapshot from Raft storage", zap.Error(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{
+ getLead: func() (lead uint64) { return s.getLead() },
+ updateLead: func(lead uint64) { s.setLead(lead) },
+ 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()
+ }
+ }
+ if newLeader {
+ s.leaderChangedMu.Lock()
+ lc := s.leaderChanged
+ s.leaderChanged = make(chan struct{})
+ close(lc)
+ s.leaderChangedMu.Unlock()
+ }
+ // 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()
+
+ s.Cleanup()
+
+ 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.revokeExpiredLeases(leases)
+ case err := <-s.errorc:
+ lg.Warn("server error", zap.Error(err))
+ lg.Warn("data-dir used by this member must be removed")
+ return
+ case <-getSyncC():
+ if s.v2store.HasTTLKeys() {
+ s.sync(s.Cfg.ReqTimeout())
+ }
+ case <-s.stop:
+ return
+ }
+ }
+}
+
+func (s *EtcdServer) revokeExpiredLeases(leases []*lease.Lease) {
+ s.GoAttach(func() {
+ lg := s.Logger()
+ // Increases throughput of expired leases deletion process through parallelization
+ c := make(chan struct{}, maxPendingRevokes)
+ for _, curLease := range leases {
+ select {
+ case c <- struct{}{}:
+ case <-s.stopping:
+ return
+ }
+
+ f := func(lid int64) {
+ s.GoAttach(func() {
+ ctx := s.authStore.WithRoot(s.ctx)
+ _, lerr := s.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: lid})
+ if lerr == nil {
+ leaseExpired.Inc()
+ } else {
+ lg.Warn(
+ "failed to revoke lease",
+ zap.String("lease-id", fmt.Sprintf("%016x", lid)),
+ zap.Error(lerr),
+ )
+ }
+
+ <-c
+ })
+ }
+
+ f(int64(curLease.ID))
+ }
+ })
+}
+
+// Cleanup removes allocated objects by EtcdServer.NewServer in
+// situation that EtcdServer::Start was not called (that takes care of cleanup).
+func (s *EtcdServer) Cleanup() {
+ // 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()
+ }
+}
+
+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
+ }
+ applySnapshotInProgress.Inc()
+
+ lg := s.Logger()
+ lg.Info(
+ "applying snapshot",
+ zap.Uint64("current-snapshot-index", ep.snapi),
+ zap.Uint64("current-applied-index", ep.appliedi),
+ zap.Uint64("incoming-leader-snapshot-index", apply.snapshot.Metadata.Index),
+ zap.Uint64("incoming-leader-snapshot-term", apply.snapshot.Metadata.Term),
+ )
+ defer func() {
+ lg.Info(
+ "applied snapshot",
+ zap.Uint64("current-snapshot-index", ep.snapi),
+ zap.Uint64("current-applied-index", ep.appliedi),
+ zap.Uint64("incoming-leader-snapshot-index", apply.snapshot.Metadata.Index),
+ zap.Uint64("incoming-leader-snapshot-term", apply.snapshot.Metadata.Term),
+ )
+ applySnapshotInProgress.Dec()
+ }()
+
+ if apply.snapshot.Metadata.Index <= ep.appliedi {
+ lg.Panic(
+ "unexpected leader snapshot from outdated index",
+ zap.Uint64("current-snapshot-index", ep.snapi),
+ zap.Uint64("current-applied-index", ep.appliedi),
+ zap.Uint64("incoming-leader-snapshot-index", apply.snapshot.Metadata.Index),
+ zap.Uint64("incoming-leader-snapshot-term", apply.snapshot.Metadata.Term),
+ )
+ }
+
+ // wait for raftNode to persist snapshot onto the disk
+ <-apply.notifyc
+
+ newbe, err := openSnapshotBackend(s.Cfg, s.snapshotter, apply.snapshot, s.beHooks)
+ if err != nil {
+ lg.Panic("failed to open snapshot backend", zap.Error(err))
+ }
+
+ // We need to set the backend to consistIndex before recovering the lessor,
+ // because lessor.Recover will commit the boltDB transaction, accordingly it
+ // will get the old consistent_index persisted into the db in OnPreCommitUnsafe.
+ // Eventually the new consistent_index value coming from snapshot is overwritten
+ // by the old value.
+ s.consistIndex.SetBackend(newbe)
+
+ // 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 {
+ lg.Info("restoring lease store")
+
+ s.lessor.Recover(newbe, func() lease.TxnDelete { return s.kv.Write(traceutil.TODO()) })
+
+ lg.Info("restored lease store")
+ }
+
+ lg.Info("restoring mvcc store")
+
+ if err := s.kv.Restore(newbe); err != nil {
+ lg.Panic("failed to restore mvcc store", zap.Error(err))
+ }
+
+ newbe.SetTxPostLockInsideApplyHook(s.getTxPostLockInsideApplyHook())
+ lg.Info("restored mvcc store", zap.Uint64("consistent-index", s.consistIndex.ConsistentIndex()))
+
+ // 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() {
+ lg.Info("closing old backend file")
+ defer func() {
+ lg.Info("closed old backend file")
+ }()
+ if err := oldbe.Close(); err != nil {
+ lg.Panic("failed to close old backend", zap.Error(err))
+ }
+ }()
+
+ s.be = newbe
+ s.bemu.Unlock()
+
+ lg.Info("restoring alarm store")
+
+ if err := s.restoreAlarms(); err != nil {
+ lg.Panic("failed to restore alarm store", zap.Error(err))
+ }
+
+ lg.Info("restored alarm store")
+
+ if s.authStore != nil {
+ lg.Info("restoring auth store")
+
+ s.authStore.Recover(newbe)
+
+ lg.Info("restored auth store")
+ }
+
+ lg.Info("restoring v2 store")
+ if err := s.v2store.Recovery(apply.snapshot.Data); err != nil {
+ lg.Panic("failed to restore v2 store", zap.Error(err))
+ }
+
+ if err := assertNoV2StoreContent(lg, s.v2store, s.Cfg.V2Deprecation); err != nil {
+ lg.Panic("illegal v2store content", zap.Error(err))
+ }
+
+ lg.Info("restored v2 store")
+
+ s.cluster.SetBackend(newbe)
+
+ lg.Info("restoring cluster configuration")
+
+ s.cluster.Recover(api.UpdateCapability)
+
+ lg.Info("restored cluster configuration")
+ lg.Info("removing old peers from network")
+
+ // recover raft transport
+ s.r.transport.RemoveAllPeers()
+
+ lg.Info("removed old peers from network")
+ lg.Info("adding peers from new cluster configuration")
+
+ for _, m := range s.cluster.Members() {
+ if m.ID == s.ID() {
+ continue
+ }
+ s.r.transport.AddPeer(m.ID, m.PeerURLs)
+ }
+
+ lg.Info("added peers from new cluster configuration")
+
+ 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 {
+ lg := s.Logger()
+ lg.Panic(
+ "unexpected committed entry index",
+ zap.Uint64("current-applied-index", ep.appliedi),
+ zap.Uint64("first-committed-entry-index", firsti),
+ )
+ }
+ 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.SnapshotCount {
+ return
+ }
+
+ lg := s.Logger()
+ lg.Info(
+ "triggering snapshot",
+ zap.String("local-member-id", s.ID().String()),
+ zap.Uint64("local-member-applied-index", ep.appliedi),
+ zap.Uint64("local-member-snapshot-index", ep.snapi),
+ zap.Uint64("local-member-snapshot-count", s.Cfg.SnapshotCount),
+ )
+
+ s.snapshot(ep.appliedi, ep.confState)
+ ep.snapi = ep.appliedi
+}
+
+func (s *EtcdServer) hasMultipleVotingMembers() bool {
+ return s.cluster != nil && len(s.cluster.VotingMemberIDs()) > 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 {
+ if !s.cluster.IsMemberExist(types.ID(transferee)) || s.cluster.Member(types.ID(transferee)).IsLearner {
+ return ErrBadLeaderTransferee
+ }
+
+ now := time.Now()
+ interval := time.Duration(s.Cfg.TickMs) * time.Millisecond
+
+ lg := s.Logger()
+ lg.Info(
+ "leadership transfer starting",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("current-leader-member-id", types.ID(lead).String()),
+ zap.String("transferee-member-id", types.ID(transferee).String()),
+ )
+
+ 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
+ lg.Info(
+ "leadership transfer finished",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("old-leader-member-id", types.ID(lead).String()),
+ zap.String("new-leader-member-id", types.ID(transferee).String()),
+ zap.Duration("took", time.Since(now)),
+ )
+ return nil
+}
+
+// TransferLeadership transfers the leader to the chosen transferee.
+func (s *EtcdServer) TransferLeadership() error {
+ lg := s.Logger()
+ if !s.isLeader() {
+ lg.Info(
+ "skipped leadership transfer; local server is not leader",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("current-leader-member-id", types.ID(s.Lead()).String()),
+ )
+ return nil
+ }
+
+ if !s.hasMultipleVotingMembers() {
+ lg.Info(
+ "skipped leadership transfer for single voting member cluster",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("current-leader-member-id", types.ID(s.Lead()).String()),
+ )
+ return nil
+ }
+
+ transferee, ok := longestConnected(s.r.transport, s.cluster.VotingMemberIDs())
+ 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() {
+ lg := s.Logger()
+ if err := s.TransferLeadership(); err != nil {
+ lg.Warn("leadership transfer failed", zap.String("local-member-id", s.ID().String()), zap.Error(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 }
+
+// StoppingNotify returns a channel that receives a empty struct
+// when the server is being stopped.
+func (s *EtcdServer) StoppingNotify() <-chan struct{} { return s.stopping }
+
+func (s *EtcdServer) SelfStats() []byte { return s.stats.JSON() }
+
+func (s *EtcdServer) LeaderStats() []byte {
+ lead := s.getLead()
+ if lead != uint64(s.id) {
+ return nil
+ }
+ return s.lstats.JSON()
+}
+
+func (s *EtcdServer) StoreStats() []byte { return s.v2store.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
+ }
+
+ // TODO: move Member to protobuf type
+ b, err := json.Marshal(memb)
+ if err != nil {
+ return nil, err
+ }
+
+ // by default StrictReconfigCheck is enabled; reject new members if unhealthy.
+ if err := s.mayAddMember(memb); err != nil {
+ return nil, err
+ }
+
+ cc := raftpb.ConfChange{
+ Type: raftpb.ConfChangeAddNode,
+ NodeID: uint64(memb.ID),
+ Context: b,
+ }
+
+ if memb.IsLearner {
+ cc.Type = raftpb.ConfChangeAddLearnerNode
+ }
+
+ return s.configure(ctx, cc)
+}
+
+func (s *EtcdServer) mayAddMember(memb membership.Member) error {
+ lg := s.Logger()
+ if !s.Cfg.StrictReconfigCheck {
+ return nil
+ }
+
+ // protect quorum when adding voting member
+ if !memb.IsLearner && !s.cluster.IsReadyToAddVotingMember() {
+ lg.Warn(
+ "rejecting member add request; not enough healthy members",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("requested-member-add", fmt.Sprintf("%+v", memb)),
+ zap.Error(ErrNotEnoughStartedMembers),
+ )
+ return ErrNotEnoughStartedMembers
+ }
+
+ if !isConnectedFullySince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), s.cluster.VotingMembers()) {
+ lg.Warn(
+ "rejecting member add request; local member has not been connected to all peers, reconfigure breaks active quorum",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("requested-member-add", fmt.Sprintf("%+v", memb)),
+ zap.Error(ErrUnhealthy),
+ )
+ return ErrUnhealthy
+ }
+
+ return nil
+}
+
+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)
+}
+
+// PromoteMember promotes a learner node to a voting node.
+func (s *EtcdServer) PromoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) {
+ // only raft leader has information on whether the to-be-promoted learner node is ready. If promoteMember call
+ // fails with ErrNotLeader, forward the request to leader node via HTTP. If promoteMember call fails with error
+ // other than ErrNotLeader, return the error.
+ resp, err := s.promoteMember(ctx, id)
+ if err == nil {
+ learnerPromoteSucceed.Inc()
+ return resp, nil
+ }
+ if err != ErrNotLeader {
+ learnerPromoteFailed.WithLabelValues(err.Error()).Inc()
+ return resp, err
+ }
+
+ 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 {
+ resp, err := promoteMemberHTTP(cctx, url, id, s.peerRt)
+ if err == nil {
+ return resp, nil
+ }
+ // If member promotion failed, return early. Otherwise keep retry.
+ if err == ErrLearnerNotReady || err == membership.ErrIDNotFound || err == membership.ErrMemberNotLearner {
+ return nil, err
+ }
+ }
+ }
+
+ if cctx.Err() == context.DeadlineExceeded {
+ return nil, ErrTimeout
+ }
+ return nil, ErrCanceled
+}
+
+// promoteMember checks whether the to-be-promoted learner node is ready before sending the promote
+// request to raft.
+// The function returns ErrNotLeader if the local node is not raft leader (therefore does not have
+// enough information to determine if the learner node is ready), returns ErrLearnerNotReady if the
+// local node is leader (therefore has enough information) but decided the learner node is not ready
+// to be promoted.
+func (s *EtcdServer) promoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) {
+ if err := s.checkMembershipOperationPermission(ctx); err != nil {
+ return nil, err
+ }
+
+ // check if we can promote this learner.
+ if err := s.mayPromoteMember(types.ID(id)); err != nil {
+ return nil, err
+ }
+
+ // build the context for the promote confChange. mark IsLearner to false and IsPromote to true.
+ promoteChangeContext := membership.ConfigChangeContext{
+ Member: membership.Member{
+ ID: types.ID(id),
+ },
+ IsPromote: true,
+ }
+
+ b, err := json.Marshal(promoteChangeContext)
+ if err != nil {
+ return nil, err
+ }
+
+ cc := raftpb.ConfChange{
+ Type: raftpb.ConfChangeAddNode,
+ NodeID: id,
+ Context: b,
+ }
+
+ return s.configure(ctx, cc)
+}
+
+func (s *EtcdServer) mayPromoteMember(id types.ID) error {
+ lg := s.Logger()
+ err := s.isLearnerReady(uint64(id))
+ if err != nil {
+ return err
+ }
+
+ if !s.Cfg.StrictReconfigCheck {
+ return nil
+ }
+ if !s.cluster.IsReadyToPromoteMember(uint64(id)) {
+ lg.Warn(
+ "rejecting member promote request; not enough healthy members",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("requested-member-remove-id", id.String()),
+ zap.Error(ErrNotEnoughStartedMembers),
+ )
+ return ErrNotEnoughStartedMembers
+ }
+
+ return nil
+}
+
+// check whether the learner catches up with leader or not.
+// Note: it will return nil if member is not found in cluster or if member is not learner.
+// These two conditions will be checked before apply phase later.
+func (s *EtcdServer) isLearnerReady(id uint64) error {
+ if err := s.waitAppliedIndex(); err != nil {
+ return err
+ }
+
+ rs := s.raftStatus()
+
+ // leader's raftStatus.Progress is not nil
+ if rs.Progress == nil {
+ return ErrNotLeader
+ }
+
+ var learnerMatch uint64
+ isFound := false
+ leaderID := rs.ID
+ for memberID, progress := range rs.Progress {
+ if id == memberID {
+ // check its status
+ learnerMatch = progress.Match
+ isFound = true
+ break
+ }
+ }
+
+ // We should return an error in API directly, to avoid the request
+ // being unnecessarily delivered to raft.
+ if !isFound {
+ return membership.ErrIDNotFound
+ }
+
+ leaderMatch := rs.Progress[leaderID].Match
+ // the learner's Match not caught up with leader yet
+ if float64(learnerMatch) < float64(leaderMatch)*readyPercent {
+ return ErrLearnerNotReady
+ }
+
+ return nil
+}
+
+func (s *EtcdServer) mayRemoveMember(id types.ID) error {
+ if !s.Cfg.StrictReconfigCheck {
+ return nil
+ }
+
+ lg := s.Logger()
+ isLearner := s.cluster.IsMemberExist(id) && s.cluster.Member(id).IsLearner
+ // no need to check quorum when removing non-voting member
+ if isLearner {
+ return nil
+ }
+
+ if !s.cluster.IsReadyToRemoveVotingMember(uint64(id)) {
+ lg.Warn(
+ "rejecting member remove request; not enough healthy members",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("requested-member-remove-id", id.String()),
+ zap.Error(ErrNotEnoughStartedMembers),
+ )
+ 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.VotingMembers()
+ active := numConnectedSince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), m)
+ if (active - 1) < 1+((len(m)-1)/2) {
+ lg.Warn(
+ "rejecting member remove request; local member has not been connected to all peers, reconfigure breaks active quorum",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("requested-member-remove", id.String()),
+ zap.Int("active-peers", active),
+ zap.Error(ErrUnhealthy),
+ )
+ 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)
+}
+
+func (s *EtcdServer) setCommittedIndex(v uint64) {
+ atomic.StoreUint64(&s.committedIndex, v)
+}
+
+func (s *EtcdServer) getCommittedIndex() uint64 {
+ return atomic.LoadUint64(&s.committedIndex)
+}
+
+func (s *EtcdServer) setAppliedIndex(v uint64) {
+ atomic.StoreUint64(&s.appliedIndex, v)
+}
+
+func (s *EtcdServer) getAppliedIndex() uint64 {
+ return atomic.LoadUint64(&s.appliedIndex)
+}
+
+func (s *EtcdServer) setTerm(v uint64) {
+ atomic.StoreUint64(&s.term, v)
+}
+
+func (s *EtcdServer) getTerm() uint64 {
+ return atomic.LoadUint64(&s.term)
+}
+
+func (s *EtcdServer) setLead(v uint64) {
+ atomic.StoreUint64(&s.lead, v)
+}
+
+func (s *EtcdServer) getLead() uint64 {
+ return atomic.LoadUint64(&s.lead)
+}
+
+func (s *EtcdServer) LeaderChangedNotify() <-chan struct{} {
+ s.leaderChangedMu.RLock()
+ defer s.leaderChangedMu.RUnlock()
+ return s.leaderChanged
+}
+
+// FirstCommitInTermNotify returns channel that will be unlocked on first
+// entry committed in new term, which is necessary for new leader to answer
+// read-only requests (leader is not able to respond any read-only requests
+// as long as linearizable semantic is required)
+func (s *EtcdServer) FirstCommitInTermNotify() <-chan struct{} {
+ s.firstCommitInTermMu.RLock()
+ defer s.firstCommitInTermMu.RUnlock()
+ return s.firstCommitInTermC
+}
+
+// RaftStatusGetter represents etcd server and Raft progress.
+type RaftStatusGetter interface {
+ ID() types.ID
+ Leader() types.ID
+ CommittedIndex() uint64
+ AppliedIndex() uint64
+ Term() uint64
+}
+
+func (s *EtcdServer) ID() types.ID { return s.id }
+
+func (s *EtcdServer) Leader() types.ID { return types.ID(s.getLead()) }
+
+func (s *EtcdServer) Lead() uint64 { return s.getLead() }
+
+func (s *EtcdServer) CommittedIndex() uint64 { return s.getCommittedIndex() }
+
+func (s *EtcdServer) AppliedIndex() uint64 { return s.getAppliedIndex() }
+
+func (s *EtcdServer) Term() uint64 { return s.getTerm() }
+
+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) {
+ lg := s.Logger()
+ 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 {
+ lg.Panic("failed to configure")
+ }
+ resp := x.(*confChangeResponse)
+ lg.Info(
+ "applied a configuration change through raft",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("raft-conf-change", cc.Type.String()),
+ zap.String("raft-conf-change-node-id", types.ID(cc.NodeID).String()),
+ )
+ 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()
+ })
+}
+
+// publishV3 registers server information into the cluster using v3 request. 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) publishV3(timeout time.Duration) {
+ req := &membershippb.ClusterMemberAttrSetRequest{
+ Member_ID: uint64(s.id),
+ MemberAttributes: &membershippb.Attributes{
+ Name: s.attributes.Name,
+ ClientUrls: s.attributes.ClientURLs,
+ },
+ }
+ lg := s.Logger()
+ for {
+ select {
+ case <-s.stopping:
+ lg.Warn(
+ "stopped publish because server is stopping",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)),
+ zap.Duration("publish-timeout", timeout),
+ )
+ return
+
+ default:
+ }
+
+ ctx, cancel := context.WithTimeout(s.ctx, timeout)
+ _, err := s.raftRequest(ctx, pb.InternalRaftRequest{ClusterMemberAttrSet: req})
+ cancel()
+ switch err {
+ case nil:
+ close(s.readych)
+ lg.Info(
+ "published local member to cluster through raft",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)),
+ zap.String("cluster-id", s.cluster.ID().String()),
+ zap.Duration("publish-timeout", timeout),
+ )
+ return
+
+ default:
+ lg.Warn(
+ "failed to publish local member to cluster through raft",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)),
+ zap.Duration("publish-timeout", timeout),
+ zap.Error(err),
+ )
+ }
+ }
+}
+
+// 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.
+//
+// Use v2 store to encode member attributes, and apply through Raft
+// but does not go through v2 API endpoint, which means even with v2
+// client handler disabled (e.g. --enable-v2=false), cluster can still
+// process publish requests through rafthttp
+// TODO: Remove in 3.6 (start using publishV3)
+func (s *EtcdServer) publish(timeout time.Duration) {
+ lg := s.Logger()
+ b, err := json.Marshal(s.attributes)
+ if err != nil {
+ lg.Panic("failed to marshal JSON", zap.Error(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)
+ lg.Info(
+ "published local member to cluster through raft",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)),
+ zap.String("request-path", req.Path),
+ zap.String("cluster-id", s.cluster.ID().String()),
+ zap.Duration("publish-timeout", timeout),
+ )
+ return
+
+ case ErrStopped:
+ lg.Warn(
+ "stopped publish because server is stopped",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)),
+ zap.Duration("publish-timeout", timeout),
+ zap.Error(err),
+ )
+ return
+
+ default:
+ lg.Warn(
+ "failed to publish local member to cluster through raft",
+ zap.String("local-member-id", s.ID().String()),
+ zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)),
+ zap.String("request-path", req.Path),
+ zap.Duration("publish-timeout", timeout),
+ zap.Error(err),
+ )
+ }
+ }
+}
+
+func (s *EtcdServer) sendMergedSnap(merged snap.Message) {
+ atomic.AddInt64(&s.inflightSnapshots, 1)
+
+ lg := s.Logger()
+ fields := []zap.Field{
+ zap.String("from", s.ID().String()),
+ zap.String("to", types.ID(merged.To).String()),
+ zap.Int64("bytes", merged.TotalSize),
+ zap.String("size", humanize.Bytes(uint64(merged.TotalSize))),
+ }
+
+ now := time.Now()
+ s.r.transport.SendSnapshot(merged)
+ lg.Info("sending merged snapshot", fields...)
+
+ 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)
+
+ lg.Info("sent merged snapshot", append(fields, zap.Duration("took", time.Since(now)))...)
+
+ case <-s.stopping:
+ lg.Warn("canceled sending merged snapshot; server stopping", fields...)
+ 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) {
+ s.lg.Debug("Applying entries", zap.Int("num-entries", len(es)))
+ for i := range es {
+ e := es[i]
+ s.lg.Debug("Applying entry",
+ zap.Uint64("index", e.Index),
+ zap.Uint64("term", e.Term),
+ zap.Stringer("type", e.Type))
+ switch e.Type {
+ case raftpb.EntryNormal:
+ s.applyEntryNormal(&e)
+ s.setAppliedIndex(e.Index)
+ s.setTerm(e.Term)
+
+ case raftpb.EntryConfChange:
+ // We need to apply all WAL entries on top of v2store
+ // and only 'unapplied' (e.Index>backend.ConsistentIndex) on the backend.
+ shouldApplyV3 := membership.ApplyV2storeOnly
+
+ // set the consistent index of current executing entry
+ if e.Index > s.consistIndex.ConsistentIndex() {
+ s.consistIndex.SetConsistentApplyingIndex(e.Index, e.Term)
+ shouldApplyV3 = membership.ApplyBoth
+ }
+
+ var cc raftpb.ConfChange
+ pbutil.MustUnmarshal(&cc, e.Data)
+ removedSelf, err := s.applyConfChange(cc, confState, shouldApplyV3)
+ s.setAppliedIndex(e.Index)
+ s.setTerm(e.Term)
+ shouldStop = shouldStop || removedSelf
+ s.w.Trigger(cc.ID, &confChangeResponse{s.cluster.Members(), err})
+
+ default:
+ lg := s.Logger()
+ lg.Panic(
+ "unknown entry type; must be either EntryNormal or EntryConfChange",
+ zap.String("type", e.Type.String()),
+ )
+ }
+ appliedi, appliedt = e.Index, e.Term
+ }
+ return appliedt, appliedi, shouldStop
+}
+
+// applyEntryNormal apples an EntryNormal type raftpb request to the EtcdServer
+func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) {
+ shouldApplyV3 := membership.ApplyV2storeOnly
+ var ar *applyResult
+ index := s.consistIndex.ConsistentIndex()
+ if e.Index > index {
+ // set the consistent index of current executing entry
+ s.consistIndex.SetConsistentApplyingIndex(e.Index, e.Term)
+ shouldApplyV3 = membership.ApplyBoth
+ defer func() {
+ // The txPostLockInsideApplyHook will not get called in some cases,
+ // in which we should move the consistent index forward directly.
+ newIndex := s.consistIndex.ConsistentIndex()
+ if newIndex < e.Index {
+ s.consistIndex.SetConsistentIndex(e.Index, e.Term)
+ }
+ }()
+ }
+ s.lg.Debug("apply entry normal",
+ zap.Uint64("consistent-index", index),
+ zap.Uint64("entry-index", e.Index),
+ zap.Bool("should-applyV3", bool(shouldApplyV3)))
+
+ // 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 {
+ s.notifyAboutFirstCommitInTerm()
+
+ // 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.lg.Debug("applyEntryNormal", zap.Stringer("V2request", rp))
+ s.w.Trigger(r.ID, s.applyV2Request((*RequestV2)(rp), shouldApplyV3))
+ return
+ }
+ s.lg.Debug("applyEntryNormal", zap.Stringer("raftReq", &raftReq))
+
+ if raftReq.V2 != nil {
+ req := (*RequestV2)(raftReq.V2)
+ s.w.Trigger(req.ID, s.applyV2Request(req, shouldApplyV3))
+ return
+ }
+
+ id := raftReq.ID
+ if id == 0 {
+ id = raftReq.Header.ID
+ }
+
+ needResult := s.w.IsRegistered(id)
+ if needResult || !noSideEffect(&raftReq) {
+ if !needResult && raftReq.Txn != nil {
+ removeNeedlessRangeReqs(raftReq.Txn)
+ }
+ ar = s.applyV3.Apply(&raftReq, shouldApplyV3)
+ }
+
+ // do not re-apply applied entries.
+ if !shouldApplyV3 {
+ return
+ }
+
+ if ar == nil {
+ return
+ }
+
+ if ar.err != ErrNoSpace || len(s.alarmStore.Get(pb.AlarmType_NOSPACE)) > 0 {
+ s.w.Trigger(id, ar)
+ return
+ }
+
+ lg := s.Logger()
+ lg.Warn(
+ "message exceeded backend quota; raising alarm",
+ zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes),
+ zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))),
+ zap.Error(ar.err),
+ )
+
+ 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)
+ })
+}
+
+func (s *EtcdServer) notifyAboutFirstCommitInTerm() {
+ newNotifier := make(chan struct{})
+ s.firstCommitInTermMu.Lock()
+ notifierToClose := s.firstCommitInTermC
+ s.firstCommitInTermC = newNotifier
+ s.firstCommitInTermMu.Unlock()
+ close(notifierToClose)
+}
+
+// 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, shouldApplyV3 membership.ShouldApplyV3) (bool, error) {
+ if err := s.cluster.ValidateConfigurationChange(cc); err != nil {
+ cc.NodeID = raft.None
+ s.r.ApplyConfChange(cc)
+
+ // The txPostLock callback will not get called in this case,
+ // so we should set the consistent index directly.
+ if s.consistIndex != nil && membership.ApplyBoth == shouldApplyV3 {
+ applyingIndex, applyingTerm := s.consistIndex.ConsistentApplyingIndex()
+ s.consistIndex.SetConsistentIndex(applyingIndex, applyingTerm)
+ }
+ return false, err
+ }
+
+ lg := s.Logger()
+ *confState = *s.r.ApplyConfChange(cc)
+ s.beHooks.SetConfState(confState)
+ switch cc.Type {
+ case raftpb.ConfChangeAddNode, raftpb.ConfChangeAddLearnerNode:
+ confChangeContext := new(membership.ConfigChangeContext)
+ if err := json.Unmarshal(cc.Context, confChangeContext); err != nil {
+ lg.Panic("failed to unmarshal member", zap.Error(err))
+ }
+ if cc.NodeID != uint64(confChangeContext.Member.ID) {
+ lg.Panic(
+ "got different member ID",
+ zap.String("member-id-from-config-change-entry", types.ID(cc.NodeID).String()),
+ zap.String("member-id-from-message", confChangeContext.Member.ID.String()),
+ )
+ }
+ if confChangeContext.IsPromote {
+ s.cluster.PromoteMember(confChangeContext.Member.ID, shouldApplyV3)
+ } else {
+ s.cluster.AddMember(&confChangeContext.Member, shouldApplyV3)
+
+ if confChangeContext.Member.ID != s.id {
+ s.r.transport.AddPeer(confChangeContext.Member.ID, confChangeContext.PeerURLs)
+ }
+ }
+
+ // update the isLearner metric when this server id is equal to the id in raft member confChange
+ if confChangeContext.Member.ID == s.id {
+ if cc.Type == raftpb.ConfChangeAddLearnerNode {
+ isLearner.Set(1)
+ } else {
+ isLearner.Set(0)
+ }
+ }
+
+ case raftpb.ConfChangeRemoveNode:
+ id := types.ID(cc.NodeID)
+ s.cluster.RemoveMember(id, shouldApplyV3)
+ 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 {
+ lg.Panic("failed to unmarshal member", zap.Error(err))
+ }
+ if cc.NodeID != uint64(m.ID) {
+ lg.Panic(
+ "got different member ID",
+ zap.String("member-id-from-config-change-entry", types.ID(cc.NodeID).String()),
+ zap.String("member-id-from-message", m.ID.String()),
+ )
+ }
+ s.cluster.UpdateRaftAttributes(m.ID, m.RaftAttributes, shouldApplyV3)
+ 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.v2store.Clone()
+ // commit kv to write metadata (for example: consistent index) to disk.
+ //
+ // This guarantees that Backend's consistent_index is >= index of last snapshot.
+ //
+ // 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() {
+ lg := s.Logger()
+
+ 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 {
+ lg.Panic("failed to save v2 store", zap.Error(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
+ }
+ lg.Panic("failed to create snapshot", zap.Error(err))
+ }
+ // SaveSnap saves the snapshot to file and appends the corresponding WAL entry.
+ if err = s.r.storage.SaveSnap(snap); err != nil {
+ lg.Panic("failed to save snapshot", zap.Error(err))
+ }
+ if err = s.r.storage.Release(snap); err != nil {
+ lg.Panic("failed to release wal", zap.Error(err))
+ }
+
+ lg.Info(
+ "saved snapshot",
+ zap.Uint64("snapshot-index", 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 {
+ lg.Info("skip compaction since there is an inflight snapshot")
+ return
+ }
+
+ // keep some in memory log entries for slow followers.
+ compacti := uint64(1)
+ if snapi > s.Cfg.SnapshotCatchUpEntries {
+ compacti = snapi - s.Cfg.SnapshotCatchUpEntries
+ }
+
+ 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
+ }
+ lg.Panic("failed to compact", zap.Error(err))
+ }
+ lg.Info(
+ "compacted Raft logs",
+ zap.Uint64("compact-index", 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.
+// TODO switch to updateClusterVersionV3 in 3.6
+func (s *EtcdServer) monitorVersions() {
+ for {
+ select {
+ case <-s.FirstCommitInTermNotify():
+ case <-time.After(monitorVersionInterval):
+ case <-s.stopping:
+ return
+ }
+
+ if s.Leader() != s.ID() {
+ continue
+ }
+
+ v := decideClusterVersion(s.Logger(), getVersions(s.Logger(), 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.updateClusterVersionV2(verStr) })
+ continue
+ }
+
+ if v != nil && membership.IsValidVersionChange(s.cluster.Version(), v) {
+ s.GoAttach(func() { s.updateClusterVersionV2(v.String()) })
+ }
+ }
+}
+
+func (s *EtcdServer) monitorKVHash() {
+ t := s.Cfg.CorruptCheckTime
+ if t == 0 {
+ return
+ }
+
+ lg := s.Logger()
+ lg.Info(
+ "enabled corruption checking",
+ zap.String("local-member-id", s.ID().String()),
+ zap.Duration("interval", t),
+ )
+ for {
+ select {
+ case <-s.stopping:
+ return
+ case <-time.After(t):
+ }
+ if !s.isLeader() {
+ continue
+ }
+ if err := s.corruptionChecker.PeriodicCheck(); err != nil {
+ lg.Warn("failed to check hash KV", zap.Error(err))
+ }
+ }
+}
+
+func (s *EtcdServer) monitorCompactHash() {
+ if !s.Cfg.CompactHashCheckEnabled {
+ return
+ }
+ t := s.Cfg.CompactHashCheckTime
+ for {
+ select {
+ case <-time.After(t):
+ case <-s.stopping:
+ return
+ }
+ if !s.isLeader() {
+ continue
+ }
+ s.corruptionChecker.CompactHashCheck()
+ }
+}
+
+func (s *EtcdServer) updateClusterVersionV2(ver string) {
+ lg := s.Logger()
+
+ if s.cluster.Version() == nil {
+ lg.Info(
+ "setting up initial cluster version using v2 API",
+ zap.String("cluster-version", version.Cluster(ver)),
+ )
+ } else {
+ lg.Info(
+ "updating cluster version using v2 API",
+ zap.String("from", version.Cluster(s.cluster.Version().String())),
+ zap.String("to", 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:
+ lg.Info("cluster version is updated", zap.String("cluster-version", version.Cluster(ver)))
+ return
+
+ case ErrStopped:
+ lg.Warn("aborting cluster version update; server is stopped", zap.Error(err))
+ return
+
+ default:
+ lg.Warn("failed to update cluster version", zap.Error(err))
+ }
+}
+
+func (s *EtcdServer) updateClusterVersionV3(ver string) {
+ lg := s.Logger()
+
+ if s.cluster.Version() == nil {
+ lg.Info(
+ "setting up initial cluster version using v3 API",
+ zap.String("cluster-version", version.Cluster(ver)),
+ )
+ } else {
+ lg.Info(
+ "updating cluster version using v3 API",
+ zap.String("from", version.Cluster(s.cluster.Version().String())),
+ zap.String("to", version.Cluster(ver)),
+ )
+ }
+
+ req := membershippb.ClusterVersionSetRequest{Ver: ver}
+
+ ctx, cancel := context.WithTimeout(s.ctx, s.Cfg.ReqTimeout())
+ _, err := s.raftRequest(ctx, pb.InternalRaftRequest{ClusterVersionSet: &req})
+ cancel()
+
+ switch err {
+ case nil:
+ lg.Info("cluster version is updated", zap.String("cluster-version", version.Cluster(ver)))
+ return
+
+ case ErrStopped:
+ lg.Warn("aborting cluster version update; server is stopped", zap.Error(err))
+ return
+
+ default:
+ lg.Warn("failed to update cluster version", zap.Error(err))
+ }
+}
+
+func (s *EtcdServer) monitorDowngrade() {
+ t := s.Cfg.DowngradeCheckTime
+ if t == 0 {
+ return
+ }
+ lg := s.Logger()
+ for {
+ select {
+ case <-time.After(t):
+ case <-s.stopping:
+ return
+ }
+
+ if !s.isLeader() {
+ continue
+ }
+
+ d := s.cluster.DowngradeInfo()
+ if !d.Enabled {
+ continue
+ }
+
+ targetVersion := d.TargetVersion
+ v := semver.Must(semver.NewVersion(targetVersion))
+ if isMatchedVersions(s.Logger(), v, getVersions(s.Logger(), s.cluster, s.id, s.peerRt)) {
+ lg.Info("the cluster has been downgraded", zap.String("cluster-version", targetVersion))
+ ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout())
+ if _, err := s.downgradeCancel(ctx); err != nil {
+ lg.Warn("failed to cancel downgrade", zap.Error(err))
+ }
+ cancel()
+ }
+ }
+}
+
+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(s.getLead())
+ 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.WatchableKV { 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 := v3alarm.NewAlarmStore(s.lg, 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
+}
+
+// GoAttach creates a goroutine on a given function and tracks it using
+// the etcdserver waitgroup.
+// The passed function should interrupt on s.StoppingNotify().
+func (s *EtcdServer) GoAttach(f func()) {
+ s.wgMu.RLock() // this blocks with ongoing close(s.stopping)
+ defer s.wgMu.RUnlock()
+ select {
+ case <-s.stopping:
+ lg := s.Logger()
+ lg.Warn("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)
+}
+
+// IsLearner returns if the local member is raft learner
+func (s *EtcdServer) IsLearner() bool {
+ return s.cluster.IsLocalMemberLearner()
+}
+
+// IsMemberExist returns if the member with the given id exists in cluster.
+func (s *EtcdServer) IsMemberExist(id types.ID) bool {
+ return s.cluster.IsMemberExist(id)
+}
+
+// raftStatus returns the raft status of this etcd node.
+func (s *EtcdServer) raftStatus() raft.Status {
+ return s.r.Node.Status()
+}
+
+func (s *EtcdServer) getTxPostLockInsideApplyHook() func() {
+ return func() {
+ applyingIdx, applyingTerm := s.consistIndex.ConsistentApplyingIndex()
+ if applyingIdx > s.consistIndex.UnsafeConsistentIndex() {
+ s.consistIndex.SetConsistentIndex(applyingIdx, applyingTerm)
+ }
+ }
+}
+
+func maybeDefragBackend(cfg config.ServerConfig, be backend.Backend) error {
+ size := be.Size()
+ sizeInUse := be.SizeInUse()
+ freeableMemory := uint(size - sizeInUse)
+ thresholdBytes := cfg.ExperimentalBootstrapDefragThresholdMegabytes * 1024 * 1024
+ if freeableMemory < thresholdBytes {
+ cfg.Logger.Info("Skipping defragmentation",
+ zap.Int64("current-db-size-bytes", size),
+ zap.String("current-db-size", humanize.Bytes(uint64(size))),
+ zap.Int64("current-db-size-in-use-bytes", sizeInUse),
+ zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse))),
+ zap.Uint("experimental-bootstrap-defrag-threshold-bytes", thresholdBytes),
+ zap.String("experimental-bootstrap-defrag-threshold", humanize.Bytes(uint64(thresholdBytes))),
+ )
+ return nil
+ }
+ return be.Defrag()
+}
+
+func (s *EtcdServer) CorruptionChecker() CorruptionChecker {
+ return s.corruptionChecker
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/server_access_control.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/server_access_control.go
new file mode 100644
index 0000000000..09e2255ccc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/server_access_control.go
@@ -0,0 +1,65 @@
+// 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 etcdserver
+
+import "sync"
+
+// AccessController controls etcd server HTTP request access.
+type AccessController struct {
+ corsMu sync.RWMutex
+ CORS map[string]struct{}
+ hostWhitelistMu sync.RWMutex
+ HostWhitelist map[string]struct{}
+}
+
+// NewAccessController returns a new "AccessController" with default "*" values.
+func NewAccessController() *AccessController {
+ return &AccessController{
+ CORS: map[string]struct{}{"*": {}},
+ HostWhitelist: map[string]struct{}{"*": {}},
+ }
+}
+
+// OriginAllowed determines whether the server will allow a given CORS origin.
+// If CORS is empty, allow all.
+func (ac *AccessController) OriginAllowed(origin string) bool {
+ ac.corsMu.RLock()
+ defer ac.corsMu.RUnlock()
+ if len(ac.CORS) == 0 { // allow all
+ return true
+ }
+ _, ok := ac.CORS["*"]
+ if ok {
+ return true
+ }
+ _, ok = ac.CORS[origin]
+ return ok
+}
+
+// IsHostWhitelisted returns true if the host is whitelisted.
+// If whitelist is empty, allow all.
+func (ac *AccessController) IsHostWhitelisted(host string) bool {
+ ac.hostWhitelistMu.RLock()
+ defer ac.hostWhitelistMu.RUnlock()
+ if len(ac.HostWhitelist) == 0 { // allow all
+ return true
+ }
+ _, ok := ac.HostWhitelist["*"]
+ if ok {
+ return true
+ }
+ _, ok = ac.HostWhitelist[host]
+ return ok
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/snapshot_merge.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/snapshot_merge.go
new file mode 100644
index 0000000000..72d10c1796
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/snapshot_merge.go
@@ -0,0 +1,85 @@
+// 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"
+
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+
+ humanize "github.com/dustin/go-humanize"
+ "go.uber.org/zap"
+)
+
+// 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 {
+ lg := s.Logger()
+ // get a snapshot of v2 store as []byte
+ clone := s.v2store.Clone()
+ d, err := clone.SaveNoCopy()
+ if err != nil {
+ lg.Panic("failed to save v2 store data", zap.Error(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(lg, 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(lg *zap.Logger, snapshot backend.Snapshot) io.ReadCloser {
+ pr, pw := io.Pipe()
+ go func() {
+ n, err := snapshot.WriteTo(pw)
+ if err == nil {
+ lg.Info(
+ "sent database snapshot to writer",
+ zap.Int64("bytes", n),
+ zap.String("size", humanize.Bytes(uint64(n))),
+ )
+ } else {
+ lg.Warn(
+ "failed to send database snapshot to writer",
+ zap.String("size", humanize.Bytes(uint64(n))),
+ zap.Error(err),
+ )
+ }
+ pw.CloseWithError(err)
+ err = snapshot.Close()
+ if err != nil {
+ lg.Panic("failed to close database snapshot", zap.Error(err))
+ }
+ }()
+ return pr
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/storage.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/storage.go
new file mode 100644
index 0000000000..64fc862c0c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/storage.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 etcdserver
+
+import (
+ "errors"
+ "io"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/snap"
+ "go.etcd.io/etcd/server/v3/wal"
+ "go.etcd.io/etcd/server/v3/wal/walpb"
+
+ "go.uber.org/zap"
+)
+
+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
+ // Release releases the locked wal files older than the provided snapshot.
+ Release(snap raftpb.Snapshot) error
+ // Sync WAL
+ Sync() 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 file to disk and writes the WAL snapshot entry.
+func (st *storage) SaveSnap(snap raftpb.Snapshot) error {
+ walsnap := walpb.Snapshot{
+ Index: snap.Metadata.Index,
+ Term: snap.Metadata.Term,
+ ConfState: &snap.Metadata.ConfState,
+ }
+ // save the snapshot file before writing the snapshot to the wal.
+ // This makes it possible for the snapshot file to become orphaned, but prevents
+ // a WAL snapshot entry from having no corresponding snapshot file.
+ err := st.Snapshotter.SaveSnap(snap)
+ if err != nil {
+ return err
+ }
+ // gofail: var raftBeforeWALSaveSnaphot struct{}
+
+ return st.WAL.SaveSnapshot(walsnap)
+}
+
+// Release releases resources older than the given snap and are no longer needed:
+// - releases the locks to the wal files that are older than the provided wal for the given snap.
+// - deletes any .snap.db files that are older than the given snap.
+func (st *storage) Release(snap raftpb.Snapshot) error {
+ if err := st.WAL.ReleaseLockTo(snap.Metadata.Index); err != nil {
+ return err
+ }
+ return st.Snapshotter.ReleaseSnapDBs(snap)
+}
+
+// readWAL reads the WAL at the given snap and returns the wal, its latest HardState and cluster ID, and all entries that appear
+// after the position of the given snap in the WAL.
+// The snap must have been previously saved to the WAL, or this call will panic.
+func readWAL(lg *zap.Logger, waldir string, snap walpb.Snapshot, unsafeNoFsync bool) (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(lg, waldir, snap); err != nil {
+ lg.Fatal("failed to open WAL", zap.Error(err))
+ }
+ if unsafeNoFsync {
+ w.SetUnsafeNoFsync()
+ }
+ if wmetadata, st, ents, err = w.ReadAll(); err != nil {
+ w.Close()
+ // we can only repair ErrUnexpectedEOF and we never repair twice.
+ if repaired || !errors.Is(err, io.ErrUnexpectedEOF) {
+ lg.Fatal("failed to read WAL, cannot be repaired", zap.Error(err))
+ }
+ if !wal.Repair(lg, waldir) {
+ lg.Fatal("failed to repair WAL", zap.Error(err))
+ } else {
+ lg.Info("repaired WAL", zap.Error(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/go.etcd.io/etcd/server/v3/etcdserver/util.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/util.go
new file mode 100644
index 0000000000..b048b86416
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/util.go
@@ -0,0 +1,202 @@
+// 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"
+
+ "github.com/golang/protobuf/proto"
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
+
+ "go.uber.org/zap"
+)
+
+// 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(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, respMsg proto.Message, err error) {
+ if time.Since(now) <= warningApplyDuration {
+ return
+ }
+ var resp string
+ if !isNil(respMsg) {
+ resp = fmt.Sprintf("size:%d", proto.Size(respMsg))
+ }
+ warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "", resp, err)
+}
+
+func warnOfFailedRequest(lg *zap.Logger, 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))
+ }
+ d := time.Since(now)
+ lg.Warn(
+ "failed to apply request",
+ zap.Duration("took", d),
+ zap.String("request", reqStringer.String()),
+ zap.String("response", resp),
+ zap.Error(err),
+ )
+}
+
+func warnOfExpensiveReadOnlyTxnRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, r *pb.TxnRequest, txnResponse *pb.TxnResponse, err error) {
+ if time.Since(now) <= warningApplyDuration {
+ return
+ }
+ 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:
+ if op.ResponseRange != nil {
+ resps = append(resps, fmt.Sprintf("range_response_count:%d", len(op.ResponseRange.Kvs)))
+ } else {
+ resps = append(resps, "range_response:nil")
+ }
+ default:
+ // only range responses should be in a read only txn request
+ }
+ }
+ resp = fmt.Sprintf("responses:<%s> size:%d", strings.Join(resps, " "), txnResponse.Size())
+ }
+ warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "read-only txn ", resp, err)
+}
+
+func warnOfExpensiveReadOnlyRangeRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, rangeResponse *pb.RangeResponse, err error) {
+ if time.Since(now) <= warningApplyDuration {
+ return
+ }
+ var resp string
+ if !isNil(rangeResponse) {
+ resp = fmt.Sprintf("range_response_count:%d size:%d", len(rangeResponse.Kvs), rangeResponse.Size())
+ }
+ warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "read-only range ", resp, err)
+}
+
+// callers need make sure time has passed warningApplyDuration
+func warnOfExpensiveGenericRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, prefix string, resp string, err error) {
+ lg.Warn(
+ "apply request took too long",
+ zap.Duration("took", time.Since(now)),
+ zap.Duration("expected-duration", warningApplyDuration),
+ zap.String("prefix", prefix),
+ zap.String("request", reqStringer.String()),
+ zap.String("response", resp),
+ zap.Error(err),
+ )
+ slowApplies.Inc()
+}
+
+func isNil(msg proto.Message) bool {
+ return msg == nil || reflect.ValueOf(msg).IsNil()
+}
+
+// panicAlternativeStringer wraps a fmt.Stringer, and if calling String() panics, calls the alternative instead.
+// This is needed to ensure logging slow v2 requests does not panic, which occurs when running integration tests
+// with the embedded server with github.com/golang/protobuf v1.4.0+. See https://github.com/etcd-io/etcd/issues/12197.
+type panicAlternativeStringer struct {
+ stringer fmt.Stringer
+ alternative func() string
+}
+
+func (n panicAlternativeStringer) String() (s string) {
+ defer func() {
+ if err := recover(); err != nil {
+ s = n.alternative()
+ }
+ }()
+ s = n.stringer.String()
+ return s
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/v2_server.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/v2_server.go
new file mode 100644
index 0000000000..24c97c924a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/v2_server.go
@@ -0,0 +1,166 @@
+// 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 "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+)
+
+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 v2store.Store
+ applier ApplierV2
+}
+
+func NewStoreRequestV2Handler(s v2store.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, membership.ApplyBoth), 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.v2store,
+ applier: s.applyV2,
+ },
+ s: s,
+ }
+ rp := &r
+ resp, err := ((*RequestV2)(rp)).Handle(ctx, h)
+ resp.Term, resp.Index = s.Term(), s.CommittedIndex()
+ 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/go.etcd.io/etcd/server/v3/etcdserver/v3_server.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/v3_server.go
new file mode 100644
index 0000000000..9f69b86b9b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/v3_server.go
@@ -0,0 +1,1073 @@
+// 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/base64"
+ "encoding/binary"
+ "strconv"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/membershippb"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/server/v3/auth"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/lease/leasehttp"
+ "go.etcd.io/etcd/server/v3/mvcc"
+
+ "github.com/gogo/protobuf/proto"
+ "go.uber.org/zap"
+ "golang.org/x/crypto/bcrypt"
+)
+
+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
+ traceThreshold = 100 * time.Millisecond
+ readIndexRetryTime = 500 * time.Millisecond
+
+ // The timeout for the node to catch up its applied index, and is used in
+ // lease related operations, such as LeaseRenew and LeaseTimeToLive.
+ applyTimeout = time.Second
+)
+
+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)
+ AuthStatus(ctx context.Context, r *pb.AuthStatusRequest) (*pb.AuthStatusResponse, 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) {
+ trace := traceutil.New("range",
+ s.Logger(),
+ traceutil.Field{Key: "range_begin", Value: string(r.Key)},
+ traceutil.Field{Key: "range_end", Value: string(r.RangeEnd)},
+ )
+ ctx = context.WithValue(ctx, traceutil.TraceKey, trace)
+
+ var resp *pb.RangeResponse
+ var err error
+ defer func(start time.Time) {
+ warnOfExpensiveReadOnlyRangeRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, r, resp, err)
+ if resp != nil {
+ trace.AddField(
+ traceutil.Field{Key: "response_count", Value: len(resp.Kvs)},
+ traceutil.Field{Key: "response_revision", Value: resp.Header.Revision},
+ )
+ }
+ trace.LogIfLong(traceThreshold)
+ }(time.Now())
+
+ if !r.Serializable {
+ err = s.linearizableReadNotify(ctx)
+ trace.Step("agreement among raft nodes before linearized reading")
+ 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(ctx, 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) {
+ ctx = context.WithValue(ctx, traceutil.StartTimeKey, time.Now())
+ 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) {
+ trace := traceutil.New("transaction",
+ s.Logger(),
+ traceutil.Field{Key: "read_only", Value: true},
+ )
+ ctx = context.WithValue(ctx, traceutil.TraceKey, trace)
+ if !isTxnSerializable(r) {
+ err := s.linearizableReadNotify(ctx)
+ trace.Step("agreement among raft nodes before linearized reading")
+ 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(s.Logger(), s.Cfg.WarningApplyDuration, start, r, resp, err)
+ trace.LogIfLong(traceThreshold)
+ }(time.Now())
+
+ get := func() { resp, _, err = s.applyV3Base.Txn(ctx, r) }
+ if serr := s.doSerialize(ctx, chk, get); serr != nil {
+ return nil, serr
+ }
+ return resp, err
+ }
+
+ ctx = context.WithValue(ctx, traceutil.StartTimeKey, time.Now())
+ 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) {
+ startTime := time.Now()
+ result, err := s.processInternalRaftRequestOnce(ctx, pb.InternalRaftRequest{Compaction: r})
+ trace := traceutil.TODO()
+ if result != nil && result.trace != nil {
+ trace = result.trace
+ defer func() {
+ trace.LogIfLong(traceThreshold)
+ }()
+ applyStart := result.trace.GetStartTime()
+ result.trace.SetStartTime(startTime)
+ trace.InsertStep(0, applyStart, "process raft request")
+ }
+ 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()
+ trace.Step("physically apply compaction")
+ }
+ 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()
+ trace.AddField(traceutil.Field{Key: "response_revision", Value: resp.Header.Revision})
+ 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) waitAppliedIndex() error {
+ select {
+ case <-s.ApplyWait():
+ case <-s.stopping:
+ return ErrStopped
+ case <-time.After(applyTimeout):
+ return ErrTimeoutWaitAppliedIndex
+ }
+
+ return 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) {
+ if s.isLeader() {
+ if err := s.waitAppliedIndex(); err != nil {
+ return 0, err
+ }
+
+ 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 {
+ 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
+ }
+ }
+ // Throttle in case of e.g. connection problems.
+ time.Sleep(50 * time.Millisecond)
+ }
+
+ if cctx.Err() == context.DeadlineExceeded {
+ return -1, ErrTimeout
+ }
+ return -1, ErrCanceled
+}
+
+func (s *EtcdServer) checkLeaseTimeToLive(ctx context.Context, leaseID lease.LeaseID) (uint64, error) {
+ rev := s.AuthStore().Revision()
+ if !s.AuthStore().IsAuthEnabled() {
+ return rev, nil
+ }
+ authInfo, err := s.AuthInfoFromCtx(ctx)
+ if err != nil {
+ return rev, err
+ }
+ if authInfo == nil {
+ return rev, auth.ErrUserEmpty
+ }
+
+ l := s.lessor.Lookup(leaseID)
+ if l != nil {
+ for _, key := range l.Keys() {
+ if err := s.AuthStore().IsRangePermitted(authInfo, []byte(key), []byte{}); err != nil {
+ return 0, err
+ }
+ }
+ }
+
+ return rev, nil
+}
+
+func (s *EtcdServer) leaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) {
+ if s.isLeader() {
+ if err := s.waitAppliedIndex(); err != nil {
+ return nil, err
+ }
+ // 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
+ }
+ }
+ }
+
+ if cctx.Err() == context.DeadlineExceeded {
+ return nil, ErrTimeout
+ }
+ return nil, ErrCanceled
+}
+
+func (s *EtcdServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) {
+ var rev uint64
+ var err error
+ if r.Keys {
+ // check RBAC permission only if Keys is true
+ rev, err = s.checkLeaseTimeToLive(ctx, lease.LeaseID(r.ID))
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ resp, err := s.leaseTimeToLive(ctx, r)
+ if err != nil {
+ return nil, err
+ }
+
+ if r.Keys {
+ if s.AuthStore().IsAuthEnabled() && rev != s.AuthStore().Revision() {
+ return nil, auth.ErrAuthOldRevision
+ }
+ }
+ return resp, nil
+}
+
+// LeaseLeases is really ListLeases !???
+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) AuthStatus(ctx context.Context, r *pb.AuthStatusRequest) (*pb.AuthStatusResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthStatus: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthStatusResponse), nil
+}
+
+func (s *EtcdServer) Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) {
+ if err := s.linearizableReadNotify(ctx); err != nil {
+ return nil, err
+ }
+
+ lg := s.Logger()
+
+ // fix https://nvd.nist.gov/vuln/detail/CVE-2021-28235
+ defer func() {
+ if r != nil {
+ r.Password = ""
+ }
+ }()
+
+ var resp proto.Message
+ for {
+ checkedRevision, err := s.AuthStore().CheckPassword(r.Name, r.Password)
+ if err != nil {
+ if err != auth.ErrAuthNotEnabled {
+ lg.Warn(
+ "invalid authentication was requested",
+ zap.String("user", r.Name),
+ zap.Error(err),
+ )
+ }
+ return nil, err
+ }
+
+ st, err := s.AuthStore().GenTokenPrefix()
+ if err != nil {
+ return nil, err
+ }
+
+ // internalReq doesn't need to have Password because the above s.AuthStore().CheckPassword() already did it.
+ // In addition, it will let a WAL entry not record password as a plain text.
+ internalReq := &pb.InternalAuthenticateRequest{
+ Name: r.Name,
+ SimpleToken: st,
+ }
+
+ resp, err = s.raftRequestOnce(ctx, pb.InternalRaftRequest{Authenticate: internalReq})
+ if err != nil {
+ return nil, err
+ }
+ if checkedRevision == s.AuthStore().Revision() {
+ break
+ }
+
+ lg.Info("revision when password checked became stale; retrying")
+ }
+
+ return resp.(*pb.AuthenticateResponse), nil
+}
+
+func (s *EtcdServer) UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
+ if r.Options == nil || !r.Options.NoPassword {
+ hashedPassword, err := bcrypt.GenerateFromPassword([]byte(r.Password), s.authStore.BcryptCost())
+ if err != nil {
+ return nil, err
+ }
+ r.HashedPassword = base64.StdEncoding.EncodeToString(hashedPassword)
+ r.Password = ""
+ }
+
+ 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) {
+ if r.Password != "" {
+ hashedPassword, err := bcrypt.GenerateFromPassword([]byte(r.Password), s.authStore.BcryptCost())
+ if err != nil {
+ return nil, err
+ }
+ r.HashedPassword = base64.StdEncoding.EncodeToString(hashedPassword)
+ r.Password = ""
+ }
+
+ 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
+ }
+ if startTime, ok := ctx.Value(traceutil.StartTimeKey).(time.Time); ok && result.trace != nil {
+ applyStart := result.trace.GetStartTime()
+ // The trace object is created in apply. Here reset the start time to trace
+ // the raft request time by the difference between the request start time
+ // and apply start time
+ result.trace.SetStartTime(startTime)
+ result.trace.InsertStep(0, applyStart, "process raft request")
+ result.trace.LogIfLong(traceThreshold)
+ }
+ return result.resp, nil
+}
+
+func (s *EtcdServer) raftRequest(ctx context.Context, r pb.InternalRaftRequest) (proto.Message, error) {
+ return s.raftRequestOnce(ctx, r)
+}
+
+// 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 {
+ trace := traceutil.Get(ctx)
+ 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 {
+ return err
+ }
+ trace.Step("get authentication metadata")
+ // fetch response for serialized request
+ get()
+ // check for stale token revision in case the auth store was updated while
+ // the request has been handled.
+ if ai.Revision != 0 && ai.Revision != s.authStore.Revision() {
+ return auth.ErrAuthOldRevision
+ }
+ return nil
+}
+
+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(),
+ }
+
+ // check authinfo if it is not InternalAuthenticateRequest
+ if r.Authenticate == nil {
+ 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()
+ err = s.r.Propose(cctx, data)
+ if err != nil {
+ proposalsFailed.Inc()
+ s.w.Trigger(id, nil) // GC wait
+ return nil, err
+ }
+ 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() {
+ for {
+ requestId := s.reqIDGen.Next()
+ leaderChangedNotifier := s.LeaderChangedNotify()
+ select {
+ case <-leaderChangedNotifier:
+ continue
+ case <-s.readwaitc:
+ case <-s.stopping:
+ return
+ }
+
+ // as a single loop is can unlock multiple reads, it is not very useful
+ // to propagate the trace from Txn or Range.
+ trace := traceutil.New("linearizableReadLoop", s.Logger())
+
+ nextnr := newNotifier()
+ s.readMu.Lock()
+ nr := s.readNotifier
+ s.readNotifier = nextnr
+ s.readMu.Unlock()
+
+ confirmedIndex, err := s.requestCurrentIndex(leaderChangedNotifier, requestId)
+ if isStopped(err) {
+ return
+ }
+ if err != nil {
+ nr.notify(err)
+ continue
+ }
+
+ trace.Step("read index received")
+
+ trace.AddField(traceutil.Field{Key: "readStateIndex", Value: confirmedIndex})
+
+ appliedIndex := s.getAppliedIndex()
+ trace.AddField(traceutil.Field{Key: "appliedIndex", Value: strconv.FormatUint(appliedIndex, 10)})
+
+ if appliedIndex < confirmedIndex {
+ select {
+ case <-s.applyWait.Wait(confirmedIndex):
+ case <-s.stopping:
+ return
+ }
+ }
+ // unblock all l-reads requested at indices before confirmedIndex
+ nr.notify(nil)
+ trace.Step("applied index is now lower than readState.Index")
+
+ trace.LogAllStepsIfLong(traceThreshold)
+ }
+}
+
+func isStopped(err error) bool {
+ return err == raft.ErrStopped || err == ErrStopped
+}
+
+func (s *EtcdServer) requestCurrentIndex(leaderChangedNotifier <-chan struct{}, requestId uint64) (uint64, error) {
+ err := s.sendReadIndex(requestId)
+ if err != nil {
+ return 0, err
+ }
+
+ lg := s.Logger()
+ errorTimer := time.NewTimer(s.Cfg.ReqTimeout())
+ defer errorTimer.Stop()
+ retryTimer := time.NewTimer(readIndexRetryTime)
+ defer retryTimer.Stop()
+
+ firstCommitInTermNotifier := s.FirstCommitInTermNotify()
+
+ for {
+ select {
+ case rs := <-s.r.readStateC:
+ requestIdBytes := uint64ToBigEndianBytes(requestId)
+ gotOwnResponse := bytes.Equal(rs.RequestCtx, requestIdBytes)
+ if !gotOwnResponse {
+ // a previous request might time out. now we should ignore the response of it and
+ // continue waiting for the response of the current requests.
+ responseId := uint64(0)
+ if len(rs.RequestCtx) == 8 {
+ responseId = binary.BigEndian.Uint64(rs.RequestCtx)
+ }
+ lg.Warn(
+ "ignored out-of-date read index response; local node read indexes queueing up and waiting to be in sync with leader",
+ zap.Uint64("sent-request-id", requestId),
+ zap.Uint64("received-request-id", responseId),
+ )
+ slowReadIndex.Inc()
+ continue
+ }
+ return rs.Index, nil
+ case <-leaderChangedNotifier:
+ readIndexFailed.Inc()
+ // return a retryable error.
+ return 0, ErrLeaderChanged
+ case <-firstCommitInTermNotifier:
+ firstCommitInTermNotifier = s.FirstCommitInTermNotify()
+ lg.Info("first commit in current term: resending ReadIndex request")
+ err := s.sendReadIndex(requestId)
+ if err != nil {
+ return 0, err
+ }
+ retryTimer.Reset(readIndexRetryTime)
+ continue
+ case <-retryTimer.C:
+ lg.Warn(
+ "waiting for ReadIndex response took too long, retrying",
+ zap.Uint64("sent-request-id", requestId),
+ zap.Duration("retry-timeout", readIndexRetryTime),
+ )
+ err := s.sendReadIndex(requestId)
+ if err != nil {
+ return 0, err
+ }
+ retryTimer.Reset(readIndexRetryTime)
+ continue
+ case <-errorTimer.C:
+ lg.Warn(
+ "timed out waiting for read index response (local node might have slow network)",
+ zap.Duration("timeout", s.Cfg.ReqTimeout()),
+ )
+ slowReadIndex.Inc()
+ return 0, ErrTimeout
+ case <-s.stopping:
+ return 0, ErrStopped
+ }
+ }
+}
+
+func uint64ToBigEndianBytes(number uint64) []byte {
+ byteResult := make([]byte, 8)
+ binary.BigEndian.PutUint64(byteResult, number)
+ return byteResult
+}
+
+func (s *EtcdServer) sendReadIndex(requestIndex uint64) error {
+ ctxToSend := uint64ToBigEndianBytes(requestIndex)
+
+ cctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout())
+ err := s.r.ReadIndex(cctx, ctxToSend)
+ cancel()
+ if err == raft.ErrStopped {
+ return err
+ }
+ if err != nil {
+ lg := s.Logger()
+ lg.Warn("failed to get read index from Raft", zap.Error(err))
+ readIndexFailed.Inc()
+ return err
+ }
+ return nil
+}
+
+func (s *EtcdServer) LinearizableReadNotify(ctx context.Context) error {
+ return s.linearizableReadNotify(ctx)
+}
+
+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
+}
+
+func (s *EtcdServer) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) {
+ switch r.Action {
+ case pb.DowngradeRequest_VALIDATE:
+ return s.downgradeValidate(ctx, r.Version)
+ case pb.DowngradeRequest_ENABLE:
+ return s.downgradeEnable(ctx, r)
+ case pb.DowngradeRequest_CANCEL:
+ return s.downgradeCancel(ctx)
+ default:
+ return nil, ErrUnknownMethod
+ }
+}
+
+func (s *EtcdServer) downgradeValidate(ctx context.Context, v string) (*pb.DowngradeResponse, error) {
+ resp := &pb.DowngradeResponse{}
+
+ targetVersion, err := convertToClusterVersion(v)
+ if err != nil {
+ return nil, err
+ }
+
+ // gets leaders commit index and wait for local store to finish applying that index
+ // to avoid using stale downgrade information
+ err = s.linearizableReadNotify(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ cv := s.ClusterVersion()
+ if cv == nil {
+ return nil, ErrClusterVersionUnavailable
+ }
+ resp.Version = cv.String()
+
+ allowedTargetVersion := membership.AllowedDowngradeVersion(cv)
+ if !targetVersion.Equal(*allowedTargetVersion) {
+ return nil, ErrInvalidDowngradeTargetVersion
+ }
+
+ downgradeInfo := s.cluster.DowngradeInfo()
+ if downgradeInfo.Enabled {
+ // Todo: return the downgrade status along with the error msg
+ return nil, ErrDowngradeInProcess
+ }
+ return resp, nil
+}
+
+func (s *EtcdServer) downgradeEnable(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) {
+ // validate downgrade capability before starting downgrade
+ v := r.Version
+ lg := s.Logger()
+ if resp, err := s.downgradeValidate(ctx, v); err != nil {
+ lg.Warn("reject downgrade request", zap.Error(err))
+ return resp, err
+ }
+ targetVersion, err := convertToClusterVersion(v)
+ if err != nil {
+ lg.Warn("reject downgrade request", zap.Error(err))
+ return nil, err
+ }
+
+ raftRequest := membershippb.DowngradeInfoSetRequest{Enabled: true, Ver: targetVersion.String()}
+ _, err = s.raftRequest(ctx, pb.InternalRaftRequest{DowngradeInfoSet: &raftRequest})
+ if err != nil {
+ lg.Warn("reject downgrade request", zap.Error(err))
+ return nil, err
+ }
+ resp := pb.DowngradeResponse{Version: s.ClusterVersion().String()}
+ return &resp, nil
+}
+
+func (s *EtcdServer) downgradeCancel(ctx context.Context) (*pb.DowngradeResponse, error) {
+ // gets leaders commit index and wait for local store to finish applying that index
+ // to avoid using stale downgrade information
+ if err := s.linearizableReadNotify(ctx); err != nil {
+ return nil, err
+ }
+
+ downgradeInfo := s.cluster.DowngradeInfo()
+ if !downgradeInfo.Enabled {
+ return nil, ErrNoInflightDowngrade
+ }
+
+ raftRequest := membershippb.DowngradeInfoSetRequest{Enabled: false}
+ _, err := s.raftRequest(ctx, pb.InternalRaftRequest{DowngradeInfoSet: &raftRequest})
+ if err != nil {
+ return nil, err
+ }
+ resp := pb.DowngradeResponse{Version: s.ClusterVersion().String()}
+ return &resp, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/etcdserver/zap_raft.go b/vendor/go.etcd.io/etcd/server/v3/etcdserver/zap_raft.go
new file mode 100644
index 0000000000..e8174f396f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/etcdserver/zap_raft.go
@@ -0,0 +1,102 @@
+// 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 etcdserver
+
+import (
+ "errors"
+
+ "go.etcd.io/etcd/raft/v3"
+
+ "go.uber.org/zap"
+ "go.uber.org/zap/zapcore"
+)
+
+// NewRaftLogger builds "raft.Logger" from "*zap.Config".
+func NewRaftLogger(lcfg *zap.Config) (raft.Logger, error) {
+ if lcfg == nil {
+ return nil, errors.New("nil zap.Config")
+ }
+ lg, err := lcfg.Build(zap.AddCallerSkip(1)) // to annotate caller outside of "logutil"
+ if err != nil {
+ return nil, err
+ }
+ return &zapRaftLogger{lg: lg, sugar: lg.Sugar()}, nil
+}
+
+// NewRaftLoggerZap converts "*zap.Logger" to "raft.Logger".
+func NewRaftLoggerZap(lg *zap.Logger) raft.Logger {
+ return &zapRaftLogger{lg: lg, sugar: lg.Sugar()}
+}
+
+// NewRaftLoggerFromZapCore creates "raft.Logger" from "zap.Core"
+// and "zapcore.WriteSyncer".
+func NewRaftLoggerFromZapCore(cr zapcore.Core, syncer zapcore.WriteSyncer) raft.Logger {
+ // "AddCallerSkip" to annotate caller outside of "logutil"
+ lg := zap.New(cr, zap.AddCaller(), zap.AddCallerSkip(1), zap.ErrorOutput(syncer))
+ return &zapRaftLogger{lg: lg, sugar: lg.Sugar()}
+}
+
+type zapRaftLogger struct {
+ lg *zap.Logger
+ sugar *zap.SugaredLogger
+}
+
+func (zl *zapRaftLogger) Debug(args ...interface{}) {
+ zl.sugar.Debug(args...)
+}
+
+func (zl *zapRaftLogger) Debugf(format string, args ...interface{}) {
+ zl.sugar.Debugf(format, args...)
+}
+
+func (zl *zapRaftLogger) Error(args ...interface{}) {
+ zl.sugar.Error(args...)
+}
+
+func (zl *zapRaftLogger) Errorf(format string, args ...interface{}) {
+ zl.sugar.Errorf(format, args...)
+}
+
+func (zl *zapRaftLogger) Info(args ...interface{}) {
+ zl.sugar.Info(args...)
+}
+
+func (zl *zapRaftLogger) Infof(format string, args ...interface{}) {
+ zl.sugar.Infof(format, args...)
+}
+
+func (zl *zapRaftLogger) Warning(args ...interface{}) {
+ zl.sugar.Warn(args...)
+}
+
+func (zl *zapRaftLogger) Warningf(format string, args ...interface{}) {
+ zl.sugar.Warnf(format, args...)
+}
+
+func (zl *zapRaftLogger) Fatal(args ...interface{}) {
+ zl.sugar.Fatal(args...)
+}
+
+func (zl *zapRaftLogger) Fatalf(format string, args ...interface{}) {
+ zl.sugar.Fatalf(format, args...)
+}
+
+func (zl *zapRaftLogger) Panic(args ...interface{}) {
+ zl.sugar.Panic(args...)
+}
+
+func (zl *zapRaftLogger) Panicf(format string, args ...interface{}) {
+ zl.sugar.Panicf(format, args...)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/lease/doc.go b/vendor/go.etcd.io/etcd/server/v3/lease/doc.go
new file mode 100644
index 0000000000..a74eaf76fc
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/lease/lease_queue.go b/vendor/go.etcd.io/etcd/server/v3/lease/lease_queue.go
new file mode 100644
index 0000000000..ffb7285ec0
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/lease/lease_queue.go
@@ -0,0 +1,108 @@
+// 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 lease
+
+import (
+ "container/heap"
+ "time"
+)
+
+// LeaseWithTime contains lease object with a time.
+// For the lessor's lease heap, time identifies the lease expiration time.
+// For the lessor's lease checkpoint heap, the time identifies the next lease checkpoint time.
+type LeaseWithTime struct {
+ id LeaseID
+ time time.Time
+ index int
+}
+
+type LeaseQueue []*LeaseWithTime
+
+func (pq LeaseQueue) Len() int { return len(pq) }
+
+func (pq LeaseQueue) Less(i, j int) bool {
+ return pq[i].time.Before(pq[j].time)
+}
+
+func (pq LeaseQueue) Swap(i, j int) {
+ pq[i], pq[j] = pq[j], pq[i]
+ pq[i].index = i
+ pq[j].index = j
+}
+
+func (pq *LeaseQueue) Push(x interface{}) {
+ n := len(*pq)
+ item := x.(*LeaseWithTime)
+ item.index = n
+ *pq = append(*pq, item)
+}
+
+func (pq *LeaseQueue) Pop() interface{} {
+ old := *pq
+ n := len(old)
+ item := old[n-1]
+ item.index = -1 // for safety
+ *pq = old[0 : n-1]
+ return item
+}
+
+// LeaseExpiredNotifier is a queue used to notify lessor to revoke expired lease.
+// Only save one item for a lease, `Register` will update time of the corresponding lease.
+type LeaseExpiredNotifier struct {
+ m map[LeaseID]*LeaseWithTime
+ queue LeaseQueue
+}
+
+func newLeaseExpiredNotifier() *LeaseExpiredNotifier {
+ return &LeaseExpiredNotifier{
+ m: make(map[LeaseID]*LeaseWithTime),
+ queue: make(LeaseQueue, 0),
+ }
+}
+
+func (mq *LeaseExpiredNotifier) Init() {
+ heap.Init(&mq.queue)
+ mq.m = make(map[LeaseID]*LeaseWithTime)
+ for _, item := range mq.queue {
+ mq.m[item.id] = item
+ }
+}
+
+func (mq *LeaseExpiredNotifier) RegisterOrUpdate(item *LeaseWithTime) {
+ if old, ok := mq.m[item.id]; ok {
+ old.time = item.time
+ heap.Fix(&mq.queue, old.index)
+ } else {
+ heap.Push(&mq.queue, item)
+ mq.m[item.id] = item
+ }
+}
+
+func (mq *LeaseExpiredNotifier) Unregister() *LeaseWithTime {
+ item := heap.Pop(&mq.queue).(*LeaseWithTime)
+ delete(mq.m, item.id)
+ return item
+}
+
+func (mq *LeaseExpiredNotifier) Poll() *LeaseWithTime {
+ if mq.Len() == 0 {
+ return nil
+ }
+ return mq.queue[0]
+}
+
+func (mq *LeaseExpiredNotifier) Len() int {
+ return len(mq.m)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/doc.go b/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/doc.go
new file mode 100644
index 0000000000..8177a37b66
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/lease/leasehttp/http.go b/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/http.go
new file mode 100644
index 0000000000..4b0a60a9be
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/http.go
@@ -0,0 +1,248 @@
+// 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 "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/pkg/v3/httputil"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/lease/leasepb"
+)
+
+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
+ }
+
+ defer r.Body.Close()
+ 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 uerr := lreq.Unmarshal(b); uerr != 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, rerr := h.l.Renew(lease.LeaseID(lreq.ID))
+ if rerr != nil {
+ if rerr == lease.ErrLeaseNotFound {
+ http.Error(w, rerr.Error(), http.StatusNotFound)
+ return
+ }
+
+ http.Error(w, rerr.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 lerr := lreq.Unmarshal(b); lerr != 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/go.etcd.io/etcd/server/v3/lease/leasepb/lease.pb.go b/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.pb.go
new file mode 100644
index 0000000000..8a1c54922f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.pb.go
@@ -0,0 +1,733 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lease.proto
+
+package leasepb
+
+import (
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+ proto "github.com/golang/protobuf/proto"
+ etcdserverpb "go.etcd.io/etcd/api/v3/etcdserverpb"
+)
+
+// 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.ProtoPackageIsVersion3 // 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"`
+ RemainingTTL int64 `protobuf:"varint,3,opt,name=RemainingTTL,proto3" json:"RemainingTTL,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Lease) Reset() { *m = Lease{} }
+func (m *Lease) String() string { return proto.CompactTextString(m) }
+func (*Lease) ProtoMessage() {}
+func (*Lease) Descriptor() ([]byte, []int) {
+ return fileDescriptor_3dd57e402472b33a, []int{0}
+}
+func (m *Lease) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Lease) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Lease.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Lease) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Lease.Merge(m, src)
+}
+func (m *Lease) XXX_Size() int {
+ return m.Size()
+}
+func (m *Lease) XXX_DiscardUnknown() {
+ xxx_messageInfo_Lease.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Lease proto.InternalMessageInfo
+
+type LeaseInternalRequest struct {
+ LeaseTimeToLiveRequest *etcdserverpb.LeaseTimeToLiveRequest `protobuf:"bytes,1,opt,name=LeaseTimeToLiveRequest,proto3" json:"LeaseTimeToLiveRequest,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LeaseInternalRequest) Reset() { *m = LeaseInternalRequest{} }
+func (m *LeaseInternalRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaseInternalRequest) ProtoMessage() {}
+func (*LeaseInternalRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_3dd57e402472b33a, []int{1}
+}
+func (m *LeaseInternalRequest) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LeaseInternalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LeaseInternalRequest.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LeaseInternalRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LeaseInternalRequest.Merge(m, src)
+}
+func (m *LeaseInternalRequest) XXX_Size() int {
+ return m.Size()
+}
+func (m *LeaseInternalRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_LeaseInternalRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LeaseInternalRequest proto.InternalMessageInfo
+
+type LeaseInternalResponse struct {
+ LeaseTimeToLiveResponse *etcdserverpb.LeaseTimeToLiveResponse `protobuf:"bytes,1,opt,name=LeaseTimeToLiveResponse,proto3" json:"LeaseTimeToLiveResponse,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LeaseInternalResponse) Reset() { *m = LeaseInternalResponse{} }
+func (m *LeaseInternalResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaseInternalResponse) ProtoMessage() {}
+func (*LeaseInternalResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_3dd57e402472b33a, []int{2}
+}
+func (m *LeaseInternalResponse) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *LeaseInternalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_LeaseInternalResponse.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *LeaseInternalResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LeaseInternalResponse.Merge(m, src)
+}
+func (m *LeaseInternalResponse) XXX_Size() int {
+ return m.Size()
+}
+func (m *LeaseInternalResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_LeaseInternalResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LeaseInternalResponse proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterType((*Lease)(nil), "leasepb.Lease")
+ proto.RegisterType((*LeaseInternalRequest)(nil), "leasepb.LeaseInternalRequest")
+ proto.RegisterType((*LeaseInternalResponse)(nil), "leasepb.LeaseInternalResponse")
+}
+
+func init() { proto.RegisterFile("lease.proto", fileDescriptor_3dd57e402472b33a) }
+
+var fileDescriptor_3dd57e402472b33a = []byte{
+ // 256 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, 0x3e, 0xb5, 0x24, 0x39, 0x45,
+ 0x3f, 0xb1, 0x20, 0x53, 0x1f, 0xc4, 0x28, 0x4e, 0x2d, 0x2a, 0x4b, 0x2d, 0x2a, 0x48, 0xd2, 0x2f,
+ 0x2a, 0x48, 0x86, 0x28, 0x50, 0xf2, 0xe5, 0x62, 0xf5, 0x01, 0x99, 0x20, 0xc4, 0xc7, 0xc5, 0xe4,
+ 0xe9, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x1c, 0xc4, 0xe4, 0xe9, 0x22, 0x24, 0xc0, 0xc5, 0x1c,
+ 0x12, 0xe2, 0x23, 0xc1, 0x04, 0x16, 0x00, 0x31, 0x85, 0x94, 0xb8, 0x78, 0x82, 0x52, 0x73, 0x13,
+ 0x33, 0xf3, 0x32, 0xf3, 0xd2, 0x41, 0x52, 0xcc, 0x60, 0x29, 0x14, 0x31, 0xa5, 0x12, 0x2e, 0x11,
+ 0xb0, 0x71, 0x9e, 0x79, 0x25, 0xa9, 0x45, 0x79, 0x89, 0x39, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5,
+ 0x25, 0x42, 0x31, 0x5c, 0x62, 0x60, 0xf1, 0x90, 0xcc, 0xdc, 0xd4, 0x90, 0x7c, 0x9f, 0xcc, 0xb2,
+ 0x54, 0xa8, 0x0c, 0xd8, 0x46, 0x6e, 0x23, 0x15, 0x3d, 0x64, 0xf7, 0xe9, 0x61, 0x57, 0x1b, 0x84,
+ 0xc3, 0x0c, 0xa5, 0x0a, 0x2e, 0x51, 0x34, 0x5b, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0xe2,
+ 0xb9, 0xc4, 0x31, 0xb4, 0x40, 0xa4, 0xa0, 0xf6, 0xaa, 0x12, 0xb0, 0x17, 0xa2, 0x38, 0x08, 0x97,
+ 0x29, 0x4e, 0x12, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0x70, 0xe2, 0x91, 0x1c, 0xe3,
+ 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0xce, 0x78, 0x2c, 0xc7, 0x90, 0xc4, 0x06, 0x0e,
+ 0x5f, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x8a, 0x94, 0xb9, 0xae, 0x01, 0x00, 0x00,
+}
+
+func (m *Lease) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Lease) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Lease) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.RemainingTTL != 0 {
+ i = encodeVarintLease(dAtA, i, uint64(m.RemainingTTL))
+ i--
+ dAtA[i] = 0x18
+ }
+ if m.TTL != 0 {
+ i = encodeVarintLease(dAtA, i, uint64(m.TTL))
+ i--
+ dAtA[i] = 0x10
+ }
+ if m.ID != 0 {
+ i = encodeVarintLease(dAtA, i, uint64(m.ID))
+ i--
+ dAtA[i] = 0x8
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *LeaseInternalRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseInternalRequest) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LeaseInternalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.LeaseTimeToLiveRequest != nil {
+ {
+ size, err := m.LeaseTimeToLiveRequest.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintLease(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *LeaseInternalResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseInternalResponse) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *LeaseInternalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.LeaseTimeToLiveResponse != nil {
+ {
+ size, err := m.LeaseTimeToLiveResponse.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintLease(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintLease(dAtA []byte, offset int, v uint64) int {
+ offset -= sovLease(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *Lease) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovLease(uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ n += 1 + sovLease(uint64(m.TTL))
+ }
+ if m.RemainingTTL != 0 {
+ n += 1 + sovLease(uint64(m.RemainingTTL))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *LeaseInternalRequest) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.LeaseTimeToLiveRequest != nil {
+ l = m.LeaseTimeToLiveRequest.Size()
+ n += 1 + l + sovLease(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *LeaseInternalResponse) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ if m.LeaseTimeToLiveResponse != nil {
+ l = m.LeaseTimeToLiveResponse.Size()
+ n += 1 + l + sovLease(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovLease(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+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
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RemainingTTL", wireType)
+ }
+ m.RemainingTTL = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.RemainingTTL |= int64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipLease(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthLease
+ }
+ 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 *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 < 0 {
+ return ErrInvalidLengthLease
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthLease
+ }
+ 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 *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 < 0 {
+ return ErrInvalidLengthLease
+ }
+ 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) || (iNdEx+skippy) < 0 {
+ return ErrInvalidLengthLease
+ }
+ 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 skipLease(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ depth := 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
+ }
+ }
+ case 1:
+ iNdEx += 8
+ 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
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthLease
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupLease
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthLease
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthLease = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowLease = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupLease = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.proto b/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.proto
new file mode 100644
index 0000000000..5b40e3b17b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.proto
@@ -0,0 +1,25 @@
+syntax = "proto3";
+package leasepb;
+
+import "gogoproto/gogo.proto";
+import "etcd/api/etcdserverpb/rpc.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.goproto_getters_all) = false;
+option (gogoproto.goproto_enum_prefix_all) = false;
+
+message Lease {
+ int64 ID = 1;
+ int64 TTL = 2;
+ int64 RemainingTTL = 3;
+}
+
+message LeaseInternalRequest {
+ etcdserverpb.LeaseTimeToLiveRequest LeaseTimeToLiveRequest = 1;
+}
+
+message LeaseInternalResponse {
+ etcdserverpb.LeaseTimeToLiveResponse LeaseTimeToLiveResponse = 1;
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/lease/lessor.go b/vendor/go.etcd.io/etcd/server/v3/lease/lessor.go
new file mode 100644
index 0000000000..ff9cb2ca5e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/lease/lessor.go
@@ -0,0 +1,994 @@
+// 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 (
+ "container/heap"
+ "context"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/coreos/go-semver/semver"
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/server/v3/lease/leasepb"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+ "go.uber.org/zap"
+)
+
+// 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 v3_6 = semver.Version{Major: 3, Minor: 6}
+
+var (
+ forever = time.Time{}
+
+ // maximum number of leases to revoke per second; configurable for tests
+ leaseRevokeRate = 1000
+
+ // maximum number of lease checkpoints recorded to the consensus log per second; configurable for tests
+ leaseCheckpointRate = 1000
+
+ // the default interval of lease checkpoint
+ defaultLeaseCheckpointInterval = 5 * time.Minute
+
+ // maximum number of lease checkpoints to batch into a single consensus log entry
+ maxLeaseCheckpointBatchSize = 1000
+
+ // the default interval to check if the expired lease is revoked
+ defaultExpiredleaseRetryInterval = 3 * time.Second
+
+ 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
+
+// Checkpointer permits checkpointing of lease remaining TTLs to the consensus log. Defined here to
+// avoid circular dependency with mvcc.
+type Checkpointer func(ctx context.Context, lc *pb.LeaseCheckpointRequest)
+
+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)
+
+ SetCheckpointer(cp Checkpointer)
+
+ // 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
+
+ // Checkpoint applies the remainingTTL of a lease. The remainingTTL is used in Promote to set
+ // the expiry of leases to less than the full TTL when possible.
+ Checkpoint(id LeaseID, remainingTTL int64) 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.RWMutex
+
+ // demotec is set when the lessor is the primary.
+ // demotec will be closed if the lessor is demoted.
+ demotec chan struct{}
+
+ leaseMap map[LeaseID]*Lease
+ leaseExpiredNotifier *LeaseExpiredNotifier
+ leaseCheckpointHeap LeaseQueue
+ itemMap map[LeaseItem]LeaseID
+
+ // When a lease expires, the lessor will delete the
+ // leased range (or key) by the RangeDeleter.
+ rd RangeDeleter
+
+ // When a lease's deadline should be persisted to preserve the remaining TTL across leader
+ // elections and restarts, the lessor will checkpoint the lease by the Checkpointer.
+ cp Checkpointer
+
+ // 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{}
+
+ lg *zap.Logger
+
+ // Wait duration between lease checkpoints.
+ checkpointInterval time.Duration
+ // the interval to check if the expired lease is revoked
+ expiredLeaseRetryInterval time.Duration
+ // whether lessor should always persist remaining TTL (always enabled in v3.6).
+ checkpointPersist bool
+ // cluster is used to adapt lessor logic based on cluster version
+ cluster cluster
+}
+
+type cluster interface {
+ // Version is the cluster-wide minimum major.minor version.
+ Version() *semver.Version
+}
+
+type LessorConfig struct {
+ MinLeaseTTL int64
+ CheckpointInterval time.Duration
+ ExpiredLeasesRetryInterval time.Duration
+ CheckpointPersist bool
+}
+
+func NewLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) Lessor {
+ return newLessor(lg, b, cluster, cfg)
+}
+
+func newLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) *lessor {
+ checkpointInterval := cfg.CheckpointInterval
+ expiredLeaseRetryInterval := cfg.ExpiredLeasesRetryInterval
+ if checkpointInterval == 0 {
+ checkpointInterval = defaultLeaseCheckpointInterval
+ }
+ if expiredLeaseRetryInterval == 0 {
+ expiredLeaseRetryInterval = defaultExpiredleaseRetryInterval
+ }
+ l := &lessor{
+ leaseMap: make(map[LeaseID]*Lease),
+ itemMap: make(map[LeaseItem]LeaseID),
+ leaseExpiredNotifier: newLeaseExpiredNotifier(),
+ leaseCheckpointHeap: make(LeaseQueue, 0),
+ b: b,
+ minLeaseTTL: cfg.MinLeaseTTL,
+ checkpointInterval: checkpointInterval,
+ expiredLeaseRetryInterval: expiredLeaseRetryInterval,
+ checkpointPersist: cfg.CheckpointPersist,
+ // expiredC is a small buffered chan to avoid unnecessary blocking.
+ expiredC: make(chan []*Lease, 16),
+ stopC: make(chan struct{}),
+ doneC: make(chan struct{}),
+ lg: lg,
+ cluster: cluster,
+ }
+ 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) SetCheckpointer(cp Checkpointer) {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ le.cp = cp
+}
+
+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 := NewLease(id, ttl)
+
+ 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)
+
+ leaseTotalTTLs.Observe(float64(l.ttl))
+ leaseGranted.Inc()
+
+ if le.isPrimary() {
+ item := &LeaseWithTime{id: l.ID, time: l.expiry}
+ le.leaseExpiredNotifier.RegisterOrUpdate(item)
+ le.scheduleCheckpointIfNeeded(l)
+ }
+
+ 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 backend 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(buckets.Lease, int64ToBytes(int64(l.ID)))
+
+ txn.End()
+
+ leaseRevoked.Inc()
+ return nil
+}
+
+func (le *lessor) Checkpoint(id LeaseID, remainingTTL int64) error {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ if l, ok := le.leaseMap[id]; ok {
+ // when checkpointing, we only update the remainingTTL, Promote is responsible for applying this to lease expiry
+ l.remainingTTL = remainingTTL
+ if le.shouldPersistCheckpoints() {
+ l.persistTo(le.b)
+ }
+ if le.isPrimary() {
+ // schedule the next checkpoint as needed
+ le.scheduleCheckpointIfNeeded(l)
+ }
+ }
+ return nil
+}
+
+func (le *lessor) shouldPersistCheckpoints() bool {
+ cv := le.cluster.Version()
+ return le.checkpointPersist || (cv != nil && greaterOrEqual(*cv, v3_6))
+}
+
+func greaterOrEqual(first, second semver.Version) bool {
+ return !first.LessThan(second)
+}
+
+// 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.RLock()
+ if !le.isPrimary() {
+ // forward renew request to primary instead of returning error.
+ le.mu.RUnlock()
+ return -1, ErrNotPrimary
+ }
+
+ demotec := le.demotec
+
+ l := le.leaseMap[id]
+ if l == nil {
+ le.mu.RUnlock()
+ return -1, ErrLeaseNotFound
+ }
+ // Clear remaining TTL when we renew if it is set
+ clearRemainingTTL := le.cp != nil && l.remainingTTL > 0
+
+ le.mu.RUnlock()
+ if l.expired() {
+ 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
+ }
+ }
+
+ // Clear remaining TTL when we renew if it is set
+ // By applying a RAFT entry only when the remainingTTL is already set, we limit the number
+ // of RAFT entries written per lease to a max of 2 per checkpoint interval.
+ if clearRemainingTTL {
+ le.cp(context.Background(), &pb.LeaseCheckpointRequest{Checkpoints: []*pb.LeaseCheckpoint{{ID: int64(l.ID), Remaining_TTL: 0}}})
+ }
+
+ le.mu.Lock()
+ l.refresh(0)
+ item := &LeaseWithTime{id: l.ID, time: l.expiry}
+ le.leaseExpiredNotifier.RegisterOrUpdate(item)
+ le.mu.Unlock()
+
+ leaseRenewed.Inc()
+ return l.ttl, nil
+}
+
+func (le *lessor) Lookup(id LeaseID) *Lease {
+ le.mu.RLock()
+ defer le.mu.RUnlock()
+ 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)
+ }
+ return leases
+}
+
+func (le *lessor) Leases() []*Lease {
+ le.mu.RLock()
+ ls := le.unsafeLeases()
+ le.mu.RUnlock()
+ sort.Sort(leasesByExpiry(ls))
+ 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)
+ item := &LeaseWithTime{id: l.ID, time: l.expiry}
+ le.leaseExpiredNotifier.RegisterOrUpdate(item)
+ le.scheduleCheckpointIfNeeded(l)
+ }
+
+ if len(le.leaseMap) < leaseRevokeRate {
+ // no possibility of lease pile-up
+ return
+ }
+
+ // adjust expiries in case of overlap
+ leases := le.unsafeLeases()
+ sort.Sort(leasesByExpiry(leases))
+
+ 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)
+ item := &LeaseWithTime{id: l.ID, time: l.expiry}
+ le.leaseExpiredNotifier.RegisterOrUpdate(item)
+ le.scheduleCheckpointIfNeeded(l)
+ }
+}
+
+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()
+ }
+
+ le.clearScheduledLeasesCheckpoints()
+ le.clearLeaseExpiredNotifier()
+
+ 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.RLock()
+ id := le.itemMap[item]
+ le.mu.RUnlock()
+ 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 {
+ le.revokeExpiredLeases()
+ le.checkpointScheduledLeases()
+
+ select {
+ case <-time.After(500 * time.Millisecond):
+ case <-le.stopC:
+ return
+ }
+ }
+}
+
+// revokeExpiredLeases finds all leases past their expiry and sends them to expired channel for
+// to be revoked.
+func (le *lessor) revokeExpiredLeases() {
+ var ls []*Lease
+
+ // rate limit
+ revokeLimit := leaseRevokeRate / 2
+
+ le.mu.RLock()
+ if le.isPrimary() {
+ ls = le.findExpiredLeases(revokeLimit)
+ }
+ le.mu.RUnlock()
+
+ 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
+ }
+ }
+}
+
+// checkpointScheduledLeases finds all scheduled lease checkpoints that are due and
+// submits them to the checkpointer to persist them to the consensus log.
+func (le *lessor) checkpointScheduledLeases() {
+ // rate limit
+ for i := 0; i < leaseCheckpointRate/2; i++ {
+ var cps []*pb.LeaseCheckpoint
+ le.mu.Lock()
+ if le.isPrimary() {
+ cps = le.findDueScheduledCheckpoints(maxLeaseCheckpointBatchSize)
+ }
+ le.mu.Unlock()
+
+ if len(cps) != 0 {
+ le.cp(context.Background(), &pb.LeaseCheckpointRequest{Checkpoints: cps})
+ }
+ if len(cps) < maxLeaseCheckpointBatchSize {
+ return
+ }
+ }
+}
+
+func (le *lessor) clearScheduledLeasesCheckpoints() {
+ le.leaseCheckpointHeap = make(LeaseQueue, 0)
+}
+
+func (le *lessor) clearLeaseExpiredNotifier() {
+ le.leaseExpiredNotifier = newLeaseExpiredNotifier()
+}
+
+// expireExists returns true if expiry items exist.
+// It pops only when expiry item exists.
+// "next" is true, to indicate that it may exist in next attempt.
+func (le *lessor) expireExists() (l *Lease, ok bool, next bool) {
+ if le.leaseExpiredNotifier.Len() == 0 {
+ return nil, false, false
+ }
+
+ item := le.leaseExpiredNotifier.Poll()
+ l = le.leaseMap[item.id]
+ if l == nil {
+ // lease has expired or been revoked
+ // no need to revoke (nothing is expiry)
+ le.leaseExpiredNotifier.Unregister() // O(log N)
+ return nil, false, true
+ }
+ now := time.Now()
+ if now.Before(item.time) /* item.time: expiration time */ {
+ // Candidate expirations are caught up, reinsert this item
+ // and no need to revoke (nothing is expiry)
+ return l, false, false
+ }
+
+ // recheck if revoke is complete after retry interval
+ item.time = now.Add(le.expiredLeaseRetryInterval)
+ le.leaseExpiredNotifier.RegisterOrUpdate(item)
+ return l, true, false
+}
+
+// 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, ok, next := le.expireExists()
+ if !ok && !next {
+ break
+ }
+ if !ok {
+ continue
+ }
+ if next {
+ continue
+ }
+
+ if l.expired() {
+ leases = append(leases, l)
+
+ // reach expired limit
+ if len(leases) == limit {
+ break
+ }
+ }
+ }
+
+ return leases
+}
+
+func (le *lessor) scheduleCheckpointIfNeeded(lease *Lease) {
+ if le.cp == nil {
+ return
+ }
+
+ if lease.RemainingTTL() > int64(le.checkpointInterval.Seconds()) {
+ if le.lg != nil {
+ le.lg.Debug("Scheduling lease checkpoint",
+ zap.Int64("leaseID", int64(lease.ID)),
+ zap.Duration("intervalSeconds", le.checkpointInterval),
+ )
+ }
+ heap.Push(&le.leaseCheckpointHeap, &LeaseWithTime{
+ id: lease.ID,
+ time: time.Now().Add(le.checkpointInterval),
+ })
+ }
+}
+
+func (le *lessor) findDueScheduledCheckpoints(checkpointLimit int) []*pb.LeaseCheckpoint {
+ if le.cp == nil {
+ return nil
+ }
+
+ now := time.Now()
+ cps := []*pb.LeaseCheckpoint{}
+ for le.leaseCheckpointHeap.Len() > 0 && len(cps) < checkpointLimit {
+ lt := le.leaseCheckpointHeap[0]
+ if lt.time.After(now) /* lt.time: next checkpoint time */ {
+ return cps
+ }
+ heap.Pop(&le.leaseCheckpointHeap)
+ var l *Lease
+ var ok bool
+ if l, ok = le.leaseMap[lt.id]; !ok {
+ continue
+ }
+ if !now.Before(l.expiry) {
+ continue
+ }
+ remainingTTL := int64(math.Ceil(l.expiry.Sub(now).Seconds()))
+ if remainingTTL >= l.ttl {
+ continue
+ }
+ if le.lg != nil {
+ le.lg.Debug("Checkpointing lease",
+ zap.Int64("leaseID", int64(lt.id)),
+ zap.Int64("remainingTTL", remainingTTL),
+ )
+ }
+ cps = append(cps, &pb.LeaseCheckpoint{ID: int64(lt.id), Remaining_TTL: remainingTTL})
+ }
+ return cps
+}
+
+func (le *lessor) initAndRecover() {
+ tx := le.b.BatchTx()
+ tx.LockOutsideApply()
+
+ tx.UnsafeCreateBucket(buckets.Lease)
+ lpbs := unsafeGetAllLeases(tx)
+ tx.Unlock()
+ for _, lpb := range lpbs {
+ 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{}),
+ remainingTTL: lpb.RemainingTTL,
+ }
+ }
+ le.leaseExpiredNotifier.Init()
+ heap.Init(&le.leaseCheckpointHeap)
+
+ le.b.ForceCommit()
+}
+
+type Lease struct {
+ ID LeaseID
+ ttl int64 // time to live of the lease in seconds
+ remainingTTL int64 // remaining time to live in seconds, if zero valued it is considered unset and the full ttl should be used
+ // 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 NewLease(id LeaseID, ttl int64) *Lease {
+ return &Lease{
+ ID: id,
+ ttl: ttl,
+ itemSet: make(map[LeaseItem]struct{}),
+ revokec: make(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: l.ttl, RemainingTTL: l.remainingTTL}
+ val, err := lpb.Marshal()
+ if err != nil {
+ panic("failed to marshal lease proto item")
+ }
+
+ b.BatchTx().LockInsideApply()
+ b.BatchTx().UnsafePut(buckets.Lease, key, val)
+ b.BatchTx().Unlock()
+}
+
+// TTL returns the TTL of the Lease.
+func (l *Lease) TTL() int64 {
+ return l.ttl
+}
+
+// SetLeaseItem sets the given lease item, this func is thread-safe
+func (l *Lease) SetLeaseItem(item LeaseItem) {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ l.itemSet[item] = struct{}{}
+}
+
+// RemainingTTL returns the last checkpointed remaining TTL of the lease.
+// TODO(jpbetz): do not expose this utility method
+func (l *Lease) RemainingTTL() int64 {
+ if l.remainingTTL > 0 {
+ return l.remainingTTL
+ }
+ 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.RemainingTTL())*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
+}
+
+func bytesToLeaseID(bytes []byte) int64 {
+ if len(bytes) != 8 {
+ panic(fmt.Errorf("lease ID must be 8-byte"))
+ }
+ return int64(binary.BigEndian.Uint64(bytes))
+}
+
+func unsafeGetAllLeases(tx backend.ReadTx) []*leasepb.Lease {
+ ls := make([]*leasepb.Lease, 0)
+ err := tx.UnsafeForEach(buckets.Lease, func(k, v []byte) error {
+ var lpb leasepb.Lease
+ err := lpb.Unmarshal(v)
+ if err != nil {
+ return fmt.Errorf("failed to Unmarshal lease proto item; lease ID=%016x", bytesToLeaseID(k))
+ }
+ ls = append(ls, &lpb)
+ return nil
+ })
+ if err != nil {
+ panic(err)
+ }
+ return ls
+}
+
+// FakeLessor is a fake implementation of Lessor interface.
+// Used for testing only.
+type FakeLessor struct{}
+
+func (fl *FakeLessor) SetRangeDeleter(dr RangeDeleter) {}
+
+func (fl *FakeLessor) SetCheckpointer(cp Checkpointer) {}
+
+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) Checkpoint(id LeaseID, remainingTTL int64) 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() {}
+
+type FakeTxnDelete struct {
+ backend.BatchTx
+}
+
+func (ftd *FakeTxnDelete) DeleteRange(key, end []byte) (n, rev int64) { return 0, 0 }
+func (ftd *FakeTxnDelete) End() { ftd.Unlock() }
diff --git a/vendor/go.etcd.io/etcd/server/v3/lease/metrics.go b/vendor/go.etcd.io/etcd/server/v3/lease/metrics.go
new file mode 100644
index 0000000000..06f8b58015
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/lease/metrics.go
@@ -0,0 +1,59 @@
+// 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 lease
+
+import (
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+ leaseGranted = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "lease",
+ Name: "granted_total",
+ Help: "The total number of granted leases.",
+ })
+
+ leaseRevoked = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "lease",
+ Name: "revoked_total",
+ Help: "The total number of revoked leases.",
+ })
+
+ leaseRenewed = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "lease",
+ Name: "renewed_total",
+ Help: "The number of renewed leases seen by the leader.",
+ })
+
+ leaseTotalTTLs = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "lease",
+ Name: "ttl_total",
+ Help: "Bucketed histogram of lease TTLs.",
+ // 1 second -> 3 months
+ Buckets: prometheus.ExponentialBuckets(1, 2, 24),
+ })
+)
+
+func init() {
+ prometheus.MustRegister(leaseGranted)
+ prometheus.MustRegister(leaseRevoked)
+ prometheus.MustRegister(leaseRenewed)
+ prometheus.MustRegister(leaseTotalTTLs)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/backend.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/backend.go
new file mode 100644
index 0000000000..f156ae9948
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/backend.go
@@ -0,0 +1,660 @@
+// 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"
+
+ humanize "github.com/dustin/go-humanize"
+ bolt "go.etcd.io/bbolt"
+ "go.uber.org/zap"
+)
+
+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)
+
+ // minSnapshotWarningTimeout is the minimum threshold to trigger a long running snapshot warning.
+ minSnapshotWarningTimeout = 30 * time.Second
+)
+
+type Backend interface {
+ // ReadTx returns a read transaction. It is replaced by ConcurrentReadTx in the main data path, see #10523.
+ ReadTx() ReadTx
+ BatchTx() BatchTx
+ // ConcurrentReadTx returns a non-blocking read transaction.
+ ConcurrentReadTx() ReadTx
+
+ Snapshot() Snapshot
+ Hash(ignores func(bucketName, keyName []byte) bool) (uint32, error)
+ // Size returns the current size of the backend physically allocated.
+ // The backend can hold DB space that is not utilized at the moment,
+ // since it can conduct pre-allocation or spare unused space for recycling.
+ // Use SizeInUse() instead for the actual DB size.
+ 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
+ // OpenReadTxN returns the number of currently open read transactions in the backend.
+ OpenReadTxN() int64
+ Defrag() error
+ ForceCommit()
+ Close() error
+
+ // SetTxPostLockInsideApplyHook sets a txPostLockInsideApplyHook.
+ SetTxPostLockInsideApplyHook(func())
+}
+
+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 txReadBufferCache struct {
+ mu sync.Mutex
+ buf *txReadBuffer
+ bufVersion uint64
+}
+
+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 allocated 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
+ // openReadTxN is the number of currently open read transactions in the backend
+ openReadTxN int64
+ // mlock prevents backend database file to be swapped
+ mlock bool
+
+ mu sync.RWMutex
+ bopts *bolt.Options
+ db *bolt.DB
+
+ batchInterval time.Duration
+ batchLimit int
+ batchTx *batchTxBuffered
+
+ readTx *readTx
+ // txReadBufferCache mirrors "txReadBuffer" within "readTx" -- readTx.baseReadTx.buf.
+ // When creating "concurrentReadTx":
+ // - if the cache is up-to-date, "readTx.baseReadTx.buf" copy can be skipped
+ // - if the cache is empty or outdated, "readTx.baseReadTx.buf" copy is required
+ txReadBufferCache txReadBufferCache
+
+ stopc chan struct{}
+ donec chan struct{}
+
+ hooks Hooks
+
+ // txPostLockInsideApplyHook is called each time right after locking the tx.
+ txPostLockInsideApplyHook func()
+
+ lg *zap.Logger
+}
+
+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
+ // BackendFreelistType is the backend boltdb's freelist type.
+ BackendFreelistType bolt.FreelistType
+ // MmapSize is the number of bytes to mmap for the backend.
+ MmapSize uint64
+ // Logger logs backend-side operations.
+ Logger *zap.Logger
+ // UnsafeNoFsync disables all uses of fsync.
+ UnsafeNoFsync bool `json:"unsafe-no-fsync"`
+ // Mlock prevents backend database file to be swapped
+ Mlock bool
+
+ // Hooks are getting executed during lifecycle of Backend's transactions.
+ Hooks Hooks
+}
+
+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 {
+ if bcfg.Logger == nil {
+ bcfg.Logger = zap.NewNop()
+ }
+
+ bopts := &bolt.Options{}
+ if boltOpenOptions != nil {
+ *bopts = *boltOpenOptions
+ }
+ bopts.InitialMmapSize = bcfg.mmapSize()
+ bopts.FreelistType = bcfg.BackendFreelistType
+ bopts.NoSync = bcfg.UnsafeNoFsync
+ bopts.NoGrowSync = bcfg.UnsafeNoFsync
+ bopts.Mlock = bcfg.Mlock
+
+ db, err := bolt.Open(bcfg.Path, 0600, bopts)
+ if err != nil {
+ bcfg.Logger.Panic("failed to open database", zap.String("path", bcfg.Path), zap.Error(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{
+ bopts: bopts,
+ db: db,
+
+ batchInterval: bcfg.BatchInterval,
+ batchLimit: bcfg.BatchLimit,
+ mlock: bcfg.Mlock,
+
+ readTx: &readTx{
+ baseReadTx: baseReadTx{
+ buf: txReadBuffer{
+ txBuffer: txBuffer{make(map[BucketID]*bucketBuffer)},
+ bufVersion: 0,
+ },
+ buckets: make(map[BucketID]*bolt.Bucket),
+ txWg: new(sync.WaitGroup),
+ txMu: new(sync.RWMutex),
+ },
+ },
+ txReadBufferCache: txReadBufferCache{
+ mu: sync.Mutex{},
+ bufVersion: 0,
+ buf: nil,
+ },
+
+ stopc: make(chan struct{}),
+ donec: make(chan struct{}),
+
+ lg: bcfg.Logger,
+ }
+
+ b.batchTx = newBatchTxBuffered(b)
+ // We set it after newBatchTxBuffered to skip the 'empty' commit.
+ b.hooks = bcfg.Hooks
+
+ 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) SetTxPostLockInsideApplyHook(hook func()) {
+ // It needs to lock the batchTx, because the periodic commit
+ // may be accessing the txPostLockInsideApplyHook at the moment.
+ b.batchTx.lock()
+ defer b.batchTx.Unlock()
+ b.txPostLockInsideApplyHook = hook
+}
+
+func (b *backend) ReadTx() ReadTx { return b.readTx }
+
+// ConcurrentReadTx creates and returns a new ReadTx, which:
+// A) creates and keeps a copy of backend.readTx.txReadBuffer,
+// B) references the boltdb read Tx (and its bucket cache) of current batch interval.
+func (b *backend) ConcurrentReadTx() ReadTx {
+ b.readTx.RLock()
+ defer b.readTx.RUnlock()
+ // prevent boltdb read Tx from been rolled back until store read Tx is done. Needs to be called when holding readTx.RLock().
+ b.readTx.txWg.Add(1)
+
+ // TODO: might want to copy the read buffer lazily - create copy when A) end of a write transaction B) end of a batch interval.
+
+ // inspect/update cache recency iff there's no ongoing update to the cache
+ // this falls through if there's no cache update
+
+ // by this line, "ConcurrentReadTx" code path is already protected against concurrent "writeback" operations
+ // which requires write lock to update "readTx.baseReadTx.buf".
+ // Which means setting "buf *txReadBuffer" with "readTx.buf.unsafeCopy()" is guaranteed to be up-to-date,
+ // whereas "txReadBufferCache.buf" may be stale from concurrent "writeback" operations.
+ // We only update "txReadBufferCache.buf" if we know "buf *txReadBuffer" is up-to-date.
+ // The update to "txReadBufferCache.buf" will benefit the following "ConcurrentReadTx" creation
+ // by avoiding copying "readTx.baseReadTx.buf".
+ b.txReadBufferCache.mu.Lock()
+
+ curCache := b.txReadBufferCache.buf
+ curCacheVer := b.txReadBufferCache.bufVersion
+ curBufVer := b.readTx.buf.bufVersion
+
+ isEmptyCache := curCache == nil
+ isStaleCache := curCacheVer != curBufVer
+
+ var buf *txReadBuffer
+ switch {
+ case isEmptyCache:
+ // perform safe copy of buffer while holding "b.txReadBufferCache.mu.Lock"
+ // this is only supposed to run once so there won't be much overhead
+ curBuf := b.readTx.buf.unsafeCopy()
+ buf = &curBuf
+ case isStaleCache:
+ // to maximize the concurrency, try unsafe copy of buffer
+ // release the lock while copying buffer -- cache may become stale again and
+ // get overwritten by someone else.
+ // therefore, we need to check the readTx buffer version again
+ b.txReadBufferCache.mu.Unlock()
+ curBuf := b.readTx.buf.unsafeCopy()
+ b.txReadBufferCache.mu.Lock()
+ buf = &curBuf
+ default:
+ // neither empty nor stale cache, just use the current buffer
+ buf = curCache
+ }
+ // txReadBufferCache.bufVersion can be modified when we doing an unsafeCopy()
+ // as a result, curCacheVer could be no longer the same as
+ // txReadBufferCache.bufVersion
+ // if !isEmptyCache && curCacheVer != b.txReadBufferCache.bufVersion
+ // then the cache became stale while copying "readTx.baseReadTx.buf".
+ // It is safe to not update "txReadBufferCache.buf", because the next following
+ // "ConcurrentReadTx" creation will trigger a new "readTx.baseReadTx.buf" copy
+ // and "buf" is still used for the current "concurrentReadTx.baseReadTx.buf".
+ if isEmptyCache || curCacheVer == b.txReadBufferCache.bufVersion {
+ // continue if the cache is never set or no one has modified the cache
+ b.txReadBufferCache.buf = buf
+ b.txReadBufferCache.bufVersion = curBufVer
+ }
+
+ b.txReadBufferCache.mu.Unlock()
+
+ // concurrentReadTx is not supposed to write to its txReadBuffer
+ return &concurrentReadTx{
+ baseReadTx: baseReadTx{
+ buf: *buf,
+ txMu: b.readTx.txMu,
+ tx: b.readTx.tx,
+ buckets: b.readTx.buckets,
+ txWg: b.readTx.txWg,
+ },
+ }
+}
+
+// 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 {
+ b.lg.Fatal("failed to begin tx", zap.Error(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 * 1024
+ 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:
+ b.lg.Warn(
+ "snapshotting taking too long to transfer",
+ zap.Duration("taking", time.Since(start)),
+ zap.Int64("bytes", dbBytes),
+ zap.String("size", humanize.Bytes(uint64(dbBytes))),
+ )
+
+ case <-stopc:
+ snapshotTransferSec.Observe(time.Since(start).Seconds())
+ return
+ }
+ }
+ }()
+
+ return &snapshot{tx, stopc, donec}
+}
+
+func (b *backend) Hash(ignores func(bucketName, keyName []byte) bool) (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 {
+ if ignores != nil && !ignores(next, k) {
+ 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
+ }
+ if b.batchTx.safePending() != 0 {
+ 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()
+ isDefragActive.Set(1)
+ defer isDefragActive.Set(0)
+
+ // TODO: make this non-blocking?
+ // lock batchTx to ensure nobody is using previous tx, and then
+ // close previous ongoing tx.
+ b.batchTx.LockOutsideApply()
+ 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.Lock()
+ defer b.readTx.Unlock()
+
+ b.batchTx.unsafeCommit(true)
+
+ b.batchTx.tx = nil
+
+ // Create a temporary file to ensure we start with a clean slate.
+ // Snapshotter.cleanupSnapdir cleans up any of these that are found during startup.
+ dir := filepath.Dir(b.db.Path())
+ temp, err := ioutil.TempFile(dir, "db.tmp.*")
+ if err != nil {
+ return err
+ }
+ options := bolt.Options{}
+ if boltOpenOptions != nil {
+ options = *boltOpenOptions
+ }
+ options.OpenFile = func(_ string, _ int, _ os.FileMode) (file *os.File, err error) {
+ return temp, nil
+ }
+ // Don't load tmp db into memory regardless of opening options
+ options.Mlock = false
+ tdbp := temp.Name()
+ tmpdb, err := bolt.Open(tdbp, 0600, &options)
+ if err != nil {
+ return err
+ }
+
+ dbp := b.db.Path()
+ size1, sizeInUse1 := b.Size(), b.SizeInUse()
+ if b.lg != nil {
+ b.lg.Info(
+ "defragmenting",
+ zap.String("path", dbp),
+ zap.Int64("current-db-size-bytes", size1),
+ zap.String("current-db-size", humanize.Bytes(uint64(size1))),
+ zap.Int64("current-db-size-in-use-bytes", sizeInUse1),
+ zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse1))),
+ )
+ }
+ // gofail: var defragBeforeCopy struct{}
+ err = defragdb(b.db, tmpdb, defragLimit)
+ if err != nil {
+ tmpdb.Close()
+ if rmErr := os.RemoveAll(tmpdb.Path()); rmErr != nil {
+ b.lg.Error("failed to remove db.tmp after defragmentation completed", zap.Error(rmErr))
+ }
+ return err
+ }
+
+ err = b.db.Close()
+ if err != nil {
+ b.lg.Fatal("failed to close database", zap.Error(err))
+ }
+ err = tmpdb.Close()
+ if err != nil {
+ b.lg.Fatal("failed to close tmp database", zap.Error(err))
+ }
+ // gofail: var defragBeforeRename struct{}
+ err = os.Rename(tdbp, dbp)
+ if err != nil {
+ b.lg.Fatal("failed to rename tmp database", zap.Error(err))
+ }
+
+ b.db, err = bolt.Open(dbp, 0600, b.bopts)
+ if err != nil {
+ b.lg.Fatal("failed to open database", zap.String("path", dbp), zap.Error(err))
+ }
+ b.batchTx.tx = b.unsafeBegin(true)
+
+ b.readTx.reset()
+ b.readTx.tx = b.unsafeBegin(false)
+
+ size := b.readTx.tx.Size()
+ db := b.readTx.tx.DB()
+ atomic.StoreInt64(&b.size, size)
+ atomic.StoreInt64(&b.sizeInUse, size-(int64(db.Stats().FreePageN)*int64(db.Info().PageSize)))
+
+ took := time.Since(now)
+ defragSec.Observe(took.Seconds())
+
+ size2, sizeInUse2 := b.Size(), b.SizeInUse()
+ if b.lg != nil {
+ b.lg.Info(
+ "finished defragmenting directory",
+ zap.String("path", dbp),
+ zap.Int64("current-db-size-bytes-diff", size2-size1),
+ zap.Int64("current-db-size-bytes", size2),
+ zap.String("current-db-size", humanize.Bytes(uint64(size2))),
+ zap.Int64("current-db-size-in-use-bytes-diff", sizeInUse2-sizeInUse1),
+ zap.Int64("current-db-size-in-use-bytes", sizeInUse2),
+ zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse2))),
+ zap.Duration("took", took),
+ )
+ }
+ 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
+ }
+ defer func() {
+ if err != nil {
+ tmptx.Rollback()
+ }
+ }()
+
+ // 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 bucket2seq write in for each
+
+ if err = 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 bucket2seq write in for each
+
+ count = 0
+ }
+ return tmpb.Put(k, v)
+ }); err != nil {
+ return err
+ }
+ }
+
+ 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()
+ stats := db.Stats()
+ atomic.StoreInt64(&b.size, size)
+ atomic.StoreInt64(&b.sizeInUse, size-(int64(stats.FreePageN)*int64(db.Info().PageSize)))
+ atomic.StoreInt64(&b.openReadTxN, int64(stats.OpenTxN))
+
+ return tx
+}
+
+func (b *backend) unsafeBegin(write bool) *bolt.Tx {
+ tx, err := b.db.Begin(write)
+ if err != nil {
+ b.lg.Fatal("failed to begin tx", zap.Error(err))
+ }
+ return tx
+}
+
+func (b *backend) OpenReadTxN() int64 {
+ return atomic.LoadInt64(&b.openReadTxN)
+}
+
+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/go.etcd.io/etcd/server/v3/mvcc/backend/batch_tx.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/batch_tx.go
new file mode 100644
index 0000000000..9c025d79e1
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/batch_tx.go
@@ -0,0 +1,369 @@
+// 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 "go.etcd.io/bbolt"
+ "go.uber.org/zap"
+)
+
+type BucketID int
+
+type Bucket interface {
+ // ID returns a unique identifier of a bucket.
+ // The id must NOT be persisted and can be used as lightweight identificator
+ // in the in-memory maps.
+ ID() BucketID
+ Name() []byte
+ // String implements Stringer (human readable name).
+ String() string
+
+ // IsSafeRangeBucket 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.
+ IsSafeRangeBucket() bool
+}
+
+type BatchTx interface {
+ ReadTx
+ UnsafeCreateBucket(bucket Bucket)
+ UnsafeDeleteBucket(bucket Bucket)
+ UnsafePut(bucket Bucket, key []byte, value []byte)
+ UnsafeSeqPut(bucket Bucket, key []byte, value []byte)
+ UnsafeDelete(bucket Bucket, 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()
+ LockInsideApply()
+ LockOutsideApply()
+}
+
+type batchTx struct {
+ sync.Mutex
+ tx *bolt.Tx
+ backend *backend
+
+ pending int
+}
+
+// Lock is supposed to be called only by the unit test.
+func (t *batchTx) Lock() {
+ ValidateCalledInsideUnittest(t.backend.lg)
+ t.lock()
+}
+
+func (t *batchTx) lock() {
+ t.Mutex.Lock()
+}
+
+func (t *batchTx) LockInsideApply() {
+ t.lock()
+ if t.backend.txPostLockInsideApplyHook != nil {
+ // The callers of some methods (i.e., (*RaftCluster).AddMember)
+ // can be coming from both InsideApply and OutsideApply, but the
+ // callers from OutsideApply will have a nil txPostLockInsideApplyHook.
+ // So we should check the txPostLockInsideApplyHook before validating
+ // the callstack.
+ ValidateCalledInsideApply(t.backend.lg)
+ t.backend.txPostLockInsideApplyHook()
+ }
+}
+
+func (t *batchTx) LockOutsideApply() {
+ ValidateCalledOutSideApply(t.backend.lg)
+ t.lock()
+}
+
+func (t *batchTx) Unlock() {
+ if t.pending >= t.backend.batchLimit {
+ t.commit(false)
+ }
+ t.Mutex.Unlock()
+}
+
+// BatchTx interface embeds ReadTx interface. But RLock() and RUnlock() do not
+// have appropriate semantics in BatchTx interface. Therefore should not be called.
+// TODO: might want to decouple ReadTx and BatchTx
+
+func (t *batchTx) RLock() {
+ panic("unexpected RLock")
+}
+
+func (t *batchTx) RUnlock() {
+ panic("unexpected RUnlock")
+}
+
+func (t *batchTx) UnsafeCreateBucket(bucket Bucket) {
+ _, err := t.tx.CreateBucket(bucket.Name())
+ if err != nil && err != bolt.ErrBucketExists {
+ t.backend.lg.Fatal(
+ "failed to create a bucket",
+ zap.Stringer("bucket-name", bucket),
+ zap.Error(err),
+ )
+ }
+ t.pending++
+}
+
+func (t *batchTx) UnsafeDeleteBucket(bucket Bucket) {
+ err := t.tx.DeleteBucket(bucket.Name())
+ if err != nil && err != bolt.ErrBucketNotFound {
+ t.backend.lg.Fatal(
+ "failed to delete a bucket",
+ zap.Stringer("bucket-name", bucket),
+ zap.Error(err),
+ )
+ }
+ t.pending++
+}
+
+// UnsafePut must be called holding the lock on the tx.
+func (t *batchTx) UnsafePut(bucket Bucket, key []byte, value []byte) {
+ t.unsafePut(bucket, key, value, false)
+}
+
+// UnsafeSeqPut must be called holding the lock on the tx.
+func (t *batchTx) UnsafeSeqPut(bucket Bucket, key []byte, value []byte) {
+ t.unsafePut(bucket, key, value, true)
+}
+
+func (t *batchTx) unsafePut(bucketType Bucket, key []byte, value []byte, seq bool) {
+ bucket := t.tx.Bucket(bucketType.Name())
+ if bucket == nil {
+ t.backend.lg.Fatal(
+ "failed to find a bucket",
+ zap.Stringer("bucket-name", bucketType),
+ zap.Stack("stack"),
+ )
+ }
+ 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 {
+ t.backend.lg.Fatal(
+ "failed to write to a bucket",
+ zap.Stringer("bucket-name", bucketType),
+ zap.Error(err),
+ )
+ }
+ t.pending++
+}
+
+// UnsafeRange must be called holding the lock on the tx.
+func (t *batchTx) UnsafeRange(bucketType Bucket, key, endKey []byte, limit int64) ([][]byte, [][]byte) {
+ bucket := t.tx.Bucket(bucketType.Name())
+ if bucket == nil {
+ t.backend.lg.Fatal(
+ "failed to find a bucket",
+ zap.Stringer("bucket-name", bucketType),
+ zap.Stack("stack"),
+ )
+ }
+ 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(bucketType Bucket, key []byte) {
+ bucket := t.tx.Bucket(bucketType.Name())
+ if bucket == nil {
+ t.backend.lg.Fatal(
+ "failed to find a bucket",
+ zap.Stringer("bucket-name", bucketType),
+ zap.Stack("stack"),
+ )
+ }
+ err := bucket.Delete(key)
+ if err != nil {
+ t.backend.lg.Fatal(
+ "failed to delete a key",
+ zap.Stringer("bucket-name", bucketType),
+ zap.Error(err),
+ )
+ }
+ t.pending++
+}
+
+// UnsafeForEach must be called holding the lock on the tx.
+func (t *batchTx) UnsafeForEach(bucket Bucket, visitor func(k, v []byte) error) error {
+ return unsafeForEach(t.tx, bucket, visitor)
+}
+
+func unsafeForEach(tx *bolt.Tx, bucket Bucket, visitor func(k, v []byte) error) error {
+ if b := tx.Bucket(bucket.Name()); 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) safePending() int {
+ t.Mutex.Lock()
+ defer t.Mutex.Unlock()
+ return t.pending
+}
+
+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{}
+
+ rebalanceSec.Observe(t.tx.Stats().RebalanceTime.Seconds())
+ spillSec.Observe(t.tx.Stats().SpillTime.Seconds())
+ writeSec.Observe(t.tx.Stats().WriteTime.Seconds())
+ commitSec.Observe(time.Since(start).Seconds())
+ atomic.AddInt64(&t.backend.commits, 1)
+
+ t.pending = 0
+ if err != nil {
+ t.backend.lg.Fatal("failed to commit tx", zap.Error(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[BucketID]*bucketBuffer)},
+ bucket2seq: make(map[BucketID]bool),
+ },
+ }
+ tx.Commit()
+ return tx
+}
+
+func (t *batchTxBuffered) Unlock() {
+ if t.pending != 0 {
+ t.backend.readTx.Lock() // blocks txReadBuffer for writing.
+ t.buf.writeback(&t.backend.readTx.buf)
+ t.backend.readTx.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.Lock()
+ t.unsafeCommit(stop)
+ t.backend.readTx.Unlock()
+}
+
+func (t *batchTxBuffered) unsafeCommit(stop bool) {
+ if t.backend.hooks != nil {
+ t.backend.hooks.OnPreCommitUnsafe(t)
+ }
+ if t.backend.readTx.tx != nil {
+ // wait all store read transactions using the current boltdb tx to finish,
+ // then close the boltdb tx
+ go func(tx *bolt.Tx, wg *sync.WaitGroup) {
+ wg.Wait()
+ if err := tx.Rollback(); err != nil {
+ t.backend.lg.Fatal("failed to rollback tx", zap.Error(err))
+ }
+ }(t.backend.readTx.tx, t.backend.readTx.txWg)
+ t.backend.readTx.reset()
+ }
+
+ t.batchTx.commit(stop)
+
+ if !stop {
+ t.backend.readTx.tx = t.backend.begin(false)
+ }
+}
+
+func (t *batchTxBuffered) UnsafePut(bucket Bucket, key []byte, value []byte) {
+ t.batchTx.UnsafePut(bucket, key, value)
+ t.buf.put(bucket, key, value)
+}
+
+func (t *batchTxBuffered) UnsafeSeqPut(bucket Bucket, key []byte, value []byte) {
+ t.batchTx.UnsafeSeqPut(bucket, key, value)
+ t.buf.putSeq(bucket, key, value)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_default.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_default.go
new file mode 100644
index 0000000000..847bd10fd7
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_default.go
@@ -0,0 +1,24 @@
+// 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.
+
+//go:build !linux && !windows
+// +build !linux,!windows
+
+package backend
+
+import bolt "go.etcd.io/bbolt"
+
+var boltOpenOptions *bolt.Options
+
+func (bcfg *BackendConfig) mmapSize() int { return int(bcfg.MmapSize) }
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_linux.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_linux.go
new file mode 100644
index 0000000000..f712671af4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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 "go.etcd.io/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/go.etcd.io/etcd/server/v3/mvcc/backend/config_windows.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_windows.go
new file mode 100644
index 0000000000..ba6e5a1284
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_windows.go
@@ -0,0 +1,27 @@
+// 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.
+
+//go:build windows
+// +build windows
+
+package backend
+
+import bolt "go.etcd.io/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/go.etcd.io/etcd/server/v3/mvcc/backend/doc.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/doc.go
new file mode 100644
index 0000000000..9cc42fa793
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/mvcc/backend/hooks.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/hooks.go
new file mode 100644
index 0000000000..9750828ef7
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/hooks.go
@@ -0,0 +1,36 @@
+// Copyright 2021 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
+
+type HookFunc func(tx BatchTx)
+
+// Hooks allow to add additional logic executed during transaction lifetime.
+type Hooks interface {
+ // OnPreCommitUnsafe is executed before Commit of transactions.
+ // The given transaction is already locked.
+ OnPreCommitUnsafe(tx BatchTx)
+}
+
+type hooks struct {
+ onPreCommitUnsafe HookFunc
+}
+
+func (h hooks) OnPreCommitUnsafe(tx BatchTx) {
+ h.onPreCommitUnsafe(tx)
+}
+
+func NewHooks(onPreCommitUnsafe HookFunc) Hooks {
+ return hooks{onPreCommitUnsafe: onPreCommitUnsafe}
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/metrics.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/metrics.go
new file mode 100644
index 0000000000..9d58c00638
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/metrics.go
@@ -0,0 +1,103 @@
+// 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 (
+ commitSec = 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),
+ })
+
+ rebalanceSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "disk",
+ Name: "backend_commit_rebalance_duration_seconds",
+ Help: "The latency distributions of commit.rebalance called by bboltdb 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),
+ })
+
+ spillSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "disk",
+ Name: "backend_commit_spill_duration_seconds",
+ Help: "The latency distributions of commit.spill called by bboltdb 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),
+ })
+
+ writeSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "disk",
+ Name: "backend_commit_write_duration_seconds",
+ Help: "The latency distributions of commit.write called by bboltdb 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),
+ })
+
+ defragSec = 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),
+ })
+
+ snapshotTransferSec = 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),
+ })
+
+ isDefragActive = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "disk",
+ Name: "defrag_inflight",
+ Help: "Whether or not defrag is active on the member. 1 means active, 0 means not.",
+ })
+)
+
+func init() {
+ prometheus.MustRegister(commitSec)
+ prometheus.MustRegister(rebalanceSec)
+ prometheus.MustRegister(spillSec)
+ prometheus.MustRegister(writeSec)
+ prometheus.MustRegister(defragSec)
+ prometheus.MustRegister(snapshotTransferSec)
+ prometheus.MustRegister(isDefragActive)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/read_tx.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/read_tx.go
new file mode 100644
index 0000000000..56327d52ae
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/read_tx.go
@@ -0,0 +1,150 @@
+// 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 (
+ "math"
+ "sync"
+
+ bolt "go.etcd.io/bbolt"
+)
+
+// IsSafeRangeBucket is a hack to avoid inadvertently reading duplicate keys;
+// overwrites on a bucket should only fetch with limit=1, but IsSafeRangeBucket
+// is known to never overwrite any key so range is safe.
+
+type ReadTx interface {
+ Lock()
+ Unlock()
+ RLock()
+ RUnlock()
+
+ UnsafeRange(bucket Bucket, key, endKey []byte, limit int64) (keys [][]byte, vals [][]byte)
+ UnsafeForEach(bucket Bucket, visitor func(k, v []byte) error) error
+}
+
+// Base type for readTx and concurrentReadTx to eliminate duplicate functions between these
+type baseReadTx struct {
+ // mu protects accesses to the txReadBuffer
+ mu sync.RWMutex
+ buf txReadBuffer
+
+ // TODO: group and encapsulate {txMu, tx, buckets, txWg}, as they share the same lifecycle.
+ // txMu protects accesses to buckets and tx on Range requests.
+ txMu *sync.RWMutex
+ tx *bolt.Tx
+ buckets map[BucketID]*bolt.Bucket
+ // txWg protects tx from being rolled back at the end of a batch interval until all reads using this tx are done.
+ txWg *sync.WaitGroup
+}
+
+func (baseReadTx *baseReadTx) UnsafeForEach(bucket Bucket, 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 := baseReadTx.buf.ForEach(bucket, getDups); err != nil {
+ return err
+ }
+ baseReadTx.txMu.Lock()
+ err := unsafeForEach(baseReadTx.tx, bucket, visitNoDup)
+ baseReadTx.txMu.Unlock()
+ if err != nil {
+ return err
+ }
+ return baseReadTx.buf.ForEach(bucket, visitor)
+}
+
+func (baseReadTx *baseReadTx) UnsafeRange(bucketType Bucket, 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 && !bucketType.IsSafeRangeBucket() {
+ panic("do not use unsafeRange on non-keys bucket")
+ }
+ keys, vals := baseReadTx.buf.Range(bucketType, key, endKey, limit)
+ if int64(len(keys)) == limit {
+ return keys, vals
+ }
+
+ // find/cache bucket
+ bn := bucketType.ID()
+ baseReadTx.txMu.RLock()
+ bucket, ok := baseReadTx.buckets[bn]
+ baseReadTx.txMu.RUnlock()
+ lockHeld := false
+ if !ok {
+ baseReadTx.txMu.Lock()
+ lockHeld = true
+ bucket = baseReadTx.tx.Bucket(bucketType.Name())
+ baseReadTx.buckets[bn] = bucket
+ }
+
+ // ignore missing bucket since may have been created in this batch
+ if bucket == nil {
+ if lockHeld {
+ baseReadTx.txMu.Unlock()
+ }
+ return keys, vals
+ }
+ if !lockHeld {
+ baseReadTx.txMu.Lock()
+ }
+ c := bucket.Cursor()
+ baseReadTx.txMu.Unlock()
+
+ k2, v2 := unsafeRange(c, key, endKey, limit-int64(len(keys)))
+ return append(k2, keys...), append(v2, vals...)
+}
+
+type readTx struct {
+ baseReadTx
+}
+
+func (rt *readTx) Lock() { rt.mu.Lock() }
+func (rt *readTx) Unlock() { rt.mu.Unlock() }
+func (rt *readTx) RLock() { rt.mu.RLock() }
+func (rt *readTx) RUnlock() { rt.mu.RUnlock() }
+
+func (rt *readTx) reset() {
+ rt.buf.reset()
+ rt.buckets = make(map[BucketID]*bolt.Bucket)
+ rt.tx = nil
+ rt.txWg = new(sync.WaitGroup)
+}
+
+type concurrentReadTx struct {
+ baseReadTx
+}
+
+func (rt *concurrentReadTx) Lock() {}
+func (rt *concurrentReadTx) Unlock() {}
+
+// RLock is no-op. concurrentReadTx does not need to be locked after it is created.
+func (rt *concurrentReadTx) RLock() {}
+
+// RUnlock signals the end of concurrentReadTx.
+func (rt *concurrentReadTx) RUnlock() { rt.txWg.Done() }
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/tx_buffer.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/tx_buffer.go
new file mode 100644
index 0000000000..6674002483
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/tx_buffer.go
@@ -0,0 +1,231 @@
+// 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"
+)
+
+const bucketBufferInitialSize = 512
+
+// txBuffer handles functionality shared between txWriteBuffer and txReadBuffer.
+type txBuffer struct {
+ buckets map[BucketID]*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
+ // Map from bucket ID into information whether this bucket is edited
+ // sequentially (i.e. keys are growing monotonically).
+ bucket2seq map[BucketID]bool
+}
+
+func (txw *txWriteBuffer) put(bucket Bucket, k, v []byte) {
+ txw.bucket2seq[bucket.ID()] = false
+ txw.putInternal(bucket, k, v)
+}
+
+func (txw *txWriteBuffer) putSeq(bucket Bucket, k, v []byte) {
+ // TODO: Add (in tests?) verification whether k>b[len(b)]
+ txw.putInternal(bucket, k, v)
+}
+
+func (txw *txWriteBuffer) putInternal(bucket Bucket, k, v []byte) {
+ b, ok := txw.buckets[bucket.ID()]
+ if !ok {
+ b = newBucketBuffer()
+ txw.buckets[bucket.ID()] = b
+ }
+ b.add(k, v)
+}
+
+func (txw *txWriteBuffer) reset() {
+ txw.txBuffer.reset()
+ for k := range txw.bucket2seq {
+ v, ok := txw.buckets[k]
+ if !ok {
+ delete(txw.bucket2seq, k)
+ } else if v.used == 0 {
+ txw.bucket2seq[k] = true
+ }
+ }
+}
+
+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 seq, ok := txw.bucket2seq[k]; ok && !seq && wb.used > 1 {
+ // assume no duplicate keys
+ sort.Sort(wb)
+ }
+ rb.merge(wb)
+ }
+ txw.reset()
+ // increase the buffer version
+ txr.bufVersion++
+}
+
+// txReadBuffer accesses buffered updates.
+type txReadBuffer struct {
+ txBuffer
+ // bufVersion is used to check if the buffer is modified recently
+ bufVersion uint64
+}
+
+func (txr *txReadBuffer) Range(bucket Bucket, key, endKey []byte, limit int64) ([][]byte, [][]byte) {
+ if b := txr.buckets[bucket.ID()]; b != nil {
+ return b.Range(key, endKey, limit)
+ }
+ return nil, nil
+}
+
+func (txr *txReadBuffer) ForEach(bucket Bucket, visitor func(k, v []byte) error) error {
+ if b := txr.buckets[bucket.ID()]; b != nil {
+ return b.ForEach(visitor)
+ }
+ return nil
+}
+
+// unsafeCopy returns a copy of txReadBuffer, caller should acquire backend.readTx.RLock()
+func (txr *txReadBuffer) unsafeCopy() txReadBuffer {
+ txrCopy := txReadBuffer{
+ txBuffer: txBuffer{
+ buckets: make(map[BucketID]*bucketBuffer, len(txr.txBuffer.buckets)),
+ },
+ bufVersion: 0,
+ }
+ for bucketName, bucket := range txr.txBuffer.buckets {
+ txrCopy.txBuffer.buckets[bucketName] = bucket.Copy()
+ }
+ return txrCopy
+}
+
+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, bucketBufferInitialSize), 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 bbsrc into bb.
+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] }
+
+func (bb *bucketBuffer) Copy() *bucketBuffer {
+ bbCopy := bucketBuffer{
+ buf: make([]kv, len(bb.buf)),
+ used: bb.used,
+ }
+ copy(bbCopy.buf, bb.buf)
+ return &bbCopy
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/verify.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/verify.go
new file mode 100644
index 0000000000..a6a0b8675e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/verify.go
@@ -0,0 +1,70 @@
+// Copyright 2022 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 (
+ "os"
+ "runtime/debug"
+ "strings"
+
+ "go.uber.org/zap"
+)
+
+const (
+ ENV_VERIFY = "ETCD_VERIFY"
+ ENV_VERIFY_ALL_VALUE = "all"
+ ENV_VERIFY_LOCK = "lock"
+)
+
+func ValidateCalledInsideApply(lg *zap.Logger) {
+ if !verifyLockEnabled() {
+ return
+ }
+ if !insideApply() {
+ lg.Panic("Called outside of APPLY!", zap.Stack("stacktrace"))
+ }
+}
+
+func ValidateCalledOutSideApply(lg *zap.Logger) {
+ if !verifyLockEnabled() {
+ return
+ }
+ if insideApply() {
+ lg.Panic("Called inside of APPLY!", zap.Stack("stacktrace"))
+ }
+}
+
+func ValidateCalledInsideUnittest(lg *zap.Logger) {
+ if !verifyLockEnabled() {
+ return
+ }
+ if !insideUnittest() {
+ lg.Fatal("Lock called outside of unit test!", zap.Stack("stacktrace"))
+ }
+}
+
+func verifyLockEnabled() bool {
+ return os.Getenv(ENV_VERIFY) == ENV_VERIFY_ALL_VALUE || os.Getenv(ENV_VERIFY) == ENV_VERIFY_LOCK
+}
+
+func insideApply() bool {
+ stackTraceStr := string(debug.Stack())
+ return strings.Contains(stackTraceStr, ".applyEntries")
+}
+
+func insideUnittest() bool {
+ stackTraceStr := string(debug.Stack())
+ return strings.Contains(stackTraceStr, "_test.go") && !strings.Contains(stackTraceStr, "tests/")
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/buckets/bucket.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/buckets/bucket.go
new file mode 100644
index 0000000000..9214f72f25
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/buckets/bucket.go
@@ -0,0 +1,80 @@
+// Copyright 2021 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 buckets
+
+import (
+ "bytes"
+
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+)
+
+var (
+ keyBucketName = []byte("key")
+ metaBucketName = []byte("meta")
+ leaseBucketName = []byte("lease")
+ alarmBucketName = []byte("alarm")
+
+ clusterBucketName = []byte("cluster")
+
+ membersBucketName = []byte("members")
+ membersRemovedBucketName = []byte("members_removed")
+
+ authBucketName = []byte("auth")
+ authUsersBucketName = []byte("authUsers")
+ authRolesBucketName = []byte("authRoles")
+
+ testBucketName = []byte("test")
+)
+
+var (
+ Key = backend.Bucket(bucket{id: 1, name: keyBucketName, safeRangeBucket: true})
+ Meta = backend.Bucket(bucket{id: 2, name: metaBucketName, safeRangeBucket: false})
+ Lease = backend.Bucket(bucket{id: 3, name: leaseBucketName, safeRangeBucket: false})
+ Alarm = backend.Bucket(bucket{id: 4, name: alarmBucketName, safeRangeBucket: false})
+ Cluster = backend.Bucket(bucket{id: 5, name: clusterBucketName, safeRangeBucket: false})
+
+ Members = backend.Bucket(bucket{id: 10, name: membersBucketName, safeRangeBucket: false})
+ MembersRemoved = backend.Bucket(bucket{id: 11, name: membersRemovedBucketName, safeRangeBucket: false})
+
+ Auth = backend.Bucket(bucket{id: 20, name: authBucketName, safeRangeBucket: false})
+ AuthUsers = backend.Bucket(bucket{id: 21, name: authUsersBucketName, safeRangeBucket: false})
+ AuthRoles = backend.Bucket(bucket{id: 22, name: authRolesBucketName, safeRangeBucket: false})
+
+ Test = backend.Bucket(bucket{id: 100, name: testBucketName, safeRangeBucket: false})
+)
+
+type bucket struct {
+ id backend.BucketID
+ name []byte
+ safeRangeBucket bool
+}
+
+func (b bucket) ID() backend.BucketID { return b.id }
+func (b bucket) Name() []byte { return b.name }
+func (b bucket) String() string { return string(b.Name()) }
+func (b bucket) IsSafeRangeBucket() bool { return b.safeRangeBucket }
+
+var (
+ MetaConsistentIndexKeyName = []byte("consistent_index")
+ MetaTermKeyName = []byte("term")
+)
+
+// DefaultIgnores defines buckets & keys to ignore in hash checking.
+func DefaultIgnores(bucket, key []byte) bool {
+ // consistent index & term might be changed due to v2 internal sync, which
+ // is not controllable by the user.
+ return bytes.Compare(bucket, Meta.Name()) == 0 &&
+ (bytes.Compare(key, MetaTermKeyName) == 0 || bytes.Compare(key, MetaConsistentIndexKeyName) == 0)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/doc.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/doc.go
new file mode 100644
index 0000000000..ad5be03086
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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/go.etcd.io/etcd/server/v3/mvcc/hash.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/hash.go
new file mode 100644
index 0000000000..11232bf567
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/hash.go
@@ -0,0 +1,162 @@
+// Copyright 2022 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 (
+ "hash"
+ "hash/crc32"
+ "sort"
+ "sync"
+
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+ "go.uber.org/zap"
+)
+
+const (
+ hashStorageMaxSize = 10
+)
+
+func unsafeHashByRev(tx backend.ReadTx, compactRevision, revision int64, keep map[revision]struct{}) (KeyValueHash, error) {
+ h := newKVHasher(compactRevision, revision, keep)
+ err := tx.UnsafeForEach(buckets.Key, func(k, v []byte) error {
+ h.WriteKeyValue(k, v)
+ return nil
+ })
+ return h.Hash(), err
+}
+
+type kvHasher struct {
+ hash hash.Hash32
+ compactRevision int64
+ revision int64
+ keep map[revision]struct{}
+}
+
+func newKVHasher(compactRev, rev int64, keep map[revision]struct{}) kvHasher {
+ h := crc32.New(crc32.MakeTable(crc32.Castagnoli))
+ h.Write(buckets.Key.Name())
+ return kvHasher{
+ hash: h,
+ compactRevision: compactRev,
+ revision: rev,
+ keep: keep,
+ }
+}
+
+func (h *kvHasher) WriteKeyValue(k, v []byte) {
+ kr := bytesToRev(k)
+ upper := revision{main: h.revision + 1}
+ if !upper.GreaterThan(kr) {
+ return
+ }
+ lower := revision{main: h.compactRevision + 1}
+ // skip revisions that are scheduled for deletion
+ // due to compacting; don't skip if there isn't one.
+ if lower.GreaterThan(kr) && len(h.keep) > 0 {
+ if _, ok := h.keep[kr]; !ok {
+ return
+ }
+ }
+ h.hash.Write(k)
+ h.hash.Write(v)
+}
+
+func (h *kvHasher) Hash() KeyValueHash {
+ return KeyValueHash{Hash: h.hash.Sum32(), CompactRevision: h.compactRevision, Revision: h.revision}
+}
+
+type KeyValueHash struct {
+ Hash uint32
+ CompactRevision int64
+ Revision int64
+}
+
+type HashStorage interface {
+ // 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 KeyValueHash, currentRev int64, err error)
+
+ // Store adds hash value in local cache, allowing it can be returned by HashByRev.
+ Store(valueHash KeyValueHash)
+
+ // Hashes returns list of up to `hashStorageMaxSize` newest previously stored hashes.
+ Hashes() []KeyValueHash
+}
+
+type hashStorage struct {
+ store *store
+ hashMu sync.RWMutex
+ hashes []KeyValueHash
+ lg *zap.Logger
+}
+
+func newHashStorage(lg *zap.Logger, s *store) *hashStorage {
+ return &hashStorage{
+ store: s,
+ lg: lg,
+ }
+}
+
+func (s *hashStorage) Hash() (hash uint32, revision int64, err error) {
+ return s.store.hash()
+}
+
+func (s *hashStorage) HashByRev(rev int64) (KeyValueHash, int64, error) {
+ s.hashMu.RLock()
+ for _, h := range s.hashes {
+ if rev == h.Revision {
+ s.hashMu.RUnlock()
+
+ s.store.revMu.RLock()
+ currentRev := s.store.currentRev
+ s.store.revMu.RUnlock()
+ return h, currentRev, nil
+ }
+ }
+ s.hashMu.RUnlock()
+
+ return s.store.hashByRev(rev)
+}
+
+func (s *hashStorage) Store(hash KeyValueHash) {
+ s.lg.Info("storing new hash",
+ zap.Uint32("hash", hash.Hash),
+ zap.Int64("revision", hash.Revision),
+ zap.Int64("compact-revision", hash.CompactRevision),
+ )
+ s.hashMu.Lock()
+ defer s.hashMu.Unlock()
+ s.hashes = append(s.hashes, hash)
+ sort.Slice(s.hashes, func(i, j int) bool {
+ return s.hashes[i].Revision < s.hashes[j].Revision
+ })
+ if len(s.hashes) > hashStorageMaxSize {
+ s.hashes = s.hashes[len(s.hashes)-hashStorageMaxSize:]
+ }
+}
+
+func (s *hashStorage) Hashes() []KeyValueHash {
+ s.hashMu.RLock()
+ // Copy out hashes under lock just to be safe
+ hashes := make([]KeyValueHash, 0, len(s.hashes))
+ for _, hash := range s.hashes {
+ hashes = append(hashes, hash)
+ }
+ s.hashMu.RUnlock()
+ return hashes
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/index.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/index.go
new file mode 100644
index 0000000000..0a5cb00516
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/index.go
@@ -0,0 +1,276 @@
+// 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"
+ "go.uber.org/zap"
+)
+
+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, limit int) ([]revision, int)
+ CountRevisions(key, end []byte, atRev int64) int
+ 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
+ lg *zap.Logger
+}
+
+func newTreeIndex(lg *zap.Logger) index {
+ return &treeIndex{
+ tree: btree.New(32),
+ lg: lg,
+ }
+}
+
+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(ti.lg, rev.main, rev.sub)
+ ti.tree.ReplaceOrInsert(keyi)
+ return
+ }
+ okeyi := item.(*keyIndex)
+ okeyi.put(ti.lg, 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(ti.lg, 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) bool) {
+ 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
+ }
+ if !f(item.(*keyIndex)) {
+ return false
+ }
+ return true
+ })
+}
+
+func (ti *treeIndex) Revisions(key, end []byte, atRev int64, limit int) (revs []revision, total int) {
+ if end == nil {
+ rev, _, _, err := ti.Get(key, atRev)
+ if err != nil {
+ return nil, 0
+ }
+ return []revision{rev}, 1
+ }
+ ti.visit(key, end, func(ki *keyIndex) bool {
+ if rev, _, _, err := ki.get(ti.lg, atRev); err == nil {
+ if limit <= 0 || len(revs) < limit {
+ revs = append(revs, rev)
+ }
+ total++
+ }
+ return true
+ })
+ return revs, total
+}
+
+func (ti *treeIndex) CountRevisions(key, end []byte, atRev int64) int {
+ if end == nil {
+ _, _, _, err := ti.Get(key, atRev)
+ if err != nil {
+ return 0
+ }
+ return 1
+ }
+ total := 0
+ ti.visit(key, end, func(ki *keyIndex) bool {
+ if _, _, _, err := ki.get(ti.lg, atRev); err == nil {
+ total++
+ }
+ return true
+ })
+ return total
+}
+
+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) bool {
+ if rev, _, _, err := ki.get(ti.lg, atRev); err == nil {
+ revs = append(revs, rev)
+ keys = append(keys, ki.key)
+ }
+ return true
+ })
+ 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(ti.lg, 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(ti.lg, 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(ti.lg, rev)...)
+ return true
+ })
+ sort.Sort(revisions(revs))
+
+ return revs
+}
+
+func (ti *treeIndex) Compact(rev int64) map[revision]struct{} {
+ available := make(map[revision]struct{})
+ ti.lg.Info("compact tree index", zap.Int64("revision", rev))
+ ti.Lock()
+ clone := ti.tree.Clone()
+ ti.Unlock()
+
+ clone.Ascend(func(item btree.Item) bool {
+ keyi := item.(*keyIndex)
+ //Lock is needed here to prevent modification to the keyIndex while
+ //compaction is going on or revision added to empty before deletion
+ ti.Lock()
+ keyi.compact(ti.lg, rev, available)
+ if keyi.isEmpty() {
+ item := ti.tree.Delete(keyi)
+ if item == nil {
+ ti.lg.Panic("failed to delete during compaction")
+ }
+ }
+ ti.Unlock()
+ return true
+ })
+ 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 (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/go.etcd.io/etcd/server/v3/mvcc/key_index.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/key_index.go
new file mode 100644
index 0000000000..daec978258
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/key_index.go
@@ -0,0 +1,383 @@
+// 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"
+ "go.uber.org/zap"
+)
+
+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(lg *zap.Logger, main int64, sub int64) {
+ rev := revision{main: main, sub: sub}
+
+ if !rev.GreaterThan(ki.modified) {
+ lg.Panic(
+ "'put' with an unexpected smaller revision",
+ zap.Int64("given-revision-main", rev.main),
+ zap.Int64("given-revision-sub", rev.sub),
+ zap.Int64("modified-revision-main", ki.modified.main),
+ zap.Int64("modified-revision-sub", ki.modified.sub),
+ )
+ }
+ 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(lg *zap.Logger, created, modified revision, ver int64) {
+ if len(ki.generations) != 0 {
+ lg.Panic(
+ "'restore' got an unexpected non-empty generations",
+ zap.Int("generations-size", len(ki.generations)),
+ )
+ }
+
+ 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(lg *zap.Logger, main int64, sub int64) error {
+ if ki.isEmpty() {
+ lg.Panic(
+ "'tombstone' got an unexpected empty keyIndex",
+ zap.String("key", string(ki.key)),
+ )
+ }
+ if ki.generations[len(ki.generations)-1].isEmpty() {
+ return ErrRevisionNotFound
+ }
+ ki.put(lg, 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(lg *zap.Logger, atRev int64) (modified, created revision, ver int64, err error) {
+ if ki.isEmpty() {
+ lg.Panic(
+ "'get' got an unexpected empty keyIndex",
+ zap.String("key", 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(lg *zap.Logger, rev int64) []revision {
+ if ki.isEmpty() {
+ lg.Panic(
+ "'since' got an unexpected empty keyIndex",
+ zap.String("key", 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(lg *zap.Logger, atRev int64, available map[revision]struct{}) {
+ if ki.isEmpty() {
+ lg.Panic(
+ "'compact' got an unexpected empty keyIndex",
+ zap.String("key", 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 (ki *keyIndex) Less(b btree.Item) bool {
+ return bytes.Compare(ki.key, b.(*keyIndex).key) == -1
+}
+
+func (ki *keyIndex) equal(b *keyIndex) bool {
+ if !bytes.Equal(ki.key, b.key) {
+ return false
+ }
+ if ki.modified != b.modified {
+ return false
+ }
+ if len(ki.generations) != len(b.generations) {
+ return false
+ }
+ for i := range ki.generations {
+ ag, bg := ki.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 (g generation) equal(b generation) bool {
+ if g.ver != b.ver {
+ return false
+ }
+ if len(g.revs) != len(b.revs) {
+ return false
+ }
+
+ for i := range g.revs {
+ ar, br := g.revs[i], b.revs[i]
+ if ar != br {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/kv.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/kv.go
new file mode 100644
index 0000000000..109b0d7ccb
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/kv.go
@@ -0,0 +1,147 @@
+// 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"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+)
+
+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(ctx context.Context, 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 ReadTxMode uint32
+
+const (
+ // Use ConcurrentReadTx and the txReadBuffer is copied
+ ConcurrentReadTxMode = ReadTxMode(1)
+ // Use backend ReadTx and txReadBuffer is not copied
+ SharedBufReadTxMode = ReadTxMode(2)
+)
+
+type KV interface {
+ ReadView
+ WriteView
+
+ // Read creates a read transaction.
+ Read(mode ReadTxMode, trace *traceutil.Trace) TxnRead
+
+ // Write creates a write transaction.
+ Write(trace *traceutil.Trace) TxnWrite
+
+ // HashStorage returns HashStorage interface for KV storage.
+ HashStorage() HashStorage
+
+ // Compact frees all superseded keys with revisions less than rev.
+ Compact(trace *traceutil.Trace, 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
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/kv_view.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/kv_view.go
new file mode 100644
index 0000000000..56260e7599
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/kv_view.go
@@ -0,0 +1,56 @@
+// 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 (
+ "context"
+
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/lease"
+)
+
+type readView struct{ kv KV }
+
+func (rv *readView) FirstRev() int64 {
+ tr := rv.kv.Read(ConcurrentReadTxMode, traceutil.TODO())
+ defer tr.End()
+ return tr.FirstRev()
+}
+
+func (rv *readView) Rev() int64 {
+ tr := rv.kv.Read(ConcurrentReadTxMode, traceutil.TODO())
+ defer tr.End()
+ return tr.Rev()
+}
+
+func (rv *readView) Range(ctx context.Context, key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
+ tr := rv.kv.Read(ConcurrentReadTxMode, traceutil.TODO())
+ defer tr.End()
+ return tr.Range(ctx, key, end, ro)
+}
+
+type writeView struct{ kv KV }
+
+func (wv *writeView) DeleteRange(key, end []byte) (n, rev int64) {
+ tw := wv.kv.Write(traceutil.TODO())
+ defer tw.End()
+ return tw.DeleteRange(key, end)
+}
+
+func (wv *writeView) Put(key, value []byte, lease lease.LeaseID) (rev int64) {
+ tw := wv.kv.Write(traceutil.TODO())
+ defer tw.End()
+ return tw.Put(key, value, lease)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore.go
new file mode 100644
index 0000000000..e1f74760ed
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore.go
@@ -0,0 +1,551 @@
+// 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"
+ "errors"
+ "fmt"
+ "math"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/pkg/v3/schedule"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+
+ "go.uber.org/zap"
+)
+
+var (
+ 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")
+)
+
+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
+var defaultCompactBatchLimit = 1000
+
+type StoreConfig struct {
+ CompactionBatchLimit int
+}
+
+type store struct {
+ ReadView
+ WriteView
+
+ cfg StoreConfig
+
+ // mu read locks for txns and write locks for non-txn store changes.
+ mu sync.RWMutex
+
+ 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
+
+ fifoSched schedule.Scheduler
+
+ stopc chan struct{}
+
+ lg *zap.Logger
+ hashes HashStorage
+}
+
+// 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(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfig) *store {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ if cfg.CompactionBatchLimit == 0 {
+ cfg.CompactionBatchLimit = defaultCompactBatchLimit
+ }
+ s := &store{
+ cfg: cfg,
+ b: b,
+ kvindex: newTreeIndex(lg),
+
+ le: le,
+
+ currentRev: 1,
+ compactMainRev: -1,
+
+ fifoSched: schedule.NewFIFOScheduler(),
+
+ stopc: make(chan struct{}),
+
+ lg: lg,
+ }
+ s.hashes = newHashStorage(lg, s)
+ s.ReadView = &readView{s}
+ s.WriteView = &writeView{s}
+ if s.le != nil {
+ s.le.SetRangeDeleter(func() lease.TxnDelete { return s.Write(traceutil.TODO()) })
+ }
+
+ tx := s.b.BatchTx()
+ tx.LockOutsideApply()
+ tx.UnsafeCreateBucket(buckets.Key)
+ tx.UnsafeCreateBucket(buckets.Meta)
+ tx.Unlock()
+ s.b.ForceCommit()
+
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ 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 {
+ select {
+ case <-s.stopc:
+ default:
+ // fix deadlock in mvcc,for more information, please refer to pr 11817.
+ // s.stopc is only updated in restore operation, which is called by apply
+ // snapshot call, compaction and apply snapshot requests are serialized by
+ // raft, and do not happen at the same time.
+ s.mu.Lock()
+ 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) {
+ // TODO: hash and revision could be inconsistent, one possible fix is to add s.revMu.RLock() at the beginning of function, which is costly
+ start := time.Now()
+
+ s.b.ForceCommit()
+ h, err := s.b.Hash(buckets.DefaultIgnores)
+
+ hashSec.Observe(time.Since(start).Seconds())
+ return h, s.currentRev, err
+}
+
+func (s *store) hashByRev(rev int64) (hash KeyValueHash, currentRev int64, err error) {
+ var compactRev int64
+ 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 KeyValueHash{}, 0, ErrCompacted
+ } else if rev > 0 && rev > currentRev {
+ s.mu.RUnlock()
+ return KeyValueHash{}, currentRev, ErrFutureRev
+ }
+ if rev == 0 {
+ rev = currentRev
+ }
+ keep := s.kvindex.Keep(rev)
+
+ tx := s.b.ReadTx()
+ tx.RLock()
+ defer tx.RUnlock()
+ s.mu.RUnlock()
+ hash, err = unsafeHashByRev(tx, compactRev, rev, keep)
+ hashRevSec.Observe(time.Since(start).Seconds())
+ return hash, currentRev, err
+}
+
+func (s *store) updateCompactRev(rev int64) (<-chan struct{}, int64, error) {
+ s.revMu.Lock()
+ if rev <= s.compactMainRev {
+ ch := make(chan struct{})
+ f := func(ctx context.Context) { s.compactBarrier(ctx, ch) }
+ s.fifoSched.Schedule(f)
+ s.revMu.Unlock()
+ return ch, 0, ErrCompacted
+ }
+ if rev > s.currentRev {
+ s.revMu.Unlock()
+ return nil, 0, ErrFutureRev
+ }
+ compactMainRev := s.compactMainRev
+ s.compactMainRev = rev
+
+ rbytes := newRevBytes()
+ revToBytes(revision{main: rev}, rbytes)
+
+ tx := s.b.BatchTx()
+ tx.LockInsideApply()
+ tx.UnsafePut(buckets.Meta, scheduledCompactKeyName, rbytes)
+ tx.Unlock()
+ // ensure that desired compaction is persisted
+ s.b.ForceCommit()
+
+ s.revMu.Unlock()
+
+ return nil, compactMainRev, nil
+}
+
+// checkPrevCompactionCompleted checks whether the previous scheduled compaction is completed.
+func (s *store) checkPrevCompactionCompleted() bool {
+ tx := s.b.ReadTx()
+ tx.Lock()
+ defer tx.Unlock()
+ scheduledCompact, scheduledCompactFound := UnsafeReadScheduledCompact(tx)
+ finishedCompact, finishedCompactFound := UnsafeReadFinishedCompact(tx)
+ return scheduledCompact == finishedCompact && scheduledCompactFound == finishedCompactFound
+}
+
+func (s *store) compact(trace *traceutil.Trace, rev, prevCompactRev int64, prevCompactionCompleted bool) (<-chan struct{}, error) {
+ ch := make(chan struct{})
+ var j = func(ctx context.Context) {
+ if ctx.Err() != nil {
+ s.compactBarrier(ctx, ch)
+ return
+ }
+ hash, err := s.scheduleCompaction(rev, prevCompactRev)
+ if err != nil {
+ s.lg.Warn("Failed compaction", zap.Error(err))
+ s.compactBarrier(context.TODO(), ch)
+ return
+ }
+ // Only store the hash value if the previous hash is completed, i.e. this compaction
+ // hashes every revision from last compaction. For more details, see #15919.
+ if prevCompactionCompleted {
+ s.hashes.Store(hash)
+ } else {
+ s.lg.Info("previous compaction was interrupted, skip storing compaction hash value")
+ }
+ close(ch)
+ }
+
+ s.fifoSched.Schedule(j)
+ trace.Step("schedule compaction")
+ return ch, nil
+}
+
+func (s *store) compactLockfree(rev int64) (<-chan struct{}, error) {
+ prevCompactionCompleted := s.checkPrevCompactionCompleted()
+ ch, prevCompactRev, err := s.updateCompactRev(rev)
+ if err != nil {
+ return ch, err
+ }
+
+ return s.compact(traceutil.TODO(), rev, prevCompactRev, prevCompactionCompleted)
+}
+
+func (s *store) Compact(trace *traceutil.Trace, rev int64) (<-chan struct{}, error) {
+ s.mu.Lock()
+
+ prevCompactionCompleted := s.checkPrevCompactionCompleted()
+ ch, prevCompactRev, err := s.updateCompactRev(rev)
+ trace.Step("check and update compact revision")
+ if err != nil {
+ s.mu.Unlock()
+ return ch, err
+ }
+ s.mu.Unlock()
+
+ return s.compact(trace, rev, prevCompactRev, prevCompactionCompleted)
+}
+
+func (s *store) Commit() {
+ s.mu.Lock()
+ defer s.mu.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()
+
+ s.b = b
+ s.kvindex = newTreeIndex(s.lg)
+
+ {
+ // During restore the metrics might report 'special' values
+ s.revMu.Lock()
+ s.currentRev = 1
+ s.compactMainRev = -1
+ s.revMu.Unlock()
+ }
+
+ s.fifoSched = schedule.NewFIFOScheduler()
+ s.stopc = make(chan struct{})
+
+ return s.restore()
+}
+
+func (s *store) restore() error {
+ s.setupMetricsReporter()
+
+ 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.ReadTx()
+ tx.Lock()
+
+ finishedCompact, found := UnsafeReadFinishedCompact(tx)
+ if found {
+ s.revMu.Lock()
+ s.compactMainRev = finishedCompact
+
+ s.lg.Info(
+ "restored last compact revision",
+ zap.Stringer("meta-bucket-name", buckets.Meta),
+ zap.String("meta-bucket-name-key", string(finishedCompactKeyName)),
+ zap.Int64("restored-compact-revision", s.compactMainRev),
+ )
+ s.revMu.Unlock()
+ }
+ scheduledCompact, _ := UnsafeReadScheduledCompact(tx)
+
+ // index keys concurrently as they're loaded in from tx
+ keysGauge.Set(0)
+ rkvc, revc := restoreIntoIndex(s.lg, s.kvindex)
+ for {
+ keys, vals := tx.UnsafeRange(buckets.Key, 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(s.lg, 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.revMu.Lock()
+ 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
+ }
+ s.revMu.Unlock()
+ }
+
+ if scheduledCompact <= s.compactMainRev {
+ scheduledCompact = 0
+ }
+
+ for key, lid := range keyToLease {
+ if s.le == nil {
+ tx.Unlock()
+ panic("no lessor to attach lease")
+ }
+ err := s.le.Attach(lid, []lease.LeaseItem{{Key: key}})
+ if err != nil {
+ s.lg.Error(
+ "failed to attach a lease",
+ zap.String("lease-id", fmt.Sprintf("%016x", lid)),
+ zap.Error(err),
+ )
+ }
+ }
+
+ tx.Unlock()
+
+ s.lg.Info("kvstore restored", zap.Int64("current-rev", s.currentRev))
+
+ if scheduledCompact != 0 {
+ if _, err := s.compactLockfree(scheduledCompact); err != nil {
+ s.lg.Warn("compaction encountered error", zap.Error(err))
+ }
+
+ s.lg.Info(
+ "resume scheduled compaction",
+ zap.Stringer("meta-bucket-name", buckets.Meta),
+ zap.String("meta-bucket-name-key", string(scheduledCompactKeyName)),
+ zap.Int64("scheduled-compact-revision", scheduledCompact),
+ )
+ }
+
+ return nil
+}
+
+type revKeyValue struct {
+ key []byte
+ kv mvccpb.KeyValue
+ kstr string
+}
+
+func restoreIntoIndex(lg *zap.Logger, 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) {
+ if err := ki.tombstone(lg, rev.main, rev.sub); err != nil {
+ lg.Warn("tombstone encountered error", zap.Error(err))
+ }
+ continue
+ }
+ ki.put(lg, rev.main, rev.sub)
+ } else if !isTombstone(rkv.key) {
+ ki.restore(lg, revision{rkv.kv.CreateRevision, 0}, rev, rkv.kv.Version)
+ idx.Insert(ki)
+ kiCache[rkv.kstr] = ki
+ }
+ }
+ }()
+ return rkvc, revc
+}
+
+func restoreChunk(lg *zap.Logger, 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 {
+ lg.Fatal("failed to unmarshal mvccpb.KeyValue", zap.Error(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) setupMetricsReporter() {
+ b := s.b
+ reportDbTotalSizeInBytesMu.Lock()
+ reportDbTotalSizeInBytes = func() float64 { return float64(b.Size()) }
+ reportDbTotalSizeInBytesMu.Unlock()
+ reportDbTotalSizeInBytesDebugMu.Lock()
+ reportDbTotalSizeInBytesDebug = func() float64 { return float64(b.Size()) }
+ reportDbTotalSizeInBytesDebugMu.Unlock()
+ reportDbTotalSizeInUseInBytesMu.Lock()
+ reportDbTotalSizeInUseInBytes = func() float64 { return float64(b.SizeInUse()) }
+ reportDbTotalSizeInUseInBytesMu.Unlock()
+ reportDbOpenReadTxNMu.Lock()
+ reportDbOpenReadTxN = func() float64 { return float64(b.OpenReadTxN()) }
+ reportDbOpenReadTxNMu.Unlock()
+ reportCurrentRevMu.Lock()
+ reportCurrentRev = func() float64 {
+ s.revMu.RLock()
+ defer s.revMu.RUnlock()
+ return float64(s.currentRev)
+ }
+ reportCurrentRevMu.Unlock()
+ reportCompactRevMu.Lock()
+ reportCompactRev = func() float64 {
+ s.revMu.RLock()
+ defer s.revMu.RUnlock()
+ return float64(s.compactMainRev)
+ }
+ reportCompactRevMu.Unlock()
+}
+
+// appendMarkTombstone appends tombstone mark to normal revision bytes.
+func appendMarkTombstone(lg *zap.Logger, b []byte) []byte {
+ if len(b) != revBytesLen {
+ lg.Panic(
+ "cannot append tombstone mark to non-normal revision bytes",
+ zap.Int("expected-revision-bytes-size", revBytesLen),
+ zap.Int("given-revision-bytes-size", len(b)),
+ )
+ }
+ 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
+}
+
+func (s *store) HashStorage() HashStorage {
+ return s.hashes
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_compaction.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_compaction.go
new file mode 100644
index 0000000000..a1028e122f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_compaction.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 mvcc
+
+import (
+ "encoding/binary"
+ "fmt"
+ "time"
+
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+ "go.uber.org/zap"
+)
+
+func (s *store) scheduleCompaction(compactMainRev, prevCompactRev int64) (KeyValueHash, error) {
+ totalStart := time.Now()
+ keep := s.kvindex.Compact(compactMainRev)
+ indexCompactionPauseMs.Observe(float64(time.Since(totalStart) / time.Millisecond))
+
+ totalStart = time.Now()
+ defer func() { dbCompactionTotalMs.Observe(float64(time.Since(totalStart) / time.Millisecond)) }()
+ keyCompactions := 0
+ defer func() { dbCompactionKeysCounter.Add(float64(keyCompactions)) }()
+ defer func() { dbCompactionLast.Set(float64(time.Now().Unix())) }()
+
+ end := make([]byte, 8)
+ binary.BigEndian.PutUint64(end, uint64(compactMainRev+1))
+
+ batchNum := s.cfg.CompactionBatchLimit
+ h := newKVHasher(prevCompactRev, compactMainRev, keep)
+ last := make([]byte, 8+1+8)
+ for {
+ var rev revision
+
+ start := time.Now()
+
+ tx := s.b.BatchTx()
+ tx.LockOutsideApply()
+ keys, values := tx.UnsafeRange(buckets.Key, last, end, int64(batchNum))
+ for i := range keys {
+ rev = bytesToRev(keys[i])
+ if _, ok := keep[rev]; !ok {
+ tx.UnsafeDelete(buckets.Key, keys[i])
+ keyCompactions++
+ }
+ h.WriteKeyValue(keys[i], values[i])
+ }
+
+ if len(keys) < s.cfg.CompactionBatchLimit {
+ rbytes := make([]byte, 8+1+8)
+ revToBytes(revision{main: compactMainRev}, rbytes)
+ tx.UnsafePut(buckets.Meta, finishedCompactKeyName, rbytes)
+ tx.Unlock()
+ hash := h.Hash()
+ s.lg.Info(
+ "finished scheduled compaction",
+ zap.Int64("compact-revision", compactMainRev),
+ zap.Duration("took", time.Since(totalStart)),
+ zap.Uint32("hash", hash.Hash),
+ )
+ return hash, nil
+ }
+
+ // update last
+ revToBytes(revision{main: rev.main, sub: rev.sub + 1}, last)
+ tx.Unlock()
+ // Immediately commit the compaction deletes instead of letting them accumulate in the write buffer
+ s.b.ForceCommit()
+ dbCompactionPauseMs.Observe(float64(time.Since(start) / time.Millisecond))
+
+ select {
+ case <-time.After(10 * time.Millisecond):
+ case <-s.stopc:
+ return KeyValueHash{}, fmt.Errorf("interrupted due to stop signal")
+ }
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_txn.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_txn.go
new file mode 100644
index 0000000000..855ededddb
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_txn.go
@@ -0,0 +1,312 @@
+// 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 (
+ "context"
+ "fmt"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+ "go.uber.org/zap"
+)
+
+type storeTxnRead struct {
+ s *store
+ tx backend.ReadTx
+
+ firstRev int64
+ rev int64
+
+ trace *traceutil.Trace
+}
+
+func (s *store) Read(mode ReadTxMode, trace *traceutil.Trace) TxnRead {
+ s.mu.RLock()
+ s.revMu.RLock()
+ // For read-only workloads, we use shared buffer by copying transaction read buffer
+ // for higher concurrency with ongoing blocking writes.
+ // For write/write-read transactions, we use the shared buffer
+ // rather than duplicating transaction read buffer to avoid transaction overhead.
+ var tx backend.ReadTx
+ if mode == ConcurrentReadTxMode {
+ tx = s.b.ConcurrentReadTx()
+ } else {
+ tx = s.b.ReadTx()
+ }
+
+ tx.RLock() // RLock is no-op. concurrentReadTx does not need to be locked after it is created.
+ firstRev, rev := s.compactMainRev, s.currentRev
+ s.revMu.RUnlock()
+ return newMetricsTxnRead(&storeTxnRead{s, tx, firstRev, rev, trace})
+}
+
+func (tr *storeTxnRead) FirstRev() int64 { return tr.firstRev }
+func (tr *storeTxnRead) Rev() int64 { return tr.rev }
+
+func (tr *storeTxnRead) Range(ctx context.Context, key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
+ return tr.rangeKeys(ctx, key, end, tr.Rev(), ro)
+}
+
+func (tr *storeTxnRead) End() {
+ tr.tx.RUnlock() // RUnlock signals the end of concurrentReadTx.
+ 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(trace *traceutil.Trace) TxnWrite {
+ s.mu.RLock()
+ tx := s.b.BatchTx()
+ tx.LockInsideApply()
+ tw := &storeTxnWrite{
+ storeTxnRead: storeTxnRead{s, tx, 0, 0, trace},
+ 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(ctx context.Context, key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
+ rev := tw.beginRev
+ if len(tw.changes) > 0 {
+ rev++
+ }
+ return tw.rangeKeys(ctx, 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, tw.beginRev + 1
+ }
+ return 0, tw.beginRev
+}
+
+func (tw *storeTxnWrite) Put(key, value []byte, lease lease.LeaseID) int64 {
+ tw.put(key, value, lease)
+ return tw.beginRev + 1
+}
+
+func (tw *storeTxnWrite) End() {
+ // only update index if the txn modifies the mvcc state.
+ if len(tw.changes) != 0 {
+ // 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(ctx context.Context, 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
+ }
+ if ro.Count {
+ total := tr.s.kvindex.CountRevisions(key, end, rev)
+ tr.trace.Step("count revisions from in-memory index tree")
+ return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil
+ }
+ revpairs, total := tr.s.kvindex.Revisions(key, end, rev, int(ro.Limit))
+ tr.trace.Step("range keys from in-memory index tree")
+ if len(revpairs) == 0 {
+ return &RangeResult{KVs: nil, Count: total, 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)] {
+ select {
+ case <-ctx.Done():
+ return nil, fmt.Errorf("rangeKeys: context cancelled: %w", ctx.Err())
+ default:
+ }
+ revToBytes(revpair, revBytes)
+ _, vs := tr.tx.UnsafeRange(buckets.Key, revBytes, nil, 0)
+ if len(vs) != 1 {
+ tr.s.lg.Fatal(
+ "range failed to find revision pair",
+ zap.Int64("revision-main", revpair.main),
+ zap.Int64("revision-sub", revpair.sub),
+ zap.Int64("revision-current", curRev),
+ zap.Int64("range-option-rev", ro.Rev),
+ zap.Int64("range-option-limit", ro.Limit),
+ zap.Binary("key", key),
+ zap.Binary("end", end),
+ zap.Int("len-revpairs", len(revpairs)),
+ zap.Int("len-values", len(vs)),
+ )
+ }
+ if err := kvs[i].Unmarshal(vs[0]); err != nil {
+ tr.s.lg.Fatal(
+ "failed to unmarshal mvccpb.KeyValue",
+ zap.Error(err),
+ )
+ }
+ }
+ tr.trace.Step("range keys from bolt db")
+ return &RangeResult{KVs: kvs, Count: total, 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)})
+ tw.trace.Step("get key's previous created_revision and leaseID")
+ }
+ 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 {
+ tw.storeTxnRead.s.lg.Fatal(
+ "failed to marshal mvccpb.KeyValue",
+ zap.Error(err),
+ )
+ }
+
+ tw.trace.Step("marshal mvccpb.KeyValue")
+ tw.tx.UnsafeSeqPut(buckets.Key, ibytes, d)
+ tw.s.kvindex.Put(key, idxRev)
+ tw.changes = append(tw.changes, kv)
+ tw.trace.Step("store kv pair into bolt db")
+
+ 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 {
+ tw.storeTxnRead.s.lg.Error(
+ "failed to detach old lease from a key",
+ zap.Error(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")
+ }
+ }
+ tw.trace.Step("attach lease to kv pair")
+}
+
+func (tw *storeTxnWrite) deleteRange(key, end []byte) int64 {
+ rrev := tw.beginRev
+ if len(tw.changes) > 0 {
+ rrev++
+ }
+ keys, _ := tw.s.kvindex.Range(key, end, rrev)
+ if len(keys) == 0 {
+ return 0
+ }
+ for _, key := range keys {
+ tw.delete(key)
+ }
+ return int64(len(keys))
+}
+
+func (tw *storeTxnWrite) delete(key []byte) {
+ ibytes := newRevBytes()
+ idxRev := revision{main: tw.beginRev + 1, sub: int64(len(tw.changes))}
+ revToBytes(idxRev, ibytes)
+
+ ibytes = appendMarkTombstone(tw.storeTxnRead.s.lg, ibytes)
+
+ kv := mvccpb.KeyValue{Key: key}
+
+ d, err := kv.Marshal()
+ if err != nil {
+ tw.storeTxnRead.s.lg.Fatal(
+ "failed to marshal mvccpb.KeyValue",
+ zap.Error(err),
+ )
+ }
+
+ tw.tx.UnsafeSeqPut(buckets.Key, ibytes, d)
+ err = tw.s.kvindex.Tombstone(key, idxRev)
+ if err != nil {
+ tw.storeTxnRead.s.lg.Fatal(
+ "failed to tombstone an existing key",
+ zap.String("key", string(key)),
+ zap.Error(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 {
+ tw.storeTxnRead.s.lg.Error(
+ "failed to detach old lease from a key",
+ zap.Error(err),
+ )
+ }
+ }
+}
+
+func (tw *storeTxnWrite) Changes() []mvccpb.KeyValue { return tw.changes }
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics.go
new file mode 100644
index 0000000000..f28d114e2b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics.go
@@ -0,0 +1,314 @@
+// 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",
+ Subsystem: "mvcc",
+ Name: "range_total",
+ Help: "Total number of ranges seen by this member.",
+ })
+ rangeCounterDebug = 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",
+ Subsystem: "mvcc",
+ Name: "put_total",
+ Help: "Total number of puts seen by this member.",
+ })
+
+ deleteCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "mvcc",
+ Name: "delete_total",
+ Help: "Total number of deletes seen by this member.",
+ })
+
+ txnCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd",
+ 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.",
+ })
+
+ indexCompactionPauseMs = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "index_compaction_pause_duration_milliseconds",
+ Help: "Bucketed histogram of index compaction pause duration.",
+
+ // lowest bucket start of upper bound 0.5 ms with factor 2
+ // highest bucket start of 0.5 ms * 2^13 == 4.096 sec
+ Buckets: prometheus.ExponentialBuckets(0.5, 2, 14),
+ })
+
+ dbCompactionPauseMs = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_compaction_pause_duration_milliseconds",
+ Help: "Bucketed histogram of db compaction pause duration.",
+
+ // lowest bucket start of upper bound 1 ms with factor 2
+ // highest bucket start of 1 ms * 2^12 == 4.096 sec
+ Buckets: prometheus.ExponentialBuckets(1, 2, 13),
+ })
+
+ dbCompactionTotalMs = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_compaction_total_duration_milliseconds",
+ Help: "Bucketed histogram of db compaction total duration.",
+
+ // lowest bucket start of upper bound 100 ms with factor 2
+ // highest bucket start of 100 ms * 2^13 == 8.192 sec
+ Buckets: prometheus.ExponentialBuckets(100, 2, 14),
+ })
+
+ dbCompactionLast = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_compaction_last",
+ Help: "The unix time of the last db compaction. Resets to 0 on start.",
+ })
+
+ dbCompactionKeysCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_compaction_keys_total",
+ Help: "Total number of db keys compacted.",
+ })
+
+ 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 }
+
+ // overridden by mvcc initialization
+ reportDbTotalSizeInBytesDebugMu sync.RWMutex
+ reportDbTotalSizeInBytesDebug = 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 { return 0 }
+
+ dbOpenReadTxN = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "mvcc",
+ Name: "db_open_read_transactions",
+ Help: "The number of currently open read transactions",
+ },
+
+ func() float64 {
+ reportDbOpenReadTxNMu.RLock()
+ defer reportDbOpenReadTxNMu.RUnlock()
+ return reportDbOpenReadTxN()
+ },
+ )
+ // overridden by mvcc initialization
+ reportDbOpenReadTxNMu sync.RWMutex
+ reportDbOpenReadTxN = func() float64 { return 0 }
+
+ hashSec = 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),
+ })
+
+ hashRevSec = 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),
+ })
+
+ currentRev = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "current_revision",
+ Help: "The current revision of store.",
+ },
+ func() float64 {
+ reportCurrentRevMu.RLock()
+ defer reportCurrentRevMu.RUnlock()
+ return reportCurrentRev()
+ },
+ )
+ // overridden by mvcc initialization
+ reportCurrentRevMu sync.RWMutex
+ reportCurrentRev = func() float64 { return 0 }
+
+ compactRev = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "compact_revision",
+ Help: "The revision of the last compaction in store.",
+ },
+ func() float64 {
+ reportCompactRevMu.RLock()
+ defer reportCompactRevMu.RUnlock()
+ return reportCompactRev()
+ },
+ )
+ // overridden by mvcc initialization
+ reportCompactRevMu sync.RWMutex
+ reportCompactRev = func() float64 { return 0 }
+
+ totalPutSizeGauge = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "total_put_size_in_bytes",
+ Help: "The total size of put kv pairs seen by this member.",
+ })
+)
+
+func init() {
+ prometheus.MustRegister(rangeCounter)
+ prometheus.MustRegister(rangeCounterDebug)
+ 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(indexCompactionPauseMs)
+ prometheus.MustRegister(dbCompactionPauseMs)
+ prometheus.MustRegister(dbCompactionTotalMs)
+ prometheus.MustRegister(dbCompactionLast)
+ prometheus.MustRegister(dbCompactionKeysCounter)
+ prometheus.MustRegister(dbTotalSize)
+ prometheus.MustRegister(dbTotalSizeInUse)
+ prometheus.MustRegister(dbOpenReadTxN)
+ prometheus.MustRegister(hashSec)
+ prometheus.MustRegister(hashRevSec)
+ prometheus.MustRegister(currentRev)
+ prometheus.MustRegister(compactRev)
+ prometheus.MustRegister(totalPutSizeGauge)
+}
+
+// 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/go.etcd.io/etcd/server/v3/mvcc/metrics_txn.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics_txn.go
new file mode 100644
index 0000000000..af844f8468
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics_txn.go
@@ -0,0 +1,72 @@
+// 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 (
+ "context"
+
+ "go.etcd.io/etcd/server/v3/lease"
+)
+
+type metricsTxnWrite struct {
+ TxnWrite
+ ranges uint
+ puts uint
+ deletes uint
+ putSize int64
+}
+
+func newMetricsTxnRead(tr TxnRead) TxnRead {
+ return &metricsTxnWrite{&txnReadWrite{tr}, 0, 0, 0, 0}
+}
+
+func newMetricsTxnWrite(tw TxnWrite) TxnWrite {
+ return &metricsTxnWrite{tw, 0, 0, 0, 0}
+}
+
+func (tw *metricsTxnWrite) Range(ctx context.Context, key, end []byte, ro RangeOptions) (*RangeResult, error) {
+ tw.ranges++
+ return tw.TxnWrite.Range(ctx, 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++
+ size := int64(len(key) + len(value))
+ tw.putSize += size
+ 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()
+ }
+
+ ranges := float64(tw.ranges)
+ rangeCounter.Add(ranges)
+ rangeCounterDebug.Add(ranges) // TODO: remove in 3.5 release
+
+ puts := float64(tw.puts)
+ putCounter.Add(puts)
+ totalPutSizeGauge.Add(float64(tw.putSize))
+
+ deletes := float64(tw.deletes)
+ deleteCounter.Add(deletes)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/revision.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/revision.go
new file mode 100644
index 0000000000..d6213866f2
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/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 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/go.etcd.io/etcd/server/v3/mvcc/util.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/util.go
new file mode 100644
index 0000000000..ea3111267b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/util.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 mvcc
+
+import (
+ "fmt"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+)
+
+func WriteKV(be backend.Backend, kv mvccpb.KeyValue) {
+ ibytes := newRevBytes()
+ revToBytes(revision{main: kv.ModRevision}, ibytes)
+
+ d, err := kv.Marshal()
+ if err != nil {
+ panic(fmt.Errorf("cannot marshal event: %v", err))
+ }
+
+ be.BatchTx().LockOutsideApply()
+ be.BatchTx().UnsafePut(buckets.Key, ibytes, d)
+ be.BatchTx().Unlock()
+}
+
+func UnsafeSetScheduledCompact(tx backend.BatchTx, value int64) {
+ rbytes := newRevBytes()
+ revToBytes(revision{main: value}, rbytes)
+ tx.UnsafePut(buckets.Meta, scheduledCompactKeyName, rbytes)
+}
+
+func UnsafeReadFinishedCompact(tx backend.ReadTx) (int64, bool) {
+ _, finishedCompactBytes := tx.UnsafeRange(buckets.Meta, finishedCompactKeyName, nil, 0)
+ if len(finishedCompactBytes) != 0 {
+ return bytesToRev(finishedCompactBytes[0]).main, true
+ }
+ return 0, false
+}
+
+func UnsafeReadScheduledCompact(tx backend.ReadTx) (int64, bool) {
+ _, scheduledCompactBytes := tx.UnsafeRange(buckets.Meta, scheduledCompactKeyName, nil, 0)
+ if len(scheduledCompactBytes) != 0 {
+ return bytesToRev(scheduledCompactBytes[0]).main, true
+ }
+ return 0, false
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store.go
new file mode 100644
index 0000000000..85429e850a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store.go
@@ -0,0 +1,573 @@
+// 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"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ clientv3 "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+ "go.etcd.io/etcd/server/v3/lease"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ "go.etcd.io/etcd/server/v3/mvcc/buckets"
+
+ "go.uber.org/zap"
+)
+
+// non-const so modifiable by tests
+var (
+ // chanBufLen is the length of the buffered chan
+ // for sending out watched events.
+ // See https://github.com/etcd-io/etcd/issues/11906 for more detail.
+ chanBufLen = 128
+
+ // 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)
+ progressAll(watchers map[WatchID]*watcher) bool
+ 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(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfig) WatchableKV {
+ return newWatchableStore(lg, b, le, cfg)
+}
+
+func newWatchableStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfig) *watchableStore {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ s := &watchableStore{
+ store: NewStore(lg, b, le, cfg),
+ 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(traceutil.TODO()) })
+ }
+ 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
+ }
+ 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()
+ watcherGauge.Dec()
+ break
+ } else if s.synced.delete(wa) {
+ watcherGauge.Dec()
+ break
+ } else if wa.compacted {
+ watcherGauge.Dec()
+ break
+ } else if wa.ch == nil {
+ // already canceled (e.g., cancel/close race)
+ break
+ }
+
+ if !wa.victim {
+ s.mu.Unlock()
+ 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()
+ watcherGauge.Dec()
+ delete(victimBatch, wa)
+ break
+ }
+
+ // victim being processed so not accessible; retry
+ s.mu.Unlock()
+ time.Sleep(time.Millisecond)
+ }
+
+ 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.RLock()
+ revs, vs := tx.UnsafeRange(buckets.Key, minBytes, maxBytes, 0)
+ evs := kvsToEvents(s.store.lg, wg, revs, vs)
+ // Must unlock after kvsToEvents, because vs (come from boltdb memory) is not deep copy.
+ // We can only unlock after Unmarshal, which will do deep copy.
+ // Otherwise we will trigger SIGSEGV during boltdb re-mmap.
+ tx.RUnlock()
+
+ 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(lg *zap.Logger, wg *watcherGroup, revs, vals [][]byte) (evs []mvccpb.Event) {
+ for i, v := range vals {
+ var kv mvccpb.KeyValue
+ if err := kv.Unmarshal(v); err != nil {
+ lg.Panic("failed to unmarshal mvccpb.KeyValue", zap.Error(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 {
+ s.store.lg.Panic(
+ "unexpected multiple revisions in watch notification",
+ zap.Int("number-of-revisions", eb.revs),
+ )
+ }
+ if w.send(WatchResponse{WatchID: w.id, Events: eb.evs, Revision: rev}) {
+ pendingEventsGauge.Add(float64(len(eb.evs)))
+ } else {
+ // move slow watcher to victims
+ if victim == nil {
+ victim = make(watcherBatch)
+ }
+ w.victim = true
+ victim[w] = eb
+ s.synced.delete(w)
+ slowWatcherGauge.Inc()
+ }
+ // always update minRev
+ // in case 'send' returns true and watcher stays synced, this is needed for Restore when all watchers become unsynced
+ // in case 'send' returns false, this is needed for syncWatchers
+ w.minRev = rev + 1
+ }
+ 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.progressIfSync(map[WatchID]*watcher{w.id: w}, w.id)
+}
+
+func (s *watchableStore) progressAll(watchers map[WatchID]*watcher) bool {
+ return s.progressIfSync(watchers, clientv3.InvalidWatchID)
+}
+
+func (s *watchableStore) progressIfSync(watchers map[WatchID]*watcher, responseWatchID WatchID) bool {
+ s.mu.RLock()
+ defer s.mu.RUnlock()
+
+ // Any watcher unsynced?
+ for _, w := range watchers {
+ if _, ok := s.synced.watchers[w]; !ok {
+ return false
+ }
+ }
+
+ // If all watchers are synchronised, send out progress
+ // notification on first watcher. Note that all watchers
+ // should have the same underlying stream, and the progress
+ // notification will be broadcasted client-side if required
+ // (see dispatchEvent in client/v3/watch.go)
+ for _, w := range watchers {
+ w.send(WatchResponse{WatchID: responseWatchID, Revision: s.rev()})
+ return true
+ }
+ return true
+}
+
+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/go.etcd.io/etcd/server/v3/mvcc/watchable_store_txn.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store_txn.go
new file mode 100644
index 0000000000..b70d8ceca4
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store_txn.go
@@ -0,0 +1,56 @@
+// 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 (
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/pkg/v3/traceutil"
+)
+
+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(trace *traceutil.Trace) TxnWrite {
+ return &watchableStoreTxnWrite{s.store.Write(trace), s}
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher.go
new file mode 100644
index 0000000000..c67c21d613
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher.go
@@ -0,0 +1,203 @@
+// 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"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ clientv3 "go.etcd.io/etcd/client/v3"
+)
+
+var (
+ ErrWatcherNotExist = errors.New("mvcc: watcher does not exist")
+ ErrEmptyWatcherRange = errors.New("mvcc: watcher range is empty")
+ ErrWatcherDuplicateID = errors.New("mvcc: duplicate watch ID provided on the WatchStream")
+)
+
+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.
+ // The watch ID is used when it's not equal to AutoWatchID. Otherwise,
+ // an auto-generated watch ID is returned.
+ Watch(id WatchID, key, end []byte, startRev int64, fcs ...FilterFunc) (WatchID, error)
+
+ // 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)
+
+ // RequestProgressAll requests a progress notification for all
+ // watchers sharing the stream. If all watchers are synced, a
+ // progress notification with watch ID -1 will be sent to an
+ // arbitrary watcher of this stream, and the function returns
+ // true.
+ RequestProgressAll() bool
+
+ // 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.
+func (ws *watchStream) Watch(id WatchID, key, end []byte, startRev int64, fcs ...FilterFunc) (WatchID, error) {
+ // 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, ErrEmptyWatcherRange
+ }
+
+ ws.mu.Lock()
+ defer ws.mu.Unlock()
+ if ws.closed {
+ return -1, ErrEmptyWatcherRange
+ }
+
+ if id == clientv3.AutoWatchID {
+ for ws.watchers[ws.nextID] != nil {
+ ws.nextID++
+ }
+ id = ws.nextID
+ ws.nextID++
+ } else if _, ok := ws.watchers[id]; ok {
+ return -1, ErrWatcherDuplicateID
+ }
+
+ w, c := ws.watchable.watch(key, end, startRev, id, ws.ch, fcs...)
+
+ ws.cancels[id] = c
+ ws.watchers[id] = w
+ return id, nil
+}
+
+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)
+}
+
+func (ws *watchStream) RequestProgressAll() bool {
+ ws.mu.Lock()
+ defer ws.mu.Unlock()
+ return ws.watchable.progressAll(ws.watchers)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher_group.go b/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher_group.go
new file mode 100644
index 0000000000..356b49e641
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher_group.go
@@ -0,0 +1,293 @@
+// 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"
+
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/pkg/v3/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),
+ ranges: adt.NewIntervalTree(),
+ 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/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/auth_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/auth_client_adapter.go
new file mode 100644
index 0000000000..140212b962
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/auth_client_adapter.go
@@ -0,0 +1,97 @@
+// 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 adapter
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+
+ grpc "google.golang.org/grpc"
+)
+
+type as2ac struct{ as pb.AuthServer }
+
+func AuthServerToAuthClient(as pb.AuthServer) pb.AuthClient {
+ return &as2ac{as}
+}
+
+func (s *as2ac) AuthEnable(ctx context.Context, in *pb.AuthEnableRequest, opts ...grpc.CallOption) (*pb.AuthEnableResponse, error) {
+ return s.as.AuthEnable(ctx, in)
+}
+
+func (s *as2ac) AuthDisable(ctx context.Context, in *pb.AuthDisableRequest, opts ...grpc.CallOption) (*pb.AuthDisableResponse, error) {
+ return s.as.AuthDisable(ctx, in)
+}
+
+func (s *as2ac) AuthStatus(ctx context.Context, in *pb.AuthStatusRequest, opts ...grpc.CallOption) (*pb.AuthStatusResponse, error) {
+ return s.as.AuthStatus(ctx, in)
+}
+
+func (s *as2ac) Authenticate(ctx context.Context, in *pb.AuthenticateRequest, opts ...grpc.CallOption) (*pb.AuthenticateResponse, error) {
+ return s.as.Authenticate(ctx, in)
+}
+
+func (s *as2ac) RoleAdd(ctx context.Context, in *pb.AuthRoleAddRequest, opts ...grpc.CallOption) (*pb.AuthRoleAddResponse, error) {
+ return s.as.RoleAdd(ctx, in)
+}
+
+func (s *as2ac) RoleDelete(ctx context.Context, in *pb.AuthRoleDeleteRequest, opts ...grpc.CallOption) (*pb.AuthRoleDeleteResponse, error) {
+ return s.as.RoleDelete(ctx, in)
+}
+
+func (s *as2ac) RoleGet(ctx context.Context, in *pb.AuthRoleGetRequest, opts ...grpc.CallOption) (*pb.AuthRoleGetResponse, error) {
+ return s.as.RoleGet(ctx, in)
+}
+
+func (s *as2ac) RoleList(ctx context.Context, in *pb.AuthRoleListRequest, opts ...grpc.CallOption) (*pb.AuthRoleListResponse, error) {
+ return s.as.RoleList(ctx, in)
+}
+
+func (s *as2ac) RoleRevokePermission(ctx context.Context, in *pb.AuthRoleRevokePermissionRequest, opts ...grpc.CallOption) (*pb.AuthRoleRevokePermissionResponse, error) {
+ return s.as.RoleRevokePermission(ctx, in)
+}
+
+func (s *as2ac) RoleGrantPermission(ctx context.Context, in *pb.AuthRoleGrantPermissionRequest, opts ...grpc.CallOption) (*pb.AuthRoleGrantPermissionResponse, error) {
+ return s.as.RoleGrantPermission(ctx, in)
+}
+
+func (s *as2ac) UserDelete(ctx context.Context, in *pb.AuthUserDeleteRequest, opts ...grpc.CallOption) (*pb.AuthUserDeleteResponse, error) {
+ return s.as.UserDelete(ctx, in)
+}
+
+func (s *as2ac) UserAdd(ctx context.Context, in *pb.AuthUserAddRequest, opts ...grpc.CallOption) (*pb.AuthUserAddResponse, error) {
+ return s.as.UserAdd(ctx, in)
+}
+
+func (s *as2ac) UserGet(ctx context.Context, in *pb.AuthUserGetRequest, opts ...grpc.CallOption) (*pb.AuthUserGetResponse, error) {
+ return s.as.UserGet(ctx, in)
+}
+
+func (s *as2ac) UserList(ctx context.Context, in *pb.AuthUserListRequest, opts ...grpc.CallOption) (*pb.AuthUserListResponse, error) {
+ return s.as.UserList(ctx, in)
+}
+
+func (s *as2ac) UserGrantRole(ctx context.Context, in *pb.AuthUserGrantRoleRequest, opts ...grpc.CallOption) (*pb.AuthUserGrantRoleResponse, error) {
+ return s.as.UserGrantRole(ctx, in)
+}
+
+func (s *as2ac) UserRevokeRole(ctx context.Context, in *pb.AuthUserRevokeRoleRequest, opts ...grpc.CallOption) (*pb.AuthUserRevokeRoleResponse, error) {
+ return s.as.UserRevokeRole(ctx, in)
+}
+
+func (s *as2ac) UserChangePassword(ctx context.Context, in *pb.AuthUserChangePasswordRequest, opts ...grpc.CallOption) (*pb.AuthUserChangePasswordResponse, error) {
+ return s.as.UserChangePassword(ctx, in)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/chan_stream.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/chan_stream.go
new file mode 100644
index 0000000000..1af514b1fd
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/chan_stream.go
@@ -0,0 +1,167 @@
+// 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 adapter
+
+import (
+ "context"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+// chanServerStream implements grpc.ServerStream with a chanStream
+type chanServerStream struct {
+ headerc chan<- metadata.MD
+ trailerc chan<- metadata.MD
+ grpc.Stream
+
+ headers []metadata.MD
+}
+
+func (ss *chanServerStream) SendHeader(md metadata.MD) error {
+ if ss.headerc == nil {
+ return errAlreadySentHeader
+ }
+ outmd := make(map[string][]string)
+ for _, h := range append(ss.headers, md) {
+ for k, v := range h {
+ outmd[k] = v
+ }
+ }
+ select {
+ case ss.headerc <- outmd:
+ ss.headerc = nil
+ ss.headers = nil
+ return nil
+ case <-ss.Context().Done():
+ }
+ return ss.Context().Err()
+}
+
+func (ss *chanServerStream) SetHeader(md metadata.MD) error {
+ if ss.headerc == nil {
+ return errAlreadySentHeader
+ }
+ ss.headers = append(ss.headers, md)
+ return nil
+}
+
+func (ss *chanServerStream) SetTrailer(md metadata.MD) {
+ ss.trailerc <- md
+}
+
+// chanClientStream implements grpc.ClientStream with a chanStream
+type chanClientStream struct {
+ headerc <-chan metadata.MD
+ trailerc <-chan metadata.MD
+ *chanStream
+}
+
+func (cs *chanClientStream) Header() (metadata.MD, error) {
+ select {
+ case md := <-cs.headerc:
+ return md, nil
+ case <-cs.Context().Done():
+ }
+ return nil, cs.Context().Err()
+}
+
+func (cs *chanClientStream) Trailer() metadata.MD {
+ select {
+ case md := <-cs.trailerc:
+ return md
+ case <-cs.Context().Done():
+ return nil
+ }
+}
+
+func (cs *chanClientStream) CloseSend() error {
+ close(cs.chanStream.sendc)
+ return nil
+}
+
+// chanStream implements grpc.Stream using channels
+type chanStream struct {
+ recvc <-chan interface{}
+ sendc chan<- interface{}
+ ctx context.Context
+ cancel context.CancelFunc
+}
+
+func (s *chanStream) Context() context.Context { return s.ctx }
+
+func (s *chanStream) SendMsg(m interface{}) error {
+ select {
+ case s.sendc <- m:
+ if err, ok := m.(error); ok {
+ return err
+ }
+ return nil
+ case <-s.ctx.Done():
+ }
+ return s.ctx.Err()
+}
+
+func (s *chanStream) RecvMsg(m interface{}) error {
+ v := m.(*interface{})
+ for {
+ select {
+ case msg, ok := <-s.recvc:
+ if !ok {
+ return status.Error(codes.Canceled, "the client connection is closing")
+ }
+ if err, ok := msg.(error); ok {
+ return err
+ }
+ *v = msg
+ return nil
+ case <-s.ctx.Done():
+ }
+ if len(s.recvc) == 0 {
+ // prioritize any pending recv messages over canceled context
+ break
+ }
+ }
+ return s.ctx.Err()
+}
+
+func newPipeStream(ctx context.Context, ssHandler func(chanServerStream) error) chanClientStream {
+ // ch1 is buffered so server can send error on close
+ ch1, ch2 := make(chan interface{}, 1), make(chan interface{})
+ headerc, trailerc := make(chan metadata.MD, 1), make(chan metadata.MD, 1)
+
+ cctx, ccancel := context.WithCancel(ctx)
+ cli := &chanStream{recvc: ch1, sendc: ch2, ctx: cctx, cancel: ccancel}
+ cs := chanClientStream{headerc, trailerc, cli}
+
+ sctx, scancel := context.WithCancel(ctx)
+ srv := &chanStream{recvc: ch2, sendc: ch1, ctx: sctx, cancel: scancel}
+ ss := chanServerStream{headerc, trailerc, srv, nil}
+
+ go func() {
+ if err := ssHandler(ss); err != nil {
+ select {
+ case srv.sendc <- err:
+ case <-sctx.Done():
+ case <-cctx.Done():
+ }
+ }
+ scancel()
+ ccancel()
+ }()
+ return cs
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/cluster_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/cluster_client_adapter.go
new file mode 100644
index 0000000000..c1fff054de
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/cluster_client_adapter.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 adapter
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+
+ "google.golang.org/grpc"
+)
+
+type cls2clc struct{ cls pb.ClusterServer }
+
+func ClusterServerToClusterClient(cls pb.ClusterServer) pb.ClusterClient {
+ return &cls2clc{cls}
+}
+
+func (s *cls2clc) MemberList(ctx context.Context, r *pb.MemberListRequest, opts ...grpc.CallOption) (*pb.MemberListResponse, error) {
+ return s.cls.MemberList(ctx, r)
+}
+
+func (s *cls2clc) MemberAdd(ctx context.Context, r *pb.MemberAddRequest, opts ...grpc.CallOption) (*pb.MemberAddResponse, error) {
+ return s.cls.MemberAdd(ctx, r)
+}
+
+func (s *cls2clc) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest, opts ...grpc.CallOption) (*pb.MemberUpdateResponse, error) {
+ return s.cls.MemberUpdate(ctx, r)
+}
+
+func (s *cls2clc) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest, opts ...grpc.CallOption) (*pb.MemberRemoveResponse, error) {
+ return s.cls.MemberRemove(ctx, r)
+}
+
+func (s *cls2clc) MemberPromote(ctx context.Context, r *pb.MemberPromoteRequest, opts ...grpc.CallOption) (*pb.MemberPromoteResponse, error) {
+ return s.cls.MemberPromote(ctx, r)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/doc.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/doc.go
new file mode 100644
index 0000000000..7170be2330
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/doc.go
@@ -0,0 +1,17 @@
+// 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 adapter provides gRPC adapters between client and server
+// gRPC interfaces without needing to go through a gRPC connection.
+package adapter
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/election_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/election_client_adapter.go
new file mode 100644
index 0000000000..81d7434474
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/election_client_adapter.go
@@ -0,0 +1,80 @@
+// 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 adapter
+
+import (
+ "context"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
+
+ "google.golang.org/grpc"
+)
+
+type es2ec struct{ es v3electionpb.ElectionServer }
+
+func ElectionServerToElectionClient(es v3electionpb.ElectionServer) v3electionpb.ElectionClient {
+ return &es2ec{es}
+}
+
+func (s *es2ec) Campaign(ctx context.Context, r *v3electionpb.CampaignRequest, opts ...grpc.CallOption) (*v3electionpb.CampaignResponse, error) {
+ return s.es.Campaign(ctx, r)
+}
+
+func (s *es2ec) Proclaim(ctx context.Context, r *v3electionpb.ProclaimRequest, opts ...grpc.CallOption) (*v3electionpb.ProclaimResponse, error) {
+ return s.es.Proclaim(ctx, r)
+}
+
+func (s *es2ec) Leader(ctx context.Context, r *v3electionpb.LeaderRequest, opts ...grpc.CallOption) (*v3electionpb.LeaderResponse, error) {
+ return s.es.Leader(ctx, r)
+}
+
+func (s *es2ec) Resign(ctx context.Context, r *v3electionpb.ResignRequest, opts ...grpc.CallOption) (*v3electionpb.ResignResponse, error) {
+ return s.es.Resign(ctx, r)
+}
+
+func (s *es2ec) Observe(ctx context.Context, in *v3electionpb.LeaderRequest, opts ...grpc.CallOption) (v3electionpb.Election_ObserveClient, error) {
+ cs := newPipeStream(ctx, func(ss chanServerStream) error {
+ return s.es.Observe(in, &es2ecServerStream{ss})
+ })
+ return &es2ecClientStream{cs}, nil
+}
+
+// es2ecClientStream implements Election_ObserveClient
+type es2ecClientStream struct{ chanClientStream }
+
+// es2ecServerStream implements Election_ObserveServer
+type es2ecServerStream struct{ chanServerStream }
+
+func (s *es2ecClientStream) Send(rr *v3electionpb.LeaderRequest) error {
+ return s.SendMsg(rr)
+}
+func (s *es2ecClientStream) Recv() (*v3electionpb.LeaderResponse, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*v3electionpb.LeaderResponse), nil
+}
+
+func (s *es2ecServerStream) Send(rr *v3electionpb.LeaderResponse) error {
+ return s.SendMsg(rr)
+}
+func (s *es2ecServerStream) Recv() (*v3electionpb.LeaderRequest, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*v3electionpb.LeaderRequest), nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/kv_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/kv_client_adapter.go
new file mode 100644
index 0000000000..ddb6ada473
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/kv_client_adapter.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 adapter
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+
+ grpc "google.golang.org/grpc"
+)
+
+type kvs2kvc struct{ kvs pb.KVServer }
+
+func KvServerToKvClient(kvs pb.KVServer) pb.KVClient {
+ return &kvs2kvc{kvs}
+}
+
+func (s *kvs2kvc) Range(ctx context.Context, in *pb.RangeRequest, opts ...grpc.CallOption) (*pb.RangeResponse, error) {
+ return s.kvs.Range(ctx, in)
+}
+
+func (s *kvs2kvc) Put(ctx context.Context, in *pb.PutRequest, opts ...grpc.CallOption) (*pb.PutResponse, error) {
+ return s.kvs.Put(ctx, in)
+}
+
+func (s *kvs2kvc) DeleteRange(ctx context.Context, in *pb.DeleteRangeRequest, opts ...grpc.CallOption) (*pb.DeleteRangeResponse, error) {
+ return s.kvs.DeleteRange(ctx, in)
+}
+
+func (s *kvs2kvc) Txn(ctx context.Context, in *pb.TxnRequest, opts ...grpc.CallOption) (*pb.TxnResponse, error) {
+ return s.kvs.Txn(ctx, in)
+}
+
+func (s *kvs2kvc) Compact(ctx context.Context, in *pb.CompactionRequest, opts ...grpc.CallOption) (*pb.CompactionResponse, error) {
+ return s.kvs.Compact(ctx, in)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lease_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lease_client_adapter.go
new file mode 100644
index 0000000000..6640d1d39e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lease_client_adapter.go
@@ -0,0 +1,82 @@
+// 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 adapter
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+
+ "google.golang.org/grpc"
+)
+
+type ls2lc struct {
+ leaseServer pb.LeaseServer
+}
+
+func LeaseServerToLeaseClient(ls pb.LeaseServer) pb.LeaseClient {
+ return &ls2lc{ls}
+}
+
+func (c *ls2lc) LeaseGrant(ctx context.Context, in *pb.LeaseGrantRequest, opts ...grpc.CallOption) (*pb.LeaseGrantResponse, error) {
+ return c.leaseServer.LeaseGrant(ctx, in)
+}
+
+func (c *ls2lc) LeaseRevoke(ctx context.Context, in *pb.LeaseRevokeRequest, opts ...grpc.CallOption) (*pb.LeaseRevokeResponse, error) {
+ return c.leaseServer.LeaseRevoke(ctx, in)
+}
+
+func (c *ls2lc) LeaseKeepAlive(ctx context.Context, opts ...grpc.CallOption) (pb.Lease_LeaseKeepAliveClient, error) {
+ cs := newPipeStream(ctx, func(ss chanServerStream) error {
+ return c.leaseServer.LeaseKeepAlive(&ls2lcServerStream{ss})
+ })
+ return &ls2lcClientStream{cs}, nil
+}
+
+func (c *ls2lc) LeaseTimeToLive(ctx context.Context, in *pb.LeaseTimeToLiveRequest, opts ...grpc.CallOption) (*pb.LeaseTimeToLiveResponse, error) {
+ return c.leaseServer.LeaseTimeToLive(ctx, in)
+}
+
+func (c *ls2lc) LeaseLeases(ctx context.Context, in *pb.LeaseLeasesRequest, opts ...grpc.CallOption) (*pb.LeaseLeasesResponse, error) {
+ return c.leaseServer.LeaseLeases(ctx, in)
+}
+
+// ls2lcClientStream implements Lease_LeaseKeepAliveClient
+type ls2lcClientStream struct{ chanClientStream }
+
+// ls2lcServerStream implements Lease_LeaseKeepAliveServer
+type ls2lcServerStream struct{ chanServerStream }
+
+func (s *ls2lcClientStream) Send(rr *pb.LeaseKeepAliveRequest) error {
+ return s.SendMsg(rr)
+}
+func (s *ls2lcClientStream) Recv() (*pb.LeaseKeepAliveResponse, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*pb.LeaseKeepAliveResponse), nil
+}
+
+func (s *ls2lcServerStream) Send(rr *pb.LeaseKeepAliveResponse) error {
+ return s.SendMsg(rr)
+}
+func (s *ls2lcServerStream) Recv() (*pb.LeaseKeepAliveRequest, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*pb.LeaseKeepAliveRequest), nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lock_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lock_client_adapter.go
new file mode 100644
index 0000000000..a3ceaf26da
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lock_client_adapter.go
@@ -0,0 +1,37 @@
+// 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 adapter
+
+import (
+ "context"
+
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"
+
+ "google.golang.org/grpc"
+)
+
+type ls2lsc struct{ ls v3lockpb.LockServer }
+
+func LockServerToLockClient(ls v3lockpb.LockServer) v3lockpb.LockClient {
+ return &ls2lsc{ls}
+}
+
+func (s *ls2lsc) Lock(ctx context.Context, r *v3lockpb.LockRequest, opts ...grpc.CallOption) (*v3lockpb.LockResponse, error) {
+ return s.ls.Lock(ctx, r)
+}
+
+func (s *ls2lsc) Unlock(ctx context.Context, r *v3lockpb.UnlockRequest, opts ...grpc.CallOption) (*v3lockpb.UnlockResponse, error) {
+ return s.ls.Unlock(ctx, r)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/maintenance_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/maintenance_client_adapter.go
new file mode 100644
index 0000000000..6369a16d8b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/maintenance_client_adapter.go
@@ -0,0 +1,92 @@
+// 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 adapter
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+
+ "google.golang.org/grpc"
+)
+
+type mts2mtc struct{ mts pb.MaintenanceServer }
+
+func MaintenanceServerToMaintenanceClient(mts pb.MaintenanceServer) pb.MaintenanceClient {
+ return &mts2mtc{mts}
+}
+
+func (s *mts2mtc) Alarm(ctx context.Context, r *pb.AlarmRequest, opts ...grpc.CallOption) (*pb.AlarmResponse, error) {
+ return s.mts.Alarm(ctx, r)
+}
+
+func (s *mts2mtc) Status(ctx context.Context, r *pb.StatusRequest, opts ...grpc.CallOption) (*pb.StatusResponse, error) {
+ return s.mts.Status(ctx, r)
+}
+
+func (s *mts2mtc) Defragment(ctx context.Context, dr *pb.DefragmentRequest, opts ...grpc.CallOption) (*pb.DefragmentResponse, error) {
+ return s.mts.Defragment(ctx, dr)
+}
+
+func (s *mts2mtc) Hash(ctx context.Context, r *pb.HashRequest, opts ...grpc.CallOption) (*pb.HashResponse, error) {
+ return s.mts.Hash(ctx, r)
+}
+
+func (s *mts2mtc) HashKV(ctx context.Context, r *pb.HashKVRequest, opts ...grpc.CallOption) (*pb.HashKVResponse, error) {
+ return s.mts.HashKV(ctx, r)
+}
+
+func (s *mts2mtc) MoveLeader(ctx context.Context, r *pb.MoveLeaderRequest, opts ...grpc.CallOption) (*pb.MoveLeaderResponse, error) {
+ return s.mts.MoveLeader(ctx, r)
+}
+
+func (s *mts2mtc) Downgrade(ctx context.Context, r *pb.DowngradeRequest, opts ...grpc.CallOption) (*pb.DowngradeResponse, error) {
+ return s.mts.Downgrade(ctx, r)
+}
+
+func (s *mts2mtc) Snapshot(ctx context.Context, in *pb.SnapshotRequest, opts ...grpc.CallOption) (pb.Maintenance_SnapshotClient, error) {
+ cs := newPipeStream(ctx, func(ss chanServerStream) error {
+ return s.mts.Snapshot(in, &ss2scServerStream{ss})
+ })
+ return &ss2scClientStream{cs}, nil
+}
+
+// ss2scClientStream implements Maintenance_SnapshotClient
+type ss2scClientStream struct{ chanClientStream }
+
+// ss2scServerStream implements Maintenance_SnapshotServer
+type ss2scServerStream struct{ chanServerStream }
+
+func (s *ss2scClientStream) Send(rr *pb.SnapshotRequest) error {
+ return s.SendMsg(rr)
+}
+func (s *ss2scClientStream) Recv() (*pb.SnapshotResponse, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*pb.SnapshotResponse), nil
+}
+
+func (s *ss2scServerStream) Send(rr *pb.SnapshotResponse) error {
+ return s.SendMsg(rr)
+}
+func (s *ss2scServerStream) Recv() (*pb.SnapshotRequest, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*pb.SnapshotRequest), nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/watch_client_adapter.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/watch_client_adapter.go
new file mode 100644
index 0000000000..fbc09f6ff6
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/watch_client_adapter.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 adapter
+
+import (
+ "context"
+ "errors"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "google.golang.org/grpc"
+)
+
+var errAlreadySentHeader = errors.New("adapter: already sent header")
+
+type ws2wc struct{ wserv pb.WatchServer }
+
+func WatchServerToWatchClient(wserv pb.WatchServer) pb.WatchClient {
+ return &ws2wc{wserv}
+}
+
+func (s *ws2wc) Watch(ctx context.Context, opts ...grpc.CallOption) (pb.Watch_WatchClient, error) {
+ cs := newPipeStream(ctx, func(ss chanServerStream) error {
+ return s.wserv.Watch(&ws2wcServerStream{ss})
+ })
+ return &ws2wcClientStream{cs}, nil
+}
+
+// ws2wcClientStream implements Watch_WatchClient
+type ws2wcClientStream struct{ chanClientStream }
+
+// ws2wcServerStream implements Watch_WatchServer
+type ws2wcServerStream struct{ chanServerStream }
+
+func (s *ws2wcClientStream) Send(wr *pb.WatchRequest) error {
+ return s.SendMsg(wr)
+}
+func (s *ws2wcClientStream) Recv() (*pb.WatchResponse, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*pb.WatchResponse), nil
+}
+
+func (s *ws2wcServerStream) Send(wr *pb.WatchResponse) error {
+ return s.SendMsg(wr)
+}
+func (s *ws2wcServerStream) Recv() (*pb.WatchRequest, error) {
+ var v interface{}
+ if err := s.RecvMsg(&v); err != nil {
+ return nil, err
+ }
+ return v.(*pb.WatchRequest), nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/auth.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/auth.go
new file mode 100644
index 0000000000..0cabfc146e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/auth.go
@@ -0,0 +1,115 @@
+// 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 grpcproxy
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/v3"
+)
+
+type AuthProxy struct {
+ client *clientv3.Client
+}
+
+func NewAuthProxy(c *clientv3.Client) pb.AuthServer {
+ return &AuthProxy{client: c}
+}
+
+func (ap *AuthProxy) AuthEnable(ctx context.Context, r *pb.AuthEnableRequest) (*pb.AuthEnableResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).AuthEnable(ctx, r)
+}
+
+func (ap *AuthProxy) AuthDisable(ctx context.Context, r *pb.AuthDisableRequest) (*pb.AuthDisableResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).AuthDisable(ctx, r)
+}
+
+func (ap *AuthProxy) AuthStatus(ctx context.Context, r *pb.AuthStatusRequest) (*pb.AuthStatusResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).AuthStatus(ctx, r)
+}
+
+func (ap *AuthProxy) Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).Authenticate(ctx, r)
+}
+
+func (ap *AuthProxy) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).RoleAdd(ctx, r)
+}
+
+func (ap *AuthProxy) RoleDelete(ctx context.Context, r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).RoleDelete(ctx, r)
+}
+
+func (ap *AuthProxy) RoleGet(ctx context.Context, r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).RoleGet(ctx, r)
+}
+
+func (ap *AuthProxy) RoleList(ctx context.Context, r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).RoleList(ctx, r)
+}
+
+func (ap *AuthProxy) RoleRevokePermission(ctx context.Context, r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).RoleRevokePermission(ctx, r)
+}
+
+func (ap *AuthProxy) RoleGrantPermission(ctx context.Context, r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).RoleGrantPermission(ctx, r)
+}
+
+func (ap *AuthProxy) UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).UserAdd(ctx, r)
+}
+
+func (ap *AuthProxy) UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).UserDelete(ctx, r)
+}
+
+func (ap *AuthProxy) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).UserGet(ctx, r)
+}
+
+func (ap *AuthProxy) UserList(ctx context.Context, r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).UserList(ctx, r)
+}
+
+func (ap *AuthProxy) UserGrantRole(ctx context.Context, r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).UserGrantRole(ctx, r)
+}
+
+func (ap *AuthProxy) UserRevokeRole(ctx context.Context, r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).UserRevokeRole(ctx, r)
+}
+
+func (ap *AuthProxy) UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) {
+ conn := ap.client.ActiveConnection()
+ return pb.NewAuthClient(conn).UserChangePassword(ctx, r)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache/store.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache/store.go
new file mode 100644
index 0000000000..2c189644a8
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache/store.go
@@ -0,0 +1,172 @@
+// 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 cache exports functionality for efficiently caching and mapping
+// `RangeRequest`s to corresponding `RangeResponse`s.
+package cache
+
+import (
+ "errors"
+ "sync"
+
+ "github.com/golang/groupcache/lru"
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/pkg/v3/adt"
+)
+
+var (
+ DefaultMaxEntries = 2048
+ ErrCompacted = rpctypes.ErrGRPCCompacted
+)
+
+type Cache interface {
+ Add(req *pb.RangeRequest, resp *pb.RangeResponse)
+ Get(req *pb.RangeRequest) (*pb.RangeResponse, error)
+ Compact(revision int64)
+ Invalidate(key []byte, endkey []byte)
+ Size() int
+ Close()
+}
+
+// keyFunc returns the key of a request, which is used to look up its caching response in the cache.
+func keyFunc(req *pb.RangeRequest) string {
+ // TODO: use marshalTo to reduce allocation
+ b, err := req.Marshal()
+ if err != nil {
+ panic(err)
+ }
+ return string(b)
+}
+
+func NewCache(maxCacheEntries int) Cache {
+ return &cache{
+ lru: lru.New(maxCacheEntries),
+ cachedRanges: adt.NewIntervalTree(),
+ compactedRev: -1,
+ }
+}
+
+func (c *cache) Close() {}
+
+// cache implements Cache
+type cache struct {
+ mu sync.RWMutex
+ lru *lru.Cache
+
+ // a reverse index for cache invalidation
+ cachedRanges adt.IntervalTree
+
+ compactedRev int64
+}
+
+// Add adds the response of a request to the cache if its revision is larger than the compacted revision of the cache.
+func (c *cache) Add(req *pb.RangeRequest, resp *pb.RangeResponse) {
+ key := keyFunc(req)
+
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if req.Revision > c.compactedRev {
+ c.lru.Add(key, resp)
+ }
+ // we do not need to invalidate a request with a revision specified.
+ // so we do not need to add it into the reverse index.
+ if req.Revision != 0 {
+ return
+ }
+
+ var (
+ iv *adt.IntervalValue
+ ivl adt.Interval
+ )
+ if len(req.RangeEnd) != 0 {
+ ivl = adt.NewStringAffineInterval(string(req.Key), string(req.RangeEnd))
+ } else {
+ ivl = adt.NewStringAffinePoint(string(req.Key))
+ }
+
+ iv = c.cachedRanges.Find(ivl)
+
+ if iv == nil {
+ val := map[string]struct{}{key: {}}
+ c.cachedRanges.Insert(ivl, val)
+ } else {
+ val := iv.Val.(map[string]struct{})
+ val[key] = struct{}{}
+ iv.Val = val
+ }
+}
+
+// Get looks up the caching response for a given request.
+// Get is also responsible for lazy eviction when accessing compacted entries.
+func (c *cache) Get(req *pb.RangeRequest) (*pb.RangeResponse, error) {
+ key := keyFunc(req)
+
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if req.Revision > 0 && req.Revision < c.compactedRev {
+ c.lru.Remove(key)
+ return nil, ErrCompacted
+ }
+
+ if resp, ok := c.lru.Get(key); ok {
+ return resp.(*pb.RangeResponse), nil
+ }
+ return nil, errors.New("not exist")
+}
+
+// Invalidate invalidates the cache entries that intersecting with the given range from key to endkey.
+func (c *cache) Invalidate(key, endkey []byte) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ var (
+ ivs []*adt.IntervalValue
+ ivl adt.Interval
+ )
+ if len(endkey) == 0 {
+ ivl = adt.NewStringAffinePoint(string(key))
+ } else {
+ ivl = adt.NewStringAffineInterval(string(key), string(endkey))
+ }
+
+ ivs = c.cachedRanges.Stab(ivl)
+ for _, iv := range ivs {
+ keys := iv.Val.(map[string]struct{})
+ for key := range keys {
+ c.lru.Remove(key)
+ }
+ }
+ // delete after removing all keys since it is destructive to 'ivs'
+ c.cachedRanges.Delete(ivl)
+}
+
+// Compact invalidate all caching response before the given rev.
+// Replace with the invalidation is lazy. The actual removal happens when the entries is accessed.
+func (c *cache) Compact(revision int64) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if revision > c.compactedRev {
+ c.compactedRev = revision
+ }
+}
+
+func (c *cache) Size() int {
+ c.mu.RLock()
+ defer c.mu.RUnlock()
+ return c.lru.Len()
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cluster.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cluster.go
new file mode 100644
index 0000000000..e225fd8ef1
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/cluster.go
@@ -0,0 +1,213 @@
+// 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 grpcproxy
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "os"
+ "sync"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/client/v3/naming/endpoints"
+ "golang.org/x/time/rate"
+
+ "go.uber.org/zap"
+)
+
+// allow maximum 1 retry per second
+const resolveRetryRate = 1
+
+type clusterProxy struct {
+ lg *zap.Logger
+ clus clientv3.Cluster
+ ctx context.Context
+
+ // advertise client URL
+ advaddr string
+ prefix string
+
+ em endpoints.Manager
+
+ umu sync.RWMutex
+ umap map[string]endpoints.Endpoint
+}
+
+// NewClusterProxy takes optional prefix to fetch grpc-proxy member endpoints.
+// The returned channel is closed when there is grpc-proxy endpoint registered
+// and the client's context is canceled so the 'register' loop returns.
+// TODO: Expand the API to report creation errors
+func NewClusterProxy(lg *zap.Logger, c *clientv3.Client, advaddr string, prefix string) (pb.ClusterServer, <-chan struct{}) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+
+ var em endpoints.Manager
+ if advaddr != "" && prefix != "" {
+ var err error
+ if em, err = endpoints.NewManager(c, prefix); err != nil {
+ lg.Error("failed to provision endpointsManager", zap.String("prefix", prefix), zap.Error(err))
+ return nil, nil
+ }
+ }
+
+ cp := &clusterProxy{
+ lg: lg,
+ clus: c.Cluster,
+ ctx: c.Ctx(),
+
+ advaddr: advaddr,
+ prefix: prefix,
+ umap: make(map[string]endpoints.Endpoint),
+ em: em,
+ }
+
+ donec := make(chan struct{})
+ if em != nil {
+ go func() {
+ defer close(donec)
+ cp.establishEndpointWatch(prefix)
+ }()
+ return cp, donec
+ }
+
+ close(donec)
+ return cp, donec
+}
+
+func (cp *clusterProxy) establishEndpointWatch(prefix string) {
+ rm := rate.NewLimiter(rate.Limit(resolveRetryRate), resolveRetryRate)
+ for rm.Wait(cp.ctx) == nil {
+ wc, err := cp.em.NewWatchChannel(cp.ctx)
+ if err != nil {
+ cp.lg.Warn("failed to establish endpoint watch", zap.String("prefix", prefix), zap.Error(err))
+ continue
+ }
+ cp.monitor(wc)
+ }
+}
+
+func (cp *clusterProxy) monitor(wa endpoints.WatchChannel) {
+ for {
+ select {
+ case <-cp.ctx.Done():
+ cp.lg.Info("watching endpoints interrupted", zap.Error(cp.ctx.Err()))
+ return
+ case updates := <-wa:
+ cp.umu.Lock()
+ for _, up := range updates {
+ switch up.Op {
+ case endpoints.Add:
+ cp.umap[up.Key] = up.Endpoint
+ case endpoints.Delete:
+ delete(cp.umap, up.Key)
+ }
+ }
+ cp.umu.Unlock()
+ }
+ }
+}
+
+func (cp *clusterProxy) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) (*pb.MemberAddResponse, error) {
+ if r.IsLearner {
+ return cp.memberAddAsLearner(ctx, r.PeerURLs)
+ }
+ return cp.memberAdd(ctx, r.PeerURLs)
+}
+
+func (cp *clusterProxy) memberAdd(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) {
+ mresp, err := cp.clus.MemberAdd(ctx, peerURLs)
+ if err != nil {
+ return nil, err
+ }
+ resp := (pb.MemberAddResponse)(*mresp)
+ return &resp, err
+}
+
+func (cp *clusterProxy) memberAddAsLearner(ctx context.Context, peerURLs []string) (*pb.MemberAddResponse, error) {
+ mresp, err := cp.clus.MemberAddAsLearner(ctx, peerURLs)
+ if err != nil {
+ return nil, err
+ }
+ resp := (pb.MemberAddResponse)(*mresp)
+ return &resp, err
+}
+
+func (cp *clusterProxy) MemberRemove(ctx context.Context, r *pb.MemberRemoveRequest) (*pb.MemberRemoveResponse, error) {
+ mresp, err := cp.clus.MemberRemove(ctx, r.ID)
+ if err != nil {
+ return nil, err
+ }
+ resp := (pb.MemberRemoveResponse)(*mresp)
+ return &resp, err
+}
+
+func (cp *clusterProxy) MemberUpdate(ctx context.Context, r *pb.MemberUpdateRequest) (*pb.MemberUpdateResponse, error) {
+ mresp, err := cp.clus.MemberUpdate(ctx, r.ID, r.PeerURLs)
+ if err != nil {
+ return nil, err
+ }
+ resp := (pb.MemberUpdateResponse)(*mresp)
+ return &resp, err
+}
+
+func (cp *clusterProxy) membersFromUpdates() ([]*pb.Member, error) {
+ cp.umu.RLock()
+ defer cp.umu.RUnlock()
+ mbs := make([]*pb.Member, 0, len(cp.umap))
+ for _, upt := range cp.umap {
+ m, err := decodeMeta(fmt.Sprint(upt.Metadata))
+ if err != nil {
+ return nil, err
+ }
+ mbs = append(mbs, &pb.Member{Name: m.Name, ClientURLs: []string{upt.Addr}})
+ }
+ return mbs, nil
+}
+
+// MemberList wraps member list API with following rules:
+// - If 'advaddr' is not empty and 'prefix' is not empty, return registered member lists via resolver
+// - If 'advaddr' is not empty and 'prefix' is not empty and registered grpc-proxy members haven't been fetched, return the 'advaddr'
+// - If 'advaddr' is not empty and 'prefix' is empty, return 'advaddr' without forcing it to 'register'
+// - If 'advaddr' is empty, forward to member list API
+func (cp *clusterProxy) MemberList(ctx context.Context, r *pb.MemberListRequest) (*pb.MemberListResponse, error) {
+ if cp.advaddr != "" {
+ if cp.prefix != "" {
+ mbs, err := cp.membersFromUpdates()
+ if err != nil {
+ return nil, err
+ }
+ if len(mbs) > 0 {
+ return &pb.MemberListResponse{Members: mbs}, nil
+ }
+ }
+ // prefix is empty or no grpc-proxy members haven't been registered
+ hostname, _ := os.Hostname()
+ return &pb.MemberListResponse{Members: []*pb.Member{{Name: hostname, ClientURLs: []string{cp.advaddr}}}}, nil
+ }
+ mresp, err := cp.clus.MemberList(ctx)
+ if err != nil {
+ return nil, err
+ }
+ resp := (pb.MemberListResponse)(*mresp)
+ return &resp, err
+}
+
+func (cp *clusterProxy) MemberPromote(ctx context.Context, r *pb.MemberPromoteRequest) (*pb.MemberPromoteResponse, error) {
+ // TODO: implement
+ return nil, errors.New("not implemented")
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/doc.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/doc.go
new file mode 100644
index 0000000000..fc022e3c57
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/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 grpcproxy is an OSI level 7 proxy for etcd v3 API requests.
+package grpcproxy
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/election.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/election.go
new file mode 100644
index 0000000000..a9ec0fddd3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/election.go
@@ -0,0 +1,65 @@
+// Copyright 2017 The etcd Lockors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package grpcproxy
+
+import (
+ "context"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
+)
+
+type electionProxy struct {
+ client *clientv3.Client
+}
+
+func NewElectionProxy(client *clientv3.Client) v3electionpb.ElectionServer {
+ return &electionProxy{client: client}
+}
+
+func (ep *electionProxy) Campaign(ctx context.Context, req *v3electionpb.CampaignRequest) (*v3electionpb.CampaignResponse, error) {
+ return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Campaign(ctx, req)
+}
+
+func (ep *electionProxy) Proclaim(ctx context.Context, req *v3electionpb.ProclaimRequest) (*v3electionpb.ProclaimResponse, error) {
+ return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Proclaim(ctx, req)
+}
+
+func (ep *electionProxy) Leader(ctx context.Context, req *v3electionpb.LeaderRequest) (*v3electionpb.LeaderResponse, error) {
+ return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Leader(ctx, req)
+}
+
+func (ep *electionProxy) Observe(req *v3electionpb.LeaderRequest, s v3electionpb.Election_ObserveServer) error {
+ conn := ep.client.ActiveConnection()
+ ctx, cancel := context.WithCancel(s.Context())
+ defer cancel()
+ sc, err := v3electionpb.NewElectionClient(conn).Observe(ctx, req)
+ if err != nil {
+ return err
+ }
+ for {
+ rr, err := sc.Recv()
+ if err != nil {
+ return err
+ }
+ if err = s.Send(rr); err != nil {
+ return err
+ }
+ }
+}
+
+func (ep *electionProxy) Resign(ctx context.Context, req *v3electionpb.ResignRequest) (*v3electionpb.ResignResponse, error) {
+ return v3electionpb.NewElectionClient(ep.client.ActiveConnection()).Resign(ctx, req)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/health.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/health.go
new file mode 100644
index 0000000000..882af4b46a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/health.go
@@ -0,0 +1,76 @@
+// 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 grpcproxy
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "time"
+
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
+ "go.uber.org/zap"
+)
+
+// HandleHealth registers health handler on '/health'.
+func HandleHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ mux.Handle(etcdhttp.PathHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet, serializable bool) etcdhttp.Health { return checkHealth(c) }))
+}
+
+// HandleProxyHealth registers health handler on '/proxy/health'.
+func HandleProxyHealth(lg *zap.Logger, mux *http.ServeMux, c *clientv3.Client) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ mux.Handle(etcdhttp.PathProxyHealth, etcdhttp.NewHealthHandler(lg, func(excludedAlarms etcdhttp.AlarmSet, serializable bool) etcdhttp.Health { return checkProxyHealth(c) }))
+}
+
+func checkHealth(c *clientv3.Client) etcdhttp.Health {
+ h := etcdhttp.Health{Health: "false"}
+ ctx, cancel := context.WithTimeout(c.Ctx(), time.Second)
+ _, err := c.Get(ctx, "a")
+ cancel()
+ if err == nil || err == rpctypes.ErrPermissionDenied {
+ h.Health = "true"
+ } else {
+ h.Reason = fmt.Sprintf("GET ERROR:%s", err)
+ }
+ return h
+}
+
+func checkProxyHealth(c *clientv3.Client) etcdhttp.Health {
+ if c == nil {
+ return etcdhttp.Health{Health: "false", Reason: "no connection to proxy"}
+ }
+ h := checkHealth(c)
+ if h.Health != "true" {
+ return h
+ }
+ ctx, cancel := context.WithTimeout(c.Ctx(), time.Second*3)
+ ch := c.Watch(ctx, "a", clientv3.WithCreatedNotify())
+ select {
+ case <-ch:
+ case <-ctx.Done():
+ h.Health = "false"
+ h.Reason = "WATCH TIMEOUT"
+ }
+ cancel()
+ return h
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/kv.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/kv.go
new file mode 100644
index 0000000000..6e88eb9fb9
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/kv.go
@@ -0,0 +1,232 @@
+// 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 grpcproxy
+
+import (
+ "context"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache"
+)
+
+type kvProxy struct {
+ kv clientv3.KV
+ cache cache.Cache
+}
+
+func NewKvProxy(c *clientv3.Client) (pb.KVServer, <-chan struct{}) {
+ kv := &kvProxy{
+ kv: c.KV,
+ cache: cache.NewCache(cache.DefaultMaxEntries),
+ }
+ donec := make(chan struct{})
+ close(donec)
+ return kv, donec
+}
+
+func (p *kvProxy) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
+ if r.Serializable {
+ resp, err := p.cache.Get(r)
+ switch err {
+ case nil:
+ cacheHits.Inc()
+ return resp, nil
+ case cache.ErrCompacted:
+ cacheHits.Inc()
+ return nil, err
+ }
+
+ cachedMisses.Inc()
+ }
+
+ resp, err := p.kv.Do(ctx, RangeRequestToOp(r))
+ if err != nil {
+ return nil, err
+ }
+
+ // cache linearizable as serializable
+ req := *r
+ req.Serializable = true
+ gresp := (*pb.RangeResponse)(resp.Get())
+ p.cache.Add(&req, gresp)
+ cacheKeys.Set(float64(p.cache.Size()))
+
+ return gresp, nil
+}
+
+func (p *kvProxy) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) {
+ p.cache.Invalidate(r.Key, nil)
+ cacheKeys.Set(float64(p.cache.Size()))
+
+ resp, err := p.kv.Do(ctx, PutRequestToOp(r))
+ return (*pb.PutResponse)(resp.Put()), err
+}
+
+func (p *kvProxy) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
+ p.cache.Invalidate(r.Key, r.RangeEnd)
+ cacheKeys.Set(float64(p.cache.Size()))
+
+ resp, err := p.kv.Do(ctx, DelRequestToOp(r))
+ return (*pb.DeleteRangeResponse)(resp.Del()), err
+}
+
+func (p *kvProxy) txnToCache(reqs []*pb.RequestOp, resps []*pb.ResponseOp) {
+ for i := range resps {
+ switch tv := resps[i].Response.(type) {
+ case *pb.ResponseOp_ResponsePut:
+ p.cache.Invalidate(reqs[i].GetRequestPut().Key, nil)
+ case *pb.ResponseOp_ResponseDeleteRange:
+ rdr := reqs[i].GetRequestDeleteRange()
+ p.cache.Invalidate(rdr.Key, rdr.RangeEnd)
+ case *pb.ResponseOp_ResponseRange:
+ req := *(reqs[i].GetRequestRange())
+ req.Serializable = true
+ p.cache.Add(&req, tv.ResponseRange)
+ }
+ }
+}
+
+func (p *kvProxy) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
+ op := TxnRequestToOp(r)
+ opResp, err := p.kv.Do(ctx, op)
+ if err != nil {
+ return nil, err
+ }
+ resp := opResp.Txn()
+
+ // txn may claim an outdated key is updated; be safe and invalidate
+ for _, cmp := range r.Compare {
+ p.cache.Invalidate(cmp.Key, cmp.RangeEnd)
+ }
+ // update any fetched keys
+ if resp.Succeeded {
+ p.txnToCache(r.Success, resp.Responses)
+ } else {
+ p.txnToCache(r.Failure, resp.Responses)
+ }
+
+ cacheKeys.Set(float64(p.cache.Size()))
+
+ return (*pb.TxnResponse)(resp), nil
+}
+
+func (p *kvProxy) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error) {
+ var opts []clientv3.CompactOption
+ if r.Physical {
+ opts = append(opts, clientv3.WithCompactPhysical())
+ }
+
+ resp, err := p.kv.Compact(ctx, r.Revision, opts...)
+ if err == nil {
+ p.cache.Compact(r.Revision)
+ }
+
+ cacheKeys.Set(float64(p.cache.Size()))
+
+ return (*pb.CompactionResponse)(resp), err
+}
+
+func requestOpToOp(union *pb.RequestOp) clientv3.Op {
+ switch tv := union.Request.(type) {
+ case *pb.RequestOp_RequestRange:
+ if tv.RequestRange != nil {
+ return RangeRequestToOp(tv.RequestRange)
+ }
+ case *pb.RequestOp_RequestPut:
+ if tv.RequestPut != nil {
+ return PutRequestToOp(tv.RequestPut)
+ }
+ case *pb.RequestOp_RequestDeleteRange:
+ if tv.RequestDeleteRange != nil {
+ return DelRequestToOp(tv.RequestDeleteRange)
+ }
+ case *pb.RequestOp_RequestTxn:
+ if tv.RequestTxn != nil {
+ return TxnRequestToOp(tv.RequestTxn)
+ }
+ }
+ panic("unknown request")
+}
+
+func RangeRequestToOp(r *pb.RangeRequest) clientv3.Op {
+ opts := []clientv3.OpOption{}
+ if len(r.RangeEnd) != 0 {
+ opts = append(opts, clientv3.WithRange(string(r.RangeEnd)))
+ }
+ opts = append(opts, clientv3.WithRev(r.Revision))
+ opts = append(opts, clientv3.WithLimit(r.Limit))
+ opts = append(opts, clientv3.WithSort(
+ clientv3.SortTarget(r.SortTarget),
+ clientv3.SortOrder(r.SortOrder)),
+ )
+ opts = append(opts, clientv3.WithMaxCreateRev(r.MaxCreateRevision))
+ opts = append(opts, clientv3.WithMinCreateRev(r.MinCreateRevision))
+ opts = append(opts, clientv3.WithMaxModRev(r.MaxModRevision))
+ opts = append(opts, clientv3.WithMinModRev(r.MinModRevision))
+ if r.CountOnly {
+ opts = append(opts, clientv3.WithCountOnly())
+ }
+ if r.KeysOnly {
+ opts = append(opts, clientv3.WithKeysOnly())
+ }
+ if r.Serializable {
+ opts = append(opts, clientv3.WithSerializable())
+ }
+
+ return clientv3.OpGet(string(r.Key), opts...)
+}
+
+func PutRequestToOp(r *pb.PutRequest) clientv3.Op {
+ opts := []clientv3.OpOption{}
+ opts = append(opts, clientv3.WithLease(clientv3.LeaseID(r.Lease)))
+ if r.IgnoreValue {
+ opts = append(opts, clientv3.WithIgnoreValue())
+ }
+ if r.IgnoreLease {
+ opts = append(opts, clientv3.WithIgnoreLease())
+ }
+ if r.PrevKv {
+ opts = append(opts, clientv3.WithPrevKV())
+ }
+ return clientv3.OpPut(string(r.Key), string(r.Value), opts...)
+}
+
+func DelRequestToOp(r *pb.DeleteRangeRequest) clientv3.Op {
+ opts := []clientv3.OpOption{}
+ if len(r.RangeEnd) != 0 {
+ opts = append(opts, clientv3.WithRange(string(r.RangeEnd)))
+ }
+ if r.PrevKv {
+ opts = append(opts, clientv3.WithPrevKV())
+ }
+ return clientv3.OpDelete(string(r.Key), opts...)
+}
+
+func TxnRequestToOp(r *pb.TxnRequest) clientv3.Op {
+ cmps := make([]clientv3.Cmp, len(r.Compare))
+ thenops := make([]clientv3.Op, len(r.Success))
+ elseops := make([]clientv3.Op, len(r.Failure))
+ for i := range r.Compare {
+ cmps[i] = (clientv3.Cmp)(*r.Compare[i])
+ }
+ for i := range r.Success {
+ thenops[i] = requestOpToOp(r.Success[i])
+ }
+ for i := range r.Failure {
+ elseops[i] = requestOpToOp(r.Failure[i])
+ }
+ return clientv3.OpTxn(cmps, thenops, elseops)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/leader.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/leader.go
new file mode 100644
index 0000000000..c078c89bb3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/leader.go
@@ -0,0 +1,113 @@
+// 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 grpcproxy
+
+import (
+ "context"
+ "math"
+ "sync"
+
+ "go.etcd.io/etcd/client/v3"
+
+ "golang.org/x/time/rate"
+)
+
+const (
+ lostLeaderKey = "__lostleader" // watched to detect leader loss
+ retryPerSecond = 10
+)
+
+type leader struct {
+ ctx context.Context
+ w clientv3.Watcher
+ // mu protects leaderc updates.
+ mu sync.RWMutex
+ leaderc chan struct{}
+ disconnc chan struct{}
+ donec chan struct{}
+}
+
+func newLeader(ctx context.Context, w clientv3.Watcher) *leader {
+ l := &leader{
+ ctx: clientv3.WithRequireLeader(ctx),
+ w: w,
+ leaderc: make(chan struct{}),
+ disconnc: make(chan struct{}),
+ donec: make(chan struct{}),
+ }
+ // begin assuming leader is lost
+ close(l.leaderc)
+ go l.recvLoop()
+ return l
+}
+
+func (l *leader) recvLoop() {
+ defer close(l.donec)
+
+ limiter := rate.NewLimiter(rate.Limit(retryPerSecond), retryPerSecond)
+ rev := int64(math.MaxInt64 - 2)
+ for limiter.Wait(l.ctx) == nil {
+ wch := l.w.Watch(l.ctx, lostLeaderKey, clientv3.WithRev(rev), clientv3.WithCreatedNotify())
+ cresp, ok := <-wch
+ if !ok {
+ l.loseLeader()
+ continue
+ }
+ if cresp.Err() != nil {
+ l.loseLeader()
+ if clientv3.IsConnCanceled(cresp.Err()) {
+ close(l.disconnc)
+ return
+ }
+ continue
+ }
+ l.gotLeader()
+ <-wch
+ l.loseLeader()
+ }
+}
+
+func (l *leader) loseLeader() {
+ l.mu.RLock()
+ defer l.mu.RUnlock()
+ select {
+ case <-l.leaderc:
+ default:
+ close(l.leaderc)
+ }
+}
+
+// gotLeader will force update the leadership status to having a leader.
+func (l *leader) gotLeader() {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ select {
+ case <-l.leaderc:
+ l.leaderc = make(chan struct{})
+ default:
+ }
+}
+
+func (l *leader) disconnectNotify() <-chan struct{} { return l.disconnc }
+
+func (l *leader) stopNotify() <-chan struct{} { return l.donec }
+
+// lostNotify returns a channel that is closed if there has been
+// a leader loss not yet followed by a leader reacquire.
+func (l *leader) lostNotify() <-chan struct{} {
+ l.mu.RLock()
+ defer l.mu.RUnlock()
+ return l.leaderc
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lease.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lease.go
new file mode 100644
index 0000000000..875256c432
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lease.go
@@ -0,0 +1,384 @@
+// 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 grpcproxy
+
+import (
+ "context"
+ "io"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/v3"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+type leaseProxy struct {
+ // leaseClient handles req from LeaseGrant() that requires a lease ID.
+ leaseClient pb.LeaseClient
+
+ lessor clientv3.Lease
+
+ ctx context.Context
+
+ leader *leader
+
+ // mu protects adding outstanding leaseProxyStream through wg.
+ mu sync.RWMutex
+
+ // wg waits until all outstanding leaseProxyStream quit.
+ wg sync.WaitGroup
+}
+
+func NewLeaseProxy(ctx context.Context, c *clientv3.Client) (pb.LeaseServer, <-chan struct{}) {
+ cctx, cancel := context.WithCancel(ctx)
+ lp := &leaseProxy{
+ leaseClient: pb.NewLeaseClient(c.ActiveConnection()),
+ lessor: c.Lease,
+ ctx: cctx,
+ leader: newLeader(cctx, c.Watcher),
+ }
+ ch := make(chan struct{})
+ go func() {
+ defer close(ch)
+ <-lp.leader.stopNotify()
+ lp.mu.Lock()
+ select {
+ case <-lp.ctx.Done():
+ case <-lp.leader.disconnectNotify():
+ cancel()
+ }
+ <-lp.ctx.Done()
+ lp.mu.Unlock()
+ lp.wg.Wait()
+ }()
+ return lp, ch
+}
+
+func (lp *leaseProxy) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ rp, err := lp.leaseClient.LeaseGrant(ctx, cr, grpc.WaitForReady(true))
+ if err != nil {
+ return nil, err
+ }
+ lp.leader.gotLeader()
+ return rp, nil
+}
+
+func (lp *leaseProxy) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) {
+ r, err := lp.lessor.Revoke(ctx, clientv3.LeaseID(rr.ID))
+ if err != nil {
+ return nil, err
+ }
+ lp.leader.gotLeader()
+ return (*pb.LeaseRevokeResponse)(r), nil
+}
+
+func (lp *leaseProxy) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) {
+ var (
+ r *clientv3.LeaseTimeToLiveResponse
+ err error
+ )
+ if rr.Keys {
+ r, err = lp.lessor.TimeToLive(ctx, clientv3.LeaseID(rr.ID), clientv3.WithAttachedKeys())
+ } else {
+ r, err = lp.lessor.TimeToLive(ctx, clientv3.LeaseID(rr.ID))
+ }
+ if err != nil {
+ return nil, err
+ }
+ rp := &pb.LeaseTimeToLiveResponse{
+ Header: r.ResponseHeader,
+ ID: int64(r.ID),
+ TTL: r.TTL,
+ GrantedTTL: r.GrantedTTL,
+ Keys: r.Keys,
+ }
+ return rp, err
+}
+
+func (lp *leaseProxy) LeaseLeases(ctx context.Context, rr *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) {
+ r, err := lp.lessor.Leases(ctx)
+ if err != nil {
+ return nil, err
+ }
+ leases := make([]*pb.LeaseStatus, len(r.Leases))
+ for i := range r.Leases {
+ leases[i] = &pb.LeaseStatus{ID: int64(r.Leases[i].ID)}
+ }
+ rp := &pb.LeaseLeasesResponse{
+ Header: r.ResponseHeader,
+ Leases: leases,
+ }
+ return rp, err
+}
+
+func (lp *leaseProxy) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) error {
+ lp.mu.Lock()
+ select {
+ case <-lp.ctx.Done():
+ lp.mu.Unlock()
+ return lp.ctx.Err()
+ default:
+ lp.wg.Add(1)
+ }
+ lp.mu.Unlock()
+
+ ctx, cancel := context.WithCancel(stream.Context())
+ lps := leaseProxyStream{
+ stream: stream,
+ lessor: lp.lessor,
+ keepAliveLeases: make(map[int64]*atomicCounter),
+ respc: make(chan *pb.LeaseKeepAliveResponse),
+ ctx: ctx,
+ cancel: cancel,
+ }
+
+ errc := make(chan error, 2)
+
+ var lostLeaderC <-chan struct{}
+ if md, ok := metadata.FromOutgoingContext(stream.Context()); ok {
+ v := md[rpctypes.MetadataRequireLeaderKey]
+ if len(v) > 0 && v[0] == rpctypes.MetadataHasLeader {
+ lostLeaderC = lp.leader.lostNotify()
+ // if leader is known to be lost at creation time, avoid
+ // letting events through at all
+ select {
+ case <-lostLeaderC:
+ lp.wg.Done()
+ return rpctypes.ErrNoLeader
+ default:
+ }
+ }
+ }
+ stopc := make(chan struct{}, 3)
+ go func() {
+ defer func() { stopc <- struct{}{} }()
+ if err := lps.recvLoop(); err != nil {
+ errc <- err
+ }
+ }()
+
+ go func() {
+ defer func() { stopc <- struct{}{} }()
+ if err := lps.sendLoop(); err != nil {
+ errc <- err
+ }
+ }()
+
+ // tears down LeaseKeepAlive stream if leader goes down or entire leaseProxy is terminated.
+ go func() {
+ defer func() { stopc <- struct{}{} }()
+ select {
+ case <-lostLeaderC:
+ case <-ctx.Done():
+ case <-lp.ctx.Done():
+ }
+ }()
+
+ var err error
+ select {
+ case <-stopc:
+ stopc <- struct{}{}
+ case err = <-errc:
+ }
+ cancel()
+
+ // recv/send may only shutdown after function exits;
+ // this goroutine notifies lease proxy that the stream is through
+ go func() {
+ <-stopc
+ <-stopc
+ <-stopc
+ lps.close()
+ close(errc)
+ lp.wg.Done()
+ }()
+
+ select {
+ case <-lostLeaderC:
+ return rpctypes.ErrNoLeader
+ case <-lp.leader.disconnectNotify():
+ return status.Error(codes.Canceled, "the client connection is closing")
+ default:
+ if err != nil {
+ return err
+ }
+ return ctx.Err()
+ }
+}
+
+type leaseProxyStream struct {
+ stream pb.Lease_LeaseKeepAliveServer
+
+ lessor clientv3.Lease
+ // wg tracks keepAliveLoop goroutines
+ wg sync.WaitGroup
+ // mu protects keepAliveLeases
+ mu sync.RWMutex
+ // keepAliveLeases tracks how many outstanding keepalive requests which need responses are on a lease.
+ keepAliveLeases map[int64]*atomicCounter
+ // respc receives lease keepalive responses from etcd backend
+ respc chan *pb.LeaseKeepAliveResponse
+
+ ctx context.Context
+ cancel context.CancelFunc
+}
+
+func (lps *leaseProxyStream) recvLoop() error {
+ for {
+ rr, err := lps.stream.Recv()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ lps.mu.Lock()
+ neededResps, ok := lps.keepAliveLeases[rr.ID]
+ if !ok {
+ neededResps = &atomicCounter{}
+ lps.keepAliveLeases[rr.ID] = neededResps
+ lps.wg.Add(1)
+ go func() {
+ defer lps.wg.Done()
+ if err := lps.keepAliveLoop(rr.ID, neededResps); err != nil {
+ lps.cancel()
+ }
+ }()
+ }
+ neededResps.add(1)
+ lps.mu.Unlock()
+ }
+}
+
+func (lps *leaseProxyStream) keepAliveLoop(leaseID int64, neededResps *atomicCounter) error {
+ cctx, ccancel := context.WithCancel(lps.ctx)
+ defer ccancel()
+ respc, err := lps.lessor.KeepAlive(cctx, clientv3.LeaseID(leaseID))
+ if err != nil {
+ return err
+ }
+ // ticker expires when loop hasn't received keepalive within TTL
+ var ticker <-chan time.Time
+ for {
+ select {
+ case <-ticker:
+ lps.mu.Lock()
+ // if there are outstanding keepAlive reqs at the moment of ticker firing,
+ // don't close keepAliveLoop(), let it continuing to process the KeepAlive reqs.
+ if neededResps.get() > 0 {
+ lps.mu.Unlock()
+ ticker = nil
+ continue
+ }
+ delete(lps.keepAliveLeases, leaseID)
+ lps.mu.Unlock()
+ return nil
+ case rp, ok := <-respc:
+ if !ok {
+ lps.mu.Lock()
+ delete(lps.keepAliveLeases, leaseID)
+ lps.mu.Unlock()
+ if neededResps.get() == 0 {
+ return nil
+ }
+ ttlResp, err := lps.lessor.TimeToLive(cctx, clientv3.LeaseID(leaseID))
+ if err != nil {
+ return err
+ }
+ r := &pb.LeaseKeepAliveResponse{
+ Header: ttlResp.ResponseHeader,
+ ID: int64(ttlResp.ID),
+ TTL: ttlResp.TTL,
+ }
+ for neededResps.get() > 0 {
+ select {
+ case lps.respc <- r:
+ neededResps.add(-1)
+ case <-lps.ctx.Done():
+ return nil
+ }
+ }
+ return nil
+ }
+ if neededResps.get() == 0 {
+ continue
+ }
+ ticker = time.After(time.Duration(rp.TTL) * time.Second)
+ r := &pb.LeaseKeepAliveResponse{
+ Header: rp.ResponseHeader,
+ ID: int64(rp.ID),
+ TTL: rp.TTL,
+ }
+ lps.replyToClient(r, neededResps)
+ }
+ }
+}
+
+func (lps *leaseProxyStream) replyToClient(r *pb.LeaseKeepAliveResponse, neededResps *atomicCounter) {
+ timer := time.After(500 * time.Millisecond)
+ for neededResps.get() > 0 {
+ select {
+ case lps.respc <- r:
+ neededResps.add(-1)
+ case <-timer:
+ return
+ case <-lps.ctx.Done():
+ return
+ }
+ }
+}
+
+func (lps *leaseProxyStream) sendLoop() error {
+ for {
+ select {
+ case lrp, ok := <-lps.respc:
+ if !ok {
+ return nil
+ }
+ if err := lps.stream.Send(lrp); err != nil {
+ return err
+ }
+ case <-lps.ctx.Done():
+ return lps.ctx.Err()
+ }
+ }
+}
+
+func (lps *leaseProxyStream) close() {
+ lps.cancel()
+ lps.wg.Wait()
+ // only close respc channel if all the keepAliveLoop() goroutines have finished
+ // this ensures those goroutines don't send resp to a closed resp channel
+ close(lps.respc)
+}
+
+type atomicCounter struct {
+ counter int64
+}
+
+func (ac *atomicCounter) add(delta int64) {
+ atomic.AddInt64(&ac.counter, delta)
+}
+
+func (ac *atomicCounter) get() int64 {
+ return atomic.LoadInt64(&ac.counter)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lock.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lock.go
new file mode 100644
index 0000000000..9859b93699
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/lock.go
@@ -0,0 +1,38 @@
+// Copyright 2017 The etcd Lockors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package grpcproxy
+
+import (
+ "context"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"
+)
+
+type lockProxy struct {
+ client *clientv3.Client
+}
+
+func NewLockProxy(client *clientv3.Client) v3lockpb.LockServer {
+ return &lockProxy{client: client}
+}
+
+func (lp *lockProxy) Lock(ctx context.Context, req *v3lockpb.LockRequest) (*v3lockpb.LockResponse, error) {
+ return v3lockpb.NewLockClient(lp.client.ActiveConnection()).Lock(ctx, req)
+}
+
+func (lp *lockProxy) Unlock(ctx context.Context, req *v3lockpb.UnlockRequest) (*v3lockpb.UnlockResponse, error) {
+ return v3lockpb.NewLockClient(lp.client.ActiveConnection()).Unlock(ctx, req)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/maintenance.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/maintenance.go
new file mode 100644
index 0000000000..3e81656259
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/maintenance.go
@@ -0,0 +1,95 @@
+// 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 grpcproxy
+
+import (
+ "context"
+ "io"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/v3"
+)
+
+type maintenanceProxy struct {
+ client *clientv3.Client
+}
+
+func NewMaintenanceProxy(c *clientv3.Client) pb.MaintenanceServer {
+ return &maintenanceProxy{
+ client: c,
+ }
+}
+
+func (mp *maintenanceProxy) Defragment(ctx context.Context, dr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) {
+ conn := mp.client.ActiveConnection()
+ return pb.NewMaintenanceClient(conn).Defragment(ctx, dr)
+}
+
+func (mp *maintenanceProxy) Snapshot(sr *pb.SnapshotRequest, stream pb.Maintenance_SnapshotServer) error {
+ conn := mp.client.ActiveConnection()
+ ctx, cancel := context.WithCancel(stream.Context())
+ defer cancel()
+
+ ctx = withClientAuthToken(ctx, stream.Context())
+
+ sc, err := pb.NewMaintenanceClient(conn).Snapshot(ctx, sr)
+ if err != nil {
+ return err
+ }
+
+ for {
+ rr, err := sc.Recv()
+ if err != nil {
+ if err == io.EOF {
+ return nil
+ }
+ return err
+ }
+ err = stream.Send(rr)
+ if err != nil {
+ return err
+ }
+ }
+}
+
+func (mp *maintenanceProxy) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) {
+ conn := mp.client.ActiveConnection()
+ return pb.NewMaintenanceClient(conn).Hash(ctx, r)
+}
+
+func (mp *maintenanceProxy) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) {
+ conn := mp.client.ActiveConnection()
+ return pb.NewMaintenanceClient(conn).HashKV(ctx, r)
+}
+
+func (mp *maintenanceProxy) Alarm(ctx context.Context, r *pb.AlarmRequest) (*pb.AlarmResponse, error) {
+ conn := mp.client.ActiveConnection()
+ return pb.NewMaintenanceClient(conn).Alarm(ctx, r)
+}
+
+func (mp *maintenanceProxy) Status(ctx context.Context, r *pb.StatusRequest) (*pb.StatusResponse, error) {
+ conn := mp.client.ActiveConnection()
+ return pb.NewMaintenanceClient(conn).Status(ctx, r)
+}
+
+func (mp *maintenanceProxy) MoveLeader(ctx context.Context, r *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) {
+ conn := mp.client.ActiveConnection()
+ return pb.NewMaintenanceClient(conn).MoveLeader(ctx, r)
+}
+
+func (mp *maintenanceProxy) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) {
+ conn := mp.client.ActiveConnection()
+ return pb.NewMaintenanceClient(conn).Downgrade(ctx, r)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/metrics.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/metrics.go
new file mode 100644
index 0000000000..01a7a94c89
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/metrics.go
@@ -0,0 +1,121 @@
+// 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 grpcproxy
+
+import (
+ "fmt"
+ "io/ioutil"
+ "math/rand"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
+)
+
+var (
+ watchersCoalescing = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "grpc_proxy",
+ Name: "watchers_coalescing_total",
+ Help: "Total number of current watchers coalescing",
+ })
+ eventsCoalescing = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "grpc_proxy",
+ Name: "events_coalescing_total",
+ Help: "Total number of events coalescing",
+ })
+ cacheKeys = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "grpc_proxy",
+ Name: "cache_keys_total",
+ Help: "Total number of keys/ranges cached",
+ })
+ cacheHits = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "grpc_proxy",
+ Name: "cache_hits_total",
+ Help: "Total number of cache hits",
+ })
+ cachedMisses = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "grpc_proxy",
+ Name: "cache_misses_total",
+ Help: "Total number of cache misses",
+ })
+)
+
+func init() {
+ prometheus.MustRegister(watchersCoalescing)
+ prometheus.MustRegister(eventsCoalescing)
+ prometheus.MustRegister(cacheKeys)
+ prometheus.MustRegister(cacheHits)
+ prometheus.MustRegister(cachedMisses)
+}
+
+// HandleMetrics performs a GET request against etcd endpoint and returns '/metrics'.
+func HandleMetrics(mux *http.ServeMux, c *http.Client, eps []string) {
+ // random shuffle endpoints
+ r := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
+ if len(eps) > 1 {
+ eps = shuffleEndpoints(r, eps)
+ }
+
+ pathMetrics := etcdhttp.PathMetrics
+ mux.HandleFunc(pathMetrics, func(w http.ResponseWriter, r *http.Request) {
+ target := fmt.Sprintf("%s%s", eps[0], pathMetrics)
+ if !strings.HasPrefix(target, "http") {
+ scheme := "http"
+ if r.TLS != nil {
+ scheme = "https"
+ }
+ target = fmt.Sprintf("%s://%s", scheme, target)
+ }
+
+ resp, err := c.Get(target)
+ if err != nil {
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
+ return
+ }
+ defer resp.Body.Close()
+ w.Header().Set("Content-Type", "text/plain; version=0.0.4")
+ body, _ := ioutil.ReadAll(resp.Body)
+ fmt.Fprintf(w, "%s", body)
+ })
+}
+
+// HandleProxyMetrics registers metrics handler on '/proxy/metrics'.
+func HandleProxyMetrics(mux *http.ServeMux) {
+ mux.Handle(etcdhttp.PathProxyMetrics, promhttp.Handler())
+}
+
+func shuffleEndpoints(r *rand.Rand, eps []string) []string {
+ // 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([]string, n)
+ for i, k := range p {
+ neps[i] = eps[k]
+ }
+ return neps
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/register.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/register.go
new file mode 100644
index 0000000000..14ec034ead
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/register.go
@@ -0,0 +1,102 @@
+// 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 grpcproxy
+
+import (
+ "encoding/json"
+ "os"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/client/v3/concurrency"
+ "go.etcd.io/etcd/client/v3/naming/endpoints"
+
+ "go.uber.org/zap"
+ "golang.org/x/time/rate"
+)
+
+// allow maximum 1 retry per second
+const registerRetryRate = 1
+
+// Register registers itself as a grpc-proxy server by writing prefixed-key
+// with session of specified TTL (in seconds). The returned channel is closed
+// when the client's context is canceled.
+func Register(lg *zap.Logger, c *clientv3.Client, prefix string, addr string, ttl int) <-chan struct{} {
+ rm := rate.NewLimiter(rate.Limit(registerRetryRate), registerRetryRate)
+
+ donec := make(chan struct{})
+ go func() {
+ defer close(donec)
+
+ for rm.Wait(c.Ctx()) == nil {
+ ss, err := registerSession(lg, c, prefix, addr, ttl)
+ if err != nil {
+ lg.Warn("failed to create a session", zap.Error(err))
+ continue
+ }
+ select {
+ case <-c.Ctx().Done():
+ ss.Close()
+ return
+
+ case <-ss.Done():
+ lg.Warn("session expired; possible network partition or server restart")
+ lg.Warn("creating a new session to rejoin")
+ continue
+ }
+ }
+ }()
+
+ return donec
+}
+
+func registerSession(lg *zap.Logger, c *clientv3.Client, prefix string, addr string, ttl int) (*concurrency.Session, error) {
+ ss, err := concurrency.NewSession(c, concurrency.WithTTL(ttl))
+ if err != nil {
+ return nil, err
+ }
+
+ em, err := endpoints.NewManager(c, prefix)
+ if err != nil {
+ return nil, err
+ }
+ endpoint := endpoints.Endpoint{Addr: addr, Metadata: getMeta()}
+ if err = em.AddEndpoint(c.Ctx(), prefix+"/"+addr, endpoint, clientv3.WithLease(ss.Lease())); err != nil {
+ return nil, err
+ }
+
+ lg.Info(
+ "registered session with lease",
+ zap.String("addr", addr),
+ zap.Int("lease-ttl", ttl),
+ )
+ return ss, nil
+}
+
+// meta represents metadata of proxy register.
+type meta struct {
+ Name string `json:"name"`
+}
+
+func getMeta() string {
+ hostname, _ := os.Hostname()
+ bts, _ := json.Marshal(meta{Name: hostname})
+ return string(bts)
+}
+
+func decodeMeta(s string) (meta, error) {
+ m := meta{}
+ err := json.Unmarshal([]byte(s), &m)
+ return m, err
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/util.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/util.go
new file mode 100644
index 0000000000..856ac5769e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/util.go
@@ -0,0 +1,75 @@
+// 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 grpcproxy
+
+import (
+ "context"
+
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/metadata"
+)
+
+func getAuthTokenFromClient(ctx context.Context) string {
+ md, ok := metadata.FromIncomingContext(ctx)
+ if ok {
+ ts, ok := md[rpctypes.TokenFieldNameGRPC]
+ if ok {
+ return ts[0]
+ }
+ }
+ return ""
+}
+
+func withClientAuthToken(ctx, ctxWithToken context.Context) context.Context {
+ token := getAuthTokenFromClient(ctxWithToken)
+ if token != "" {
+ ctx = context.WithValue(ctx, rpctypes.TokenFieldNameGRPC, token)
+ }
+ return ctx
+}
+
+type proxyTokenCredential struct {
+ token string
+}
+
+func (cred *proxyTokenCredential) RequireTransportSecurity() bool {
+ return false
+}
+
+func (cred *proxyTokenCredential) GetRequestMetadata(ctx context.Context, s ...string) (map[string]string, error) {
+ return map[string]string{
+ rpctypes.TokenFieldNameGRPC: cred.token,
+ }, nil
+}
+
+func AuthUnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+ token := getAuthTokenFromClient(ctx)
+ if token != "" {
+ tokenCred := &proxyTokenCredential{token}
+ opts = append(opts, grpc.PerRPCCredentials(tokenCred))
+ }
+ return invoker(ctx, method, req, reply, cc, opts...)
+}
+
+func AuthStreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ tokenif := ctx.Value(rpctypes.TokenFieldNameGRPC)
+ if tokenif != nil {
+ tokenCred := &proxyTokenCredential{tokenif.(string)}
+ opts = append(opts, grpc.PerRPCCredentials(tokenCred))
+ }
+ return streamer(ctx, desc, cc, method, opts...)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch.go
new file mode 100644
index 0000000000..c84a71bce9
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch.go
@@ -0,0 +1,313 @@
+// 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 grpcproxy
+
+import (
+ "context"
+ "sync"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
+
+ "go.uber.org/zap"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+type watchProxy struct {
+ cw clientv3.Watcher
+ ctx context.Context
+
+ leader *leader
+
+ ranges *watchRanges
+
+ // mu protects adding outstanding watch servers through wg.
+ mu sync.Mutex
+
+ // wg waits until all outstanding watch servers quit.
+ wg sync.WaitGroup
+
+ // kv is used for permission checking
+ kv clientv3.KV
+ lg *zap.Logger
+}
+
+func NewWatchProxy(ctx context.Context, lg *zap.Logger, c *clientv3.Client) (pb.WatchServer, <-chan struct{}) {
+ cctx, cancel := context.WithCancel(ctx)
+ wp := &watchProxy{
+ cw: c.Watcher,
+ ctx: cctx,
+ leader: newLeader(cctx, c.Watcher),
+
+ kv: c.KV, // for permission checking
+ lg: lg,
+ }
+ wp.ranges = newWatchRanges(wp)
+ ch := make(chan struct{})
+ go func() {
+ defer close(ch)
+ <-wp.leader.stopNotify()
+ wp.mu.Lock()
+ select {
+ case <-wp.ctx.Done():
+ case <-wp.leader.disconnectNotify():
+ cancel()
+ }
+ <-wp.ctx.Done()
+ wp.mu.Unlock()
+ wp.wg.Wait()
+ wp.ranges.stop()
+ }()
+ return wp, ch
+}
+
+func (wp *watchProxy) Watch(stream pb.Watch_WatchServer) (err error) {
+ wp.mu.Lock()
+ select {
+ case <-wp.ctx.Done():
+ wp.mu.Unlock()
+ select {
+ case <-wp.leader.disconnectNotify():
+ return status.Error(codes.Canceled, "the client connection is closing")
+ default:
+ return wp.ctx.Err()
+ }
+ default:
+ wp.wg.Add(1)
+ }
+ wp.mu.Unlock()
+
+ ctx, cancel := context.WithCancel(stream.Context())
+ wps := &watchProxyStream{
+ ranges: wp.ranges,
+ watchers: make(map[int64]*watcher),
+ stream: stream,
+ watchCh: make(chan *pb.WatchResponse, 1024),
+ ctx: ctx,
+ cancel: cancel,
+ kv: wp.kv,
+ lg: wp.lg,
+ }
+
+ var lostLeaderC <-chan struct{}
+ if md, ok := metadata.FromOutgoingContext(stream.Context()); ok {
+ v := md[rpctypes.MetadataRequireLeaderKey]
+ if len(v) > 0 && v[0] == rpctypes.MetadataHasLeader {
+ lostLeaderC = wp.leader.lostNotify()
+ // if leader is known to be lost at creation time, avoid
+ // letting events through at all
+ select {
+ case <-lostLeaderC:
+ wp.wg.Done()
+ return rpctypes.ErrNoLeader
+ default:
+ }
+ }
+ }
+
+ // post to stopc => terminate server stream; can't use a waitgroup
+ // since all goroutines will only terminate after Watch() exits.
+ stopc := make(chan struct{}, 3)
+ go func() {
+ defer func() { stopc <- struct{}{} }()
+ wps.recvLoop()
+ }()
+ go func() {
+ defer func() { stopc <- struct{}{} }()
+ wps.sendLoop()
+ }()
+ // tear down watch if leader goes down or entire watch proxy is terminated
+ go func() {
+ defer func() { stopc <- struct{}{} }()
+ select {
+ case <-lostLeaderC:
+ case <-ctx.Done():
+ case <-wp.ctx.Done():
+ }
+ }()
+
+ <-stopc
+ cancel()
+
+ // recv/send may only shutdown after function exits;
+ // goroutine notifies proxy that stream is through
+ go func() {
+ <-stopc
+ <-stopc
+ wps.close()
+ wp.wg.Done()
+ }()
+
+ select {
+ case <-lostLeaderC:
+ return rpctypes.ErrNoLeader
+ case <-wp.leader.disconnectNotify():
+ return status.Error(codes.Canceled, "the client connection is closing")
+ default:
+ return wps.ctx.Err()
+ }
+}
+
+// watchProxyStream forwards etcd watch events to a proxied client stream.
+type watchProxyStream struct {
+ ranges *watchRanges
+
+ // mu protects watchers and nextWatcherID
+ mu sync.Mutex
+ // watchers receive events from watch broadcast.
+ watchers map[int64]*watcher
+ // nextWatcherID is the id to assign the next watcher on this stream.
+ nextWatcherID int64
+
+ stream pb.Watch_WatchServer
+
+ // watchCh receives watch responses from the watchers.
+ watchCh chan *pb.WatchResponse
+
+ ctx context.Context
+ cancel context.CancelFunc
+
+ // kv is used for permission checking
+ kv clientv3.KV
+ lg *zap.Logger
+}
+
+func (wps *watchProxyStream) close() {
+ var wg sync.WaitGroup
+ wps.cancel()
+ wps.mu.Lock()
+ wg.Add(len(wps.watchers))
+ for _, wpsw := range wps.watchers {
+ go func(w *watcher) {
+ wps.ranges.delete(w)
+ wg.Done()
+ }(wpsw)
+ }
+ wps.watchers = nil
+ wps.mu.Unlock()
+
+ wg.Wait()
+
+ close(wps.watchCh)
+}
+
+func (wps *watchProxyStream) checkPermissionForWatch(key, rangeEnd []byte) error {
+ if len(key) == 0 {
+ // If the length of the key is 0, we need to obtain full range.
+ // look at clientv3.WithPrefix()
+ key = []byte{0}
+ rangeEnd = []byte{0}
+ }
+ req := &pb.RangeRequest{
+ Serializable: true,
+ Key: key,
+ RangeEnd: rangeEnd,
+ CountOnly: true,
+ Limit: 1,
+ }
+ _, err := wps.kv.Do(wps.ctx, RangeRequestToOp(req))
+ return err
+}
+
+func (wps *watchProxyStream) recvLoop() error {
+ for {
+ req, err := wps.stream.Recv()
+ if err != nil {
+ return err
+ }
+ switch uv := req.RequestUnion.(type) {
+ case *pb.WatchRequest_CreateRequest:
+ cr := uv.CreateRequest
+
+ if err := wps.checkPermissionForWatch(cr.Key, cr.RangeEnd); err != nil {
+ wps.watchCh <- &pb.WatchResponse{
+ Header: &pb.ResponseHeader{},
+ WatchId: clientv3.InvalidWatchID,
+ Created: true,
+ Canceled: true,
+ CancelReason: err.Error(),
+ }
+ continue
+ }
+
+ wps.mu.Lock()
+ w := &watcher{
+ wr: watchRange{string(cr.Key), string(cr.RangeEnd)},
+ id: wps.nextWatcherID,
+ wps: wps,
+
+ nextrev: cr.StartRevision,
+ progress: cr.ProgressNotify,
+ prevKV: cr.PrevKv,
+ filters: v3rpc.FiltersFromRequest(cr),
+ }
+ if !w.wr.valid() {
+ w.post(&pb.WatchResponse{WatchId: clientv3.InvalidWatchID, Created: true, Canceled: true})
+ wps.mu.Unlock()
+ continue
+ }
+ wps.nextWatcherID++
+ w.nextrev = cr.StartRevision
+ wps.watchers[w.id] = w
+ wps.ranges.add(w)
+ wps.mu.Unlock()
+ wps.lg.Debug("create watcher", zap.String("key", w.wr.key), zap.String("end", w.wr.end), zap.Int64("watcherId", wps.nextWatcherID))
+ case *pb.WatchRequest_CancelRequest:
+ wps.delete(uv.CancelRequest.WatchId)
+ wps.lg.Debug("cancel watcher", zap.Int64("watcherId", uv.CancelRequest.WatchId))
+ default:
+ // Panic or Fatalf would allow to network clients to crash the serve remotely.
+ wps.lg.Error("not supported request type by gRPC proxy", zap.Stringer("request", req))
+ }
+ }
+}
+
+func (wps *watchProxyStream) sendLoop() {
+ for {
+ select {
+ case wresp, ok := <-wps.watchCh:
+ if !ok {
+ return
+ }
+ if err := wps.stream.Send(wresp); err != nil {
+ return
+ }
+ case <-wps.ctx.Done():
+ return
+ }
+ }
+}
+
+func (wps *watchProxyStream) delete(id int64) {
+ wps.mu.Lock()
+ defer wps.mu.Unlock()
+
+ w, ok := wps.watchers[id]
+ if !ok {
+ return
+ }
+ wps.ranges.delete(w)
+ delete(wps.watchers, id)
+ resp := &pb.WatchResponse{
+ Header: &w.lastHeader,
+ WatchId: id,
+ Canceled: true,
+ }
+ wps.watchCh <- resp
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcast.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcast.go
new file mode 100644
index 0000000000..1d9a43df14
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcast.go
@@ -0,0 +1,166 @@
+// 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 grpcproxy
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ clientv3 "go.etcd.io/etcd/client/v3"
+
+ "go.uber.org/zap"
+)
+
+// watchBroadcast broadcasts a server watcher to many client watchers.
+type watchBroadcast struct {
+ // cancel stops the underlying etcd server watcher and closes ch.
+ cancel context.CancelFunc
+ donec chan struct{}
+
+ // mu protects rev and receivers.
+ mu sync.RWMutex
+ // nextrev is the minimum expected next revision of the watcher on ch.
+ nextrev int64
+ // receivers contains all the client-side watchers to serve.
+ receivers map[*watcher]struct{}
+ // responses counts the number of responses
+ responses int
+ lg *zap.Logger
+}
+
+func newWatchBroadcast(lg *zap.Logger, wp *watchProxy, w *watcher, update func(*watchBroadcast)) *watchBroadcast {
+ cctx, cancel := context.WithCancel(wp.ctx)
+ wb := &watchBroadcast{
+ cancel: cancel,
+ nextrev: w.nextrev,
+ receivers: make(map[*watcher]struct{}),
+ donec: make(chan struct{}),
+ lg: lg,
+ }
+ wb.add(w)
+ go func() {
+ defer close(wb.donec)
+
+ opts := []clientv3.OpOption{
+ clientv3.WithRange(w.wr.end),
+ clientv3.WithProgressNotify(),
+ clientv3.WithRev(wb.nextrev),
+ clientv3.WithPrevKV(),
+ clientv3.WithCreatedNotify(),
+ }
+
+ cctx = withClientAuthToken(cctx, w.wps.stream.Context())
+
+ wch := wp.cw.Watch(cctx, w.wr.key, opts...)
+ wp.lg.Debug("watch", zap.String("key", w.wr.key))
+
+ for wr := range wch {
+ wb.bcast(wr)
+ update(wb)
+ }
+ }()
+ return wb
+}
+
+func (wb *watchBroadcast) bcast(wr clientv3.WatchResponse) {
+ wb.mu.Lock()
+ defer wb.mu.Unlock()
+ // watchers start on the given revision, if any; ignore header rev on create
+ if wb.responses > 0 || wb.nextrev == 0 {
+ wb.nextrev = wr.Header.Revision + 1
+ }
+ wb.responses++
+ for r := range wb.receivers {
+ r.send(wr)
+ }
+ if len(wb.receivers) > 0 {
+ eventsCoalescing.Add(float64(len(wb.receivers) - 1))
+ }
+}
+
+// add puts a watcher into receiving a broadcast if its revision at least
+// meets the broadcast revision. Returns true if added.
+func (wb *watchBroadcast) add(w *watcher) bool {
+ wb.mu.Lock()
+ defer wb.mu.Unlock()
+ if wb.nextrev > w.nextrev || (wb.nextrev == 0 && w.nextrev != 0) {
+ // wb is too far ahead, w will miss events
+ // or wb is being established with a current watcher
+ return false
+ }
+ if wb.responses == 0 {
+ // Newly created; create event will be sent by etcd.
+ wb.receivers[w] = struct{}{}
+ return true
+ }
+ // already sent by etcd; emulate create event
+ ok := w.post(&pb.WatchResponse{
+ Header: &pb.ResponseHeader{
+ // todo: fill in ClusterId
+ // todo: fill in MemberId:
+ Revision: w.nextrev,
+ // todo: fill in RaftTerm:
+ },
+ WatchId: w.id,
+ Created: true,
+ })
+ if !ok {
+ return false
+ }
+ wb.receivers[w] = struct{}{}
+ watchersCoalescing.Inc()
+
+ return true
+}
+func (wb *watchBroadcast) delete(w *watcher) {
+ wb.mu.Lock()
+ defer wb.mu.Unlock()
+ if _, ok := wb.receivers[w]; !ok {
+ panic("deleting missing watcher from broadcast")
+ }
+ delete(wb.receivers, w)
+ if len(wb.receivers) > 0 {
+ // do not dec the only left watcher for coalescing.
+ watchersCoalescing.Dec()
+ }
+}
+
+func (wb *watchBroadcast) size() int {
+ wb.mu.RLock()
+ defer wb.mu.RUnlock()
+ return len(wb.receivers)
+}
+
+func (wb *watchBroadcast) empty() bool { return wb.size() == 0 }
+
+func (wb *watchBroadcast) stop() {
+ if !wb.empty() {
+ // do not dec the only left watcher for coalescing.
+ watchersCoalescing.Sub(float64(wb.size() - 1))
+ }
+
+ wb.cancel()
+
+ select {
+ case <-wb.donec:
+ // watchProxyStream will hold watchRanges global mutex lock all the time if client failed to cancel etcd watchers.
+ // and it will cause the watch proxy to not work.
+ // please see pr https://github.com/etcd-io/etcd/pull/12030 to get more detail info.
+ case <-time.After(time.Second):
+ wb.lg.Error("failed to cancel etcd watcher")
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcasts.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcasts.go
new file mode 100644
index 0000000000..dacd3007d1
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_broadcasts.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 grpcproxy
+
+import (
+ "sync"
+)
+
+type watchBroadcasts struct {
+ wp *watchProxy
+
+ // mu protects bcasts and watchers from the coalesce loop.
+ mu sync.Mutex
+ bcasts map[*watchBroadcast]struct{}
+ watchers map[*watcher]*watchBroadcast
+
+ updatec chan *watchBroadcast
+ donec chan struct{}
+}
+
+// maxCoalesceRecievers prevents a popular watchBroadcast from being coalseced.
+const maxCoalesceReceivers = 5
+
+func newWatchBroadcasts(wp *watchProxy) *watchBroadcasts {
+ wbs := &watchBroadcasts{
+ wp: wp,
+ bcasts: make(map[*watchBroadcast]struct{}),
+ watchers: make(map[*watcher]*watchBroadcast),
+ updatec: make(chan *watchBroadcast, 1),
+ donec: make(chan struct{}),
+ }
+ go func() {
+ defer close(wbs.donec)
+ for wb := range wbs.updatec {
+ wbs.coalesce(wb)
+ }
+ }()
+ return wbs
+}
+
+func (wbs *watchBroadcasts) coalesce(wb *watchBroadcast) {
+ if wb.size() >= maxCoalesceReceivers {
+ return
+ }
+ wbs.mu.Lock()
+ for wbswb := range wbs.bcasts {
+ if wbswb == wb {
+ continue
+ }
+ wb.mu.Lock()
+ wbswb.mu.Lock()
+ // 1. check if wbswb is behind wb so it won't skip any events in wb
+ // 2. ensure wbswb started; nextrev == 0 may mean wbswb is waiting
+ // for a current watcher and expects a create event from the server.
+ if wb.nextrev >= wbswb.nextrev && wbswb.responses > 0 {
+ for w := range wb.receivers {
+ wbswb.receivers[w] = struct{}{}
+ wbs.watchers[w] = wbswb
+ }
+ wb.receivers = nil
+ }
+ wbswb.mu.Unlock()
+ wb.mu.Unlock()
+ if wb.empty() {
+ delete(wbs.bcasts, wb)
+ wb.stop()
+ break
+ }
+ }
+ wbs.mu.Unlock()
+}
+
+func (wbs *watchBroadcasts) add(w *watcher) {
+ wbs.mu.Lock()
+ defer wbs.mu.Unlock()
+ // find fitting bcast
+ for wb := range wbs.bcasts {
+ if wb.add(w) {
+ wbs.watchers[w] = wb
+ return
+ }
+ }
+ // no fit; create a bcast
+ wb := newWatchBroadcast(wbs.wp.lg, wbs.wp, w, wbs.update)
+ wbs.watchers[w] = wb
+ wbs.bcasts[wb] = struct{}{}
+}
+
+// delete removes a watcher and returns the number of remaining watchers.
+func (wbs *watchBroadcasts) delete(w *watcher) int {
+ wbs.mu.Lock()
+ defer wbs.mu.Unlock()
+
+ wb, ok := wbs.watchers[w]
+ if !ok {
+ panic("deleting missing watcher from broadcasts")
+ }
+ delete(wbs.watchers, w)
+ wb.delete(w)
+ if wb.empty() {
+ delete(wbs.bcasts, wb)
+ wb.stop()
+ }
+ return len(wbs.bcasts)
+}
+
+func (wbs *watchBroadcasts) stop() {
+ wbs.mu.Lock()
+ for wb := range wbs.bcasts {
+ wb.stop()
+ }
+ wbs.bcasts = nil
+ close(wbs.updatec)
+ wbs.mu.Unlock()
+ <-wbs.donec
+}
+
+func (wbs *watchBroadcasts) update(wb *watchBroadcast) {
+ select {
+ case wbs.updatec <- wb:
+ default:
+ }
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_ranges.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_ranges.go
new file mode 100644
index 0000000000..31c6b5925e
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watch_ranges.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 grpcproxy
+
+import (
+ "sync"
+)
+
+// watchRanges tracks all open watches for the proxy.
+type watchRanges struct {
+ wp *watchProxy
+
+ mu sync.Mutex
+ bcasts map[watchRange]*watchBroadcasts
+}
+
+func newWatchRanges(wp *watchProxy) *watchRanges {
+ return &watchRanges{
+ wp: wp,
+ bcasts: make(map[watchRange]*watchBroadcasts),
+ }
+}
+
+func (wrs *watchRanges) add(w *watcher) {
+ wrs.mu.Lock()
+ defer wrs.mu.Unlock()
+
+ if wbs := wrs.bcasts[w.wr]; wbs != nil {
+ wbs.add(w)
+ return
+ }
+ wbs := newWatchBroadcasts(wrs.wp)
+ wrs.bcasts[w.wr] = wbs
+ wbs.add(w)
+}
+
+func (wrs *watchRanges) delete(w *watcher) {
+ wrs.mu.Lock()
+ defer wrs.mu.Unlock()
+ wbs, ok := wrs.bcasts[w.wr]
+ if !ok {
+ panic("deleting missing range")
+ }
+ if wbs.delete(w) == 0 {
+ wbs.stop()
+ delete(wrs.bcasts, w.wr)
+ }
+}
+
+func (wrs *watchRanges) stop() {
+ wrs.mu.Lock()
+ defer wrs.mu.Unlock()
+ for _, wb := range wrs.bcasts {
+ wb.stop()
+ }
+ wrs.bcasts = nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watcher.go b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watcher.go
new file mode 100644
index 0000000000..5f6c3db808
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/watcher.go
@@ -0,0 +1,130 @@
+// 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 grpcproxy
+
+import (
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/api/v3/mvccpb"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/mvcc"
+)
+
+type watchRange struct {
+ key, end string
+}
+
+func (wr *watchRange) valid() bool {
+ return len(wr.end) == 0 || wr.end > wr.key || (wr.end[0] == 0 && len(wr.end) == 1)
+}
+
+type watcher struct {
+ // user configuration
+
+ wr watchRange
+ filters []mvcc.FilterFunc
+ progress bool
+ prevKV bool
+
+ // id is the id returned to the client on its watch stream.
+ id int64
+ // nextrev is the minimum expected next event revision.
+ nextrev int64
+ // lastHeader has the last header sent over the stream.
+ lastHeader pb.ResponseHeader
+
+ // wps is the parent.
+ wps *watchProxyStream
+}
+
+// send filters out repeated events by discarding revisions older
+// than the last one sent over the watch channel.
+func (w *watcher) send(wr clientv3.WatchResponse) {
+ if wr.IsProgressNotify() && !w.progress {
+ return
+ }
+ if w.nextrev > wr.Header.Revision && len(wr.Events) > 0 {
+ return
+ }
+ if w.nextrev == 0 {
+ // current watch; expect updates following this revision
+ w.nextrev = wr.Header.Revision + 1
+ }
+
+ events := make([]*mvccpb.Event, 0, len(wr.Events))
+
+ var lastRev int64
+ for i := range wr.Events {
+ ev := (*mvccpb.Event)(wr.Events[i])
+ if ev.Kv.ModRevision < w.nextrev {
+ continue
+ } else {
+ // We cannot update w.rev here.
+ // txn can have multiple events with the same rev.
+ // If w.nextrev updates here, it would skip events in the same txn.
+ lastRev = ev.Kv.ModRevision
+ }
+
+ filtered := false
+ for _, filter := range w.filters {
+ if filter(*ev) {
+ filtered = true
+ break
+ }
+ }
+ if filtered {
+ continue
+ }
+
+ if !w.prevKV {
+ evCopy := *ev
+ evCopy.PrevKv = nil
+ ev = &evCopy
+ }
+ events = append(events, ev)
+ }
+
+ if lastRev >= w.nextrev {
+ w.nextrev = lastRev + 1
+ }
+
+ // all events are filtered out?
+ if !wr.IsProgressNotify() && !wr.Created && len(events) == 0 && wr.CompactRevision == 0 {
+ return
+ }
+
+ w.lastHeader = wr.Header
+ w.post(&pb.WatchResponse{
+ Header: &wr.Header,
+ Created: wr.Created,
+ CompactRevision: wr.CompactRevision,
+ Canceled: wr.Canceled,
+ WatchId: w.id,
+ Events: events,
+ })
+}
+
+// post puts a watch response on the watcher's proxy stream channel
+func (w *watcher) post(wr *pb.WatchResponse) bool {
+ select {
+ case w.wps.watchCh <- wr:
+ case <-time.After(50 * time.Millisecond):
+ w.wps.cancel()
+ w.wps.lg.Error("failed to put a watch response on the watcher's proxy stream channel,err is timeout")
+ return false
+ }
+ return true
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/verify/doc.go b/vendor/go.etcd.io/etcd/server/v3/verify/doc.go
new file mode 100644
index 0000000000..2c42bf6f19
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/verify/doc.go
@@ -0,0 +1,20 @@
+// Copyright 2021 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 verify
+
+// verify package is analyzing persistent state of etcd to find potential
+// inconsistencies.
+// In particular it covers cross-checking between different aspacts of etcd
+// storage like WAL & Backend.
diff --git a/vendor/go.etcd.io/etcd/server/v3/verify/verify.go b/vendor/go.etcd.io/etcd/server/v3/verify/verify.go
new file mode 100644
index 0000000000..ef613d7eb0
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/verify/verify.go
@@ -0,0 +1,147 @@
+// Copyright 2021 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 verify
+
+import (
+ "fmt"
+ "os"
+
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/datadir"
+ "go.etcd.io/etcd/server/v3/etcdserver/cindex"
+ "go.etcd.io/etcd/server/v3/mvcc/backend"
+ wal2 "go.etcd.io/etcd/server/v3/wal"
+ "go.etcd.io/etcd/server/v3/wal/walpb"
+ "go.uber.org/zap"
+)
+
+const ENV_VERIFY = "ETCD_VERIFY"
+const ENV_VERIFY_ALL_VALUE = "all"
+
+type Config struct {
+ // DataDir is a root directory where the data being verified are stored.
+ DataDir string
+
+ // ExactIndex requires consistent_index in backend exactly match the last committed WAL entry.
+ // Usually backend's consistent_index needs to be <= WAL.commit, but for backups the match
+ // is expected to be exact.
+ ExactIndex bool
+
+ Logger *zap.Logger
+}
+
+// Verify performs consistency checks of given etcd data-directory.
+// The errors are reported as the returned error, but for some situations
+// the function can also panic.
+// The function is expected to work on not-in-use data model, i.e.
+// no file-locks should be taken. Verify does not modified the data.
+func Verify(cfg Config) error {
+ lg := cfg.Logger
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+
+ var err error
+ lg.Info("verification of persisted state", zap.String("data-dir", cfg.DataDir))
+ defer func() {
+ if err != nil {
+ lg.Error("verification of persisted state failed",
+ zap.String("data-dir", cfg.DataDir),
+ zap.Error(err))
+ } else if r := recover(); r != nil {
+ lg.Error("verification of persisted state failed",
+ zap.String("data-dir", cfg.DataDir))
+ panic(r)
+ } else {
+ lg.Info("verification of persisted state successful", zap.String("data-dir", cfg.DataDir))
+ }
+ }()
+
+ beConfig := backend.DefaultBackendConfig()
+ beConfig.Path = datadir.ToBackendFileName(cfg.DataDir)
+ beConfig.Logger = cfg.Logger
+
+ be := backend.New(beConfig)
+ defer be.Close()
+
+ snapshot, hardstate, err := validateWal(cfg)
+ if err != nil {
+ return err
+ }
+
+ // TODO: Perform validation of consistency of membership between
+ // backend/members & WAL confstate (and maybe storev2 if still exists).
+
+ return validateConsistentIndex(cfg, hardstate, snapshot, be)
+}
+
+// VerifyIfEnabled performs verification according to ETCD_VERIFY env settings.
+// See Verify for more information.
+func VerifyIfEnabled(cfg Config) error {
+ if os.Getenv(ENV_VERIFY) == ENV_VERIFY_ALL_VALUE {
+ return Verify(cfg)
+ }
+ return nil
+}
+
+// MustVerifyIfEnabled performs verification according to ETCD_VERIFY env settings
+// and exits in case of found problems.
+// See Verify for more information.
+func MustVerifyIfEnabled(cfg Config) {
+ if err := VerifyIfEnabled(cfg); err != nil {
+ cfg.Logger.Fatal("Verification failed",
+ zap.String("data-dir", cfg.DataDir),
+ zap.Error(err))
+ }
+}
+
+func validateConsistentIndex(cfg Config, hardstate *raftpb.HardState, snapshot *walpb.Snapshot, be backend.Backend) error {
+ index, term := cindex.ReadConsistentIndex(be.ReadTx())
+ if cfg.ExactIndex && index != hardstate.Commit {
+ return fmt.Errorf("backend.ConsistentIndex (%v) expected == WAL.HardState.commit (%v)", index, hardstate.Commit)
+ }
+ if cfg.ExactIndex && term != hardstate.Term {
+ return fmt.Errorf("backend.Term (%v) expected == WAL.HardState.term, (%v)", term, hardstate.Term)
+ }
+ if index > hardstate.Commit {
+ return fmt.Errorf("backend.ConsistentIndex (%v) must be <= WAL.HardState.commit (%v)", index, hardstate.Commit)
+ }
+ if term > hardstate.Term {
+ return fmt.Errorf("backend.Term (%v) must be <= WAL.HardState.term, (%v)", term, hardstate.Term)
+ }
+
+ if index < snapshot.Index {
+ return fmt.Errorf("backend.ConsistentIndex (%v) must be >= last snapshot index (%v)", index, snapshot.Index)
+ }
+
+ cfg.Logger.Info("verification: consistentIndex OK", zap.Uint64("backend-consistent-index", index), zap.Uint64("hardstate-commit", hardstate.Commit))
+ return nil
+}
+
+func validateWal(cfg Config) (*walpb.Snapshot, *raftpb.HardState, error) {
+ walDir := datadir.ToWalDir(cfg.DataDir)
+
+ walSnaps, err := wal2.ValidSnapshotEntries(cfg.Logger, walDir)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ snapshot := walSnaps[len(walSnaps)-1]
+ hardstate, err := wal2.Verify(cfg.Logger, walDir, snapshot)
+ if err != nil {
+ return nil, nil, err
+ }
+ return &snapshot, hardstate, nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/wal/decoder.go b/vendor/go.etcd.io/etcd/server/v3/wal/decoder.go
new file mode 100644
index 0000000000..b8c68bef6d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/decoder.go
@@ -0,0 +1,196 @@
+// 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"
+ "fmt"
+ "hash"
+ "io"
+ "sync"
+
+ "go.etcd.io/etcd/client/pkg/v3/fileutil"
+ "go.etcd.io/etcd/pkg/v3/crc"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/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 []*fileutil.FileBufReader
+
+ // lastValidOff file offset following the last valid decoded record
+ lastValidOff int64
+ crc hash.Hash32
+}
+
+func newDecoder(r ...fileutil.FileReader) *decoder {
+ readers := make([]*fileutil.FileBufReader, len(r))
+ for i := range r {
+ readers[i] = fileutil.NewFileBufReader(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
+ }
+
+ fileBufReader := d.brs[0]
+ l, err := readInt64(fileBufReader)
+ 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)
+ // The length of current WAL entry must be less than the remaining file size.
+ maxEntryLimit := fileBufReader.FileInfo().Size() - d.lastValidOff - padBytes
+ if recBytes > maxEntryLimit {
+ return fmt.Errorf("%w: [wal] max entry size limit exceeded when decoding %q, recBytes: %d, fileSize(%d) - offset(%d) - padBytes(%d) = entryLimit(%d)",
+ io.ErrUnexpectedEOF, fileBufReader.FileInfo().Name(), recBytes, fileBufReader.FileInfo().Size(), d.lastValidOff, padBytes, maxEntryLimit)
+ }
+
+ data := make([]byte, recBytes+padBytes)
+ if _, err = io.ReadFull(fileBufReader, 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/go.etcd.io/etcd/server/v3/wal/doc.go b/vendor/go.etcd.io/etcd/server/v3/wal/doc.go
new file mode 100644
index 0000000000..4288495461
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/doc.go
@@ -0,0 +1,74 @@
+// 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(zap.NewExample(), "/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/go.etcd.io/etcd/server/v3/wal/encoder.go b/vendor/go.etcd.io/etcd/server/v3/wal/encoder.go
new file mode 100644
index 0000000000..61b4c20efb
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/encoder.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 wal
+
+import (
+ "encoding/binary"
+ "hash"
+ "io"
+ "os"
+ "sync"
+
+ "go.etcd.io/etcd/pkg/v3/crc"
+ "go.etcd.io/etcd/pkg/v3/ioutil"
+ "go.etcd.io/etcd/server/v3/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)...)
+ }
+ n, err = e.bw.Write(data)
+ walWriteBytes.Add(float64(n))
+ 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()
+ n, err := e.bw.FlushN()
+ e.mu.Unlock()
+ walWriteBytes.Add(float64(n))
+ return err
+}
+
+func writeUint64(w io.Writer, n uint64, buf []byte) error {
+ // http://golang.org/src/encoding/binary/binary.go
+ binary.LittleEndian.PutUint64(buf, n)
+ nv, err := w.Write(buf)
+ walWriteBytes.Add(float64(nv))
+ return err
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/wal/file_pipeline.go b/vendor/go.etcd.io/etcd/server/v3/wal/file_pipeline.go
new file mode 100644
index 0000000000..c2feba6c1d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/file_pipeline.go
@@ -0,0 +1,105 @@
+// 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"
+
+ "go.etcd.io/etcd/client/pkg/v3/fileutil"
+
+ "go.uber.org/zap"
+)
+
+// filePipeline pipelines allocating disk space
+type filePipeline struct {
+ lg *zap.Logger
+
+ // 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(lg *zap.Logger, dir string, fileSize int64) *filePipeline {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ fp := &filePipeline{
+ lg: lg,
+ 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 {
+ fp.lg.Error("failed to preallocate space when creating a new WAL", zap.Int64("size", fp.size), zap.Error(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/go.etcd.io/etcd/server/v3/wal/metrics.go b/vendor/go.etcd.io/etcd/server/v3/wal/metrics.go
new file mode 100644
index 0000000000..814d654cdd
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/metrics.go
@@ -0,0 +1,42 @@
+// 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 (
+ walFsyncSec = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "disk",
+ Name: "wal_fsync_duration_seconds",
+ Help: "The latency distributions of fsync called by WAL.",
+
+ // 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),
+ })
+
+ walWriteBytes = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "disk",
+ Name: "wal_write_bytes_total",
+ Help: "Total number of bytes written in WAL.",
+ })
+)
+
+func init() {
+ prometheus.MustRegister(walFsyncSec)
+ prometheus.MustRegister(walWriteBytes)
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/wal/repair.go b/vendor/go.etcd.io/etcd/server/v3/wal/repair.go
new file mode 100644
index 0000000000..dec2fa240b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/repair.go
@@ -0,0 +1,115 @@
+// 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"
+ "io"
+ "os"
+ "path/filepath"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/fileutil"
+ "go.etcd.io/etcd/server/v3/wal/walpb"
+ "go.uber.org/zap"
+)
+
+// Repair tries to repair ErrUnexpectedEOF in the
+// last wal file by truncating.
+func Repair(lg *zap.Logger, dirpath string) bool {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ f, err := openLast(lg, dirpath)
+ if err != nil {
+ return false
+ }
+ defer f.Close()
+
+ lg.Info("repairing", zap.String("path", f.Name()))
+
+ rec := &walpb.Record{}
+ decoder := newDecoder(fileutil.NewFileReader(f.File))
+ for {
+ lastOffset := decoder.lastOffset()
+ err := decoder.decode(rec)
+ switch {
+ case err == 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 errors.Is(err, io.EOF):
+ lg.Info("repaired", zap.String("path", f.Name()), zap.Error(io.EOF))
+ return true
+
+ case errors.Is(err, io.ErrUnexpectedEOF):
+ bf, bferr := os.Create(f.Name() + ".broken")
+ if bferr != nil {
+ lg.Warn("failed to create backup file", zap.String("path", f.Name()+".broken"), zap.Error(bferr))
+ return false
+ }
+ defer bf.Close()
+
+ if _, err = f.Seek(0, io.SeekStart); err != nil {
+ lg.Warn("failed to read file", zap.String("path", f.Name()), zap.Error(err))
+ return false
+ }
+
+ if _, err = io.Copy(bf, f); err != nil {
+ lg.Warn("failed to copy", zap.String("from", f.Name()+".broken"), zap.String("to", f.Name()), zap.Error(err))
+ return false
+ }
+
+ if err = f.Truncate(lastOffset); err != nil {
+ lg.Warn("failed to truncate", zap.String("path", f.Name()), zap.Error(err))
+ return false
+ }
+
+ start := time.Now()
+ if err = fileutil.Fsync(f.File); err != nil {
+ lg.Warn("failed to fsync", zap.String("path", f.Name()), zap.Error(err))
+ return false
+ }
+ walFsyncSec.Observe(time.Since(start).Seconds())
+
+ lg.Info("repaired", zap.String("path", f.Name()), zap.Error(io.ErrUnexpectedEOF))
+ return true
+
+ default:
+ lg.Warn("failed to repair", zap.String("path", f.Name()), zap.Error(err))
+ return false
+ }
+ }
+}
+
+// openLast opens the last wal file for read and write.
+func openLast(lg *zap.Logger, dirpath string) (*fileutil.LockedFile, error) {
+ names, err := readWALNames(lg, 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/go.etcd.io/etcd/server/v3/wal/util.go b/vendor/go.etcd.io/etcd/server/v3/wal/util.go
new file mode 100644
index 0000000000..4a21ae6182
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/util.go
@@ -0,0 +1,112 @@
+// 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"
+
+ "go.etcd.io/etcd/client/pkg/v3/fileutil"
+
+ "go.uber.org/zap"
+)
+
+var errBadWALName = errors.New("bad wal name")
+
+// Exist returns true if there are any files in a given directory.
+func Exist(dir string) bool {
+ names, err := fileutil.ReadDir(dir, fileutil.WithExt(".wal"))
+ 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(lg *zap.Logger, names []string, index uint64) (int, bool) {
+ for i := len(names) - 1; i >= 0; i-- {
+ name := names[i]
+ _, curIndex, err := parseWALName(name)
+ if err != nil {
+ lg.Panic("failed to parse WAL file name", zap.String("path", name), zap.Error(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(lg *zap.Logger, names []string) bool {
+ var lastSeq uint64
+ for _, name := range names {
+ curSeq, _, err := parseWALName(name)
+ if err != nil {
+ lg.Panic("failed to parse WAL file name", zap.String("path", name), zap.Error(err))
+ }
+ if lastSeq != 0 && lastSeq != curSeq-1 {
+ return false
+ }
+ lastSeq = curSeq
+ }
+ return true
+}
+
+func readWALNames(lg *zap.Logger, dirpath string) ([]string, error) {
+ names, err := fileutil.ReadDir(dirpath)
+ if err != nil {
+ return nil, err
+ }
+ wnames := checkWalNames(lg, names)
+ if len(wnames) == 0 {
+ return nil, ErrFileNotFound
+ }
+ return wnames, nil
+}
+
+func checkWalNames(lg *zap.Logger, 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") {
+ lg.Warn(
+ "ignored file in WAL directory",
+ zap.String("path", 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, errBadWALName
+ }
+ _, 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/go.etcd.io/etcd/server/v3/wal/wal.go b/vendor/go.etcd.io/etcd/server/v3/wal/wal.go
new file mode 100644
index 0000000000..db90078770
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/wal.go
@@ -0,0 +1,1009 @@
+// 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"
+ "strings"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/fileutil"
+ "go.etcd.io/etcd/pkg/v3/pbutil"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/wal/walpb"
+
+ "go.uber.org/zap"
+)
+
+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
+
+ 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")
+ ErrSliceOutOfRange = errors.New("wal: slice bounds out of range")
+ ErrDecoderNotFound = errors.New("wal: decoder 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 {
+ lg *zap.Logger
+
+ 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
+
+ unsafeNoSync bool // if set, do not fsync
+
+ 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
+// after the file is Open.
+func Create(lg *zap.Logger, dirpath string, metadata []byte) (*WAL, error) {
+ if Exist(dirpath) {
+ return nil, os.ErrExist
+ }
+
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+
+ // 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
+ }
+ }
+ defer os.RemoveAll(tmpdirpath)
+
+ if err := fileutil.CreateDirAll(lg, tmpdirpath); err != nil {
+ lg.Warn(
+ "failed to create a temporary WAL directory",
+ zap.String("tmp-dir-path", tmpdirpath),
+ zap.String("dir-path", dirpath),
+ zap.Error(err),
+ )
+ 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 {
+ lg.Warn(
+ "failed to flock an initial WAL file",
+ zap.String("path", p),
+ zap.Error(err),
+ )
+ return nil, err
+ }
+ if _, err = f.Seek(0, io.SeekEnd); err != nil {
+ lg.Warn(
+ "failed to seek an initial WAL file",
+ zap.String("path", p),
+ zap.Error(err),
+ )
+ return nil, err
+ }
+ if err = fileutil.Preallocate(f.File, SegmentSizeBytes, true); err != nil {
+ lg.Warn(
+ "failed to preallocate an initial WAL file",
+ zap.String("path", p),
+ zap.Int64("segment-bytes", SegmentSizeBytes),
+ zap.Error(err),
+ )
+ return nil, err
+ }
+
+ w := &WAL{
+ lg: lg,
+ 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
+ }
+
+ logDirPath := w.dir
+ if w, err = w.renameWAL(tmpdirpath); err != nil {
+ lg.Warn(
+ "failed to rename the temporary WAL directory",
+ zap.String("tmp-dir-path", tmpdirpath),
+ zap.String("dir-path", logDirPath),
+ zap.Error(err),
+ )
+ return nil, err
+ }
+
+ var perr error
+ defer func() {
+ if perr != nil {
+ w.cleanupWAL(lg)
+ }
+ }()
+
+ // directory was renamed; sync parent dir to persist rename
+ pdir, perr := fileutil.OpenDir(filepath.Dir(w.dir))
+ if perr != nil {
+ lg.Warn(
+ "failed to open the parent data directory",
+ zap.String("parent-dir-path", filepath.Dir(w.dir)),
+ zap.String("dir-path", w.dir),
+ zap.Error(perr),
+ )
+ return nil, perr
+ }
+ dirCloser := func() error {
+ if perr = pdir.Close(); perr != nil {
+ lg.Warn(
+ "failed to close the parent data directory file",
+ zap.String("parent-dir-path", filepath.Dir(w.dir)),
+ zap.String("dir-path", w.dir),
+ zap.Error(perr),
+ )
+ return perr
+ }
+ return nil
+ }
+ start := time.Now()
+ if perr = fileutil.Fsync(pdir); perr != nil {
+ dirCloser()
+ lg.Warn(
+ "failed to fsync the parent data directory file",
+ zap.String("parent-dir-path", filepath.Dir(w.dir)),
+ zap.String("dir-path", w.dir),
+ zap.Error(perr),
+ )
+ return nil, perr
+ }
+ walFsyncSec.Observe(time.Since(start).Seconds())
+ if err = dirCloser(); err != nil {
+ return nil, err
+ }
+
+ return w, nil
+}
+
+func (w *WAL) SetUnsafeNoFsync() {
+ w.unsafeNoSync = true
+}
+
+func (w *WAL) cleanupWAL(lg *zap.Logger) {
+ var err error
+ if err = w.Close(); err != nil {
+ lg.Panic("failed to close WAL during cleanup", zap.Error(err))
+ }
+ brokenDirName := fmt.Sprintf("%s.broken.%v", w.dir, time.Now().Format("20060102.150405.999999"))
+ if err = os.Rename(w.dir, brokenDirName); err != nil {
+ lg.Panic(
+ "failed to rename WAL during cleanup",
+ zap.Error(err),
+ zap.String("source-path", w.dir),
+ zap.String("rename-path", brokenDirName),
+ )
+ }
+}
+
+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.lg, 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.
+ w.lg.Info(
+ "closing WAL to release flock and retry directory renaming",
+ zap.String("from", tmpdirpath),
+ zap.String("to", w.dir),
+ )
+ w.Close()
+
+ if err := os.Rename(tmpdirpath, w.dir); err != nil {
+ return nil, err
+ }
+
+ // reopen and relock
+ newWAL, oerr := Open(w.lg, 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(lg *zap.Logger, dirpath string, snap walpb.Snapshot) (*WAL, error) {
+ w, err := openAtIndex(lg, 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(lg *zap.Logger, dirpath string, snap walpb.Snapshot) (*WAL, error) {
+ return openAtIndex(lg, dirpath, snap, false)
+}
+
+func openAtIndex(lg *zap.Logger, dirpath string, snap walpb.Snapshot, write bool) (*WAL, error) {
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ names, nameIndex, err := selectWALFiles(lg, dirpath, snap)
+ if err != nil {
+ return nil, err
+ }
+
+ rs, ls, closer, err := openWALFiles(lg, dirpath, names, nameIndex, write)
+ if err != nil {
+ return nil, err
+ }
+
+ // create a WAL ready for reading
+ w := &WAL{
+ lg: lg,
+ 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(lg, w.dir, SegmentSizeBytes)
+ }
+
+ return w, nil
+}
+
+func selectWALFiles(lg *zap.Logger, dirpath string, snap walpb.Snapshot) ([]string, int, error) {
+ names, err := readWALNames(lg, dirpath)
+ if err != nil {
+ return nil, -1, err
+ }
+
+ nameIndex, ok := searchIndex(lg, names, snap.Index)
+ if !ok || !isValidSeq(lg, names[nameIndex:]) {
+ err = ErrFileNotFound
+ return nil, -1, err
+ }
+
+ return names, nameIndex, nil
+}
+
+func openWALFiles(lg *zap.Logger, dirpath string, names []string, nameIndex int, write bool) ([]fileutil.FileReader, []*fileutil.LockedFile, func() error, error) {
+ rcs := make([]io.ReadCloser, 0)
+ rs := make([]fileutil.FileReader, 0)
+ ls := make([]*fileutil.LockedFile, 0)
+ for _, name := range names[nameIndex:] {
+ p := filepath.Join(dirpath, name)
+ var f *os.File
+ if write {
+ l, err := fileutil.TryLockFile(p, os.O_RDWR, fileutil.PrivateFileMode)
+ if err != nil {
+ closeAll(lg, rcs...)
+ return nil, nil, nil, err
+ }
+ ls = append(ls, l)
+ rcs = append(rcs, l)
+ f = l.File
+ } else {
+ rf, err := os.OpenFile(p, os.O_RDONLY, fileutil.PrivateFileMode)
+ if err != nil {
+ closeAll(lg, rcs...)
+ return nil, nil, nil, err
+ }
+ ls = append(ls, nil)
+ rcs = append(rcs, rf)
+ f = rf
+ }
+ fileReader := fileutil.NewFileReader(f)
+ rs = append(rs, fileReader)
+ }
+
+ closer := func() error { return closeAll(lg, rcs...) }
+
+ return rs, ls, closer, 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.
+//
+// ReadAll suppresses WAL entries that got overridden (i.e. a newer entry with the same index
+// exists in the log). Such a situation can happen in cases described in figure 7. of the
+// RAFT paper (http://web.stanford.edu/~ouster/cgi-bin/papers/raft-atc14.pdf).
+//
+// ReadAll may return uncommitted yet entries, that are subject to be overriden.
+// Do not apply entries that have index > state.commit, as they are subject to change.
+func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.Entry, err error) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ rec := &walpb.Record{}
+
+ if w.decoder == nil {
+ return nil, state, nil, ErrDecoderNotFound
+ }
+ 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)
+ // 0 <= e.Index-w.start.Index - 1 < len(ents)
+ if e.Index > w.start.Index {
+ // prevent "panic: runtime error: slice bounds out of range [:13038096702221461992] with capacity 0"
+ up := e.Index - w.start.Index - 1
+ if up > uint64(len(ents)) {
+ // return error before append call causes runtime panic
+ return nil, state, nil, ErrSliceOutOfRange
+ }
+ // The line below is potentially overriding some 'uncommitted' entries.
+ ents = append(ents[:up], 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 !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) {
+ state.Reset()
+ return nil, state, nil, err
+ }
+ default:
+ // We must read all the entries if WAL is opened in write mode.
+ if !errors.Is(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
+}
+
+// ValidSnapshotEntries returns all the valid snapshot entries in the wal logs in the given directory.
+// Snapshot entries are valid if their index is less than or equal to the most recent committed hardstate.
+func ValidSnapshotEntries(lg *zap.Logger, walDir string) ([]walpb.Snapshot, error) {
+ var snaps []walpb.Snapshot
+ var state raftpb.HardState
+ var err error
+
+ rec := &walpb.Record{}
+ names, err := readWALNames(lg, walDir)
+ if err != nil {
+ return nil, err
+ }
+
+ // open wal files in read mode, so that there is no conflict
+ // when the same WAL is opened elsewhere in write mode
+ rs, _, closer, err := openWALFiles(lg, walDir, names, 0, false)
+ if err != nil {
+ return nil, err
+ }
+ defer func() {
+ if closer != nil {
+ closer()
+ }
+ }()
+
+ // create a new decoder from the readers on the WAL files
+ decoder := newDecoder(rs...)
+
+ for err = decoder.decode(rec); err == nil; err = decoder.decode(rec) {
+ switch rec.Type {
+ case snapshotType:
+ var loadedSnap walpb.Snapshot
+ pbutil.MustUnmarshal(&loadedSnap, rec.Data)
+ snaps = append(snaps, loadedSnap)
+ case stateType:
+ state = mustUnmarshalState(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 {
+ return nil, ErrCRCMismatch
+ }
+ decoder.updateCRC(rec.Crc)
+ }
+ }
+ // We do not have to read out all the WAL entries
+ // as the decoder is opened in read mode.
+ if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) {
+ return nil, err
+ }
+
+ // filter out any snaps that are newer than the committed hardstate
+ n := 0
+ for _, s := range snaps {
+ if s.Index <= state.Commit {
+ snaps[n] = s
+ n++
+ }
+ }
+ snaps = snaps[:n:n]
+ return snaps, nil
+}
+
+// Verify reads through the given WAL and verifies that it is not corrupted.
+// It creates a new decoder to read through the records of the given WAL.
+// It does not conflict with any open WAL, but it is recommended not to
+// call this function after opening the WAL for writing.
+// If it cannot read out the expected snap, it will return ErrSnapshotNotFound.
+// If the loaded snap doesn't match with the expected one, it will
+// return error ErrSnapshotMismatch.
+func Verify(lg *zap.Logger, walDir string, snap walpb.Snapshot) (*raftpb.HardState, error) {
+ var metadata []byte
+ var err error
+ var match bool
+ var state raftpb.HardState
+
+ rec := &walpb.Record{}
+
+ if lg == nil {
+ lg = zap.NewNop()
+ }
+ names, nameIndex, err := selectWALFiles(lg, walDir, snap)
+ if err != nil {
+ return nil, err
+ }
+
+ // open wal files in read mode, so that there is no conflict
+ // when the same WAL is opened elsewhere in write mode
+ rs, _, closer, err := openWALFiles(lg, walDir, names, nameIndex, false)
+ if err != nil {
+ return nil, err
+ }
+ defer func() {
+ if closer != nil {
+ closer()
+ }
+ }()
+
+ // create a new decoder from the readers on the WAL files
+ decoder := newDecoder(rs...)
+
+ for err = decoder.decode(rec); err == nil; err = decoder.decode(rec) {
+ switch rec.Type {
+ case metadataType:
+ if metadata != nil && !bytes.Equal(metadata, rec.Data) {
+ return nil, ErrMetadataConflict
+ }
+ metadata = rec.Data
+ case crcType:
+ crc := decoder.crc.Sum32()
+ // Current crc of decoder must match the crc of the record.
+ // We need not match 0 crc, since the decoder is a new one at this point.
+ if crc != 0 && rec.Validate(crc) != nil {
+ return nil, ErrCRCMismatch
+ }
+ decoder.updateCRC(rec.Crc)
+ case snapshotType:
+ var loadedSnap walpb.Snapshot
+ pbutil.MustUnmarshal(&loadedSnap, rec.Data)
+ if loadedSnap.Index == snap.Index {
+ if loadedSnap.Term != snap.Term {
+ return nil, ErrSnapshotMismatch
+ }
+ match = true
+ }
+ // We ignore all entry and state type records as these
+ // are not necessary for validating the WAL contents
+ case entryType:
+ case stateType:
+ pbutil.MustUnmarshal(&state, rec.Data)
+ default:
+ return nil, fmt.Errorf("unexpected block type %d", rec.Type)
+ }
+ }
+
+ // We do not have to read out all the WAL entries
+ // as the decoder is opened in read mode.
+ if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) {
+ return nil, err
+ }
+
+ if !match {
+ return nil, ErrSnapshotNotFound
+ }
+
+ return &state, nil
+}
+
+// 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
+ }
+ start := time.Now()
+ if err = fileutil.Fsync(w.dirFile); err != nil {
+ return err
+ }
+ walFsyncSec.Observe(time.Since(start).Seconds())
+
+ // 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
+ }
+
+ w.lg.Info("created a new WAL segment", zap.String("path", fpath))
+ return nil
+}
+
+func (w *WAL) sync() error {
+ if w.encoder != nil {
+ if err := w.encoder.flush(); err != nil {
+ return err
+ }
+ }
+
+ if w.unsafeNoSync {
+ return nil
+ }
+
+ start := time.Now()
+ err := fileutil.Fdatasync(w.tail().File)
+
+ took := time.Since(start)
+ if took > warnSyncDuration {
+ w.lg.Warn(
+ "slow fdatasync",
+ zap.Duration("took", took),
+ zap.Duration("expected-duration", warnSyncDuration),
+ )
+ }
+ walFsyncSec.Observe(took.Seconds())
+
+ return err
+}
+
+func (w *WAL) Sync() error {
+ return w.sync()
+}
+
+// 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
+}
+
+// Close closes the current WAL file and directory.
+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 {
+ w.lg.Error("failed to close WAL", zap.Error(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 {
+ // gofail: var walBeforeSync struct{}
+ err = w.sync()
+ // gofail: var walAfterSync struct{}
+ return err
+ }
+ return nil
+ }
+
+ return w.cut()
+}
+
+func (w *WAL) SaveSnapshot(e walpb.Snapshot) error {
+ if err := walpb.ValidateSnapshotForWrite(&e); err != nil {
+ return err
+ }
+
+ 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 {
+ w.lg.Fatal("failed to parse WAL name", zap.String("name", t.Name()), zap.Error(err))
+ }
+ return seq
+}
+
+func closeAll(lg *zap.Logger, rcs ...io.ReadCloser) error {
+ stringArr := make([]string, 0)
+ for _, f := range rcs {
+ if err := f.Close(); err != nil {
+ lg.Warn("failed to close: ", zap.Error(err))
+ stringArr = append(stringArr, err.Error())
+ }
+ }
+ if len(stringArr) == 0 {
+ return nil
+ }
+ return errors.New(strings.Join(stringArr, ", "))
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.go b/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.go
new file mode 100644
index 0000000000..e2070fbba3
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.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 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
+}
+
+// ValidateSnapshotForWrite ensures the Snapshot the newly written snapshot is valid.
+//
+// There might exist log-entries written by old etcd versions that does not conform
+// to the requirements.
+func ValidateSnapshotForWrite(e *Snapshot) error {
+ // Since etcd>=3.5.0
+ if e.ConfState == nil && e.Index > 0 {
+ return errors.New("Saved (not-initial) snapshot is missing ConfState: " + e.String())
+ }
+ return nil
+}
diff --git a/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.pb.go b/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.pb.go
new file mode 100644
index 0000000000..654d82636c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.pb.go
@@ -0,0 +1,609 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: record.proto
+
+package walpb
+
+import (
+ fmt "fmt"
+ io "io"
+ math "math"
+ math_bits "math/bits"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+ proto "github.com/golang/protobuf/proto"
+ raftpb "go.etcd.io/etcd/raft/v3/raftpb"
+)
+
+// 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.ProtoPackageIsVersion3 // 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_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `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 fileDescriptor_bf94fd919e302a1d, []int{0}
+}
+func (m *Record) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Record) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Record.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Record) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Record.Merge(m, src)
+}
+func (m *Record) XXX_Size() int {
+ return m.Size()
+}
+func (m *Record) XXX_DiscardUnknown() {
+ xxx_messageInfo_Record.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Record proto.InternalMessageInfo
+
+// Keep in sync with raftpb.SnapshotMetadata.
+type Snapshot struct {
+ Index uint64 `protobuf:"varint,1,opt,name=index" json:"index"`
+ Term uint64 `protobuf:"varint,2,opt,name=term" json:"term"`
+ // Field populated since >=etcd-3.5.0.
+ ConfState *raftpb.ConfState `protobuf:"bytes,3,opt,name=conf_state,json=confState" json:"conf_state,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `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 fileDescriptor_bf94fd919e302a1d, []int{1}
+}
+func (m *Snapshot) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_Snapshot.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *Snapshot) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Snapshot.Merge(m, src)
+}
+func (m *Snapshot) XXX_Size() int {
+ return m.Size()
+}
+func (m *Snapshot) XXX_DiscardUnknown() {
+ xxx_messageInfo_Snapshot.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Snapshot proto.InternalMessageInfo
+
+func init() {
+ proto.RegisterType((*Record)(nil), "walpb.Record")
+ proto.RegisterType((*Snapshot)(nil), "walpb.Snapshot")
+}
+
+func init() { proto.RegisterFile("record.proto", fileDescriptor_bf94fd919e302a1d) }
+
+var fileDescriptor_bf94fd919e302a1d = []byte{
+ // 234 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x8e, 0x41, 0x4e, 0xc3, 0x30,
+ 0x10, 0x45, 0x63, 0xe2, 0x22, 0x18, 0xca, 0x02, 0xab, 0xaa, 0xa2, 0x2c, 0x4c, 0xd4, 0x55, 0x56,
+ 0x29, 0xe2, 0x08, 0x65, 0xcf, 0x22, 0x3d, 0x00, 0x72, 0x1d, 0xa7, 0x20, 0xd1, 0x8c, 0x35, 0xb5,
+ 0x04, 0xdc, 0x84, 0x23, 0x65, 0xc9, 0x09, 0x10, 0x84, 0x8b, 0xa0, 0x8c, 0x03, 0x1b, 0xfb, 0xeb,
+ 0x7d, 0xf9, 0x7d, 0xc3, 0x9c, 0x9c, 0x45, 0x6a, 0x2a, 0x4f, 0x18, 0x50, 0xcd, 0x5e, 0xcc, 0xb3,
+ 0xdf, 0xe5, 0x8b, 0x3d, 0xee, 0x91, 0xc9, 0x7a, 0x4c, 0xb1, 0xcc, 0x97, 0x64, 0xda, 0xb0, 0x1e,
+ 0x0f, 0xbf, 0xe3, 0x2b, 0xf2, 0xd5, 0x3d, 0x9c, 0xd6, 0x2c, 0x51, 0x19, 0xc8, 0xf0, 0xe6, 0x5d,
+ 0x26, 0x0a, 0x51, 0xa6, 0x1b, 0xd9, 0x7f, 0x5e, 0x27, 0x35, 0x13, 0xb5, 0x84, 0xd4, 0x92, 0xcd,
+ 0x4e, 0x0a, 0x51, 0x5e, 0x4e, 0xc5, 0x08, 0x94, 0x02, 0xd9, 0x98, 0x60, 0xb2, 0xb4, 0x10, 0xe5,
+ 0xbc, 0xe6, 0xbc, 0x22, 0x38, 0xdb, 0x76, 0xc6, 0x1f, 0x1f, 0x31, 0xa8, 0x1c, 0x66, 0x4f, 0x5d,
+ 0xe3, 0x5e, 0x59, 0x29, 0xa7, 0x97, 0x11, 0xf1, 0x9a, 0xa3, 0x03, 0x4b, 0xe5, 0xff, 0x9a, 0xa3,
+ 0x83, 0xba, 0x01, 0xb0, 0xd8, 0xb5, 0x0f, 0xc7, 0x60, 0x82, 0x63, 0xf7, 0xc5, 0xed, 0x55, 0x15,
+ 0x7f, 0x5e, 0xdd, 0x61, 0xd7, 0x6e, 0xc7, 0xa2, 0x3e, 0xb7, 0x7f, 0x71, 0xb3, 0xe8, 0xbf, 0x75,
+ 0xd2, 0x0f, 0x5a, 0x7c, 0x0c, 0x5a, 0x7c, 0x0d, 0x5a, 0xbc, 0xff, 0xe8, 0xe4, 0x37, 0x00, 0x00,
+ 0xff, 0xff, 0xc3, 0x36, 0x0c, 0xad, 0x1d, 0x01, 0x00, 0x00,
+}
+
+func (m *Record) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Record) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Record) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.Data != nil {
+ i -= len(m.Data)
+ copy(dAtA[i:], m.Data)
+ i = encodeVarintRecord(dAtA, i, uint64(len(m.Data)))
+ i--
+ dAtA[i] = 0x1a
+ }
+ i = encodeVarintRecord(dAtA, i, uint64(m.Crc))
+ i--
+ dAtA[i] = 0x10
+ i = encodeVarintRecord(dAtA, i, uint64(m.Type))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func (m *Snapshot) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *Snapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if m.XXX_unrecognized != nil {
+ i -= len(m.XXX_unrecognized)
+ copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ if m.ConfState != nil {
+ {
+ size, err := m.ConfState.MarshalToSizedBuffer(dAtA[:i])
+ if err != nil {
+ return 0, err
+ }
+ i -= size
+ i = encodeVarintRecord(dAtA, i, uint64(size))
+ }
+ i--
+ dAtA[i] = 0x1a
+ }
+ i = encodeVarintRecord(dAtA, i, uint64(m.Term))
+ i--
+ dAtA[i] = 0x10
+ i = encodeVarintRecord(dAtA, i, uint64(m.Index))
+ i--
+ dAtA[i] = 0x8
+ return len(dAtA) - i, nil
+}
+
+func encodeVarintRecord(dAtA []byte, offset int, v uint64) int {
+ offset -= sovRecord(v)
+ base := offset
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return base
+}
+func (m *Record) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ 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) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ n += 1 + sovRecord(uint64(m.Index))
+ n += 1 + sovRecord(uint64(m.Term))
+ if m.ConfState != nil {
+ l = m.ConfState.Size()
+ n += 1 + l + sovRecord(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovRecord(x uint64) (n int) {
+ return (math_bits.Len64(x|1) + 6) / 7
+}
+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 < 0 {
+ return ErrInvalidLengthRecord
+ }
+ 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) || (iNdEx+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
+ }
+ }
+ case 3:
+ 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 ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRecord
+ }
+ postIndex := iNdEx + msglen
+ if postIndex < 0 {
+ return ErrInvalidLengthRecord
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.ConfState == nil {
+ m.ConfState = &raftpb.ConfState{}
+ }
+ if err := m.ConfState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRecord(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if (skippy < 0) || (iNdEx+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
+ depth := 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
+ }
+ }
+ case 1:
+ iNdEx += 8
+ 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
+ }
+ }
+ if length < 0 {
+ return 0, ErrInvalidLengthRecord
+ }
+ iNdEx += length
+ case 3:
+ depth++
+ case 4:
+ if depth == 0 {
+ return 0, ErrUnexpectedEndOfGroupRecord
+ }
+ depth--
+ case 5:
+ iNdEx += 4
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ if iNdEx < 0 {
+ return 0, ErrInvalidLengthRecord
+ }
+ if depth == 0 {
+ return iNdEx, nil
+ }
+ }
+ return 0, io.ErrUnexpectedEOF
+}
+
+var (
+ ErrInvalidLengthRecord = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowRecord = fmt.Errorf("proto: integer overflow")
+ ErrUnexpectedEndOfGroupRecord = fmt.Errorf("proto: unexpected end of group")
+)
diff --git a/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.proto b/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.proto
new file mode 100644
index 0000000000..536fa6c19c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.proto
@@ -0,0 +1,24 @@
+syntax = "proto2";
+package walpb;
+
+import "gogoproto/gogo.proto";
+import "raft/raftpb/raft.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.sizer_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+option (gogoproto.goproto_getters_all) = false;
+
+message Record {
+ optional int64 type = 1 [(gogoproto.nullable) = false];
+ optional uint32 crc = 2 [(gogoproto.nullable) = false];
+ optional bytes data = 3;
+}
+
+// Keep in sync with raftpb.SnapshotMetadata.
+message Snapshot {
+ optional uint64 index = 1 [(gogoproto.nullable) = false];
+ optional uint64 term = 2 [(gogoproto.nullable) = false];
+ // Field populated since >=etcd-3.5.0.
+ optional raftpb.ConfState conf_state = 3;
+}
diff --git a/vendor/go.etcd.io/etcd/tests/v3/LICENSE b/vendor/go.etcd.io/etcd/tests/v3/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/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/go.etcd.io/etcd/tests/v3/integration/bridge.go b/vendor/go.etcd.io/etcd/tests/v3/integration/bridge.go
new file mode 100644
index 0000000000..746168fc7a
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/integration/bridge.go
@@ -0,0 +1,220 @@
+// 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 integration
+
+import (
+ "io"
+ "io/ioutil"
+ "net"
+ "sync"
+)
+
+type Dialer interface {
+ Dial() (net.Conn, error)
+}
+
+// bridge proxies connections between listener and dialer, making it possible
+// to disconnect grpc network connections without closing the logical grpc connection.
+type bridge struct {
+ dialer Dialer
+ l net.Listener
+ conns map[*bridgeConn]struct{}
+
+ stopc chan struct{}
+ pausec chan struct{}
+ blackholec chan struct{}
+ wg sync.WaitGroup
+
+ mu sync.Mutex
+}
+
+func newBridge(dialer Dialer, listener net.Listener) (*bridge, error) {
+ b := &bridge{
+ // bridge "port" is ("%05d%05d0", port, pid) since go1.8 expects the port to be a number
+ dialer: dialer,
+ l: listener,
+ conns: make(map[*bridgeConn]struct{}),
+ stopc: make(chan struct{}),
+ pausec: make(chan struct{}),
+ blackholec: make(chan struct{}),
+ }
+ close(b.pausec)
+ b.wg.Add(1)
+ go b.serveListen()
+ return b, nil
+}
+
+func (b *bridge) Close() {
+ b.l.Close()
+ b.mu.Lock()
+ select {
+ case <-b.stopc:
+ default:
+ close(b.stopc)
+ }
+ b.mu.Unlock()
+ b.wg.Wait()
+}
+
+func (b *bridge) DropConnections() {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ for bc := range b.conns {
+ bc.Close()
+ }
+ b.conns = make(map[*bridgeConn]struct{})
+}
+
+func (b *bridge) PauseConnections() {
+ b.mu.Lock()
+ b.pausec = make(chan struct{})
+ b.mu.Unlock()
+}
+
+func (b *bridge) UnpauseConnections() {
+ b.mu.Lock()
+ select {
+ case <-b.pausec:
+ default:
+ close(b.pausec)
+ }
+ b.mu.Unlock()
+}
+
+func (b *bridge) serveListen() {
+ defer func() {
+ b.l.Close()
+ b.mu.Lock()
+ for bc := range b.conns {
+ bc.Close()
+ }
+ b.mu.Unlock()
+ b.wg.Done()
+ }()
+
+ for {
+ inc, ierr := b.l.Accept()
+ if ierr != nil {
+ return
+ }
+ b.mu.Lock()
+ pausec := b.pausec
+ b.mu.Unlock()
+ select {
+ case <-b.stopc:
+ inc.Close()
+ return
+ case <-pausec:
+ }
+
+ outc, oerr := b.dialer.Dial()
+ if oerr != nil {
+ inc.Close()
+ return
+ }
+
+ bc := &bridgeConn{inc, outc, make(chan struct{})}
+ b.wg.Add(1)
+ b.mu.Lock()
+ b.conns[bc] = struct{}{}
+ go b.serveConn(bc)
+ b.mu.Unlock()
+ }
+}
+
+func (b *bridge) serveConn(bc *bridgeConn) {
+ defer func() {
+ close(bc.donec)
+ bc.Close()
+ b.mu.Lock()
+ delete(b.conns, bc)
+ b.mu.Unlock()
+ b.wg.Done()
+ }()
+
+ var wg sync.WaitGroup
+ wg.Add(2)
+ go func() {
+ b.ioCopy(bc.out, bc.in)
+ bc.close()
+ wg.Done()
+ }()
+ go func() {
+ b.ioCopy(bc.in, bc.out)
+ bc.close()
+ wg.Done()
+ }()
+ wg.Wait()
+}
+
+type bridgeConn struct {
+ in net.Conn
+ out net.Conn
+ donec chan struct{}
+}
+
+func (bc *bridgeConn) Close() {
+ bc.close()
+ <-bc.donec
+}
+
+func (bc *bridgeConn) close() {
+ bc.in.Close()
+ bc.out.Close()
+}
+
+func (b *bridge) Blackhole() {
+ b.mu.Lock()
+ close(b.blackholec)
+ b.mu.Unlock()
+}
+
+func (b *bridge) Unblackhole() {
+ b.mu.Lock()
+ for bc := range b.conns {
+ bc.Close()
+ }
+ b.conns = make(map[*bridgeConn]struct{})
+ b.blackholec = make(chan struct{})
+ b.mu.Unlock()
+}
+
+// ref. https://github.com/golang/go/blob/master/src/io/io.go copyBuffer
+func (b *bridge) ioCopy(dst io.Writer, src io.Reader) (err error) {
+ buf := make([]byte, 32*1024)
+ for {
+ select {
+ case <-b.blackholec:
+ io.Copy(ioutil.Discard, src)
+ return nil
+ default:
+ }
+ nr, er := src.Read(buf)
+ if nr > 0 {
+ nw, ew := dst.Write(buf[0:nr])
+ if ew != nil {
+ return ew
+ }
+ if nr != nw {
+ return io.ErrShortWrite
+ }
+ }
+ if er != nil {
+ err = er
+ break
+ }
+ }
+ return err
+}
diff --git a/vendor/go.etcd.io/etcd/tests/v3/integration/cluster.go b/vendor/go.etcd.io/etcd/tests/v3/integration/cluster.go
new file mode 100644
index 0000000000..1bf873f061
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/integration/cluster.go
@@ -0,0 +1,1675 @@
+// 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 integration
+
+import (
+ "context"
+ "crypto/tls"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/pkg/v3/testutil"
+ "go.etcd.io/etcd/client/pkg/v3/tlsutil"
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+ "go.etcd.io/etcd/client/pkg/v3/types"
+ "go.etcd.io/etcd/client/v2"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/pkg/v3/grpc_testing"
+ "go.etcd.io/etcd/raft/v3"
+ "go.etcd.io/etcd/server/v3/config"
+ "go.etcd.io/etcd/server/v3/embed"
+ "go.etcd.io/etcd/server/v3/etcdserver"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v2http"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3client"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3election"
+ epb "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock"
+ lockpb "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
+ "go.etcd.io/etcd/server/v3/verify"
+ "go.uber.org/zap/zapcore"
+ "go.uber.org/zap/zaptest"
+
+ "github.com/soheilhy/cmux"
+ "go.uber.org/zap"
+ "golang.org/x/crypto/bcrypt"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/keepalive"
+)
+
+const (
+ // RequestWaitTimeout is the time duration to wait for a request to go through or detect leader loss.
+ RequestWaitTimeout = 5 * time.Second
+ tickDuration = 10 * time.Millisecond
+ requestTimeout = 20 * time.Second
+
+ clusterName = "etcd"
+ basePort = 21000
+ URLScheme = "unix"
+ URLSchemeTLS = "unixs"
+ baseGRPCPort = 30000
+)
+
+var (
+ electionTicks = 10
+
+ // integration test uses unique ports, counting up, to listen for each
+ // member, ensuring restarted members can listen on the same port again.
+ localListenCount = int64(0)
+
+ TestTLSInfo = transport.TLSInfo{
+ KeyFile: MustAbsPath("../fixtures/server.key.insecure"),
+ CertFile: MustAbsPath("../fixtures/server.crt"),
+ TrustedCAFile: MustAbsPath("../fixtures/ca.crt"),
+ ClientCertAuth: true,
+ }
+
+ testTLSInfoWithSpecificUsage = transport.TLSInfo{
+ KeyFile: MustAbsPath("../fixtures/server-serverusage.key.insecure"),
+ CertFile: MustAbsPath("../fixtures/server-serverusage.crt"),
+ ClientKeyFile: MustAbsPath("../fixtures/client-clientusage.key.insecure"),
+ ClientCertFile: MustAbsPath("../fixtures/client-clientusage.crt"),
+ TrustedCAFile: MustAbsPath("../fixtures/ca.crt"),
+ ClientCertAuth: true,
+ }
+
+ testTLSInfoIP = transport.TLSInfo{
+ KeyFile: MustAbsPath("../fixtures/server-ip.key.insecure"),
+ CertFile: MustAbsPath("../fixtures/server-ip.crt"),
+ TrustedCAFile: MustAbsPath("../fixtures/ca.crt"),
+ ClientCertAuth: true,
+ }
+
+ testTLSInfoExpired = transport.TLSInfo{
+ KeyFile: MustAbsPath("./fixtures-expired/server.key.insecure"),
+ CertFile: MustAbsPath("./fixtures-expired/server.crt"),
+ TrustedCAFile: MustAbsPath("./fixtures-expired/ca.crt"),
+ ClientCertAuth: true,
+ }
+
+ testTLSInfoExpiredIP = transport.TLSInfo{
+ KeyFile: MustAbsPath("./fixtures-expired/server-ip.key.insecure"),
+ CertFile: MustAbsPath("./fixtures-expired/server-ip.crt"),
+ TrustedCAFile: MustAbsPath("./fixtures-expired/ca.crt"),
+ ClientCertAuth: true,
+ }
+
+ defaultTokenJWT = fmt.Sprintf("jwt,pub-key=%s,priv-key=%s,sign-method=RS256,ttl=1s",
+ MustAbsPath("../fixtures/server.crt"), MustAbsPath("../fixtures/server.key.insecure"))
+
+ // uniqueNumber is used to generate unique port numbers
+ // Should only be accessed via atomic package methods.
+ uniqueNumber int32
+)
+
+type ClusterConfig struct {
+ Size int
+ PeerTLS *transport.TLSInfo
+ ClientTLS *transport.TLSInfo
+
+ DiscoveryURL string
+
+ AuthToken string
+ AuthTokenTTL uint
+
+ UseGRPC bool
+
+ QuotaBackendBytes int64
+
+ MaxTxnOps uint
+ MaxRequestBytes uint
+ SnapshotCount uint64
+ SnapshotCatchUpEntries uint64
+
+ GRPCKeepAliveMinTime time.Duration
+ GRPCKeepAliveInterval time.Duration
+ GRPCKeepAliveTimeout time.Duration
+
+ // SkipCreatingClient to skip creating clients for each member.
+ SkipCreatingClient bool
+
+ ClientMaxCallSendMsgSize int
+ ClientMaxCallRecvMsgSize int
+
+ // UseIP is true to use only IP for gRPC requests.
+ UseIP bool
+ // UseBridge adds bridge between client and grpc server. Should be used in tests that
+ // want to manipulate connection or require connection not breaking despite server stop/restart.
+ UseBridge bool
+ // UseTCP configures server listen on tcp socket. If disabled unix socket is used.
+ UseTCP bool
+
+ EnableLeaseCheckpoint bool
+ LeaseCheckpointInterval time.Duration
+ LeaseCheckpointPersist bool
+
+ WatchProgressNotifyInterval time.Duration
+ CorruptCheckTime time.Duration
+}
+
+type cluster struct {
+ cfg *ClusterConfig
+ Members []*member
+ lastMemberNum int
+}
+
+func (c *cluster) generateMemberName() string {
+ c.lastMemberNum++
+ return fmt.Sprintf("m%v", c.lastMemberNum-1)
+}
+
+func schemeFromTLSInfo(tls *transport.TLSInfo) string {
+ if tls == nil {
+ return URLScheme
+ }
+ return URLSchemeTLS
+}
+
+func (c *cluster) fillClusterForMembers() error {
+ if c.cfg.DiscoveryURL != "" {
+ // cluster will be discovered
+ return nil
+ }
+
+ addrs := make([]string, 0)
+ for _, m := range c.Members {
+ scheme := schemeFromTLSInfo(m.PeerTLSInfo)
+ for _, l := range m.PeerListeners {
+ addrs = append(addrs, fmt.Sprintf("%s=%s://%s", m.Name, scheme, l.Addr().String()))
+ }
+ }
+ clusterStr := strings.Join(addrs, ",")
+ var err error
+ for _, m := range c.Members {
+ m.InitialPeerURLsMap, err = types.NewURLsMap(clusterStr)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func newCluster(t testutil.TB, cfg *ClusterConfig) *cluster {
+ testutil.SkipTestIfShortMode(t, "Cannot start etcd cluster in --short tests")
+
+ c := &cluster{cfg: cfg}
+ ms := make([]*member, cfg.Size)
+ for i := 0; i < cfg.Size; i++ {
+ ms[i] = c.mustNewMember(t, int64(i))
+ }
+ c.Members = ms
+ if err := c.fillClusterForMembers(); err != nil {
+ t.Fatal(err)
+ }
+
+ return c
+}
+
+// NewCluster returns an unlaunched cluster of the given size which has been
+// set to use static bootstrap.
+func NewCluster(t testutil.TB, size int) *cluster {
+ t.Helper()
+ return newCluster(t, &ClusterConfig{Size: size})
+}
+
+// NewClusterByConfig returns an unlaunched cluster defined by a cluster configuration
+func NewClusterByConfig(t testutil.TB, cfg *ClusterConfig) *cluster {
+ return newCluster(t, cfg)
+}
+
+func (c *cluster) Launch(t testutil.TB) {
+ errc := make(chan error)
+ for _, m := range c.Members {
+ // Members are launched in separate goroutines because if they boot
+ // using discovery url, they have to wait for others to register to continue.
+ go func(m *member) {
+ errc <- m.Launch()
+ }(m)
+ }
+ for range c.Members {
+ if err := <-errc; err != nil {
+ c.Terminate(t)
+ t.Fatalf("error setting up member: %v", err)
+ }
+ }
+ // wait cluster to be stable to receive future client requests
+ c.waitMembersMatch(t, c.HTTPMembers())
+ c.waitVersion()
+ for _, m := range c.Members {
+ t.Logf(" - %v -> %v (%v)", m.Name, m.ID(), m.GRPCURL())
+ }
+}
+
+func (c *cluster) URL(i int) string {
+ return c.Members[i].ClientURLs[0].String()
+}
+
+// URLs returns a list of all active client URLs in the cluster
+func (c *cluster) URLs() []string {
+ return getMembersURLs(c.Members)
+}
+
+func getMembersURLs(members []*member) []string {
+ urls := make([]string, 0)
+ for _, m := range members {
+ select {
+ case <-m.s.StopNotify():
+ continue
+ default:
+ }
+ for _, u := range m.ClientURLs {
+ urls = append(urls, u.String())
+ }
+ }
+ return urls
+}
+
+// HTTPMembers returns a list of all active members as client.Members
+func (c *cluster) HTTPMembers() []client.Member {
+ ms := []client.Member{}
+ for _, m := range c.Members {
+ pScheme := schemeFromTLSInfo(m.PeerTLSInfo)
+ cScheme := schemeFromTLSInfo(m.ClientTLSInfo)
+ cm := client.Member{Name: m.Name}
+ for _, ln := range m.PeerListeners {
+ cm.PeerURLs = append(cm.PeerURLs, pScheme+"://"+ln.Addr().String())
+ }
+ for _, ln := range m.ClientListeners {
+ cm.ClientURLs = append(cm.ClientURLs, cScheme+"://"+ln.Addr().String())
+ }
+ ms = append(ms, cm)
+ }
+ return ms
+}
+
+func (c *cluster) mustNewMember(t testutil.TB, memberNumber int64) *member {
+ m := mustNewMember(t,
+ memberConfig{
+ name: c.generateMemberName(),
+ memberNumber: memberNumber,
+ authToken: c.cfg.AuthToken,
+ authTokenTTL: c.cfg.AuthTokenTTL,
+ peerTLS: c.cfg.PeerTLS,
+ clientTLS: c.cfg.ClientTLS,
+ quotaBackendBytes: c.cfg.QuotaBackendBytes,
+ maxTxnOps: c.cfg.MaxTxnOps,
+ maxRequestBytes: c.cfg.MaxRequestBytes,
+ snapshotCount: c.cfg.SnapshotCount,
+ snapshotCatchUpEntries: c.cfg.SnapshotCatchUpEntries,
+ grpcKeepAliveMinTime: c.cfg.GRPCKeepAliveMinTime,
+ grpcKeepAliveInterval: c.cfg.GRPCKeepAliveInterval,
+ grpcKeepAliveTimeout: c.cfg.GRPCKeepAliveTimeout,
+ clientMaxCallSendMsgSize: c.cfg.ClientMaxCallSendMsgSize,
+ clientMaxCallRecvMsgSize: c.cfg.ClientMaxCallRecvMsgSize,
+ useIP: c.cfg.UseIP,
+ useBridge: c.cfg.UseBridge,
+ useTCP: c.cfg.UseTCP,
+ enableLeaseCheckpoint: c.cfg.EnableLeaseCheckpoint,
+ leaseCheckpointPersist: c.cfg.LeaseCheckpointPersist,
+ leaseCheckpointInterval: c.cfg.LeaseCheckpointInterval,
+ WatchProgressNotifyInterval: c.cfg.WatchProgressNotifyInterval,
+ CorruptCheckTime: c.cfg.CorruptCheckTime,
+ })
+ m.DiscoveryURL = c.cfg.DiscoveryURL
+ if c.cfg.UseGRPC {
+ if err := m.listenGRPC(); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return m
+}
+
+// addMember return PeerURLs of the added member.
+func (c *cluster) addMember(t testutil.TB) types.URLs {
+ m := c.mustNewMember(t, 0)
+
+ scheme := schemeFromTLSInfo(c.cfg.PeerTLS)
+
+ // send add request to the cluster
+ var err error
+ for i := 0; i < len(c.Members); i++ {
+ clientURL := c.URL(i)
+ peerURL := scheme + "://" + m.PeerListeners[0].Addr().String()
+ if err = c.addMemberByURL(t, clientURL, peerURL); err == nil {
+ break
+ }
+ }
+ if err != nil {
+ t.Fatalf("add member failed on all members error: %v", err)
+ }
+
+ m.InitialPeerURLsMap = types.URLsMap{}
+ for _, mm := range c.Members {
+ m.InitialPeerURLsMap[mm.Name] = mm.PeerURLs
+ }
+ m.InitialPeerURLsMap[m.Name] = m.PeerURLs
+ m.NewCluster = false
+ if err := m.Launch(); err != nil {
+ t.Fatal(err)
+ }
+ c.Members = append(c.Members, m)
+ // wait cluster to be stable to receive future client requests
+ c.waitMembersMatch(t, c.HTTPMembers())
+ return m.PeerURLs
+}
+
+func (c *cluster) addMemberByURL(t testutil.TB, clientURL, peerURL string) error {
+ cc := MustNewHTTPClient(t, []string{clientURL}, c.cfg.ClientTLS)
+ ma := client.NewMembersAPI(cc)
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
+ _, err := ma.Add(ctx, peerURL)
+ cancel()
+ if err != nil {
+ return err
+ }
+
+ // wait for the add node entry applied in the cluster
+ members := append(c.HTTPMembers(), client.Member{PeerURLs: []string{peerURL}, ClientURLs: []string{}})
+ c.waitMembersMatch(t, members)
+ return nil
+}
+
+// AddMember return PeerURLs of the added member.
+func (c *cluster) AddMember(t testutil.TB) types.URLs {
+ return c.addMember(t)
+}
+
+func (c *cluster) RemoveMember(t testutil.TB, id uint64) {
+ if err := c.removeMember(t, id); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func (c *cluster) removeMember(t testutil.TB, id uint64) error {
+ // send remove request to the cluster
+ cc := MustNewHTTPClient(t, c.URLs(), c.cfg.ClientTLS)
+ ma := client.NewMembersAPI(cc)
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
+ err := ma.Remove(ctx, types.ID(id).String())
+ cancel()
+ if err != nil {
+ return err
+ }
+ newMembers := make([]*member, 0)
+ for _, m := range c.Members {
+ if uint64(m.s.ID()) != id {
+ newMembers = append(newMembers, m)
+ } else {
+ select {
+ case <-m.s.StopNotify():
+ m.Terminate(t)
+ // 1s stop delay + election timeout + 1s disk and network delay + connection write timeout
+ // TODO: remove connection write timeout by selecting on http response closeNotifier
+ // blocking on https://github.com/golang/go/issues/9524
+ case <-time.After(time.Second + time.Duration(electionTicks)*tickDuration + time.Second + rafthttp.ConnWriteTimeout):
+ t.Fatalf("failed to remove member %s in time", m.s.ID())
+ }
+ }
+ }
+ c.Members = newMembers
+ c.waitMembersMatch(t, c.HTTPMembers())
+ return nil
+}
+
+func (c *cluster) Terminate(t testutil.TB) {
+ var wg sync.WaitGroup
+ wg.Add(len(c.Members))
+ for _, m := range c.Members {
+ go func(mm *member) {
+ defer wg.Done()
+ mm.Terminate(t)
+ }(m)
+ }
+ wg.Wait()
+}
+
+func (c *cluster) waitMembersMatch(t testutil.TB, membs []client.Member) {
+ for _, u := range c.URLs() {
+ cc := MustNewHTTPClient(t, []string{u}, c.cfg.ClientTLS)
+ ma := client.NewMembersAPI(cc)
+ for {
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
+ ms, err := ma.List(ctx)
+ cancel()
+ if err == nil && isMembersEqual(ms, membs) {
+ break
+ }
+ time.Sleep(tickDuration)
+ }
+ }
+}
+
+// WaitLeader returns index of the member in c.Members that is leader (or -1).
+func (c *cluster) WaitLeader(t testutil.TB) int { return c.waitLeader(t, c.Members) }
+
+// waitLeader waits until given members agree on the same leader,
+// and returns its 'index' in the 'membs' list (or -1).
+func (c *cluster) waitLeader(t testutil.TB, membs []*member) int {
+ possibleLead := make(map[uint64]bool)
+ var lead uint64
+ for _, m := range membs {
+ possibleLead[uint64(m.s.ID())] = true
+ }
+ cc := MustNewHTTPClient(t, getMembersURLs(membs), nil)
+ kapi := client.NewKeysAPI(cc)
+
+ // ensure leader is up via linearizable get
+ for {
+ ctx, cancel := context.WithTimeout(context.Background(), 10*tickDuration+time.Second)
+ _, err := kapi.Get(ctx, "0", &client.GetOptions{Quorum: true})
+ cancel()
+ if err == nil || strings.Contains(err.Error(), "Key not found") {
+ break
+ }
+ }
+
+ for lead == 0 || !possibleLead[lead] {
+ lead = 0
+ for _, m := range membs {
+ select {
+ case <-m.s.StopNotify():
+ continue
+ default:
+ }
+ if lead != 0 && lead != m.s.Lead() {
+ lead = 0
+ time.Sleep(10 * tickDuration)
+ break
+ }
+ lead = m.s.Lead()
+ }
+ }
+
+ for i, m := range membs {
+ if uint64(m.s.ID()) == lead {
+ return i
+ }
+ }
+
+ return -1
+}
+
+func (c *cluster) WaitNoLeader() { c.waitNoLeader(c.Members) }
+
+// waitNoLeader waits until given members lose leader.
+func (c *cluster) waitNoLeader(membs []*member) {
+ noLeader := false
+ for !noLeader {
+ noLeader = true
+ for _, m := range membs {
+ select {
+ case <-m.s.StopNotify():
+ continue
+ default:
+ }
+ if m.s.Lead() != 0 {
+ noLeader = false
+ time.Sleep(10 * tickDuration)
+ break
+ }
+ }
+ }
+}
+
+func (c *cluster) waitVersion() {
+ for _, m := range c.Members {
+ for {
+ if m.s.ClusterVersion() != nil {
+ break
+ }
+ time.Sleep(tickDuration)
+ }
+ }
+}
+
+// isMembersEqual checks whether two members equal except ID field.
+// The given wmembs should always set ID field to empty string.
+func isMembersEqual(membs []client.Member, wmembs []client.Member) bool {
+ sort.Sort(SortableMemberSliceByPeerURLs(membs))
+ sort.Sort(SortableMemberSliceByPeerURLs(wmembs))
+ for i := range membs {
+ membs[i].ID = ""
+ }
+ return reflect.DeepEqual(membs, wmembs)
+}
+
+func newLocalListener(t testutil.TB) net.Listener {
+ c := atomic.AddInt64(&localListenCount, 1)
+ // Go 1.8+ allows only numbers in port
+ addr := fmt.Sprintf("127.0.0.1:%05d%05d", c+basePort, os.Getpid())
+ return NewListenerWithAddr(t, addr)
+}
+
+func NewListenerWithAddr(t testutil.TB, addr string) net.Listener {
+ l, err := transport.NewUnixListener(addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return l
+}
+
+type member struct {
+ config.ServerConfig
+ UniqNumber int64
+ MemberNumber int64
+ PeerListeners, ClientListeners []net.Listener
+ grpcListener net.Listener
+ // PeerTLSInfo enables peer TLS when set
+ PeerTLSInfo *transport.TLSInfo
+ // ClientTLSInfo enables client TLS when set
+ ClientTLSInfo *transport.TLSInfo
+ DialOptions []grpc.DialOption
+
+ raftHandler *testutil.PauseableHandler
+ s *etcdserver.EtcdServer
+ serverClosers []func()
+
+ grpcServerOpts []grpc.ServerOption
+ grpcServer *grpc.Server
+ grpcServerPeer *grpc.Server
+ grpcURL string
+ grpcBridge *bridge
+
+ // serverClient is a clientv3 that directly calls the etcdserver.
+ serverClient *clientv3.Client
+
+ keepDataDirTerminate bool
+ clientMaxCallSendMsgSize int
+ clientMaxCallRecvMsgSize int
+ useIP bool
+ useBridge bool
+ useTCP bool
+
+ isLearner bool
+ closed bool
+
+ grpcServerRecorder *grpc_testing.GrpcRecorder
+}
+
+func (m *member) GRPCURL() string { return m.grpcURL }
+
+func (m *member) CorruptionChecker() etcdserver.CorruptionChecker {
+ return m.s.CorruptionChecker()
+}
+
+type memberConfig struct {
+ name string
+ uniqNumber int64
+ memberNumber int64
+ peerTLS *transport.TLSInfo
+ clientTLS *transport.TLSInfo
+ authToken string
+ authTokenTTL uint
+ quotaBackendBytes int64
+ maxTxnOps uint
+ maxRequestBytes uint
+ snapshotCount uint64
+ snapshotCatchUpEntries uint64
+ grpcKeepAliveMinTime time.Duration
+ grpcKeepAliveInterval time.Duration
+ grpcKeepAliveTimeout time.Duration
+ clientMaxCallSendMsgSize int
+ clientMaxCallRecvMsgSize int
+ useIP bool
+ useBridge bool
+ useTCP bool
+ enableLeaseCheckpoint bool
+ leaseCheckpointInterval time.Duration
+ leaseCheckpointPersist bool
+ WatchProgressNotifyInterval time.Duration
+ CorruptCheckTime time.Duration
+}
+
+// mustNewMember return an inited member with the given name. If peerTLS is
+// set, it will use https scheme to communicate between peers.
+func mustNewMember(t testutil.TB, mcfg memberConfig) *member {
+ var err error
+ m := &member{
+ MemberNumber: mcfg.memberNumber,
+ UniqNumber: atomic.AddInt64(&localListenCount, 1),
+ }
+
+ peerScheme := schemeFromTLSInfo(mcfg.peerTLS)
+ clientScheme := schemeFromTLSInfo(mcfg.clientTLS)
+
+ pln := newLocalListener(t)
+ m.PeerListeners = []net.Listener{pln}
+ m.PeerURLs, err = types.NewURLs([]string{peerScheme + "://" + pln.Addr().String()})
+ if err != nil {
+ t.Fatal(err)
+ }
+ m.PeerTLSInfo = mcfg.peerTLS
+
+ cln := newLocalListener(t)
+ m.ClientListeners = []net.Listener{cln}
+ m.ClientURLs, err = types.NewURLs([]string{clientScheme + "://" + cln.Addr().String()})
+ if err != nil {
+ t.Fatal(err)
+ }
+ m.ClientTLSInfo = mcfg.clientTLS
+
+ m.Name = mcfg.name
+
+ m.DataDir, err = ioutil.TempDir(t.TempDir(), "etcd")
+ if err != nil {
+ t.Fatal(err)
+ }
+ clusterStr := fmt.Sprintf("%s=%s://%s", mcfg.name, peerScheme, pln.Addr().String())
+ m.InitialPeerURLsMap, err = types.NewURLsMap(clusterStr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ m.InitialClusterToken = clusterName
+ m.NewCluster = true
+ m.BootstrapTimeout = 10 * time.Millisecond
+ if m.PeerTLSInfo != nil {
+ m.ServerConfig.PeerTLSInfo = *m.PeerTLSInfo
+ }
+ m.ElectionTicks = electionTicks
+ m.InitialElectionTickAdvance = true
+ m.TickMs = uint(tickDuration / time.Millisecond)
+ m.QuotaBackendBytes = mcfg.quotaBackendBytes
+ m.MaxTxnOps = mcfg.maxTxnOps
+ if m.MaxTxnOps == 0 {
+ m.MaxTxnOps = embed.DefaultMaxTxnOps
+ }
+ m.MaxRequestBytes = mcfg.maxRequestBytes
+ if m.MaxRequestBytes == 0 {
+ m.MaxRequestBytes = embed.DefaultMaxRequestBytes
+ }
+ m.SnapshotCount = etcdserver.DefaultSnapshotCount
+ if mcfg.snapshotCount != 0 {
+ m.SnapshotCount = mcfg.snapshotCount
+ }
+ m.SnapshotCatchUpEntries = etcdserver.DefaultSnapshotCatchUpEntries
+ if mcfg.snapshotCatchUpEntries != 0 {
+ m.SnapshotCatchUpEntries = mcfg.snapshotCatchUpEntries
+ }
+
+ // for the purpose of integration testing, simple token is enough
+ m.AuthToken = "simple"
+ if mcfg.authToken != "" {
+ m.AuthToken = mcfg.authToken
+ }
+ if mcfg.authTokenTTL != 0 {
+ m.TokenTTL = mcfg.authTokenTTL
+ }
+
+ m.BcryptCost = uint(bcrypt.MinCost) // use min bcrypt cost to speedy up integration testing
+
+ m.grpcServerOpts = []grpc.ServerOption{}
+ if mcfg.grpcKeepAliveMinTime > time.Duration(0) {
+ m.grpcServerOpts = append(m.grpcServerOpts, grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
+ MinTime: mcfg.grpcKeepAliveMinTime,
+ PermitWithoutStream: false,
+ }))
+ }
+ if mcfg.grpcKeepAliveInterval > time.Duration(0) &&
+ mcfg.grpcKeepAliveTimeout > time.Duration(0) {
+ m.grpcServerOpts = append(m.grpcServerOpts, grpc.KeepaliveParams(keepalive.ServerParameters{
+ Time: mcfg.grpcKeepAliveInterval,
+ Timeout: mcfg.grpcKeepAliveTimeout,
+ }))
+ }
+ m.clientMaxCallSendMsgSize = mcfg.clientMaxCallSendMsgSize
+ m.clientMaxCallRecvMsgSize = mcfg.clientMaxCallRecvMsgSize
+ m.useIP = mcfg.useIP
+ m.useBridge = mcfg.useBridge
+ m.useTCP = mcfg.useTCP
+ m.EnableLeaseCheckpoint = mcfg.enableLeaseCheckpoint
+ m.LeaseCheckpointInterval = mcfg.leaseCheckpointInterval
+ m.LeaseCheckpointPersist = mcfg.leaseCheckpointPersist
+
+ m.WatchProgressNotifyInterval = mcfg.WatchProgressNotifyInterval
+
+ m.InitialCorruptCheck = true
+ if mcfg.CorruptCheckTime > time.Duration(0) {
+ m.CorruptCheckTime = mcfg.CorruptCheckTime
+ }
+ m.WarningApplyDuration = embed.DefaultWarningApplyDuration
+
+ m.V2Deprecation = config.V2_DEPR_DEFAULT
+ m.grpcServerRecorder = &grpc_testing.GrpcRecorder{}
+ m.Logger = memberLogger(t, mcfg.name)
+ t.Cleanup(func() {
+ // if we didn't cleanup the logger, the consecutive test
+ // might reuse this (t).
+ raft.ResetDefaultLogger()
+ })
+ return m
+}
+
+func memberLogger(t testutil.TB, name string) *zap.Logger {
+ level := zapcore.InfoLevel
+ if os.Getenv("CLUSTER_DEBUG") != "" {
+ level = zapcore.DebugLevel
+ }
+
+ options := zaptest.WrapOptions(zap.Fields(zap.String("member", name)))
+ return zaptest.NewLogger(t, zaptest.Level(level), options).Named(name)
+}
+
+// listenGRPC starts a grpc server over a unix domain socket on the member
+func (m *member) listenGRPC() error {
+ // prefix with localhost so cert has right domain
+ network, host, port := m.grpcAddr()
+ grpcAddr := host + ":" + port
+ m.Logger.Info("LISTEN GRPC", zap.String("grpcAddr", grpcAddr), zap.String("m.Name", m.Name))
+ grpcListener, err := net.Listen(network, grpcAddr)
+ if err != nil {
+ return fmt.Errorf("listen failed on grpc socket %s (%v)", grpcAddr, err)
+ }
+ m.grpcURL = fmt.Sprintf("%s://%s", m.clientScheme(), grpcAddr)
+ if m.useBridge {
+ _, err = m.addBridge()
+ if err != nil {
+ grpcListener.Close()
+ return err
+ }
+ }
+ m.grpcListener = grpcListener
+ return nil
+}
+
+func (m *member) clientScheme() string {
+ switch {
+ case m.useTCP && m.ClientTLSInfo != nil:
+ return "https"
+ case m.useTCP && m.ClientTLSInfo == nil:
+ return "http"
+ case !m.useTCP && m.ClientTLSInfo != nil:
+ return "unixs"
+ case !m.useTCP && m.ClientTLSInfo == nil:
+ return "unix"
+ }
+ m.Logger.Panic("Failed to determine client schema")
+ return ""
+}
+
+func (m *member) addBridge() (*bridge, error) {
+ network, host, port := m.grpcAddr()
+ grpcAddr := host + ":" + port
+ bridgeAddr := grpcAddr + "0"
+ m.Logger.Info("LISTEN BRIDGE", zap.String("grpc-address", bridgeAddr), zap.String("member", m.Name))
+ bridgeListener, err := transport.NewUnixListener(bridgeAddr)
+ if err != nil {
+ return nil, fmt.Errorf("listen failed on bridge socket %s (%v)", bridgeAddr, err)
+ }
+ m.grpcBridge, err = newBridge(dialer{network: network, addr: grpcAddr}, bridgeListener)
+ if err != nil {
+ bridgeListener.Close()
+ return nil, err
+ }
+ m.grpcURL = m.clientScheme() + "://" + bridgeAddr
+ return m.grpcBridge, nil
+}
+
+func (m *member) Bridge() *bridge {
+ if !m.useBridge {
+ m.Logger.Panic("Bridge not available. Please configure using bridge before creating cluster.")
+ }
+ return m.grpcBridge
+}
+
+func (m *member) grpcAddr() (network, host, port string) {
+ // prefix with localhost so cert has right domain
+ host = "localhost"
+ if m.useIP { // for IP-only TLS certs
+ host = "127.0.0.1"
+ }
+ network = "unix"
+ if m.useTCP {
+ network = "tcp"
+ }
+ port = m.Name
+ if m.useTCP {
+ port = fmt.Sprintf("%d", GrpcPortNumber(m.UniqNumber, m.MemberNumber))
+ }
+ return network, host, port
+}
+
+func GrpcPortNumber(uniqNumber, memberNumber int64) int64 {
+ return baseGRPCPort + uniqNumber*10 + memberNumber
+}
+
+type dialer struct {
+ network string
+ addr string
+}
+
+func (d dialer) Dial() (net.Conn, error) {
+ return net.Dial(d.network, d.addr)
+}
+
+func (m *member) ElectionTimeout() time.Duration {
+ return time.Duration(m.s.Cfg.ElectionTicks*int(m.s.Cfg.TickMs)) * time.Millisecond
+}
+
+func (m *member) ID() types.ID { return m.s.ID() }
+
+// NewClientV3 creates a new grpc client connection to the member
+func NewClientV3(m *member) (*clientv3.Client, error) {
+ if m.grpcURL == "" {
+ return nil, fmt.Errorf("member not configured for grpc")
+ }
+
+ cfg := clientv3.Config{
+ Endpoints: []string{m.grpcURL},
+ DialTimeout: 5 * time.Second,
+ DialOptions: []grpc.DialOption{grpc.WithBlock()},
+ MaxCallSendMsgSize: m.clientMaxCallSendMsgSize,
+ MaxCallRecvMsgSize: m.clientMaxCallRecvMsgSize,
+ }
+
+ if m.ClientTLSInfo != nil {
+ tls, err := m.ClientTLSInfo.ClientConfig()
+ if err != nil {
+ return nil, err
+ }
+ cfg.TLS = tls
+ }
+ if m.DialOptions != nil {
+ cfg.DialOptions = append(cfg.DialOptions, m.DialOptions...)
+ }
+ return newClientV3(cfg, m.Logger.Named("client"))
+}
+
+// Clone returns a member with the same server configuration. The returned
+// member will not set PeerListeners and ClientListeners.
+func (m *member) Clone(t testutil.TB) *member {
+ mm := &member{}
+ mm.ServerConfig = m.ServerConfig
+
+ var err error
+ clientURLStrs := m.ClientURLs.StringSlice()
+ mm.ClientURLs, err = types.NewURLs(clientURLStrs)
+ if err != nil {
+ // this should never fail
+ panic(err)
+ }
+ peerURLStrs := m.PeerURLs.StringSlice()
+ mm.PeerURLs, err = types.NewURLs(peerURLStrs)
+ if err != nil {
+ // this should never fail
+ panic(err)
+ }
+ clusterStr := m.InitialPeerURLsMap.String()
+ mm.InitialPeerURLsMap, err = types.NewURLsMap(clusterStr)
+ if err != nil {
+ // this should never fail
+ panic(err)
+ }
+ mm.InitialClusterToken = m.InitialClusterToken
+ mm.ElectionTicks = m.ElectionTicks
+ mm.PeerTLSInfo = m.PeerTLSInfo
+ mm.ClientTLSInfo = m.ClientTLSInfo
+ mm.Logger = memberLogger(t, mm.Name+"c")
+ return mm
+}
+
+// Launch starts a member based on ServerConfig, PeerListeners
+// and ClientListeners.
+func (m *member) Launch() error {
+ m.Logger.Info(
+ "launching a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ )
+ var err error
+ if m.s, err = etcdserver.NewServer(m.ServerConfig); err != nil {
+ return fmt.Errorf("failed to initialize the etcd server: %v", err)
+ }
+ m.s.SyncTicker = time.NewTicker(500 * time.Millisecond)
+ m.s.Start()
+
+ var peerTLScfg *tls.Config
+ if m.PeerTLSInfo != nil && !m.PeerTLSInfo.Empty() {
+ if peerTLScfg, err = m.PeerTLSInfo.ServerConfig(); err != nil {
+ return err
+ }
+ }
+
+ if m.grpcListener != nil {
+ var (
+ tlscfg *tls.Config
+ )
+ if m.ClientTLSInfo != nil && !m.ClientTLSInfo.Empty() {
+ tlscfg, err = m.ClientTLSInfo.ServerConfig()
+ if err != nil {
+ return err
+ }
+ }
+ m.grpcServer = v3rpc.Server(m.s, tlscfg, m.grpcServerRecorder.UnaryInterceptor(), m.grpcServerOpts...)
+ m.grpcServerPeer = v3rpc.Server(m.s, peerTLScfg, m.grpcServerRecorder.UnaryInterceptor())
+ m.serverClient = v3client.New(m.s)
+ lockpb.RegisterLockServer(m.grpcServer, v3lock.NewLockServer(m.serverClient))
+ epb.RegisterElectionServer(m.grpcServer, v3election.NewElectionServer(m.serverClient))
+ go m.grpcServer.Serve(m.grpcListener)
+ }
+
+ m.raftHandler = &testutil.PauseableHandler{Next: etcdhttp.NewPeerHandler(m.Logger, m.s)}
+
+ h := (http.Handler)(m.raftHandler)
+ if m.grpcListener != nil {
+ h = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
+ m.grpcServerPeer.ServeHTTP(w, r)
+ } else {
+ m.raftHandler.ServeHTTP(w, r)
+ }
+ })
+ }
+
+ for _, ln := range m.PeerListeners {
+ cm := cmux.New(ln)
+ // don't hang on matcher after closing listener
+ cm.SetReadTimeout(time.Second)
+
+ if m.grpcServer != nil {
+ grpcl := cm.Match(cmux.HTTP2())
+ go m.grpcServerPeer.Serve(grpcl)
+ }
+
+ // serve http1/http2 rafthttp/grpc
+ ll := cm.Match(cmux.Any())
+ if peerTLScfg != nil {
+ if ll, err = transport.NewTLSListener(ll, m.PeerTLSInfo); err != nil {
+ return err
+ }
+ }
+ hs := &httptest.Server{
+ Listener: ll,
+ Config: &http.Server{
+ Handler: h,
+ TLSConfig: peerTLScfg,
+ ErrorLog: log.New(ioutil.Discard, "net/http", 0),
+ },
+ TLS: peerTLScfg,
+ }
+ hs.Start()
+
+ donec := make(chan struct{})
+ go func() {
+ defer close(donec)
+ cm.Serve()
+ }()
+ closer := func() {
+ ll.Close()
+ hs.CloseClientConnections()
+ hs.Close()
+ <-donec
+ }
+ m.serverClosers = append(m.serverClosers, closer)
+ }
+ for _, ln := range m.ClientListeners {
+ hs := &httptest.Server{
+ Listener: ln,
+ Config: &http.Server{
+ Handler: v2http.NewClientHandler(
+ m.Logger,
+ m.s,
+ m.ServerConfig.ReqTimeout(),
+ ),
+ ErrorLog: log.New(ioutil.Discard, "net/http", 0),
+ },
+ }
+ if m.ClientTLSInfo == nil {
+ hs.Start()
+ } else {
+ info := m.ClientTLSInfo
+ hs.TLS, err = info.ServerConfig()
+ if err != nil {
+ return err
+ }
+
+ // baseConfig is called on initial TLS handshake start.
+ //
+ // Previously,
+ // 1. Server has non-empty (*tls.Config).Certificates on client hello
+ // 2. Server calls (*tls.Config).GetCertificate iff:
+ // - Server's (*tls.Config).Certificates is not empty, or
+ // - Client supplies SNI; non-empty (*tls.ClientHelloInfo).ServerName
+ //
+ // When (*tls.Config).Certificates is always populated on initial handshake,
+ // client is expected to provide a valid matching SNI to pass the TLS
+ // verification, thus trigger server (*tls.Config).GetCertificate to reload
+ // TLS assets. However, a cert whose SAN field does not include domain names
+ // but only IP addresses, has empty (*tls.ClientHelloInfo).ServerName, thus
+ // it was never able to trigger TLS reload on initial handshake; first
+ // ceritifcate object was being used, never being updated.
+ //
+ // Now, (*tls.Config).Certificates is created empty on initial TLS client
+ // handshake, in order to trigger (*tls.Config).GetCertificate and populate
+ // rest of the certificates on every new TLS connection, even when client
+ // SNI is empty (e.g. cert only includes IPs).
+ //
+ // This introduces another problem with "httptest.Server":
+ // when server initial certificates are empty, certificates
+ // are overwritten by Go's internal test certs, which have
+ // different SAN fields (e.g. example.com). To work around,
+ // re-overwrite (*tls.Config).Certificates before starting
+ // test server.
+ tlsCert, err := tlsutil.NewCert(info.CertFile, info.KeyFile, nil)
+ if err != nil {
+ return err
+ }
+ hs.TLS.Certificates = []tls.Certificate{*tlsCert}
+
+ hs.StartTLS()
+ }
+ closer := func() {
+ ln.Close()
+ hs.CloseClientConnections()
+ hs.Close()
+ }
+ m.serverClosers = append(m.serverClosers, closer)
+ }
+
+ m.Logger.Info(
+ "launched a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ )
+ return nil
+}
+
+func (m *member) RecordedRequests() []grpc_testing.RequestInfo {
+ return m.grpcServerRecorder.RecordedRequests()
+}
+
+func (m *member) WaitOK(t testutil.TB) {
+ m.WaitStarted(t)
+ for m.s.Leader() == 0 {
+ time.Sleep(tickDuration)
+ }
+}
+
+func (m *member) WaitStarted(t testutil.TB) {
+ cc := MustNewHTTPClient(t, []string{m.URL()}, m.ClientTLSInfo)
+ kapi := client.NewKeysAPI(cc)
+ for {
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
+ _, err := kapi.Get(ctx, "/", nil)
+ if err != nil {
+ time.Sleep(tickDuration)
+ continue
+ }
+ cancel()
+ break
+ }
+}
+
+func WaitClientV3(t testutil.TB, kv clientv3.KV) {
+ timeout := time.Now().Add(requestTimeout)
+ var err error
+ for time.Now().Before(timeout) {
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
+ _, err = kv.Get(ctx, "/")
+ cancel()
+ if err == nil {
+ return
+ }
+ time.Sleep(tickDuration)
+ }
+ if err != nil {
+ t.Fatalf("timed out waiting for client: %v", err)
+ }
+}
+
+func (m *member) URL() string { return m.ClientURLs[0].String() }
+
+func (m *member) Pause() {
+ m.raftHandler.Pause()
+ m.s.PauseSending()
+}
+
+func (m *member) Resume() {
+ m.raftHandler.Resume()
+ m.s.ResumeSending()
+}
+
+// Close stops the member's etcdserver and closes its connections
+func (m *member) Close() {
+ if m.grpcBridge != nil {
+ m.grpcBridge.Close()
+ m.grpcBridge = nil
+ }
+ if m.serverClient != nil {
+ m.serverClient.Close()
+ m.serverClient = nil
+ }
+ if m.grpcServer != nil {
+ ch := make(chan struct{})
+ go func() {
+ defer close(ch)
+ // close listeners to stop accepting new connections,
+ // will block on any existing transports
+ m.grpcServer.GracefulStop()
+ }()
+ // wait until all pending RPCs are finished
+ select {
+ case <-ch:
+ case <-time.After(2 * time.Second):
+ // took too long, manually close open transports
+ // e.g. watch streams
+ m.grpcServer.Stop()
+ <-ch
+ }
+ m.grpcServer = nil
+ m.grpcServerPeer.GracefulStop()
+ m.grpcServerPeer.Stop()
+ m.grpcServerPeer = nil
+ }
+ if m.s != nil {
+ m.s.HardStop()
+ }
+ for _, f := range m.serverClosers {
+ f()
+ }
+ if !m.closed {
+ // Avoid verification of the same file multiple times
+ // (that might not exist any longer)
+ verify.MustVerifyIfEnabled(verify.Config{
+ Logger: m.Logger,
+ DataDir: m.DataDir,
+ ExactIndex: false,
+ })
+ }
+ m.closed = true
+}
+
+// Stop stops the member, but the data dir of the member is preserved.
+func (m *member) Stop(_ testutil.TB) {
+ m.Logger.Info(
+ "stopping a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ )
+ m.Close()
+ m.serverClosers = nil
+ m.Logger.Info(
+ "stopped a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ )
+}
+
+// checkLeaderTransition waits for leader transition, returning the new leader ID.
+func checkLeaderTransition(m *member, oldLead uint64) uint64 {
+ interval := time.Duration(m.s.Cfg.TickMs) * time.Millisecond
+ for m.s.Lead() == 0 || (m.s.Lead() == oldLead) {
+ time.Sleep(interval)
+ }
+ return m.s.Lead()
+}
+
+// StopNotify unblocks when a member stop completes
+func (m *member) StopNotify() <-chan struct{} {
+ return m.s.StopNotify()
+}
+
+// Restart starts the member using the preserved data dir.
+func (m *member) Restart(t testutil.TB) error {
+ m.Logger.Info(
+ "restarting a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ )
+ newPeerListeners := make([]net.Listener, 0)
+ for _, ln := range m.PeerListeners {
+ newPeerListeners = append(newPeerListeners, NewListenerWithAddr(t, ln.Addr().String()))
+ }
+ m.PeerListeners = newPeerListeners
+ newClientListeners := make([]net.Listener, 0)
+ for _, ln := range m.ClientListeners {
+ newClientListeners = append(newClientListeners, NewListenerWithAddr(t, ln.Addr().String()))
+ }
+ m.ClientListeners = newClientListeners
+
+ if m.grpcListener != nil {
+ if err := m.listenGRPC(); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ err := m.Launch()
+ m.Logger.Info(
+ "restarted a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ zap.Error(err),
+ )
+ return err
+}
+
+// Terminate stops the member and removes the data dir.
+func (m *member) Terminate(t testutil.TB) {
+ m.Logger.Info(
+ "terminating a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ )
+ m.Close()
+ if !m.keepDataDirTerminate {
+ if err := os.RemoveAll(m.ServerConfig.DataDir); err != nil {
+ t.Fatal(err)
+ }
+ }
+ m.Logger.Info(
+ "terminated a member",
+ zap.String("name", m.Name),
+ zap.Strings("advertise-peer-urls", m.PeerURLs.StringSlice()),
+ zap.Strings("listen-client-urls", m.ClientURLs.StringSlice()),
+ zap.String("grpc-url", m.grpcURL),
+ )
+}
+
+// Metric gets the metric value for a member
+func (m *member) Metric(metricName string, expectLabels ...string) (string, error) {
+ cfgtls := transport.TLSInfo{}
+ tr, err := transport.NewTimeoutTransport(cfgtls, time.Second, time.Second, time.Second)
+ if err != nil {
+ return "", err
+ }
+ cli := &http.Client{Transport: tr}
+ resp, err := cli.Get(m.ClientURLs[0].String() + "/metrics")
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+ b, rerr := ioutil.ReadAll(resp.Body)
+ if rerr != nil {
+ return "", rerr
+ }
+ lines := strings.Split(string(b), "\n")
+ for _, l := range lines {
+ if !strings.HasPrefix(l, metricName) {
+ continue
+ }
+ ok := true
+ for _, lv := range expectLabels {
+ if !strings.Contains(l, lv) {
+ ok = false
+ break
+ }
+ }
+ if !ok {
+ continue
+ }
+ return strings.Split(l, " ")[1], nil
+ }
+ return "", nil
+}
+
+// InjectPartition drops connections from m to others, vice versa.
+func (m *member) InjectPartition(t testutil.TB, others ...*member) {
+ for _, other := range others {
+ m.s.CutPeer(other.s.ID())
+ other.s.CutPeer(m.s.ID())
+ t.Logf("network partition injected between: %v <-> %v", m.s.ID(), other.s.ID())
+ }
+}
+
+// RecoverPartition recovers connections from m to others, vice versa.
+func (m *member) RecoverPartition(t testutil.TB, others ...*member) {
+ for _, other := range others {
+ m.s.MendPeer(other.s.ID())
+ other.s.MendPeer(m.s.ID())
+ t.Logf("network partition between: %v <-> %v", m.s.ID(), other.s.ID())
+ }
+}
+
+func (m *member) ReadyNotify() <-chan struct{} {
+ return m.s.ReadyNotify()
+}
+
+func MustNewHTTPClient(t testutil.TB, eps []string, tls *transport.TLSInfo) client.Client {
+ cfgtls := transport.TLSInfo{}
+ if tls != nil {
+ cfgtls = *tls
+ }
+ cfg := client.Config{Transport: mustNewTransport(t, cfgtls), Endpoints: eps}
+ c, err := client.New(cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return c
+}
+
+func mustNewTransport(t testutil.TB, tlsInfo transport.TLSInfo) *http.Transport {
+ // tick in integration test is short, so 1s dial timeout could play well.
+ tr, err := transport.NewTimeoutTransport(tlsInfo, time.Second, rafthttp.ConnReadTimeout, rafthttp.ConnWriteTimeout)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return tr
+}
+
+type SortableMemberSliceByPeerURLs []client.Member
+
+func (p SortableMemberSliceByPeerURLs) Len() int { return len(p) }
+func (p SortableMemberSliceByPeerURLs) Less(i, j int) bool {
+ return p[i].PeerURLs[0] < p[j].PeerURLs[0]
+}
+func (p SortableMemberSliceByPeerURLs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+type ClusterV3 struct {
+ *cluster
+
+ mu sync.Mutex
+ clients []*clientv3.Client
+ clusterClient *clientv3.Client
+}
+
+// NewClusterV3 returns a launched cluster with a grpc client connection
+// for each cluster member.
+func NewClusterV3(t testutil.TB, cfg *ClusterConfig) *ClusterV3 {
+ t.Helper()
+
+ assertInTestContext(t)
+
+ cfg.UseGRPC = true
+
+ clus := &ClusterV3{
+ cluster: NewClusterByConfig(t, cfg),
+ }
+ clus.Launch(t)
+
+ if !cfg.SkipCreatingClient {
+ for _, m := range clus.Members {
+ client, err := NewClientV3(m)
+ if err != nil {
+ t.Fatalf("cannot create client: %v", err)
+ }
+ clus.clients = append(clus.clients, client)
+ }
+ }
+
+ return clus
+}
+
+func (c *ClusterV3) TakeClient(idx int) {
+ c.mu.Lock()
+ c.clients[idx] = nil
+ c.mu.Unlock()
+}
+
+func (c *ClusterV3) Terminate(t testutil.TB) {
+ c.mu.Lock()
+ for _, client := range c.clients {
+ if client == nil {
+ continue
+ }
+ if err := client.Close(); err != nil {
+ t.Error(err)
+ }
+ }
+ if c.clusterClient != nil {
+ if err := c.clusterClient.Close(); err != nil {
+ t.Error(err)
+ }
+ }
+ c.mu.Unlock()
+ c.cluster.Terminate(t)
+}
+
+func (c *ClusterV3) RandClient() *clientv3.Client {
+ return c.clients[rand.Intn(len(c.clients))]
+}
+
+func (c *ClusterV3) Client(i int) *clientv3.Client {
+ return c.clients[i]
+}
+
+func (c *ClusterV3) ClusterClient() (client *clientv3.Client, err error) {
+ if c.clusterClient == nil {
+ var endpoints []string
+ for _, m := range c.Members {
+ endpoints = append(endpoints, m.grpcURL)
+ }
+ cfg := clientv3.Config{
+ Endpoints: endpoints,
+ DialTimeout: 5 * time.Second,
+ DialOptions: []grpc.DialOption{grpc.WithBlock()},
+ }
+ c.clusterClient, err = newClientV3(cfg, cfg.Logger)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return c.clusterClient, nil
+}
+
+// NewClientV3 creates a new grpc client connection to the member
+func (c *ClusterV3) NewClientV3(memberIndex int) (*clientv3.Client, error) {
+ return NewClientV3(c.Members[memberIndex])
+}
+
+func makeClients(t testutil.TB, clus *ClusterV3, clients *[]*clientv3.Client, chooseMemberIndex func() int) func() *clientv3.Client {
+ var mu sync.Mutex
+ *clients = nil
+ return func() *clientv3.Client {
+ cli, err := clus.NewClientV3(chooseMemberIndex())
+ if err != nil {
+ t.Fatalf("cannot create client: %v", err)
+ }
+ mu.Lock()
+ *clients = append(*clients, cli)
+ mu.Unlock()
+ return cli
+ }
+}
+
+// MakeSingleNodeClients creates factory of clients that all connect to member 0.
+// All the created clients are put on the 'clients' list. The factory is thread-safe.
+func MakeSingleNodeClients(t testutil.TB, clus *ClusterV3, clients *[]*clientv3.Client) func() *clientv3.Client {
+ return makeClients(t, clus, clients, func() int { return 0 })
+}
+
+// MakeMultiNodeClients creates factory of clients that all connect to random members.
+// All the created clients are put on the 'clients' list. The factory is thread-safe.
+func MakeMultiNodeClients(t testutil.TB, clus *ClusterV3, clients *[]*clientv3.Client) func() *clientv3.Client {
+ return makeClients(t, clus, clients, func() int { return rand.Intn(len(clus.Members)) })
+}
+
+// CloseClients closes all the clients from the 'clients' list.
+func CloseClients(t testutil.TB, clients []*clientv3.Client) {
+ for _, cli := range clients {
+ if err := cli.Close(); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+type grpcAPI struct {
+ // Cluster is the cluster API for the client's connection.
+ Cluster pb.ClusterClient
+ // KV is the keyvalue API for the client's connection.
+ KV pb.KVClient
+ // Lease is the lease API for the client's connection.
+ Lease pb.LeaseClient
+ // Watch is the watch API for the client's connection.
+ Watch pb.WatchClient
+ // Maintenance is the maintenance API for the client's connection.
+ Maintenance pb.MaintenanceClient
+ // Auth is the authentication API for the client's connection.
+ Auth pb.AuthClient
+ // Lock is the lock API for the client's connection.
+ Lock lockpb.LockClient
+ // Election is the election API for the client's connection.
+ Election epb.ElectionClient
+}
+
+// GetLearnerMembers returns the list of learner members in cluster using MemberList API.
+func (c *ClusterV3) GetLearnerMembers() ([]*pb.Member, error) {
+ cli := c.Client(0)
+ resp, err := cli.MemberList(context.Background())
+ if err != nil {
+ return nil, fmt.Errorf("failed to list member %v", err)
+ }
+ var learners []*pb.Member
+ for _, m := range resp.Members {
+ if m.IsLearner {
+ learners = append(learners, m)
+ }
+ }
+ return learners, nil
+}
+
+// AddAndLaunchLearnerMember creates a leaner member, adds it to cluster
+// via v3 MemberAdd API, and then launches the new member.
+func (c *ClusterV3) AddAndLaunchLearnerMember(t testutil.TB) {
+ m := c.mustNewMember(t, 0)
+ m.isLearner = true
+
+ scheme := schemeFromTLSInfo(c.cfg.PeerTLS)
+ peerURLs := []string{scheme + "://" + m.PeerListeners[0].Addr().String()}
+
+ cli := c.Client(0)
+ _, err := cli.MemberAddAsLearner(context.Background(), peerURLs)
+ if err != nil {
+ t.Fatalf("failed to add learner member %v", err)
+ }
+
+ m.InitialPeerURLsMap = types.URLsMap{}
+ for _, mm := range c.Members {
+ m.InitialPeerURLsMap[mm.Name] = mm.PeerURLs
+ }
+ m.InitialPeerURLsMap[m.Name] = m.PeerURLs
+ m.NewCluster = false
+
+ if err := m.Launch(); err != nil {
+ t.Fatal(err)
+ }
+
+ c.Members = append(c.Members, m)
+
+ c.waitMembersMatch(t)
+}
+
+// getMembers returns a list of members in cluster, in format of etcdserverpb.Member
+func (c *ClusterV3) getMembers() []*pb.Member {
+ var mems []*pb.Member
+ for _, m := range c.Members {
+ mem := &pb.Member{
+ Name: m.Name,
+ PeerURLs: m.PeerURLs.StringSlice(),
+ ClientURLs: m.ClientURLs.StringSlice(),
+ IsLearner: m.isLearner,
+ }
+ mems = append(mems, mem)
+ }
+ return mems
+}
+
+// waitMembersMatch waits until v3rpc MemberList returns the 'same' members info as the
+// local 'c.Members', which is the local recording of members in the testing cluster. With
+// the exception that the local recording c.Members does not have info on Member.ID, which
+// is generated when the member is been added to cluster.
+//
+// Note:
+// A successful match means the Member.clientURLs are matched. This means member has already
+// finished publishing its server attributes to cluster. Publishing attributes is a cluster-wide
+// write request (in v2 server). Therefore, at this point, any raft log entries prior to this
+// would have already been applied.
+//
+// If a new member was added to an existing cluster, at this point, it has finished publishing
+// its own server attributes to the cluster. And therefore by the same argument, it has already
+// applied the raft log entries (especially those of type raftpb.ConfChangeType). At this point,
+// the new member has the correct view of the cluster configuration.
+//
+// Special note on learner member:
+// Learner member is only added to a cluster via v3rpc MemberAdd API (as of v3.4). When starting
+// the learner member, its initial view of the cluster created by peerURLs map does not have info
+// on whether or not the new member itself is learner. But at this point, a successful match does
+// indicate that the new learner member has applied the raftpb.ConfChangeAddLearnerNode entry
+// which was used to add the learner itself to the cluster, and therefore it has the correct info
+// on learner.
+func (c *ClusterV3) waitMembersMatch(t testutil.TB) {
+ wMembers := c.getMembers()
+ sort.Sort(SortableProtoMemberSliceByPeerURLs(wMembers))
+ cli := c.Client(0)
+ for {
+ resp, err := cli.MemberList(context.Background())
+ if err != nil {
+ t.Fatalf("failed to list member %v", err)
+ }
+
+ if len(resp.Members) != len(wMembers) {
+ continue
+ }
+ sort.Sort(SortableProtoMemberSliceByPeerURLs(resp.Members))
+ for _, m := range resp.Members {
+ m.ID = 0
+ }
+ if reflect.DeepEqual(resp.Members, wMembers) {
+ return
+ }
+
+ time.Sleep(tickDuration)
+ }
+}
+
+type SortableProtoMemberSliceByPeerURLs []*pb.Member
+
+func (p SortableProtoMemberSliceByPeerURLs) Len() int { return len(p) }
+func (p SortableProtoMemberSliceByPeerURLs) Less(i, j int) bool {
+ return p[i].PeerURLs[0] < p[j].PeerURLs[0]
+}
+func (p SortableProtoMemberSliceByPeerURLs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// MustNewMember creates a new member instance based on the response of V3 Member Add API.
+func (c *ClusterV3) MustNewMember(t testutil.TB, resp *clientv3.MemberAddResponse) *member {
+ m := c.mustNewMember(t, 0)
+ m.isLearner = resp.Member.IsLearner
+ m.NewCluster = false
+
+ m.InitialPeerURLsMap = types.URLsMap{}
+ for _, mm := range c.Members {
+ m.InitialPeerURLsMap[mm.Name] = mm.PeerURLs
+ }
+ m.InitialPeerURLsMap[m.Name] = types.MustNewURLs(resp.Member.PeerURLs)
+ c.Members = append(c.Members, m)
+ return m
+}
diff --git a/vendor/go.etcd.io/etcd/tests/v3/integration/cluster_direct.go b/vendor/go.etcd.io/etcd/tests/v3/integration/cluster_direct.go
new file mode 100644
index 0000000000..67daf7caea
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/integration/cluster_direct.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.
+
+//go:build !cluster_proxy
+// +build !cluster_proxy
+
+package integration
+
+import (
+ pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"
+ "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"
+ "go.uber.org/zap"
+)
+
+const ThroughProxy = false
+
+func toGRPC(c *clientv3.Client) grpcAPI {
+ return grpcAPI{
+ pb.NewClusterClient(c.ActiveConnection()),
+ pb.NewKVClient(c.ActiveConnection()),
+ pb.NewLeaseClient(c.ActiveConnection()),
+ pb.NewWatchClient(c.ActiveConnection()),
+ pb.NewMaintenanceClient(c.ActiveConnection()),
+ pb.NewAuthClient(c.ActiveConnection()),
+ v3lockpb.NewLockClient(c.ActiveConnection()),
+ v3electionpb.NewElectionClient(c.ActiveConnection()),
+ }
+}
+
+func newClientV3(cfg clientv3.Config, lg *zap.Logger) (*clientv3.Client, error) {
+ cfg.Logger = lg
+ return clientv3.New(cfg)
+}
diff --git a/vendor/go.etcd.io/etcd/tests/v3/integration/cluster_proxy.go b/vendor/go.etcd.io/etcd/tests/v3/integration/cluster_proxy.go
new file mode 100644
index 0000000000..e8549eea3f
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/integration/cluster_proxy.go
@@ -0,0 +1,132 @@
+// 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.
+
+//go:build cluster_proxy
+// +build cluster_proxy
+
+package integration
+
+import (
+ "context"
+ "sync"
+
+ "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/client/v3/namespace"
+ "go.etcd.io/etcd/server/v3/proxy/grpcproxy"
+ "go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter"
+ "go.uber.org/zap"
+)
+
+const ThroughProxy = true
+
+var (
+ pmu sync.Mutex
+ proxies map[*clientv3.Client]grpcClientProxy = make(map[*clientv3.Client]grpcClientProxy)
+)
+
+const proxyNamespace = "proxy-namespace"
+
+type grpcClientProxy struct {
+ ctx context.Context
+ ctxCancel func()
+ grpc grpcAPI
+ wdonec <-chan struct{}
+ kvdonec <-chan struct{}
+ lpdonec <-chan struct{}
+}
+
+func toGRPC(c *clientv3.Client) grpcAPI {
+ pmu.Lock()
+ defer pmu.Unlock()
+
+ // dedicated context bound to 'grpc-proxy' lifetype
+ // (so in practice lifetime of the client connection to the proxy).
+ // TODO: Refactor to a separate clientv3.Client instance instead of the context alone.
+ ctx, ctxCancel := context.WithCancel(context.WithValue(context.TODO(), "_name", "grpcProxyContext"))
+
+ lg := c.GetLogger()
+
+ if v, ok := proxies[c]; ok {
+ return v.grpc
+ }
+
+ // test namespacing proxy
+ c.KV = namespace.NewKV(c.KV, proxyNamespace)
+ c.Watcher = namespace.NewWatcher(c.Watcher, proxyNamespace)
+ c.Lease = namespace.NewLease(c.Lease, proxyNamespace)
+ // test coalescing/caching proxy
+ kvp, kvpch := grpcproxy.NewKvProxy(c)
+ wp, wpch := grpcproxy.NewWatchProxy(ctx, lg, c)
+ lp, lpch := grpcproxy.NewLeaseProxy(ctx, c)
+ mp := grpcproxy.NewMaintenanceProxy(c)
+ clp, _ := grpcproxy.NewClusterProxy(lg, c, "", "") // without registering proxy URLs
+ authp := grpcproxy.NewAuthProxy(c)
+ lockp := grpcproxy.NewLockProxy(c)
+ electp := grpcproxy.NewElectionProxy(c)
+
+ grpc := grpcAPI{
+ adapter.ClusterServerToClusterClient(clp),
+ adapter.KvServerToKvClient(kvp),
+ adapter.LeaseServerToLeaseClient(lp),
+ adapter.WatchServerToWatchClient(wp),
+ adapter.MaintenanceServerToMaintenanceClient(mp),
+ adapter.AuthServerToAuthClient(authp),
+ adapter.LockServerToLockClient(lockp),
+ adapter.ElectionServerToElectionClient(electp),
+ }
+ proxies[c] = grpcClientProxy{ctx: ctx, ctxCancel: ctxCancel, grpc: grpc, wdonec: wpch, kvdonec: kvpch, lpdonec: lpch}
+ return grpc
+}
+
+type proxyCloser struct {
+ clientv3.Watcher
+ proxyCtxCancel func()
+ wdonec <-chan struct{}
+ kvdonec <-chan struct{}
+ lclose func()
+ lpdonec <-chan struct{}
+}
+
+func (pc *proxyCloser) Close() error {
+ pc.proxyCtxCancel()
+ <-pc.kvdonec
+ err := pc.Watcher.Close()
+ <-pc.wdonec
+ pc.lclose()
+ <-pc.lpdonec
+ return err
+}
+
+func newClientV3(cfg clientv3.Config, lg *zap.Logger) (*clientv3.Client, error) {
+ cfg.Logger = lg
+ c, err := clientv3.New(cfg)
+ if err != nil {
+ return nil, err
+ }
+ rpc := toGRPC(c)
+ c.KV = clientv3.NewKVFromKVClient(rpc.KV, c)
+ pmu.Lock()
+ lc := c.Lease
+ c.Lease = clientv3.NewLeaseFromLeaseClient(rpc.Lease, c, cfg.DialTimeout)
+ c.Watcher = &proxyCloser{
+ Watcher: clientv3.NewWatchFromWatchClient(rpc.Watch, c),
+ wdonec: proxies[c].wdonec,
+ kvdonec: proxies[c].kvdonec,
+ lclose: func() { lc.Close() },
+ lpdonec: proxies[c].lpdonec,
+ proxyCtxCancel: proxies[c].ctxCancel,
+ }
+ pmu.Unlock()
+ return c, nil
+}
diff --git a/vendor/go.etcd.io/etcd/tests/v3/integration/doc.go b/vendor/go.etcd.io/etcd/tests/v3/integration/doc.go
new file mode 100644
index 0000000000..fbf19d5436
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/integration/doc.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.
+
+/*
+Package integration implements tests built upon embedded etcd, and focus on
+etcd correctness.
+
+Features/goals of the integration tests:
+1. test the whole code base except command-line parsing.
+2. check internal data, including raft, store and etc.
+3. based on goroutines, which is faster than process.
+4. mainly tests user behavior and user-facing API.
+*/
+package integration
diff --git a/vendor/go.etcd.io/etcd/tests/v3/integration/lazy_cluster.go b/vendor/go.etcd.io/etcd/tests/v3/integration/lazy_cluster.go
new file mode 100644
index 0000000000..4cc7ae765d
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/integration/lazy_cluster.go
@@ -0,0 +1,120 @@
+// Copyright 2020 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 integration
+
+import (
+ "log"
+ "net/http"
+ "sync"
+ "time"
+
+ "go.etcd.io/etcd/client/pkg/v3/testutil"
+ "go.etcd.io/etcd/client/pkg/v3/transport"
+)
+
+// Infrastructure to provision a single shared cluster for tests - only
+// when its needed.
+//
+// See ./tests/integration/clientv3/examples/main_test.go for canonical usage.
+// Please notice that the shared (LazyCluster's) state is preserved between
+// testcases, so left-over state might has cross-testcase effects.
+// Prefer dedicated clusters for substancial test-cases.
+
+type LazyCluster interface {
+ // EndpointsV2 - exposes connection points for client v2.
+ // Calls to this method might initialize the cluster.
+ EndpointsV2() []string
+
+ // EndpointsV3 - exposes connection points for client v3.
+ // Calls to this method might initialize the cluster.
+ EndpointsV3() []string
+
+ // Cluster - calls to this method might initialize the cluster.
+ Cluster() *ClusterV3
+
+ // Transport - call to this method might initialize the cluster.
+ Transport() *http.Transport
+
+ Terminate()
+
+ TB() testutil.TB
+}
+
+type lazyCluster struct {
+ cfg ClusterConfig
+ cluster *ClusterV3
+ transport *http.Transport
+ once sync.Once
+ tb testutil.TB
+ closer func()
+}
+
+// NewLazyCluster returns a new test cluster handler that gets created on the
+// first call to GetEndpoints() or GetTransport()
+func NewLazyCluster() LazyCluster {
+ return NewLazyClusterWithConfig(ClusterConfig{Size: 1})
+}
+
+// NewLazyClusterWithConfig returns a new test cluster handler that gets created
+// on the first call to GetEndpoints() or GetTransport()
+func NewLazyClusterWithConfig(cfg ClusterConfig) LazyCluster {
+ tb, closer := testutil.NewTestingTBProthesis("lazy_cluster")
+ return &lazyCluster{cfg: cfg, tb: tb, closer: closer}
+}
+
+func (lc *lazyCluster) mustLazyInit() {
+ lc.once.Do(func() {
+ var err error
+ lc.transport, err = transport.NewTransport(transport.TLSInfo{}, time.Second)
+ if err != nil {
+ log.Fatal(err)
+ }
+ lc.cluster = NewClusterV3(lc.tb, &lc.cfg)
+ })
+}
+
+func (lc *lazyCluster) Terminate() {
+ lc.tb.Logf("Terminating...")
+ if lc != nil && lc.cluster != nil {
+ lc.cluster.Terminate(nil)
+ lc.cluster = nil
+ }
+ if lc.closer != nil {
+ lc.tb.Logf("Closer...")
+ lc.closer()
+ }
+}
+
+func (lc *lazyCluster) EndpointsV2() []string {
+ return []string{lc.Cluster().Members[0].URL()}
+}
+
+func (lc *lazyCluster) EndpointsV3() []string {
+ return lc.Cluster().Client(0).Endpoints()
+}
+
+func (lc *lazyCluster) Cluster() *ClusterV3 {
+ lc.mustLazyInit()
+ return lc.cluster
+}
+
+func (lc *lazyCluster) Transport() *http.Transport {
+ lc.mustLazyInit()
+ return lc.transport
+}
+
+func (lc *lazyCluster) TB() testutil.TB {
+ return lc.tb
+}
diff --git a/vendor/go.etcd.io/etcd/tests/v3/integration/testing.go b/vendor/go.etcd.io/etcd/tests/v3/integration/testing.go
new file mode 100644
index 0000000000..e67375180b
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/tests/v3/integration/testing.go
@@ -0,0 +1,136 @@
+// Copyright 2021 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 integration
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+
+ grpc_logsettable "github.com/grpc-ecosystem/go-grpc-middleware/logging/settable"
+ "go.etcd.io/etcd/client/pkg/v3/testutil"
+ clientv3 "go.etcd.io/etcd/client/v3"
+ "go.etcd.io/etcd/server/v3/embed"
+ "go.etcd.io/etcd/server/v3/verify"
+ "go.uber.org/zap/zapcore"
+ "go.uber.org/zap/zapgrpc"
+ "go.uber.org/zap/zaptest"
+)
+
+var grpc_logger grpc_logsettable.SettableLoggerV2
+var insideTestContext bool
+
+func init() {
+ grpc_logger = grpc_logsettable.ReplaceGrpcLoggerV2()
+}
+
+type testOptions struct {
+ goLeakDetection bool
+ skipInShort bool
+}
+
+func newTestOptions(opts ...TestOption) *testOptions {
+ o := &testOptions{goLeakDetection: true, skipInShort: true}
+ for _, opt := range opts {
+ opt(o)
+ }
+ return o
+}
+
+type TestOption func(opt *testOptions)
+
+// WithoutGoLeakDetection disables checking whether a testcase leaked a goroutine.
+func WithoutGoLeakDetection() TestOption {
+ return func(opt *testOptions) { opt.goLeakDetection = false }
+}
+
+func WithoutSkipInShort() TestOption {
+ return func(opt *testOptions) { opt.skipInShort = false }
+}
+
+// BeforeTestExternal initializes test context and is targeted for external APIs.
+// In general the `integration` package is not targeted to be used outside of
+// etcd project, but till the dedicated package is developed, this is
+// the best entry point so far (without backward compatibility promise).
+func BeforeTestExternal(t testutil.TB) {
+ BeforeTest(t, WithoutSkipInShort(), WithoutGoLeakDetection())
+}
+
+func BeforeTest(t testutil.TB, opts ...TestOption) {
+ t.Helper()
+ options := newTestOptions(opts...)
+
+ if options.skipInShort {
+ testutil.SkipTestIfShortMode(t, "Cannot create clusters in --short tests")
+ }
+
+ if options.goLeakDetection {
+ testutil.RegisterLeakDetection(t)
+ }
+
+ previousWD, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ previousInsideTestContext := insideTestContext
+
+ // Registering cleanup early, such it will get executed even if the helper fails.
+ t.Cleanup(func() {
+ grpc_logger.Reset()
+ insideTestContext = previousInsideTestContext
+ os.Chdir(previousWD)
+ })
+
+ if insideTestContext {
+ t.Fatal("already in test context. BeforeTest was likely already called")
+ }
+
+ grpc_logger.Set(zapgrpc.NewLogger(zaptest.NewLogger(t).Named("grpc")))
+ insideTestContext = true
+
+ // Integration tests should verify written state as much as possible.
+ os.Setenv(verify.ENV_VERIFY, verify.ENV_VERIFY_ALL_VALUE)
+ os.Chdir(t.TempDir())
+}
+
+func assertInTestContext(t testutil.TB) {
+ if !insideTestContext {
+ t.Errorf("the function can be called only in the test context. Was integration.BeforeTest() called ?")
+ }
+}
+
+func MustAbsPath(path string) string {
+ abs, err := filepath.Abs(path)
+ if err != nil {
+ panic(err)
+ }
+ return abs
+}
+
+func NewEmbedConfig(t testing.TB, name string) *embed.Config {
+ cfg := embed.NewConfig()
+ cfg.Name = name
+ lg := zaptest.NewLogger(t, zaptest.Level(zapcore.InfoLevel)).Named(cfg.Name)
+ cfg.ZapLoggerBuilder = embed.NewZapLoggerBuilder(lg)
+ cfg.Dir = t.TempDir()
+ return cfg
+}
+
+func NewClient(t testing.TB, cfg clientv3.Config) (*clientv3.Client, error) {
+ if cfg.Logger != nil {
+ cfg.Logger = zaptest.NewLogger(t)
+ }
+ return clientv3.New(cfg)
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go
index 6ca8d9ad6c..652aa48b85 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go
@@ -15,16 +15,15 @@ import (
// ArrayCodec is the Codec used for bsoncore.Array values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// ArrayCodec registered.
+// Deprecated: ArrayCodec will not be directly accessible in Go Driver 2.0.
type ArrayCodec struct{}
var defaultArrayCodec = NewArrayCodec()
// NewArrayCodec returns an ArrayCodec.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// ArrayCodec registered.
+// Deprecated: NewArrayCodec will not be available in Go Driver 2.0. See
+// [ArrayCodec] for more details.
func NewArrayCodec() *ArrayCodec {
return &ArrayCodec{}
}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go
index dde3e76815..0134b5a94b 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go
@@ -17,13 +17,28 @@ import (
// ByteSliceCodec is the Codec used for []byte values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// ByteSliceCodec registered.
+// Deprecated: ByteSliceCodec will not be directly configurable in Go Driver
+// 2.0. To configure the byte slice encode and decode behavior, use the
+// configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
+// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the byte slice
+// encode and decode behavior for a mongo.Client, use
+// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
+//
+// For example, to configure a mongo.Client to encode nil byte slices as empty
+// BSON binary values, use:
+//
+// opt := options.Client().SetBSONOptions(&options.BSONOptions{
+// NilByteSliceAsEmpty: true,
+// })
+//
+// See the deprecation notice for each field in ByteSliceCodec for the
+// corresponding settings.
type ByteSliceCodec struct {
// EncodeNilAsEmpty causes EncodeValue to marshal nil Go byte slices as empty BSON binary values
// instead of BSON null.
//
- // Deprecated: Use bson.Encoder.NilByteSliceAsEmpty instead.
+ // Deprecated: Use bson.Encoder.NilByteSliceAsEmpty or options.BSONOptions.NilByteSliceAsEmpty
+ // instead.
EncodeNilAsEmpty bool
}
@@ -38,8 +53,8 @@ var (
// NewByteSliceCodec returns a ByteSliceCodec with options opts.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// ByteSliceCodec registered.
+// Deprecated: NewByteSliceCodec will not be available in Go Driver 2.0. See
+// [ByteSliceCodec] for more details.
func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec {
byteSliceOpt := bsonoptions.MergeByteSliceCodecOptions(opts...)
codec := ByteSliceCodec{}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/codec_cache.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/codec_cache.go
new file mode 100644
index 0000000000..844b50299f
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/codec_cache.go
@@ -0,0 +1,166 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package bsoncodec
+
+import (
+ "reflect"
+ "sync"
+ "sync/atomic"
+)
+
+// Runtime check that the kind encoder and decoder caches can store any valid
+// reflect.Kind constant.
+func init() {
+ if s := reflect.Kind(len(kindEncoderCache{}.entries)).String(); s != "kind27" {
+ panic("The capacity of kindEncoderCache is too small.\n" +
+ "This is due to a new type being added to reflect.Kind.")
+ }
+}
+
+// statically assert array size
+var _ = (kindEncoderCache{}).entries[reflect.UnsafePointer]
+var _ = (kindDecoderCache{}).entries[reflect.UnsafePointer]
+
+type typeEncoderCache struct {
+ cache sync.Map // map[reflect.Type]ValueEncoder
+}
+
+func (c *typeEncoderCache) Store(rt reflect.Type, enc ValueEncoder) {
+ c.cache.Store(rt, enc)
+}
+
+func (c *typeEncoderCache) Load(rt reflect.Type) (ValueEncoder, bool) {
+ if v, _ := c.cache.Load(rt); v != nil {
+ return v.(ValueEncoder), true
+ }
+ return nil, false
+}
+
+func (c *typeEncoderCache) LoadOrStore(rt reflect.Type, enc ValueEncoder) ValueEncoder {
+ if v, loaded := c.cache.LoadOrStore(rt, enc); loaded {
+ enc = v.(ValueEncoder)
+ }
+ return enc
+}
+
+func (c *typeEncoderCache) Clone() *typeEncoderCache {
+ cc := new(typeEncoderCache)
+ c.cache.Range(func(k, v interface{}) bool {
+ if k != nil && v != nil {
+ cc.cache.Store(k, v)
+ }
+ return true
+ })
+ return cc
+}
+
+type typeDecoderCache struct {
+ cache sync.Map // map[reflect.Type]ValueDecoder
+}
+
+func (c *typeDecoderCache) Store(rt reflect.Type, dec ValueDecoder) {
+ c.cache.Store(rt, dec)
+}
+
+func (c *typeDecoderCache) Load(rt reflect.Type) (ValueDecoder, bool) {
+ if v, _ := c.cache.Load(rt); v != nil {
+ return v.(ValueDecoder), true
+ }
+ return nil, false
+}
+
+func (c *typeDecoderCache) LoadOrStore(rt reflect.Type, dec ValueDecoder) ValueDecoder {
+ if v, loaded := c.cache.LoadOrStore(rt, dec); loaded {
+ dec = v.(ValueDecoder)
+ }
+ return dec
+}
+
+func (c *typeDecoderCache) Clone() *typeDecoderCache {
+ cc := new(typeDecoderCache)
+ c.cache.Range(func(k, v interface{}) bool {
+ if k != nil && v != nil {
+ cc.cache.Store(k, v)
+ }
+ return true
+ })
+ return cc
+}
+
+// atomic.Value requires that all calls to Store() have the same concrete type
+// so we wrap the ValueEncoder with a kindEncoderCacheEntry to ensure the type
+// is always the same (since different concrete types may implement the
+// ValueEncoder interface).
+type kindEncoderCacheEntry struct {
+ enc ValueEncoder
+}
+
+type kindEncoderCache struct {
+ entries [reflect.UnsafePointer + 1]atomic.Value // *kindEncoderCacheEntry
+}
+
+func (c *kindEncoderCache) Store(rt reflect.Kind, enc ValueEncoder) {
+ if enc != nil && rt < reflect.Kind(len(c.entries)) {
+ c.entries[rt].Store(&kindEncoderCacheEntry{enc: enc})
+ }
+}
+
+func (c *kindEncoderCache) Load(rt reflect.Kind) (ValueEncoder, bool) {
+ if rt < reflect.Kind(len(c.entries)) {
+ if ent, ok := c.entries[rt].Load().(*kindEncoderCacheEntry); ok {
+ return ent.enc, ent.enc != nil
+ }
+ }
+ return nil, false
+}
+
+func (c *kindEncoderCache) Clone() *kindEncoderCache {
+ cc := new(kindEncoderCache)
+ for i, v := range c.entries {
+ if val := v.Load(); val != nil {
+ cc.entries[i].Store(val)
+ }
+ }
+ return cc
+}
+
+// atomic.Value requires that all calls to Store() have the same concrete type
+// so we wrap the ValueDecoder with a kindDecoderCacheEntry to ensure the type
+// is always the same (since different concrete types may implement the
+// ValueDecoder interface).
+type kindDecoderCacheEntry struct {
+ dec ValueDecoder
+}
+
+type kindDecoderCache struct {
+ entries [reflect.UnsafePointer + 1]atomic.Value // *kindDecoderCacheEntry
+}
+
+func (c *kindDecoderCache) Store(rt reflect.Kind, dec ValueDecoder) {
+ if rt < reflect.Kind(len(c.entries)) {
+ c.entries[rt].Store(&kindDecoderCacheEntry{dec: dec})
+ }
+}
+
+func (c *kindDecoderCache) Load(rt reflect.Kind) (ValueDecoder, bool) {
+ if rt < reflect.Kind(len(c.entries)) {
+ if ent, ok := c.entries[rt].Load().(*kindDecoderCacheEntry); ok {
+ return ent.dec, ent.dec != nil
+ }
+ }
+ return nil, false
+}
+
+func (c *kindDecoderCache) Clone() *kindDecoderCache {
+ cc := new(kindDecoderCache)
+ for i, v := range c.entries {
+ if val := v.Load(); val != nil {
+ cc.entries[i].Store(val)
+ }
+ }
+ return cc
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go
index e479c3585b..7e08aab35e 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go
@@ -24,7 +24,7 @@ import (
var (
defaultValueDecoders DefaultValueDecoders
- errCannotTruncate = errors.New("float64 can only be truncated to an integer type when truncation is enabled")
+ errCannotTruncate = errors.New("float64 can only be truncated to a lower precision type when truncation is enabled")
)
type decodeBinaryError struct {
@@ -41,7 +41,7 @@ func newDefaultStructCodec() *StructCodec {
if err != nil {
// This function is called from the codec registration path, so errors can't be propagated. If there's an error
// constructing the StructCodec, we panic to avoid losing it.
- panic(fmt.Errorf("error creating default StructCodec: %v", err))
+ panic(fmt.Errorf("error creating default StructCodec: %w", err))
}
return codec
}
@@ -178,7 +178,7 @@ func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueRe
for {
key, elemVr, err := dr.ReadElement()
- if err == bsonrw.ErrEOD {
+ if errors.Is(err, bsonrw.ErrEOD) {
break
} else if err != nil {
return err
@@ -1379,7 +1379,7 @@ func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr bsonrw.Value
keyType := val.Type().Key()
for {
key, vr, err := dr.ReadElement()
- if err == bsonrw.ErrEOD {
+ if errors.Is(err, bsonrw.ErrEOD) {
break
}
if err != nil {
@@ -1675,7 +1675,7 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueR
idx := 0
for {
vr, err := ar.ReadValue()
- if err == bsonrw.ErrEOA {
+ if errors.Is(err, bsonrw.ErrEOA) {
break
}
if err != nil {
@@ -1787,7 +1787,7 @@ func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr b
elems := make([]reflect.Value, 0)
for {
key, vr, err := dr.ReadElement()
- if err == bsonrw.ErrEOD {
+ if errors.Is(err, bsonrw.ErrEOD) {
break
}
if err != nil {
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go
index 4ab14a668c..4751ae995e 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go
@@ -343,7 +343,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum
}
currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key))
- if lookupErr != nil && lookupErr != errInvalidValue {
+ if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
return lookupErr
}
@@ -352,7 +352,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum
return err
}
- if lookupErr == errInvalidValue {
+ if errors.Is(lookupErr, errInvalidValue) {
err = vw.WriteNull()
if err != nil {
return err
@@ -418,7 +418,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val
for idx := 0; idx < val.Len(); idx++ {
currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx))
- if lookupErr != nil && lookupErr != errInvalidValue {
+ if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
return lookupErr
}
@@ -427,7 +427,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val
return err
}
- if lookupErr == errInvalidValue {
+ if errors.Is(lookupErr, errInvalidValue) {
err = vw.WriteNull()
if err != nil {
return err
@@ -487,7 +487,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val
for idx := 0; idx < val.Len(); idx++ {
currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx))
- if lookupErr != nil && lookupErr != errInvalidValue {
+ if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
return lookupErr
}
@@ -496,7 +496,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val
return err
}
- if lookupErr == errInvalidValue {
+ if errors.Is(lookupErr, errInvalidValue) {
err = vw.WriteNull()
if err != nil {
return err
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go
index 94f7dcf1eb..098368f071 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go
@@ -17,13 +17,27 @@ import (
// EmptyInterfaceCodec is the Codec used for interface{} values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// EmptyInterfaceCodec registered.
+// Deprecated: EmptyInterfaceCodec will not be directly configurable in Go
+// Driver 2.0. To configure the empty interface encode and decode behavior, use
+// the configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
+// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the empty interface
+// encode and decode behavior for a mongo.Client, use
+// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
+//
+// For example, to configure a mongo.Client to unmarshal BSON binary field
+// values as a Go byte slice, use:
+//
+// opt := options.Client().SetBSONOptions(&options.BSONOptions{
+// BinaryAsSlice: true,
+// })
+//
+// See the deprecation notice for each field in EmptyInterfaceCodec for the
+// corresponding settings.
type EmptyInterfaceCodec struct {
// DecodeBinaryAsSlice causes DecodeValue to unmarshal BSON binary field values that are the
// "Generic" or "Old" BSON binary subtype as a Go byte slice instead of a primitive.Binary.
//
- // Deprecated: Use bson.Decoder.BinaryAsSlice instead.
+ // Deprecated: Use bson.Decoder.BinaryAsSlice or options.BSONOptions.BinaryAsSlice instead.
DecodeBinaryAsSlice bool
}
@@ -38,8 +52,8 @@ var (
// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// EmptyInterfaceCodec registered.
+// Deprecated: NewEmptyInterfaceCodec will not be available in Go Driver 2.0. See
+// [EmptyInterfaceCodec] for more details.
func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec {
interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...)
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go
index 325c1738ab..d7e00ffa8d 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go
@@ -8,6 +8,7 @@ package bsoncodec
import (
"encoding"
+ "errors"
"fmt"
"reflect"
"strconv"
@@ -21,25 +22,40 @@ var defaultMapCodec = NewMapCodec()
// MapCodec is the Codec used for map values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// MapCodec registered.
+// Deprecated: MapCodec will not be directly configurable in Go Driver 2.0. To
+// configure the map encode and decode behavior, use the configuration methods
+// on a [go.mongodb.org/mongo-driver/bson.Encoder] or
+// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the map encode and
+// decode behavior for a mongo.Client, use
+// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
+//
+// For example, to configure a mongo.Client to marshal nil Go maps as empty BSON
+// documents, use:
+//
+// opt := options.Client().SetBSONOptions(&options.BSONOptions{
+// NilMapAsEmpty: true,
+// })
+//
+// See the deprecation notice for each field in MapCodec for the corresponding
+// settings.
type MapCodec struct {
// DecodeZerosMap causes DecodeValue to delete any existing values from Go maps in the destination
// value passed to Decode before unmarshaling BSON documents into them.
//
- // Deprecated: Use bson.Decoder.ZeroMaps instead.
+ // Deprecated: Use bson.Decoder.ZeroMaps or options.BSONOptions.ZeroMaps instead.
DecodeZerosMap bool
// EncodeNilAsEmpty causes EncodeValue to marshal nil Go maps as empty BSON documents instead of
// BSON null.
//
- // Deprecated: Use bson.Encoder.NilMapAsEmpty instead.
+ // Deprecated: Use bson.Encoder.NilMapAsEmpty or options.BSONOptions.NilMapAsEmpty instead.
EncodeNilAsEmpty bool
// EncodeKeysWithStringer causes the Encoder to convert Go map keys to BSON document field name
// strings using fmt.Sprintf() instead of the default string conversion logic.
//
- // Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt instead.
+ // Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt or
+ // options.BSONOptions.StringifyMapKeysWithFmt instead.
EncodeKeysWithStringer bool
}
@@ -61,8 +77,8 @@ type KeyUnmarshaler interface {
// NewMapCodec returns a MapCodec with options opts.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// MapCodec registered.
+// Deprecated: NewMapCodec will not be available in Go Driver 2.0. See
+// [MapCodec] for more details.
func NewMapCodec(opts ...*bsonoptions.MapCodecOptions) *MapCodec {
mapOpt := bsonoptions.MergeMapCodecOptions(opts...)
@@ -128,7 +144,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v
}
currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.MapIndex(key))
- if lookupErr != nil && lookupErr != errInvalidValue {
+ if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
return lookupErr
}
@@ -137,7 +153,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v
return err
}
- if lookupErr == errInvalidValue {
+ if errors.Is(lookupErr, errInvalidValue) {
err = vw.WriteNull()
if err != nil {
return err
@@ -200,7 +216,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref
for {
key, vr, err := dr.ReadElement()
- if err == bsonrw.ErrEOD {
+ if errors.Is(err, bsonrw.ErrEOD) {
break
}
if err != nil {
@@ -313,7 +329,7 @@ func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value,
if mc.EncodeKeysWithStringer {
parsed, err := strconv.ParseFloat(key, 64)
if err != nil {
- return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %v", keyType.Kind(), err)
+ return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %w", keyType.Kind(), err)
}
keyVal = reflect.ValueOf(parsed)
break
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go
index a1bf9c3e2b..ddfa4a33e1 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go
@@ -8,7 +8,6 @@ package bsoncodec
import (
"reflect"
- "sync"
"go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/bsontype"
@@ -19,23 +18,27 @@ var _ ValueDecoder = &PointerCodec{}
// PointerCodec is the Codec used for pointers.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// PointerCodec registered.
+// Deprecated: PointerCodec will not be directly accessible in Go Driver 2.0. To
+// override the default pointer encode and decode behavior, create a new registry
+// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new
+// encoder and decoder for pointers.
+//
+// For example,
+//
+// reg := bson.NewRegistry()
+// reg.RegisterKindEncoder(reflect.Ptr, myPointerEncoder)
+// reg.RegisterKindDecoder(reflect.Ptr, myPointerDecoder)
type PointerCodec struct {
- ecache map[reflect.Type]ValueEncoder
- dcache map[reflect.Type]ValueDecoder
- l sync.RWMutex
+ ecache typeEncoderCache
+ dcache typeDecoderCache
}
// NewPointerCodec returns a PointerCodec that has been initialized.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// PointerCodec registered.
+// Deprecated: NewPointerCodec will not be available in Go Driver 2.0. See
+// [PointerCodec] for more details.
func NewPointerCodec() *PointerCodec {
- return &PointerCodec{
- ecache: make(map[reflect.Type]ValueEncoder),
- dcache: make(map[reflect.Type]ValueDecoder),
- }
+ return &PointerCodec{}
}
// EncodeValue handles encoding a pointer by either encoding it to BSON Null if the pointer is nil
@@ -52,24 +55,19 @@ func (pc *PointerCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val
return vw.WriteNull()
}
- pc.l.RLock()
- enc, ok := pc.ecache[val.Type()]
- pc.l.RUnlock()
- if ok {
- if enc == nil {
- return ErrNoEncoder{Type: val.Type()}
+ typ := val.Type()
+ if v, ok := pc.ecache.Load(typ); ok {
+ if v == nil {
+ return ErrNoEncoder{Type: typ}
}
- return enc.EncodeValue(ec, vw, val.Elem())
+ return v.EncodeValue(ec, vw, val.Elem())
}
-
- enc, err := ec.LookupEncoder(val.Type().Elem())
- pc.l.Lock()
- pc.ecache[val.Type()] = enc
- pc.l.Unlock()
+ // TODO(charlie): handle concurrent requests for the same type
+ enc, err := ec.LookupEncoder(typ.Elem())
+ enc = pc.ecache.LoadOrStore(typ, enc)
if err != nil {
return err
}
-
return enc.EncodeValue(ec, vw, val.Elem())
}
@@ -80,36 +78,31 @@ func (pc *PointerCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val
return ValueDecoderError{Name: "PointerCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val}
}
+ typ := val.Type()
if vr.Type() == bsontype.Null {
- val.Set(reflect.Zero(val.Type()))
+ val.Set(reflect.Zero(typ))
return vr.ReadNull()
}
if vr.Type() == bsontype.Undefined {
- val.Set(reflect.Zero(val.Type()))
+ val.Set(reflect.Zero(typ))
return vr.ReadUndefined()
}
if val.IsNil() {
- val.Set(reflect.New(val.Type().Elem()))
+ val.Set(reflect.New(typ.Elem()))
}
- pc.l.RLock()
- dec, ok := pc.dcache[val.Type()]
- pc.l.RUnlock()
- if ok {
- if dec == nil {
- return ErrNoDecoder{Type: val.Type()}
+ if v, ok := pc.dcache.Load(typ); ok {
+ if v == nil {
+ return ErrNoDecoder{Type: typ}
}
- return dec.DecodeValue(dc, vr, val.Elem())
+ return v.DecodeValue(dc, vr, val.Elem())
}
-
- dec, err := dc.LookupDecoder(val.Type().Elem())
- pc.l.Lock()
- pc.dcache[val.Type()] = dec
- pc.l.Unlock()
+ // TODO(charlie): handle concurrent requests for the same type
+ dec, err := dc.LookupDecoder(typ.Elem())
+ dec = pc.dcache.LoadOrStore(typ, dec)
if err != nil {
return err
}
-
return dec.DecodeValue(dc, vr, val.Elem())
}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go
index 930de28490..196c491bbb 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go
@@ -216,72 +216,42 @@ func (rb *RegistryBuilder) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Typ
//
// Deprecated: Use NewRegistry instead.
func (rb *RegistryBuilder) Build() *Registry {
- registry := new(Registry)
-
- registry.typeEncoders = make(map[reflect.Type]ValueEncoder, len(rb.registry.typeEncoders))
- for t, enc := range rb.registry.typeEncoders {
- registry.typeEncoders[t] = enc
- }
-
- registry.typeDecoders = make(map[reflect.Type]ValueDecoder, len(rb.registry.typeDecoders))
- for t, dec := range rb.registry.typeDecoders {
- registry.typeDecoders[t] = dec
- }
-
- registry.interfaceEncoders = make([]interfaceValueEncoder, len(rb.registry.interfaceEncoders))
- copy(registry.interfaceEncoders, rb.registry.interfaceEncoders)
-
- registry.interfaceDecoders = make([]interfaceValueDecoder, len(rb.registry.interfaceDecoders))
- copy(registry.interfaceDecoders, rb.registry.interfaceDecoders)
-
- registry.kindEncoders = make(map[reflect.Kind]ValueEncoder)
- for kind, enc := range rb.registry.kindEncoders {
- registry.kindEncoders[kind] = enc
- }
-
- registry.kindDecoders = make(map[reflect.Kind]ValueDecoder)
- for kind, dec := range rb.registry.kindDecoders {
- registry.kindDecoders[kind] = dec
+ r := &Registry{
+ interfaceEncoders: append([]interfaceValueEncoder(nil), rb.registry.interfaceEncoders...),
+ interfaceDecoders: append([]interfaceValueDecoder(nil), rb.registry.interfaceDecoders...),
+ typeEncoders: rb.registry.typeEncoders.Clone(),
+ typeDecoders: rb.registry.typeDecoders.Clone(),
+ kindEncoders: rb.registry.kindEncoders.Clone(),
+ kindDecoders: rb.registry.kindDecoders.Clone(),
}
-
- registry.typeMap = make(map[bsontype.Type]reflect.Type)
- for bt, rt := range rb.registry.typeMap {
- registry.typeMap[bt] = rt
- }
-
- return registry
+ rb.registry.typeMap.Range(func(k, v interface{}) bool {
+ if k != nil && v != nil {
+ r.typeMap.Store(k, v)
+ }
+ return true
+ })
+ return r
}
// A Registry is used to store and retrieve codecs for types and interfaces. This type is the main
// typed passed around and Encoders and Decoders are constructed from it.
type Registry struct {
- typeEncoders map[reflect.Type]ValueEncoder
- typeDecoders map[reflect.Type]ValueDecoder
-
interfaceEncoders []interfaceValueEncoder
interfaceDecoders []interfaceValueDecoder
-
- kindEncoders map[reflect.Kind]ValueEncoder
- kindDecoders map[reflect.Kind]ValueDecoder
-
- typeMap map[bsontype.Type]reflect.Type
-
- mu sync.RWMutex
+ typeEncoders *typeEncoderCache
+ typeDecoders *typeDecoderCache
+ kindEncoders *kindEncoderCache
+ kindDecoders *kindDecoderCache
+ typeMap sync.Map // map[bsontype.Type]reflect.Type
}
// NewRegistry creates a new empty Registry.
func NewRegistry() *Registry {
return &Registry{
- typeEncoders: make(map[reflect.Type]ValueEncoder),
- typeDecoders: make(map[reflect.Type]ValueDecoder),
-
- interfaceEncoders: make([]interfaceValueEncoder, 0),
- interfaceDecoders: make([]interfaceValueDecoder, 0),
-
- kindEncoders: make(map[reflect.Kind]ValueEncoder),
- kindDecoders: make(map[reflect.Kind]ValueDecoder),
-
- typeMap: make(map[bsontype.Type]reflect.Type),
+ typeEncoders: new(typeEncoderCache),
+ typeDecoders: new(typeDecoderCache),
+ kindEncoders: new(kindEncoderCache),
+ kindDecoders: new(kindDecoderCache),
}
}
@@ -296,7 +266,7 @@ func NewRegistry() *Registry {
//
// RegisterTypeEncoder should not be called concurrently with any other Registry method.
func (r *Registry) RegisterTypeEncoder(valueType reflect.Type, enc ValueEncoder) {
- r.typeEncoders[valueType] = enc
+ r.typeEncoders.Store(valueType, enc)
}
// RegisterTypeDecoder registers the provided ValueDecoder for the provided type.
@@ -310,7 +280,7 @@ func (r *Registry) RegisterTypeEncoder(valueType reflect.Type, enc ValueEncoder)
//
// RegisterTypeDecoder should not be called concurrently with any other Registry method.
func (r *Registry) RegisterTypeDecoder(valueType reflect.Type, dec ValueDecoder) {
- r.typeDecoders[valueType] = dec
+ r.typeDecoders.Store(valueType, dec)
}
// RegisterKindEncoder registers the provided ValueEncoder for the provided kind.
@@ -326,7 +296,7 @@ func (r *Registry) RegisterTypeDecoder(valueType reflect.Type, dec ValueDecoder)
//
// RegisterKindEncoder should not be called concurrently with any other Registry method.
func (r *Registry) RegisterKindEncoder(kind reflect.Kind, enc ValueEncoder) {
- r.kindEncoders[kind] = enc
+ r.kindEncoders.Store(kind, enc)
}
// RegisterKindDecoder registers the provided ValueDecoder for the provided kind.
@@ -342,7 +312,7 @@ func (r *Registry) RegisterKindEncoder(kind reflect.Kind, enc ValueEncoder) {
//
// RegisterKindDecoder should not be called concurrently with any other Registry method.
func (r *Registry) RegisterKindDecoder(kind reflect.Kind, dec ValueDecoder) {
- r.kindDecoders[kind] = dec
+ r.kindDecoders.Store(kind, dec)
}
// RegisterInterfaceEncoder registers an encoder for the provided interface type iface. This encoder will
@@ -401,7 +371,7 @@ func (r *Registry) RegisterInterfaceDecoder(iface reflect.Type, dec ValueDecoder
//
// reg.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.Raw{}))
func (r *Registry) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Type) {
- r.typeMap[bt] = rt
+ r.typeMap.Store(bt, rt)
}
// LookupEncoder returns the first matching encoder in the Registry. It uses the following lookup
@@ -418,9 +388,10 @@ func (r *Registry) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Type) {
// If no encoder is found, an error of type ErrNoEncoder is returned. LookupEncoder is safe for
// concurrent use by multiple goroutines after all codecs and encoders are registered.
func (r *Registry) LookupEncoder(valueType reflect.Type) (ValueEncoder, error) {
- r.mu.RLock()
+ if valueType == nil {
+ return nil, ErrNoEncoder{Type: valueType}
+ }
enc, found := r.lookupTypeEncoder(valueType)
- r.mu.RUnlock()
if found {
if enc == nil {
return nil, ErrNoEncoder{Type: valueType}
@@ -430,36 +401,21 @@ func (r *Registry) LookupEncoder(valueType reflect.Type) (ValueEncoder, error) {
enc, found = r.lookupInterfaceEncoder(valueType, true)
if found {
- r.mu.Lock()
- r.typeEncoders[valueType] = enc
- r.mu.Unlock()
- return enc, nil
+ return r.typeEncoders.LoadOrStore(valueType, enc), nil
}
- if valueType == nil {
- r.mu.Lock()
- r.typeEncoders[valueType] = nil
- r.mu.Unlock()
- return nil, ErrNoEncoder{Type: valueType}
- }
-
- enc, found = r.kindEncoders[valueType.Kind()]
- if !found {
- r.mu.Lock()
- r.typeEncoders[valueType] = nil
- r.mu.Unlock()
- return nil, ErrNoEncoder{Type: valueType}
+ if v, ok := r.kindEncoders.Load(valueType.Kind()); ok {
+ return r.storeTypeEncoder(valueType, v), nil
}
+ return nil, ErrNoEncoder{Type: valueType}
+}
- r.mu.Lock()
- r.typeEncoders[valueType] = enc
- r.mu.Unlock()
- return enc, nil
+func (r *Registry) storeTypeEncoder(rt reflect.Type, enc ValueEncoder) ValueEncoder {
+ return r.typeEncoders.LoadOrStore(rt, enc)
}
-func (r *Registry) lookupTypeEncoder(valueType reflect.Type) (ValueEncoder, bool) {
- enc, found := r.typeEncoders[valueType]
- return enc, found
+func (r *Registry) lookupTypeEncoder(rt reflect.Type) (ValueEncoder, bool) {
+ return r.typeEncoders.Load(rt)
}
func (r *Registry) lookupInterfaceEncoder(valueType reflect.Type, allowAddr bool) (ValueEncoder, bool) {
@@ -475,7 +431,7 @@ func (r *Registry) lookupInterfaceEncoder(valueType reflect.Type, allowAddr bool
// ahead in interfaceEncoders
defaultEnc, found := r.lookupInterfaceEncoder(valueType, false)
if !found {
- defaultEnc = r.kindEncoders[valueType.Kind()]
+ defaultEnc, _ = r.kindEncoders.Load(valueType.Kind())
}
return newCondAddrEncoder(ienc.ve, defaultEnc), true
}
@@ -500,10 +456,7 @@ func (r *Registry) LookupDecoder(valueType reflect.Type) (ValueDecoder, error) {
if valueType == nil {
return nil, ErrNilType
}
- decodererr := ErrNoDecoder{Type: valueType}
- r.mu.RLock()
dec, found := r.lookupTypeDecoder(valueType)
- r.mu.RUnlock()
if found {
if dec == nil {
return nil, ErrNoDecoder{Type: valueType}
@@ -513,29 +466,21 @@ func (r *Registry) LookupDecoder(valueType reflect.Type) (ValueDecoder, error) {
dec, found = r.lookupInterfaceDecoder(valueType, true)
if found {
- r.mu.Lock()
- r.typeDecoders[valueType] = dec
- r.mu.Unlock()
- return dec, nil
+ return r.storeTypeDecoder(valueType, dec), nil
}
- dec, found = r.kindDecoders[valueType.Kind()]
- if !found {
- r.mu.Lock()
- r.typeDecoders[valueType] = nil
- r.mu.Unlock()
- return nil, decodererr
+ if v, ok := r.kindDecoders.Load(valueType.Kind()); ok {
+ return r.storeTypeDecoder(valueType, v), nil
}
-
- r.mu.Lock()
- r.typeDecoders[valueType] = dec
- r.mu.Unlock()
- return dec, nil
+ return nil, ErrNoDecoder{Type: valueType}
}
func (r *Registry) lookupTypeDecoder(valueType reflect.Type) (ValueDecoder, bool) {
- dec, found := r.typeDecoders[valueType]
- return dec, found
+ return r.typeDecoders.Load(valueType)
+}
+
+func (r *Registry) storeTypeDecoder(typ reflect.Type, dec ValueDecoder) ValueDecoder {
+ return r.typeDecoders.LoadOrStore(typ, dec)
}
func (r *Registry) lookupInterfaceDecoder(valueType reflect.Type, allowAddr bool) (ValueDecoder, bool) {
@@ -548,7 +493,7 @@ func (r *Registry) lookupInterfaceDecoder(valueType reflect.Type, allowAddr bool
// ahead in interfaceDecoders
defaultDec, found := r.lookupInterfaceDecoder(valueType, false)
if !found {
- defaultDec = r.kindDecoders[valueType.Kind()]
+ defaultDec, _ = r.kindDecoders.Load(valueType.Kind())
}
return newCondAddrDecoder(idec.vd, defaultDec), true
}
@@ -561,11 +506,11 @@ func (r *Registry) lookupInterfaceDecoder(valueType reflect.Type, allowAddr bool
//
// LookupTypeMapEntry should not be called concurrently with any other Registry method.
func (r *Registry) LookupTypeMapEntry(bt bsontype.Type) (reflect.Type, error) {
- t, ok := r.typeMap[bt]
- if !ok || t == nil {
+ v, ok := r.typeMap.Load(bt)
+ if v == nil || !ok {
return nil, ErrNoTypeMapEntry{Type: bt}
}
- return t, nil
+ return v.(reflect.Type), nil
}
type interfaceValueEncoder struct {
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go
index 20c3e7549c..14c9fd2564 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go
@@ -7,6 +7,7 @@
package bsoncodec
import (
+ "errors"
"fmt"
"reflect"
@@ -20,8 +21,22 @@ var defaultSliceCodec = NewSliceCodec()
// SliceCodec is the Codec used for slice values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// SliceCodec registered.
+// Deprecated: SliceCodec will not be directly configurable in Go Driver 2.0. To
+// configure the slice encode and decode behavior, use the configuration methods
+// on a [go.mongodb.org/mongo-driver/bson.Encoder] or
+// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the slice encode and
+// decode behavior for a mongo.Client, use
+// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
+//
+// For example, to configure a mongo.Client to marshal nil Go slices as empty
+// BSON arrays, use:
+//
+// opt := options.Client().SetBSONOptions(&options.BSONOptions{
+// NilSliceAsEmpty: true,
+// })
+//
+// See the deprecation notice for each field in SliceCodec for the corresponding
+// settings.
type SliceCodec struct {
// EncodeNilAsEmpty causes EncodeValue to marshal nil Go slices as empty BSON arrays instead of
// BSON null.
@@ -32,8 +47,8 @@ type SliceCodec struct {
// NewSliceCodec returns a MapCodec with options opts.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// SliceCodec registered.
+// Deprecated: NewSliceCodec will not be available in Go Driver 2.0. See
+// [SliceCodec] for more details.
func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec {
sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...)
@@ -62,7 +77,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re
}
// If we have a []primitive.E we want to treat it as a document instead of as an array.
- if val.Type().ConvertibleTo(tD) {
+ if val.Type() == tD || val.Type().ConvertibleTo(tD) {
d := val.Convert(tD).Interface().(primitive.D)
dw, err := vw.WriteDocument()
@@ -93,7 +108,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re
for idx := 0; idx < val.Len(); idx++ {
currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx))
- if lookupErr != nil && lookupErr != errInvalidValue {
+ if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) {
return lookupErr
}
@@ -102,7 +117,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re
return err
}
- if lookupErr == errInvalidValue {
+ if errors.Is(lookupErr, errInvalidValue) {
err = vw.WriteNull()
if err != nil {
return err
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go
index ff931b7253..a8f885a854 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go
@@ -17,8 +17,16 @@ import (
// StringCodec is the Codec used for string values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// StringCodec registered.
+// Deprecated: StringCodec will not be directly accessible in Go Driver 2.0. To
+// override the default string encode and decode behavior, create a new registry
+// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new
+// encoder and decoder for strings.
+//
+// For example,
+//
+// reg := bson.NewRegistry()
+// reg.RegisterKindEncoder(reflect.String, myStringEncoder)
+// reg.RegisterKindDecoder(reflect.String, myStringDecoder)
type StringCodec struct {
// DecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation.
// If false, a string made from the raw object ID bytes will be used. Defaults to true.
@@ -38,8 +46,8 @@ var (
// NewStringCodec returns a StringCodec with options opts.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// StringCodec registered.
+// Deprecated: NewStringCodec will not be available in Go Driver 2.0. See
+// [StringCodec] for more details.
func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec {
stringOpt := bsonoptions.MergeStringCodecOptions(opts...)
return &StringCodec{*stringOpt.DecodeObjectIDAsHex}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go
index 1dfdd98865..f8d9690c13 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go
@@ -60,17 +60,30 @@ type Zeroer interface {
// StructCodec is the Codec used for struct values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// StructCodec registered.
+// Deprecated: StructCodec will not be directly configurable in Go Driver 2.0.
+// To configure the struct encode and decode behavior, use the configuration
+// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
+// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the struct encode
+// and decode behavior for a mongo.Client, use
+// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
+//
+// For example, to configure a mongo.Client to omit zero-value structs when
+// using the "omitempty" struct tag, use:
+//
+// opt := options.Client().SetBSONOptions(&options.BSONOptions{
+// OmitZeroStruct: true,
+// })
+//
+// See the deprecation notice for each field in StructCodec for the corresponding
+// settings.
type StructCodec struct {
- cache map[reflect.Type]*structDescription
- l sync.RWMutex
+ cache sync.Map // map[reflect.Type]*structDescription
parser StructTagParser
// DecodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the
// destination value passed to Decode before unmarshaling BSON documents into them.
//
- // Deprecated: Use bson.Decoder.ZeroStructs instead.
+ // Deprecated: Use bson.Decoder.ZeroStructs or options.BSONOptions.ZeroStructs instead.
DecodeZeroStruct bool
// DecodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the
@@ -83,7 +96,7 @@ type StructCodec struct {
// MyStruct{}) as empty and omit it from the marshaled BSON when the "omitempty" struct tag
// option is set.
//
- // Deprecated: Use bson.Encoder.OmitZeroStruct instead.
+ // Deprecated: Use bson.Encoder.OmitZeroStruct or options.BSONOptions.OmitZeroStruct instead.
EncodeOmitDefaultStruct bool
// AllowUnexportedFields allows encoding and decoding values from un-exported struct fields.
@@ -96,7 +109,8 @@ type StructCodec struct {
// a duplicate field in the marshaled BSON when the "inline" struct tag option is set. The
// default value is true.
//
- // Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates instead.
+ // Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates or
+ // options.BSONOptions.ErrorOnInlineDuplicates instead.
OverwriteDuplicatedInlinedFields bool
}
@@ -105,8 +119,8 @@ var _ ValueDecoder = &StructCodec{}
// NewStructCodec returns a StructCodec that uses p for struct tag parsing.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// StructCodec registered.
+// Deprecated: NewStructCodec will not be available in Go Driver 2.0. See
+// [StructCodec] for more details.
func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) {
if p == nil {
return nil, errors.New("a StructTagParser must be provided to NewStructCodec")
@@ -115,7 +129,6 @@ func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions)
structOpt := bsonoptions.MergeStructCodecOptions(opts...)
codec := &StructCodec{
- cache: make(map[reflect.Type]*structDescription),
parser: p,
}
@@ -166,11 +179,11 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val
desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(ec, desc.encoder, rv)
- if err != nil && err != errInvalidValue {
+ if err != nil && !errors.Is(err, errInvalidValue) {
return err
}
- if err == errInvalidValue {
+ if errors.Is(err, errInvalidValue) {
if desc.omitEmpty {
continue
}
@@ -191,18 +204,17 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val
encoder := desc.encoder
- var zero bool
- rvInterface := rv.Interface()
+ var empty bool
if cz, ok := encoder.(CodecZeroer); ok {
- zero = cz.IsTypeZero(rvInterface)
+ empty = cz.IsTypeZero(rv.Interface())
} else if rv.Kind() == reflect.Interface {
- // isZero will not treat an interface rv as an interface, so we need to check for the
- // zero interface separately.
- zero = rv.IsNil()
+ // isEmpty will not treat an interface rv as an interface, so we need to check for the
+ // nil interface separately.
+ empty = rv.IsNil()
} else {
- zero = isZero(rvInterface, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct)
+ empty = isEmpty(rv, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct)
}
- if desc.omitEmpty && zero {
+ if desc.omitEmpty && empty {
continue
}
@@ -242,8 +254,8 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val
}
func newDecodeError(key string, original error) error {
- de, ok := original.(*DecodeError)
- if !ok {
+ var de *DecodeError
+ if !errors.As(original, &de) {
return &DecodeError{
keys: []string{key},
wrapped: original,
@@ -311,7 +323,7 @@ func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val
for {
name, vr, err := dr.ReadElement()
- if err == bsonrw.ErrEOD {
+ if errors.Is(err, bsonrw.ErrEOD) {
break
}
if err != nil {
@@ -394,56 +406,35 @@ func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val
return nil
}
-func isZero(i interface{}, omitZeroStruct bool) bool {
- v := reflect.ValueOf(i)
-
- // check the value validity
- if !v.IsValid() {
- return true
- }
-
- if z, ok := v.Interface().(Zeroer); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
- return z.IsZero()
+func isEmpty(v reflect.Value, omitZeroStruct bool) bool {
+ kind := v.Kind()
+ if (kind != reflect.Ptr || !v.IsNil()) && v.Type().Implements(tZeroer) {
+ return v.Interface().(Zeroer).IsZero()
}
-
- switch v.Kind() {
+ switch kind {
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:
- return v.IsNil()
case reflect.Struct:
if !omitZeroStruct {
return false
}
-
- // TODO(GODRIVER-2820): Update the logic to be able to handle private struct fields.
- // TODO Use condition "reflect.Zero(v.Type()).Equal(v)" instead.
-
vt := v.Type()
if vt == tTime {
return v.Interface().(time.Time).IsZero()
}
- for i := 0; i < v.NumField(); i++ {
- if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous {
+ numField := vt.NumField()
+ for i := 0; i < numField; i++ {
+ ff := vt.Field(i)
+ if ff.PkgPath != "" && !ff.Anonymous {
continue // Private field
}
- fld := v.Field(i)
- if !isZero(fld.Interface(), omitZeroStruct) {
+ if !isEmpty(v.Field(i), omitZeroStruct) {
return false
}
}
return true
}
-
- return false
+ return !v.IsValid() || v.IsZero()
}
type structDescription struct {
@@ -502,13 +493,27 @@ func (sc *StructCodec) describeStruct(
) (*structDescription, error) {
// We need to analyze the struct, including getting the tags, collecting
// information about inlining, and create a map of the field name to the field.
- sc.l.RLock()
- ds, exists := sc.cache[t]
- sc.l.RUnlock()
- if exists {
- return ds, nil
+ if v, ok := sc.cache.Load(t); ok {
+ return v.(*structDescription), nil
+ }
+ // TODO(charlie): Only describe the struct once when called
+ // concurrently with the same type.
+ ds, err := sc.describeStructSlow(r, t, useJSONStructTags, errorOnDuplicates)
+ if err != nil {
+ return nil, err
}
+ if v, loaded := sc.cache.LoadOrStore(t, ds); loaded {
+ ds = v.(*structDescription)
+ }
+ return ds, nil
+}
+func (sc *StructCodec) describeStructSlow(
+ r *Registry,
+ t reflect.Type,
+ useJSONStructTags bool,
+ errorOnDuplicates bool,
+) (*structDescription, error) {
numFields := t.NumField()
sd := &structDescription{
fm: make(map[string]fieldDescription, numFields),
@@ -639,10 +644,6 @@ func (sc *StructCodec) describeStruct(
sort.Sort(byIndex(sd.fl))
- sc.l.Lock()
- sc.cache[t] = sd
- sc.l.Unlock()
-
return sd, nil
}
@@ -700,21 +701,21 @@ func getInlineField(val reflect.Value, index []int) (reflect.Value, error) {
// DeepZero returns recursive zero object
func deepZero(st reflect.Type) (result reflect.Value) {
- result = reflect.Indirect(reflect.New(st))
-
- if result.Kind() == reflect.Struct {
- for i := 0; i < result.NumField(); i++ {
- if f := result.Field(i); f.Kind() == reflect.Ptr {
- if f.CanInterface() {
- if ft := reflect.TypeOf(f.Interface()); ft.Elem().Kind() == reflect.Struct {
- result.Field(i).Set(recursivePointerTo(deepZero(ft.Elem())))
- }
+ if st.Kind() == reflect.Struct {
+ numField := st.NumField()
+ for i := 0; i < numField; i++ {
+ if result == emptyValue {
+ result = reflect.Indirect(reflect.New(st))
+ }
+ f := result.Field(i)
+ if f.CanInterface() {
+ if f.Type().Kind() == reflect.Struct {
+ result.Field(i).Set(recursivePointerTo(deepZero(f.Type().Elem())))
}
}
}
}
-
- return
+ return result
}
// recursivePointerTo calls reflect.New(v.Type) but recursively for its fields inside
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go
index 7b005a9958..22fb762c41 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go
@@ -23,12 +23,26 @@ const (
// TimeCodec is the Codec used for time.Time values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// TimeCodec registered.
+// Deprecated: TimeCodec will not be directly configurable in Go Driver 2.0.
+// To configure the time.Time encode and decode behavior, use the configuration
+// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or
+// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the time.Time encode
+// and decode behavior for a mongo.Client, use
+// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
+//
+// For example, to configure a mongo.Client to ..., use:
+//
+// opt := options.Client().SetBSONOptions(&options.BSONOptions{
+// UseLocalTimeZone: true,
+// })
+//
+// See the deprecation notice for each field in TimeCodec for the corresponding
+// settings.
type TimeCodec struct {
// UseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false.
//
- // Deprecated: Use bson.Decoder.UseLocalTimeZone instead.
+ // Deprecated: Use bson.Decoder.UseLocalTimeZone or options.BSONOptions.UseLocalTimeZone
+ // instead.
UseLocalTimeZone bool
}
@@ -42,8 +56,8 @@ var (
// NewTimeCodec returns a TimeCodec with options opts.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// TimeCodec registered.
+// Deprecated: NewTimeCodec will not be available in Go Driver 2.0. See
+// [TimeCodec] for more details.
func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec {
timeOpt := bsonoptions.MergeTimeCodecOptions(opts...)
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
index 07f4b70e6d..6ade17b7d3 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
@@ -34,6 +34,7 @@ var tValueUnmarshaler = reflect.TypeOf((*ValueUnmarshaler)(nil)).Elem()
var tMarshaler = reflect.TypeOf((*Marshaler)(nil)).Elem()
var tUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
var tProxy = reflect.TypeOf((*Proxy)(nil)).Elem()
+var tZeroer = reflect.TypeOf((*Zeroer)(nil)).Elem()
var tBinary = reflect.TypeOf(primitive.Binary{})
var tUndefined = reflect.TypeOf(primitive.Undefined{})
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go
index 7eb1069050..8525472769 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go
@@ -18,13 +18,27 @@ import (
// UIntCodec is the Codec used for uint values.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// UIntCodec registered.
+// Deprecated: UIntCodec will not be directly configurable in Go Driver 2.0. To
+// configure the uint encode and decode behavior, use the configuration methods
+// on a [go.mongodb.org/mongo-driver/bson.Encoder] or
+// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the uint encode and
+// decode behavior for a mongo.Client, use
+// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions].
+//
+// For example, to configure a mongo.Client to marshal Go uint values as the
+// minimum BSON int size that can represent the value, use:
+//
+// opt := options.Client().SetBSONOptions(&options.BSONOptions{
+// IntMinSize: true,
+// })
+//
+// See the deprecation notice for each field in UIntCodec for the corresponding
+// settings.
type UIntCodec struct {
// EncodeToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the
// minimum BSON int size (either 32-bit or 64-bit) that can represent the integer value.
//
- // Deprecated: Use bson.Encoder.IntMinSize instead.
+ // Deprecated: Use bson.Encoder.IntMinSize or options.BSONOptions.IntMinSize instead.
EncodeToMinSize bool
}
@@ -38,8 +52,8 @@ var (
// NewUIntCodec returns a UIntCodec with options opts.
//
-// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
-// UIntCodec registered.
+// Deprecated: NewUIntCodec will not be available in Go Driver 2.0. See
+// [UIntCodec] for more details.
func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec {
uintOpt := bsonoptions.MergeUIntCodecOptions(opts...)
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go
index 33d59bd258..1e25570b85 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go
@@ -7,6 +7,7 @@
package bsonrw
import (
+ "errors"
"fmt"
"io"
@@ -124,7 +125,7 @@ func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error
}
func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error {
- // TODO(skriptble): Create errors types here. Anything thats a tag should be a property.
+ // TODO(skriptble): Create errors types here. Anything that is a tag should be a property.
length, rem, ok := bsoncore.ReadLength(src)
if !ok {
return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src))
@@ -193,7 +194,7 @@ func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error)
}
vw := vwPool.Get().(*valueWriter)
- defer vwPool.Put(vw)
+ defer putValueWriter(vw)
vw.reset(dst)
@@ -213,7 +214,7 @@ func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) {
}
vw := vwPool.Get().(*valueWriter)
- defer vwPool.Put(vw)
+ defer putValueWriter(vw)
vw.reset(dst)
@@ -258,7 +259,7 @@ func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []
}
vw := vwPool.Get().(*valueWriter)
- defer vwPool.Put(vw)
+ defer putValueWriter(vw)
start := len(dst)
@@ -442,7 +443,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
for {
vr, err := ar.ReadValue()
- if err == ErrEOA {
+ if errors.Is(err, ErrEOA) {
break
}
if err != nil {
@@ -466,7 +467,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error {
for {
key, vr, err := dr.ReadElement()
- if err == ErrEOD {
+ if errors.Is(err, ErrEOD) {
break
}
if err != nil {
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go
index 54c76bf746..bb52a0ec3d 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go
@@ -313,7 +313,7 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) {
// convert hex to bytes
bytes, err := hex.DecodeString(uuidNoHyphens)
if err != nil {
- return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %v", err)
+ return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %w", err)
}
ejp.advanceState()
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go
index 2aca37a91f..59ddfc4485 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go
@@ -7,6 +7,7 @@
package bsonrw
import (
+ "errors"
"fmt"
"io"
"sync"
@@ -613,7 +614,7 @@ func (ejvr *extJSONValueReader) ReadElement() (string, ValueReader, error) {
name, t, err := ejvr.p.readKey()
if err != nil {
- if err == ErrEOD {
+ if errors.Is(err, ErrEOD) {
if ejvr.stack[ejvr.frame].mode == mCodeWithScope {
_, err := ejvr.p.peekType()
if err != nil {
@@ -640,7 +641,7 @@ func (ejvr *extJSONValueReader) ReadValue() (ValueReader, error) {
t, err := ejvr.p.peekType()
if err != nil {
- if err == ErrEOA {
+ if errors.Is(err, ErrEOA) {
ejvr.pop()
}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go
index cd4843a3a4..43f3e4f383 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go
@@ -58,7 +58,7 @@ func (js *jsonScanner) nextToken() (*jsonToken, error) {
c, err = js.readNextByte()
}
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
return &jsonToken{t: jttEOF}, nil
} else if err != nil {
return nil, err
@@ -198,7 +198,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
for {
c, err = js.readNextByte()
if err != nil {
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
return nil, errors.New("end of input in JSON string")
}
return nil, err
@@ -209,7 +209,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
case '\\':
c, err = js.readNextByte()
if err != nil {
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
return nil, errors.New("end of input in JSON string")
}
return nil, err
@@ -248,7 +248,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
if utf16.IsSurrogate(rn) {
c, err = js.readNextByte()
if err != nil {
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
return nil, errors.New("end of input in JSON string")
}
return nil, err
@@ -264,7 +264,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
c, err = js.readNextByte()
if err != nil {
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
return nil, errors.New("end of input in JSON string")
}
return nil, err
@@ -325,17 +325,17 @@ func (js *jsonScanner) scanLiteral(first byte) (*jsonToken, error) {
c5, err := js.readNextByte()
- if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || err == io.EOF) {
+ if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) {
js.pos = int(math.Max(0, float64(js.pos-1)))
return &jsonToken{t: jttBool, v: true, p: p}, nil
- } else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || err == io.EOF) {
+ } else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) {
js.pos = int(math.Max(0, float64(js.pos-1)))
return &jsonToken{t: jttNull, v: nil, p: p}, nil
} else if bytes.Equal([]byte("fals"), lit) {
if c5 == 'e' {
c5, err = js.readNextByte()
- if isValueTerminator(c5) || err == io.EOF {
+ if isValueTerminator(c5) || errors.Is(err, io.EOF) {
js.pos = int(math.Max(0, float64(js.pos-1)))
return &jsonToken{t: jttBool, v: false, p: p}, nil
}
@@ -384,7 +384,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
for {
c, err = js.readNextByte()
- if err != nil && err != io.EOF {
+ if err != nil && !errors.Is(err, io.EOF) {
return nil, err
}
@@ -413,7 +413,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
case '}', ']', ',':
s = nssDone
default:
- if isWhiteSpace(c) || err == io.EOF {
+ if isWhiteSpace(c) || errors.Is(err, io.EOF) {
s = nssDone
} else {
s = nssInvalid
@@ -430,7 +430,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
case '}', ']', ',':
s = nssDone
default:
- if isWhiteSpace(c) || err == io.EOF {
+ if isWhiteSpace(c) || errors.Is(err, io.EOF) {
s = nssDone
} else if isDigit(c) {
s = nssSawIntegerDigits
@@ -455,7 +455,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
case '}', ']', ',':
s = nssDone
default:
- if isWhiteSpace(c) || err == io.EOF {
+ if isWhiteSpace(c) || errors.Is(err, io.EOF) {
s = nssDone
} else if isDigit(c) {
s = nssSawFractionDigits
@@ -490,7 +490,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) {
case '}', ']', ',':
s = nssDone
default:
- if isWhiteSpace(c) || err == io.EOF {
+ if isWhiteSpace(c) || errors.Is(err, io.EOF) {
s = nssDone
} else if isDigit(c) {
s = nssSawExponentDigits
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go
index 9bf24fae0b..a242bb57cf 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go
@@ -739,8 +739,7 @@ func (vr *valueReader) ReadValue() (ValueReader, error) {
return nil, ErrEOA
}
- _, err = vr.readCString()
- if err != nil {
+ if err := vr.skipCString(); err != nil {
return nil, err
}
@@ -794,6 +793,15 @@ func (vr *valueReader) readByte() (byte, error) {
return vr.d[vr.offset-1], nil
}
+func (vr *valueReader) skipCString() error {
+ idx := bytes.IndexByte(vr.d[vr.offset:], 0x00)
+ if idx < 0 {
+ return io.EOF
+ }
+ vr.offset += int64(idx) + 1
+ return nil
+}
+
func (vr *valueReader) readCString() (string, error) {
idx := bytes.IndexByte(vr.d[vr.offset:], 0x00)
if idx < 0 {
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go
index a6dd8d34f5..311518a80d 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go
@@ -28,6 +28,13 @@ var vwPool = sync.Pool{
},
}
+func putValueWriter(vw *valueWriter) {
+ if vw != nil {
+ vw.w = nil // don't leak the writer
+ vwPool.Put(vw)
+ }
+}
+
// BSONValueWriterPool is a pool for BSON ValueWriters.
//
// Deprecated: BSONValueWriterPool will not be supported in Go Driver 2.0.
@@ -149,32 +156,21 @@ type valueWriter struct {
}
func (vw *valueWriter) advanceFrame() {
- if vw.frame+1 >= int64(len(vw.stack)) { // We need to grow the stack
- length := len(vw.stack)
- if length+1 >= cap(vw.stack) {
- // double it
- buf := make([]vwState, 2*cap(vw.stack)+1)
- copy(buf, vw.stack)
- vw.stack = buf
- }
- vw.stack = vw.stack[:length+1]
- }
vw.frame++
+ if vw.frame >= int64(len(vw.stack)) {
+ vw.stack = append(vw.stack, vwState{})
+ }
}
func (vw *valueWriter) push(m mode) {
vw.advanceFrame()
// Clean the stack
- vw.stack[vw.frame].mode = m
- vw.stack[vw.frame].key = ""
- vw.stack[vw.frame].arrkey = 0
- vw.stack[vw.frame].start = 0
+ vw.stack[vw.frame] = vwState{mode: m}
- vw.stack[vw.frame].mode = m
switch m {
case mDocument, mArray, mCodeWithScope:
- vw.reserveLength()
+ vw.reserveLength() // WARN: this is not needed
}
}
@@ -213,6 +209,7 @@ func newValueWriter(w io.Writer) *valueWriter {
return vw
}
+// TODO: only used in tests
func newValueWriterFromSlice(buf []byte) *valueWriter {
vw := new(valueWriter)
stack := make([]vwState, 1, 5)
@@ -249,17 +246,16 @@ func (vw *valueWriter) invalidTransitionError(destination mode, name string, mod
}
func (vw *valueWriter) writeElementHeader(t bsontype.Type, destination mode, callerName string, addmodes ...mode) error {
- switch vw.stack[vw.frame].mode {
+ frame := &vw.stack[vw.frame]
+ switch frame.mode {
case mElement:
- key := vw.stack[vw.frame].key
+ key := frame.key
if !isValidCString(key) {
return errors.New("BSON element key cannot contain null bytes")
}
-
- vw.buf = bsoncore.AppendHeader(vw.buf, t, key)
+ vw.appendHeader(t, key)
case mValue:
- // TODO: Do this with a cache of the first 1000 or so array keys.
- vw.buf = bsoncore.AppendHeader(vw.buf, t, strconv.Itoa(vw.stack[vw.frame].arrkey))
+ vw.appendIntHeader(t, frame.arrkey)
default:
modes := []mode{mElement, mValue}
if addmodes != nil {
@@ -601,9 +597,11 @@ func (vw *valueWriter) writeLength() error {
if length > maxSize {
return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))}
}
- length = length - int(vw.stack[vw.frame].start)
- start := vw.stack[vw.frame].start
+ frame := &vw.stack[vw.frame]
+ length = length - int(frame.start)
+ start := frame.start
+ _ = vw.buf[start+3] // BCE
vw.buf[start+0] = byte(length)
vw.buf[start+1] = byte(length >> 8)
vw.buf[start+2] = byte(length >> 16)
@@ -612,5 +610,31 @@ func (vw *valueWriter) writeLength() error {
}
func isValidCString(cs string) bool {
- return !strings.ContainsRune(cs, '\x00')
+ // Disallow the zero byte in a cstring because the zero byte is used as the
+ // terminating character.
+ //
+ // It's safe to check bytes instead of runes because all multibyte UTF-8
+ // code points start with (binary) 11xxxxxx or 10xxxxxx, so 00000000 (i.e.
+ // 0) will never be part of a multibyte UTF-8 code point. This logic is the
+ // same as the "r < utf8.RuneSelf" case in strings.IndexRune but can be
+ // inlined.
+ //
+ // https://cs.opensource.google/go/go/+/refs/tags/go1.21.1:src/strings/strings.go;l=127
+ return strings.IndexByte(cs, 0) == -1
+}
+
+// appendHeader is the same as bsoncore.AppendHeader but does not check if the
+// key is a valid C string since the caller has already checked for that.
+//
+// The caller of this function must check if key is a valid C string.
+func (vw *valueWriter) appendHeader(t bsontype.Type, key string) {
+ vw.buf = bsoncore.AppendType(vw.buf, t)
+ vw.buf = append(vw.buf, key...)
+ vw.buf = append(vw.buf, 0x00)
+}
+
+func (vw *valueWriter) appendIntHeader(t bsontype.Type, key int) {
+ vw.buf = bsoncore.AppendType(vw.buf, t)
+ vw.buf = strconv.AppendInt(vw.buf, int64(key), 10)
+ vw.buf = append(vw.buf, 0x00)
}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go b/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go
index 8cff5492d1..255d9909e3 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go
@@ -47,6 +47,7 @@ const (
BinaryMD5 byte = 0x05
BinaryEncrypted byte = 0x06
BinaryColumn byte = 0x07
+ BinarySensitive byte = 0x08
BinaryUserDefined byte = 0x80
)
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/doc.go
index 048b5eb998..af6098475e 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/doc.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/doc.go
@@ -6,9 +6,9 @@
// Package bson is a library for reading, writing, and manipulating BSON. BSON is a binary serialization format used to
// store documents and make remote procedure calls in MongoDB. The BSON specification is located at https://bsonspec.org.
-// The BSON library handles marshalling and unmarshalling of values through a configurable codec system. For a description
-// of the codec system and examples of registering custom codecs, see the bsoncodec package. For additional information and
-// usage examples, check out the [Work with BSON] page in the Go Driver docs site.
+// The BSON library handles marshaling and unmarshaling of values through a configurable codec system. For a description
+// of the codec system and examples of registering custom codecs, see the bsoncodec package. For additional information
+// and usage examples, check out the [Work with BSON] page in the Go Driver docs site.
//
// # Raw BSON
//
@@ -38,7 +38,7 @@
// bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}}
// bson.M{"foo": "bar", "hello": "world", "pi": 3.14159}
//
-// When decoding BSON to a D or M, the following type mappings apply when unmarshalling:
+// When decoding BSON to a D or M, the following type mappings apply when unmarshaling:
//
// 1. BSON int32 unmarshals to an int32.
// 2. BSON int64 unmarshals to an int64.
@@ -62,83 +62,78 @@
// 20. BSON DBPointer unmarshals to a primitive.DBPointer.
// 21. BSON symbol unmarshals to a primitive.Symbol.
//
-// The above mappings also apply when marshalling a D or M to BSON. Some other useful marshalling mappings are:
+// The above mappings also apply when marshaling a D or M to BSON. Some other useful marshaling mappings are:
//
// 1. time.Time marshals to a BSON datetime.
// 2. int8, int16, and int32 marshal to a BSON int32.
// 3. int marshals to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, inclusive, and a BSON int64
// otherwise.
-// 4. int64 marshals to BSON int64.
+// 4. int64 marshals to BSON int64 (unless [Encoder.IntMinSize] is set).
// 5. uint8 and uint16 marshal to a BSON int32.
-// 6. uint, uint32, and uint64 marshal to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32,
-// inclusive, and BSON int64 otherwise.
-// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshalling a BSON null or
+// 6. uint, uint32, and uint64 marshal to a BSON int64 (unless [Encoder.IntMinSize] is set).
+// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshaling a BSON null or
// undefined value into a string will yield the empty string.).
//
// # Structs
//
-// Structs can be marshalled/unmarshalled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended
+// Structs can be marshaled/unmarshaled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended
// JSON, the following rules apply:
//
-// 1. Only exported fields in structs will be marshalled or unmarshalled.
+// 1. Only exported fields in structs will be marshaled or unmarshaled.
//
-// 2. When marshalling a struct, each field will be lowercased to generate the key for the corresponding BSON element.
+// 2. When marshaling a struct, each field will be lowercased to generate the key for the corresponding BSON element.
// For example, a struct field named "Foo" will generate key "foo". This can be overridden via a struct tag (e.g.
// `bson:"fooField"` to generate key "fooField" instead).
//
-// 3. An embedded struct field is marshalled as a subdocument. The key will be the lowercased name of the field's type.
+// 3. An embedded struct field is marshaled as a subdocument. The key will be the lowercased name of the field's type.
//
-// 4. A pointer field is marshalled as the underlying type if the pointer is non-nil. If the pointer is nil, it is
-// marshalled as a BSON null value.
+// 4. A pointer field is marshaled as the underlying type if the pointer is non-nil. If the pointer is nil, it is
+// marshaled as a BSON null value.
//
-// 5. When unmarshalling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents
-// unmarshalled into an interface{} field will be unmarshalled as a D.
+// 5. When unmarshaling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents
+// unmarshaled into an interface{} field will be unmarshaled as a D.
//
// The encoding of each struct field can be customized by the "bson" struct tag.
//
// This tag behavior is configurable, and different struct tag behavior can be configured by initializing a new
-// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON tags
-// are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below:
+// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON
+// tags are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below:
//
// Example:
//
// structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser)
//
// The bson tag gives the name of the field, possibly followed by a comma-separated list of options.
-// The name may be empty in order to specify options without overriding the default field name. The following options can be used
-// to configure behavior:
-//
-// 1. omitempty: If the omitempty struct tag is specified on a field, the field will not be marshalled if it is set to
-// the zero value. Fields with language primitive types such as integers, booleans, and strings are considered empty if
-// their value is equal to the zero value for the type (i.e. 0 for integers, false for booleans, and "" for strings).
-// Slices, maps, and arrays are considered empty if they are of length zero. Interfaces and pointers are considered
-// empty if their value is nil. By default, structs are only considered empty if the struct type implements the
-// bsoncodec.Zeroer interface and the IsZero method returns true. Struct fields whose types do not implement Zeroer are
-// never considered empty and will be marshalled as embedded documents.
+// The name may be empty in order to specify options without overriding the default field name. The following options can
+// be used to configure behavior:
+//
+// 1. omitempty: If the omitempty struct tag is specified on a field, the field will be omitted from the marshaling if
+// the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array,
+// slice, map, or string.
// NOTE: It is recommended that this tag be used for all slice and map fields.
//
// 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of
-// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For other
-// types, this tag is ignored.
+// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For
+// other types, this tag is ignored.
//
-// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles unmarshalled
-// into that field will be truncated at the decimal point. For example, if 3.14 is unmarshalled into a field of type int,
-// it will be unmarshalled as 3. If this tag is not specified, the decoder will throw an error if the value cannot be
-// decoded without losing precision. For float64 or non-numeric types, this tag is ignored.
+// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles
+// unmarshaled into that field will be truncated at the decimal point. For example, if 3.14 is unmarshaled into a
+// field of type int, it will be unmarshaled as 3. If this tag is not specified, the decoder will throw an error if
+// the value cannot be decoded without losing precision. For float64 or non-numeric types, this tag is ignored.
//
// 4. inline: If the inline struct tag is specified for a struct or map field, the field will be "flattened" when
-// marshalling and "un-flattened" when unmarshalling. This means that all of the fields in that struct/map will be
-// pulled up one level and will become top-level fields rather than being fields in a nested document. For example, if a
-// map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will be
-// {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If there are
-// duplicated fields in the resulting document when an inlined struct is marshalled, the inlined field will be overwritten.
-// If there are duplicated fields in the resulting document when an inlined map is marshalled, an error will be returned.
-// This tag can be used with fields that are pointers to structs. If an inlined pointer field is nil, it will not be
-// marshalled. For fields that are not maps or structs, this tag is ignored.
-//
-// # Marshalling and Unmarshalling
-//
-// Manually marshalling and unmarshalling can be done with the Marshal and Unmarshal family of functions.
+// marshaling and "un-flattened" when unmarshaling. This means that all of the fields in that struct/map will be
+// pulled up one level and will become top-level fields rather than being fields in a nested document. For example,
+// if a map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will
+// be {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If
+// there are duplicated fields in the resulting document when an inlined struct is marshaled, the inlined field will
+// be overwritten. If there are duplicated fields in the resulting document when an inlined map is marshaled, an
+// error will be returned. This tag can be used with fields that are pointers to structs. If an inlined pointer field
+// is nil, it will not be marshaled. For fields that are not maps or structs, this tag is ignored.
+//
+// # Marshaling and Unmarshaling
+//
+// Manually marshaling and unmarshaling can be done with the Marshal and Unmarshal family of functions.
//
// [Work with BSON]: https://www.mongodb.com/docs/drivers/go/current/fundamentals/bson/
package bson
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/marshal.go b/vendor/go.mongodb.org/mongo-driver/bson/marshal.go
index f2c48d049e..17ce6697e0 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/marshal.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/marshal.go
@@ -9,6 +9,7 @@ package bson
import (
"bytes"
"encoding/json"
+ "sync"
"go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsonrw"
@@ -141,6 +142,13 @@ func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{
return MarshalAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)
}
+// Pool of buffers for marshalling BSON.
+var bufPool = sync.Pool{
+ New: func() interface{} {
+ return new(bytes.Buffer)
+ },
+}
+
// MarshalAppendWithContext will encode val as a BSON document using Registry r and EncodeContext ec and append the
// bytes to dst. If dst is not large enough to hold the bytes, it will be grown. If val is not a type that can be
// transformed into a document, MarshalValueAppendWithContext should be used instead.
@@ -162,8 +170,26 @@ func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{
//
// See [Encoder] for more examples.
func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) ([]byte, error) {
- sw := new(bsonrw.SliceWriter)
- *sw = dst
+ sw := bufPool.Get().(*bytes.Buffer)
+ defer func() {
+ // Proper usage of a sync.Pool requires each entry to have approximately
+ // the same memory cost. To obtain this property when the stored type
+ // contains a variably-sized buffer, we add a hard limit on the maximum
+ // buffer to place back in the pool. We limit the size to 16MiB because
+ // that's the maximum wire message size supported by any current MongoDB
+ // server.
+ //
+ // Comment based on
+ // https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/fmt/print.go;l=147
+ //
+ // Recycle byte slices that are smaller than 16MiB and at least half
+ // occupied.
+ if sw.Cap() < 16*1024*1024 && sw.Cap()/2 < sw.Len() {
+ bufPool.Put(sw)
+ }
+ }()
+
+ sw.Reset()
vw := bvwPool.Get(sw)
defer bvwPool.Put(vw)
@@ -184,7 +210,7 @@ func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interf
return nil, err
}
- return *sw, nil
+ return append(dst, sw.Bytes()...), nil
}
// MarshalValue returns the BSON encoding of val.
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go
index 24ab58fc49..08c39514be 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go
@@ -164,9 +164,6 @@ func (d Decimal128) BigInt() (*big.Int, int, error) {
// Would be handled by the logic below, but that's trivial and common.
if high == 0 && low == 0 && exp == 0 {
- if posSign {
- return new(big.Int), 0, nil
- }
return new(big.Int), 0, nil
}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go
index 9bbaffac26..c130e3ff19 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go
@@ -183,7 +183,7 @@ func processUniqueBytes() [5]byte {
var b [5]byte
_, err := io.ReadFull(rand.Reader, b[:])
if err != nil {
- panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
+ panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err))
}
return b
@@ -193,7 +193,7 @@ func readRandomUint32() uint32 {
var b [4]byte
_, err := io.ReadFull(rand.Reader, b[:])
if err != nil {
- panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
+ panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err))
}
return (uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24)
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw.go b/vendor/go.mongodb.org/mongo-driver/bson/raw.go
index fe990a1771..130da61ba0 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/raw.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/raw.go
@@ -60,12 +60,19 @@ func (r Raw) LookupErr(key ...string) (RawValue, error) {
// elements. If the document is not valid, the elements up to the invalid point will be returned
// along with an error.
func (r Raw) Elements() ([]RawElement, error) {
- elems, err := bsoncore.Document(r).Elements()
+ doc := bsoncore.Document(r)
+ if len(doc) == 0 {
+ return nil, nil
+ }
+ elems, err := doc.Elements()
+ if err != nil {
+ return nil, err
+ }
relems := make([]RawElement, 0, len(elems))
for _, elem := range elems {
relems = append(relems, RawElement(elem))
}
- return relems, err
+ return relems, nil
}
// Values returns this document as a slice of values. The returned slice will contain valid values.
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/types.go b/vendor/go.mongodb.org/mongo-driver/bson/types.go
index e201ac37eb..ef39812467 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/types.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/types.go
@@ -45,5 +45,6 @@ const (
TypeBinaryMD5 = bsontype.BinaryMD5
TypeBinaryEncrypted = bsontype.BinaryEncrypted
TypeBinaryColumn = bsontype.BinaryColumn
+ TypeBinarySensitive = bsontype.BinarySensitive
TypeBinaryUserDefined = bsontype.BinaryUserDefined
)
diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go
index e52674aacf..88133293ea 100644
--- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go
+++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go
@@ -235,7 +235,7 @@ func BuildDocumentValue(elems ...[]byte) Value {
return Value{Type: bsontype.EmbeddedDocument, Data: BuildDocument(nil, elems...)}
}
-// BuildDocumentElement will append a BSON embedded document elemnt using key and the provided
+// BuildDocumentElement will append a BSON embedded document element using key and the provided
// elements and return the extended buffer.
func BuildDocumentElement(dst []byte, key string, elems ...[]byte) []byte {
return BuildDocument(AppendHeader(dst, bsontype.EmbeddedDocument, key), elems...)
diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/doc.go b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/doc.go
new file mode 100644
index 0000000000..c0b1723f8f
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/doc.go
@@ -0,0 +1,20 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package semconv implements OpenTelemetry semantic conventions.
+//
+// OpenTelemetry semantic conventions are agreed standardized naming
+// patterns for OpenTelemetry things. This package represents the conventions
+// as of the v1.4.0 version of the OpenTelemetry specification.
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0"
diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/exception.go b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/exception.go
new file mode 100644
index 0000000000..311cbf218f
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/exception.go
@@ -0,0 +1,20 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0"
+
+const (
+ // ExceptionEventName is the name of the Span event representing an exception.
+ ExceptionEventName = "exception"
+)
diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/http.go b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/http.go
new file mode 100644
index 0000000000..8d814edc26
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/http.go
@@ -0,0 +1,114 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0"
+
+import (
+ "net/http"
+
+ "go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/codes"
+ "go.opentelemetry.io/otel/semconv/internal"
+ "go.opentelemetry.io/otel/trace"
+)
+
+// HTTP scheme attributes.
+var (
+ HTTPSchemeHTTP = HTTPSchemeKey.String("http")
+ HTTPSchemeHTTPS = HTTPSchemeKey.String("https")
+)
+
+var sc = &internal.SemanticConventions{
+ EnduserIDKey: EnduserIDKey,
+ HTTPClientIPKey: HTTPClientIPKey,
+ HTTPFlavorKey: HTTPFlavorKey,
+ HTTPHostKey: HTTPHostKey,
+ HTTPMethodKey: HTTPMethodKey,
+ HTTPRequestContentLengthKey: HTTPRequestContentLengthKey,
+ HTTPRouteKey: HTTPRouteKey,
+ HTTPSchemeHTTP: HTTPSchemeHTTP,
+ HTTPSchemeHTTPS: HTTPSchemeHTTPS,
+ HTTPServerNameKey: HTTPServerNameKey,
+ HTTPStatusCodeKey: HTTPStatusCodeKey,
+ HTTPTargetKey: HTTPTargetKey,
+ HTTPURLKey: HTTPURLKey,
+ HTTPUserAgentKey: HTTPUserAgentKey,
+ NetHostIPKey: NetHostIPKey,
+ NetHostNameKey: NetHostNameKey,
+ NetHostPortKey: NetHostPortKey,
+ NetPeerIPKey: NetPeerIPKey,
+ NetPeerNameKey: NetPeerNameKey,
+ NetPeerPortKey: NetPeerPortKey,
+ NetTransportIP: NetTransportIP,
+ NetTransportOther: NetTransportOther,
+ NetTransportTCP: NetTransportTCP,
+ NetTransportUDP: NetTransportUDP,
+ NetTransportUnix: NetTransportUnix,
+}
+
+// NetAttributesFromHTTPRequest generates attributes of the net
+// namespace as specified by the OpenTelemetry specification for a
+// span. The network parameter is a string that net.Dial function
+// from standard library can understand.
+func NetAttributesFromHTTPRequest(network string, request *http.Request) []attribute.KeyValue {
+ return sc.NetAttributesFromHTTPRequest(network, request)
+}
+
+// EndUserAttributesFromHTTPRequest generates attributes of the
+// enduser namespace as specified by the OpenTelemetry specification
+// for a span.
+func EndUserAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue {
+ return sc.EndUserAttributesFromHTTPRequest(request)
+}
+
+// HTTPClientAttributesFromHTTPRequest generates attributes of the
+// http namespace as specified by the OpenTelemetry specification for
+// a span on the client side.
+func HTTPClientAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue {
+ return sc.HTTPClientAttributesFromHTTPRequest(request)
+}
+
+// HTTPServerMetricAttributesFromHTTPRequest generates low-cardinality attributes
+// to be used with server-side HTTP metrics.
+func HTTPServerMetricAttributesFromHTTPRequest(serverName string, request *http.Request) []attribute.KeyValue {
+ return sc.HTTPServerMetricAttributesFromHTTPRequest(serverName, request)
+}
+
+// HTTPServerAttributesFromHTTPRequest generates attributes of the
+// http namespace as specified by the OpenTelemetry specification for
+// a span on the server side. Currently, only basic authentication is
+// supported.
+func HTTPServerAttributesFromHTTPRequest(serverName, route string, request *http.Request) []attribute.KeyValue {
+ return sc.HTTPServerAttributesFromHTTPRequest(serverName, route, request)
+}
+
+// HTTPAttributesFromHTTPStatusCode generates attributes of the http
+// namespace as specified by the OpenTelemetry specification for a
+// span.
+func HTTPAttributesFromHTTPStatusCode(code int) []attribute.KeyValue {
+ return sc.HTTPAttributesFromHTTPStatusCode(code)
+}
+
+// SpanStatusFromHTTPStatusCode generates a status code and a message
+// as specified by the OpenTelemetry specification for a span.
+func SpanStatusFromHTTPStatusCode(code int) (codes.Code, string) {
+ return internal.SpanStatusFromHTTPStatusCode(code)
+}
+
+// SpanStatusFromHTTPStatusCodeAndSpanKind generates a status code and a message
+// as specified by the OpenTelemetry specification for a span.
+// Exclude 4xx for SERVER to set the appropriate status.
+func SpanStatusFromHTTPStatusCodeAndSpanKind(code int, spanKind trace.SpanKind) (codes.Code, string) {
+ return internal.SpanStatusFromHTTPStatusCodeAndSpanKind(code, spanKind)
+}
diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/resource.go b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/resource.go
new file mode 100644
index 0000000000..404bd4e751
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/resource.go
@@ -0,0 +1,906 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated from semantic convention specification. DO NOT EDIT.
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0"
+
+import "go.opentelemetry.io/otel/attribute"
+
+// A cloud environment (e.g. GCP, Azure, AWS)
+const (
+ // Name of the cloud provider.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ // Examples: 'gcp'
+ CloudProviderKey = attribute.Key("cloud.provider")
+ // The cloud account ID the resource is assigned to.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '111111111111', 'opentelemetry'
+ CloudAccountIDKey = attribute.Key("cloud.account.id")
+ // The geographical region the resource is running. Refer to your provider's docs
+ // to see the available regions, for example [AWS
+ // regions](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/),
+ // [Azure regions](https://azure.microsoft.com/en-us/global-
+ // infrastructure/geographies/), or [Google Cloud
+ // regions](https://cloud.google.com/about/locations).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'us-central1', 'us-east-1'
+ CloudRegionKey = attribute.Key("cloud.region")
+ // Cloud regions often have multiple, isolated locations known as zones to
+ // increase availability. Availability zone represents the zone where the resource
+ // is running.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'us-east-1c'
+ // Note: Availability zones are called "zones" on Google Cloud.
+ CloudAvailabilityZoneKey = attribute.Key("cloud.availability_zone")
+ // The cloud platform in use.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ // Examples: 'aws_ec2', 'azure_vm', 'gcp_compute_engine'
+ // Note: The prefix of the service SHOULD match the one specified in
+ // `cloud.provider`.
+ CloudPlatformKey = attribute.Key("cloud.platform")
+)
+
+var (
+ // Amazon Web Services
+ CloudProviderAWS = CloudProviderKey.String("aws")
+ // Microsoft Azure
+ CloudProviderAzure = CloudProviderKey.String("azure")
+ // Google Cloud Platform
+ CloudProviderGCP = CloudProviderKey.String("gcp")
+)
+
+var (
+ // AWS Elastic Compute Cloud
+ CloudPlatformAWSEC2 = CloudPlatformKey.String("aws_ec2")
+ // AWS Elastic Container Service
+ CloudPlatformAWSECS = CloudPlatformKey.String("aws_ecs")
+ // AWS Elastic Kubernetes Service
+ CloudPlatformAWSEKS = CloudPlatformKey.String("aws_eks")
+ // AWS Lambda
+ CloudPlatformAWSLambda = CloudPlatformKey.String("aws_lambda")
+ // AWS Elastic Beanstalk
+ CloudPlatformAWSElasticBeanstalk = CloudPlatformKey.String("aws_elastic_beanstalk")
+ // Azure Virtual Machines
+ CloudPlatformAzureVM = CloudPlatformKey.String("azure_vm")
+ // Azure Container Instances
+ CloudPlatformAzureContainerInstances = CloudPlatformKey.String("azure_container_instances")
+ // Azure Kubernetes Service
+ CloudPlatformAzureAKS = CloudPlatformKey.String("azure_aks")
+ // Azure Functions
+ CloudPlatformAzureFunctions = CloudPlatformKey.String("azure_functions")
+ // Azure App Service
+ CloudPlatformAzureAppService = CloudPlatformKey.String("azure_app_service")
+ // Google Cloud Compute Engine (GCE)
+ CloudPlatformGCPComputeEngine = CloudPlatformKey.String("gcp_compute_engine")
+ // Google Cloud Run
+ CloudPlatformGCPCloudRun = CloudPlatformKey.String("gcp_cloud_run")
+ // Google Cloud Kubernetes Engine (GKE)
+ CloudPlatformGCPKubernetesEngine = CloudPlatformKey.String("gcp_kubernetes_engine")
+ // Google Cloud Functions (GCF)
+ CloudPlatformGCPCloudFunctions = CloudPlatformKey.String("gcp_cloud_functions")
+ // Google Cloud App Engine (GAE)
+ CloudPlatformGCPAppEngine = CloudPlatformKey.String("gcp_app_engine")
+)
+
+// Resources used by AWS Elastic Container Service (ECS).
+const (
+ // The Amazon Resource Name (ARN) of an [ECS container instance](https://docs.aws.
+ // amazon.com/AmazonECS/latest/developerguide/ECS_instances.html).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'arn:aws:ecs:us-
+ // west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9'
+ AWSECSContainerARNKey = attribute.Key("aws.ecs.container.arn")
+ // The ARN of an [ECS cluster](https://docs.aws.amazon.com/AmazonECS/latest/develo
+ // perguide/clusters.html).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster'
+ AWSECSClusterARNKey = attribute.Key("aws.ecs.cluster.arn")
+ // The [launch type](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/l
+ // aunch_types.html) for an ECS task.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ // Examples: 'ec2', 'fargate'
+ AWSECSLaunchtypeKey = attribute.Key("aws.ecs.launchtype")
+ // The ARN of an [ECS task definition](https://docs.aws.amazon.com/AmazonECS/lates
+ // t/developerguide/task_definitions.html).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'arn:aws:ecs:us-
+ // west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b'
+ AWSECSTaskARNKey = attribute.Key("aws.ecs.task.arn")
+ // The task definition family this task definition is a member of.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry-family'
+ AWSECSTaskFamilyKey = attribute.Key("aws.ecs.task.family")
+ // The revision for this task definition.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '8', '26'
+ AWSECSTaskRevisionKey = attribute.Key("aws.ecs.task.revision")
+)
+
+var (
+ // ec2
+ AWSECSLaunchtypeEC2 = AWSECSLaunchtypeKey.String("ec2")
+ // fargate
+ AWSECSLaunchtypeFargate = AWSECSLaunchtypeKey.String("fargate")
+)
+
+// Resources used by AWS Elastic Kubernetes Service (EKS).
+const (
+ // The ARN of an EKS cluster.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster'
+ AWSEKSClusterARNKey = attribute.Key("aws.eks.cluster.arn")
+)
+
+// Resources specific to Amazon Web Services.
+const (
+ // The name(s) of the AWS log group(s) an application is writing to.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: '/aws/lambda/my-function', 'opentelemetry-service'
+ // Note: Multiple log groups must be supported for cases like multi-container
+ // applications, where a single application has sidecar containers, and each write
+ // to their own log group.
+ AWSLogGroupNamesKey = attribute.Key("aws.log.group.names")
+ // The Amazon Resource Name(s) (ARN) of the AWS log group(s).
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*'
+ // Note: See the [log group ARN format
+ // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-
+ // access-control-overview-cwl.html#CWL_ARN_Format).
+ AWSLogGroupARNsKey = attribute.Key("aws.log.group.arns")
+ // The name(s) of the AWS log stream(s) an application is writing to.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: 'logs/main/10838bed-421f-43ef-870a-f43feacbbb5b'
+ AWSLogStreamNamesKey = attribute.Key("aws.log.stream.names")
+ // The ARN(s) of the AWS log stream(s).
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log-
+ // stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b'
+ // Note: See the [log stream ARN format
+ // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-
+ // access-control-overview-cwl.html#CWL_ARN_Format). One log group can contain
+ // several log streams, so these ARNs necessarily identify both a log group and a
+ // log stream.
+ AWSLogStreamARNsKey = attribute.Key("aws.log.stream.arns")
+)
+
+// A container instance.
+const (
+ // Container name.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry-autoconf'
+ ContainerNameKey = attribute.Key("container.name")
+ // Container ID. Usually a UUID, as for example used to [identify Docker
+ // containers](https://docs.docker.com/engine/reference/run/#container-
+ // identification). The UUID might be abbreviated.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'a3bf90e006b2'
+ ContainerIDKey = attribute.Key("container.id")
+ // The container runtime managing this container.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'docker', 'containerd', 'rkt'
+ ContainerRuntimeKey = attribute.Key("container.runtime")
+ // Name of the image the container was built on.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'gcr.io/opentelemetry/operator'
+ ContainerImageNameKey = attribute.Key("container.image.name")
+ // Container image tag.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '0.1'
+ ContainerImageTagKey = attribute.Key("container.image.tag")
+)
+
+// The software deployment.
+const (
+ // Name of the [deployment
+ // environment](https://en.wikipedia.org/wiki/Deployment_environment) (aka
+ // deployment tier).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'staging', 'production'
+ DeploymentEnvironmentKey = attribute.Key("deployment.environment")
+)
+
+// The device on which the process represented by this resource is running.
+const (
+ // A unique identifier representing the device
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '2ab2916d-a51f-4ac8-80ee-45ac31a28092'
+ // Note: The device identifier MUST only be defined using the values outlined
+ // below. This value is not an advertising identifier and MUST NOT be used as
+ // such. On iOS (Swift or Objective-C), this value MUST be equal to the [vendor id
+ // entifier](https://developer.apple.com/documentation/uikit/uidevice/1620059-iden
+ // tifierforvendor). On Android (Java or Kotlin), this value MUST be equal to the
+ // Firebase Installation ID or a globally unique UUID which is persisted across
+ // sessions in your application. More information can be found
+ // [here](https://developer.android.com/training/articles/user-data-ids) on best
+ // practices and exact implementation details. Caution should be taken when
+ // storing personal data or anything which can identify a user. GDPR and data
+ // protection laws may apply, ensure you do your own due diligence.
+ DeviceIDKey = attribute.Key("device.id")
+ // The model identifier for the device
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'iPhone3,4', 'SM-G920F'
+ // Note: It's recommended this value represents a machine readable version of the
+ // model identifier rather than the market or consumer-friendly name of the
+ // device.
+ DeviceModelIdentifierKey = attribute.Key("device.model.identifier")
+ // The marketing name for the device model
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'iPhone 6s Plus', 'Samsung Galaxy S6'
+ // Note: It's recommended this value represents a human readable version of the
+ // device model rather than a machine readable alternative.
+ DeviceModelNameKey = attribute.Key("device.model.name")
+)
+
+// A serverless instance.
+const (
+ // The name of the function being executed.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'my-function'
+ FaaSNameKey = attribute.Key("faas.name")
+ // The unique ID of the function being executed.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'arn:aws:lambda:us-west-2:123456789012:function:my-function'
+ // Note: For example, in AWS Lambda this field corresponds to the
+ // [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-
+ // namespaces.html) value, in GCP to the URI of the resource, and in Azure to the
+ // [FunctionDirectory](https://github.com/Azure/azure-functions-
+ // host/wiki/Retrieving-information-about-the-currently-running-function) field.
+ FaaSIDKey = attribute.Key("faas.id")
+ // The version string of the function being executed as defined in [Version
+ // Attributes](../../resource/semantic_conventions/README.md#version-attributes).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '2.0.0'
+ FaaSVersionKey = attribute.Key("faas.version")
+ // The execution environment ID as a string.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'my-function:instance-0001'
+ FaaSInstanceKey = attribute.Key("faas.instance")
+ // The amount of memory available to the serverless function in MiB.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 128
+ // Note: It's recommended to set this attribute since e.g. too little memory can
+ // easily stop a Java AWS Lambda function from working correctly. On AWS Lambda,
+ // the environment variable `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this
+ // information.
+ FaaSMaxMemoryKey = attribute.Key("faas.max_memory")
+)
+
+// A host is defined as a general computing instance.
+const (
+ // Unique host ID. For Cloud, this must be the instance_id assigned by the cloud
+ // provider.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry-test'
+ HostIDKey = attribute.Key("host.id")
+ // Name of the host. On Unix systems, it may contain what the hostname command
+ // returns, or the fully qualified hostname, or another name specified by the
+ // user.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry-test'
+ HostNameKey = attribute.Key("host.name")
+ // Type of host. For Cloud, this must be the machine type.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'n1-standard-1'
+ HostTypeKey = attribute.Key("host.type")
+ // The CPU architecture the host system is running on.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ HostArchKey = attribute.Key("host.arch")
+ // Name of the VM image or OS install the host was instantiated from.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'infra-ami-eks-worker-node-7d4ec78312', 'CentOS-8-x86_64-1905'
+ HostImageNameKey = attribute.Key("host.image.name")
+ // VM image ID. For Cloud, this value is from the provider.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'ami-07b06b442921831e5'
+ HostImageIDKey = attribute.Key("host.image.id")
+ // The version string of the VM image as defined in [Version
+ // Attributes](README.md#version-attributes).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '0.1'
+ HostImageVersionKey = attribute.Key("host.image.version")
+)
+
+var (
+ // AMD64
+ HostArchAMD64 = HostArchKey.String("amd64")
+ // ARM32
+ HostArchARM32 = HostArchKey.String("arm32")
+ // ARM64
+ HostArchARM64 = HostArchKey.String("arm64")
+ // Itanium
+ HostArchIA64 = HostArchKey.String("ia64")
+ // 32-bit PowerPC
+ HostArchPPC32 = HostArchKey.String("ppc32")
+ // 64-bit PowerPC
+ HostArchPPC64 = HostArchKey.String("ppc64")
+ // 32-bit x86
+ HostArchX86 = HostArchKey.String("x86")
+)
+
+// A Kubernetes Cluster.
+const (
+ // The name of the cluster.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry-cluster'
+ K8SClusterNameKey = attribute.Key("k8s.cluster.name")
+)
+
+// A Kubernetes Node object.
+const (
+ // The name of the Node.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'node-1'
+ K8SNodeNameKey = attribute.Key("k8s.node.name")
+ // The UID of the Node.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2'
+ K8SNodeUIDKey = attribute.Key("k8s.node.uid")
+)
+
+// A Kubernetes Namespace.
+const (
+ // The name of the namespace that the pod is running in.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'default'
+ K8SNamespaceNameKey = attribute.Key("k8s.namespace.name")
+)
+
+// A Kubernetes Pod object.
+const (
+ // The UID of the Pod.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
+ K8SPodUIDKey = attribute.Key("k8s.pod.uid")
+ // The name of the Pod.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry-pod-autoconf'
+ K8SPodNameKey = attribute.Key("k8s.pod.name")
+)
+
+// A container in a [PodTemplate](https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates).
+const (
+ // The name of the Container in a Pod template.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'redis'
+ K8SContainerNameKey = attribute.Key("k8s.container.name")
+)
+
+// A Kubernetes ReplicaSet object.
+const (
+ // The UID of the ReplicaSet.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
+ K8SReplicasetUIDKey = attribute.Key("k8s.replicaset.uid")
+ // The name of the ReplicaSet.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry'
+ K8SReplicasetNameKey = attribute.Key("k8s.replicaset.name")
+)
+
+// A Kubernetes Deployment object.
+const (
+ // The UID of the Deployment.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
+ K8SDeploymentUIDKey = attribute.Key("k8s.deployment.uid")
+ // The name of the Deployment.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry'
+ K8SDeploymentNameKey = attribute.Key("k8s.deployment.name")
+)
+
+// A Kubernetes StatefulSet object.
+const (
+ // The UID of the StatefulSet.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
+ K8SStatefulsetUIDKey = attribute.Key("k8s.statefulset.uid")
+ // The name of the StatefulSet.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry'
+ K8SStatefulsetNameKey = attribute.Key("k8s.statefulset.name")
+)
+
+// A Kubernetes DaemonSet object.
+const (
+ // The UID of the DaemonSet.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
+ K8SDaemonsetUIDKey = attribute.Key("k8s.daemonset.uid")
+ // The name of the DaemonSet.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry'
+ K8SDaemonsetNameKey = attribute.Key("k8s.daemonset.name")
+)
+
+// A Kubernetes Job object.
+const (
+ // The UID of the Job.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
+ K8SJobUIDKey = attribute.Key("k8s.job.uid")
+ // The name of the Job.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry'
+ K8SJobNameKey = attribute.Key("k8s.job.name")
+)
+
+// A Kubernetes CronJob object.
+const (
+ // The UID of the CronJob.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff'
+ K8SCronJobUIDKey = attribute.Key("k8s.cronjob.uid")
+ // The name of the CronJob.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry'
+ K8SCronJobNameKey = attribute.Key("k8s.cronjob.name")
+)
+
+// The operating system (OS) on which the process represented by this resource is running.
+const (
+ // The operating system type.
+ //
+ // Type: Enum
+ // Required: Always
+ // Stability: stable
+ OSTypeKey = attribute.Key("os.type")
+ // Human readable (not intended to be parsed) OS version information, like e.g.
+ // reported by `ver` or `lsb_release -a` commands.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Microsoft Windows [Version 10.0.18363.778]', 'Ubuntu 18.04.1 LTS'
+ OSDescriptionKey = attribute.Key("os.description")
+ // Human readable operating system name.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'iOS', 'Android', 'Ubuntu'
+ OSNameKey = attribute.Key("os.name")
+ // The version string of the operating system as defined in [Version
+ // Attributes](../../resource/semantic_conventions/README.md#version-attributes).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '14.2.1', '18.04.1'
+ OSVersionKey = attribute.Key("os.version")
+)
+
+var (
+ // Microsoft Windows
+ OSTypeWindows = OSTypeKey.String("windows")
+ // Linux
+ OSTypeLinux = OSTypeKey.String("linux")
+ // Apple Darwin
+ OSTypeDarwin = OSTypeKey.String("darwin")
+ // FreeBSD
+ OSTypeFreeBSD = OSTypeKey.String("freebsd")
+ // NetBSD
+ OSTypeNetBSD = OSTypeKey.String("netbsd")
+ // OpenBSD
+ OSTypeOpenBSD = OSTypeKey.String("openbsd")
+ // DragonFly BSD
+ OSTypeDragonflyBSD = OSTypeKey.String("dragonflybsd")
+ // HP-UX (Hewlett Packard Unix)
+ OSTypeHPUX = OSTypeKey.String("hpux")
+ // AIX (Advanced Interactive eXecutive)
+ OSTypeAIX = OSTypeKey.String("aix")
+ // Oracle Solaris
+ OSTypeSolaris = OSTypeKey.String("solaris")
+ // IBM z/OS
+ OSTypeZOS = OSTypeKey.String("z_os")
+)
+
+// An operating system process.
+const (
+ // Process identifier (PID).
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 1234
+ ProcessPIDKey = attribute.Key("process.pid")
+ // The name of the process executable. On Linux based systems, can be set to the
+ // `Name` in `proc/[pid]/status`. On Windows, can be set to the base name of
+ // `GetProcessImageFileNameW`.
+ //
+ // Type: string
+ // Required: See below
+ // Stability: stable
+ // Examples: 'otelcol'
+ ProcessExecutableNameKey = attribute.Key("process.executable.name")
+ // The full path to the process executable. On Linux based systems, can be set to
+ // the target of `proc/[pid]/exe`. On Windows, can be set to the result of
+ // `GetProcessImageFileNameW`.
+ //
+ // Type: string
+ // Required: See below
+ // Stability: stable
+ // Examples: '/usr/bin/cmd/otelcol'
+ ProcessExecutablePathKey = attribute.Key("process.executable.path")
+ // The command used to launch the process (i.e. the command name). On Linux based
+ // systems, can be set to the zeroth string in `proc/[pid]/cmdline`. On Windows,
+ // can be set to the first parameter extracted from `GetCommandLineW`.
+ //
+ // Type: string
+ // Required: See below
+ // Stability: stable
+ // Examples: 'cmd/otelcol'
+ ProcessCommandKey = attribute.Key("process.command")
+ // The full command used to launch the process as a single string representing the
+ // full command. On Windows, can be set to the result of `GetCommandLineW`. Do not
+ // set this if you have to assemble it just for monitoring; use
+ // `process.command_args` instead.
+ //
+ // Type: string
+ // Required: See below
+ // Stability: stable
+ // Examples: 'C:\\cmd\\otecol --config="my directory\\config.yaml"'
+ ProcessCommandLineKey = attribute.Key("process.command_line")
+ // All the command arguments (including the command/executable itself) as received
+ // by the process. On Linux-based systems (and some other Unixoid systems
+ // supporting procfs), can be set according to the list of null-delimited strings
+ // extracted from `proc/[pid]/cmdline`. For libc-based executables, this would be
+ // the full argv vector passed to `main`.
+ //
+ // Type: string[]
+ // Required: See below
+ // Stability: stable
+ // Examples: 'cmd/otecol', '--config=config.yaml'
+ ProcessCommandArgsKey = attribute.Key("process.command_args")
+ // The username of the user that owns the process.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'root'
+ ProcessOwnerKey = attribute.Key("process.owner")
+)
+
+// The single (language) runtime instance which is monitored.
+const (
+ // The name of the runtime of this process. For compiled native binaries, this
+ // SHOULD be the name of the compiler.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'OpenJDK Runtime Environment'
+ ProcessRuntimeNameKey = attribute.Key("process.runtime.name")
+ // The version of the runtime of this process, as returned by the runtime without
+ // modification.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '14.0.2'
+ ProcessRuntimeVersionKey = attribute.Key("process.runtime.version")
+ // An additional description about the runtime of the process, for example a
+ // specific vendor customization of the runtime environment.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0'
+ ProcessRuntimeDescriptionKey = attribute.Key("process.runtime.description")
+)
+
+// A service instance.
+const (
+ // Logical name of the service.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'shoppingcart'
+ // Note: MUST be the same for all instances of horizontally scaled services. If
+ // the value was not specified, SDKs MUST fallback to `unknown_service:`
+ // concatenated with [`process.executable.name`](process.md#process), e.g.
+ // `unknown_service:bash`. If `process.executable.name` is not available, the
+ // value MUST be set to `unknown_service`.
+ ServiceNameKey = attribute.Key("service.name")
+ // A namespace for `service.name`.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Shop'
+ // Note: A string value having a meaning that helps to distinguish a group of
+ // services, for example the team name that owns a group of services.
+ // `service.name` is expected to be unique within the same namespace. If
+ // `service.namespace` is not specified in the Resource then `service.name` is
+ // expected to be unique for all services that have no explicit namespace defined
+ // (so the empty/unspecified namespace is simply one more valid namespace). Zero-
+ // length namespace string is assumed equal to unspecified namespace.
+ ServiceNamespaceKey = attribute.Key("service.namespace")
+ // The string ID of the service instance.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '627cc493-f310-47de-96bd-71410b7dec09'
+ // Note: MUST be unique for each instance of the same
+ // `service.namespace,service.name` pair (in other words
+ // `service.namespace,service.name,service.instance.id` triplet MUST be globally
+ // unique). The ID helps to distinguish instances of the same service that exist
+ // at the same time (e.g. instances of a horizontally scaled service). It is
+ // preferable for the ID to be persistent and stay the same for the lifetime of
+ // the service instance, however it is acceptable that the ID is ephemeral and
+ // changes during important lifetime events for the service (e.g. service
+ // restarts). If the service has no inherent unique ID that can be used as the
+ // value of this attribute it is recommended to generate a random Version 1 or
+ // Version 4 RFC 4122 UUID (services aiming for reproducible UUIDs may also use
+ // Version 5, see RFC 4122 for more recommendations).
+ ServiceInstanceIDKey = attribute.Key("service.instance.id")
+ // The version string of the service API or implementation.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '2.0.0'
+ ServiceVersionKey = attribute.Key("service.version")
+)
+
+// The telemetry SDK used to capture data recorded by the instrumentation libraries.
+const (
+ // The name of the telemetry SDK as defined above.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'opentelemetry'
+ TelemetrySDKNameKey = attribute.Key("telemetry.sdk.name")
+ // The language of the telemetry SDK.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ TelemetrySDKLanguageKey = attribute.Key("telemetry.sdk.language")
+ // The version string of the telemetry SDK.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '1.2.3'
+ TelemetrySDKVersionKey = attribute.Key("telemetry.sdk.version")
+ // The version string of the auto instrumentation agent, if used.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '1.2.3'
+ TelemetryAutoVersionKey = attribute.Key("telemetry.auto.version")
+)
+
+var (
+ // cpp
+ TelemetrySDKLanguageCPP = TelemetrySDKLanguageKey.String("cpp")
+ // dotnet
+ TelemetrySDKLanguageDotnet = TelemetrySDKLanguageKey.String("dotnet")
+ // erlang
+ TelemetrySDKLanguageErlang = TelemetrySDKLanguageKey.String("erlang")
+ // go
+ TelemetrySDKLanguageGo = TelemetrySDKLanguageKey.String("go")
+ // java
+ TelemetrySDKLanguageJava = TelemetrySDKLanguageKey.String("java")
+ // nodejs
+ TelemetrySDKLanguageNodejs = TelemetrySDKLanguageKey.String("nodejs")
+ // php
+ TelemetrySDKLanguagePHP = TelemetrySDKLanguageKey.String("php")
+ // python
+ TelemetrySDKLanguagePython = TelemetrySDKLanguageKey.String("python")
+ // ruby
+ TelemetrySDKLanguageRuby = TelemetrySDKLanguageKey.String("ruby")
+ // webjs
+ TelemetrySDKLanguageWebjs = TelemetrySDKLanguageKey.String("webjs")
+)
+
+// Resource describing the packaged software running the application code. Web engines are typically executed using process.runtime.
+const (
+ // The name of the web engine.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'WildFly'
+ WebEngineNameKey = attribute.Key("webengine.name")
+ // The version of the web engine.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '21.0.0'
+ WebEngineVersionKey = attribute.Key("webengine.version")
+ // Additional description of the web engine (e.g. detailed version and edition
+ // information).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - 2.2.2.Final'
+ WebEngineDescriptionKey = attribute.Key("webengine.description")
+)
diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/schema.go b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/schema.go
new file mode 100644
index 0000000000..a78f1bf400
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/schema.go
@@ -0,0 +1,20 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0"
+
+// SchemaURL is the schema URL that matches the version of the semantic conventions
+// that this package defines. Semconv packages starting from v1.4.0 must declare
+// non-empty schema URL in the form https://opentelemetry.io/schemas/
+const SchemaURL = "https://opentelemetry.io/schemas/1.4.0"
diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/trace.go b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/trace.go
new file mode 100644
index 0000000000..805eadc9f5
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/trace.go
@@ -0,0 +1,1378 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated from semantic convention specification. DO NOT EDIT.
+
+package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0"
+
+import "go.opentelemetry.io/otel/attribute"
+
+// This document defines the attributes used to perform database client calls.
+const (
+ // An identifier for the database management system (DBMS) product being used. See
+ // below for a list of well-known identifiers.
+ //
+ // Type: Enum
+ // Required: Always
+ // Stability: stable
+ DBSystemKey = attribute.Key("db.system")
+ // The connection string used to connect to the database. It is recommended to
+ // remove embedded credentials.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Server=(localdb)\\v11.0;Integrated Security=true;'
+ DBConnectionStringKey = attribute.Key("db.connection_string")
+ // Username for accessing the database.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'readonly_user', 'reporting_user'
+ DBUserKey = attribute.Key("db.user")
+ // The fully-qualified class name of the [Java Database Connectivity
+ // (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver
+ // used to connect.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'org.postgresql.Driver',
+ // 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
+ DBJDBCDriverClassnameKey = attribute.Key("db.jdbc.driver_classname")
+ // If no [tech-specific attribute](#call-level-attributes-for-specific-
+ // technologies) is defined, this attribute is used to report the name of the
+ // database being accessed. For commands that switch the database, this should be
+ // set to the target database (even if the command fails).
+ //
+ // Type: string
+ // Required: Required, if applicable and no more-specific attribute is defined.
+ // Stability: stable
+ // Examples: 'customers', 'main'
+ // Note: In some SQL databases, the database name to be used is called "schema
+ // name".
+ DBNameKey = attribute.Key("db.name")
+ // The database statement being executed.
+ //
+ // Type: string
+ // Required: Required if applicable and not explicitly disabled via
+ // instrumentation configuration.
+ // Stability: stable
+ // Examples: 'SELECT * FROM wuser_table', 'SET mykey "WuValue"'
+ // Note: The value may be sanitized to exclude sensitive information.
+ DBStatementKey = attribute.Key("db.statement")
+ // The name of the operation being executed, e.g. the [MongoDB command
+ // name](https://docs.mongodb.com/manual/reference/command/#database-operations)
+ // such as `findAndModify`, or the SQL keyword.
+ //
+ // Type: string
+ // Required: Required, if `db.statement` is not applicable.
+ // Stability: stable
+ // Examples: 'findAndModify', 'HMSET', 'SELECT'
+ // Note: When setting this to an SQL keyword, it is not recommended to attempt any
+ // client-side parsing of `db.statement` just to get this property, but it should
+ // be set if the operation name is provided by the library being instrumented. If
+ // the SQL statement has an ambiguous operation, or performs more than one
+ // operation, this value may be omitted.
+ DBOperationKey = attribute.Key("db.operation")
+)
+
+var (
+ // Some other SQL database. Fallback only. See notes
+ DBSystemOtherSQL = DBSystemKey.String("other_sql")
+ // Microsoft SQL Server
+ DBSystemMSSQL = DBSystemKey.String("mssql")
+ // MySQL
+ DBSystemMySQL = DBSystemKey.String("mysql")
+ // Oracle Database
+ DBSystemOracle = DBSystemKey.String("oracle")
+ // IBM DB2
+ DBSystemDB2 = DBSystemKey.String("db2")
+ // PostgreSQL
+ DBSystemPostgreSQL = DBSystemKey.String("postgresql")
+ // Amazon Redshift
+ DBSystemRedshift = DBSystemKey.String("redshift")
+ // Apache Hive
+ DBSystemHive = DBSystemKey.String("hive")
+ // Cloudscape
+ DBSystemCloudscape = DBSystemKey.String("cloudscape")
+ // HyperSQL DataBase
+ DBSystemHSQLDB = DBSystemKey.String("hsqldb")
+ // Progress Database
+ DBSystemProgress = DBSystemKey.String("progress")
+ // SAP MaxDB
+ DBSystemMaxDB = DBSystemKey.String("maxdb")
+ // SAP HANA
+ DBSystemHanaDB = DBSystemKey.String("hanadb")
+ // Ingres
+ DBSystemIngres = DBSystemKey.String("ingres")
+ // FirstSQL
+ DBSystemFirstSQL = DBSystemKey.String("firstsql")
+ // EnterpriseDB
+ DBSystemEDB = DBSystemKey.String("edb")
+ // InterSystems Caché
+ DBSystemCache = DBSystemKey.String("cache")
+ // Adabas (Adaptable Database System)
+ DBSystemAdabas = DBSystemKey.String("adabas")
+ // Firebird
+ DBSystemFirebird = DBSystemKey.String("firebird")
+ // Apache Derby
+ DBSystemDerby = DBSystemKey.String("derby")
+ // FileMaker
+ DBSystemFilemaker = DBSystemKey.String("filemaker")
+ // Informix
+ DBSystemInformix = DBSystemKey.String("informix")
+ // InstantDB
+ DBSystemInstantDB = DBSystemKey.String("instantdb")
+ // InterBase
+ DBSystemInterbase = DBSystemKey.String("interbase")
+ // MariaDB
+ DBSystemMariaDB = DBSystemKey.String("mariadb")
+ // Netezza
+ DBSystemNetezza = DBSystemKey.String("netezza")
+ // Pervasive PSQL
+ DBSystemPervasive = DBSystemKey.String("pervasive")
+ // PointBase
+ DBSystemPointbase = DBSystemKey.String("pointbase")
+ // SQLite
+ DBSystemSqlite = DBSystemKey.String("sqlite")
+ // Sybase
+ DBSystemSybase = DBSystemKey.String("sybase")
+ // Teradata
+ DBSystemTeradata = DBSystemKey.String("teradata")
+ // Vertica
+ DBSystemVertica = DBSystemKey.String("vertica")
+ // H2
+ DBSystemH2 = DBSystemKey.String("h2")
+ // ColdFusion IMQ
+ DBSystemColdfusion = DBSystemKey.String("coldfusion")
+ // Apache Cassandra
+ DBSystemCassandra = DBSystemKey.String("cassandra")
+ // Apache HBase
+ DBSystemHBase = DBSystemKey.String("hbase")
+ // MongoDB
+ DBSystemMongoDB = DBSystemKey.String("mongodb")
+ // Redis
+ DBSystemRedis = DBSystemKey.String("redis")
+ // Couchbase
+ DBSystemCouchbase = DBSystemKey.String("couchbase")
+ // CouchDB
+ DBSystemCouchDB = DBSystemKey.String("couchdb")
+ // Microsoft Azure Cosmos DB
+ DBSystemCosmosDB = DBSystemKey.String("cosmosdb")
+ // Amazon DynamoDB
+ DBSystemDynamoDB = DBSystemKey.String("dynamodb")
+ // Neo4j
+ DBSystemNeo4j = DBSystemKey.String("neo4j")
+ // Apache Geode
+ DBSystemGeode = DBSystemKey.String("geode")
+ // Elasticsearch
+ DBSystemElasticsearch = DBSystemKey.String("elasticsearch")
+ // Memcached
+ DBSystemMemcached = DBSystemKey.String("memcached")
+ // CockroachDB
+ DBSystemCockroachdb = DBSystemKey.String("cockroachdb")
+)
+
+// Connection-level attributes for Microsoft SQL Server
+const (
+ // The Microsoft SQL Server [instance name](https://docs.microsoft.com/en-
+ // us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15)
+ // connecting to. This name is used to determine the port of a named instance.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'MSSQLSERVER'
+ // Note: If setting a `db.mssql.instance_name`, `net.peer.port` is no longer
+ // required (but still recommended if non-standard).
+ DBMSSQLInstanceNameKey = attribute.Key("db.mssql.instance_name")
+)
+
+// Call-level attributes for Cassandra
+const (
+ // The name of the keyspace being accessed. To be used instead of the generic
+ // `db.name` attribute.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'mykeyspace'
+ DBCassandraKeyspaceKey = attribute.Key("db.cassandra.keyspace")
+ // The fetch size used for paging, i.e. how many rows will be returned at once.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 5000
+ DBCassandraPageSizeKey = attribute.Key("db.cassandra.page_size")
+ // The consistency level of the query. Based on consistency values from
+ // [CQL](https://docs.datastax.com/en/cassandra-
+ // oss/3.0/cassandra/dml/dmlConfigConsistency.html).
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ DBCassandraConsistencyLevelKey = attribute.Key("db.cassandra.consistency_level")
+ // The name of the primary table that the operation is acting upon, including the
+ // schema name (if applicable).
+ //
+ // Type: string
+ // Required: Recommended if available.
+ // Stability: stable
+ // Examples: 'mytable'
+ // Note: This mirrors the db.sql.table attribute but references cassandra rather
+ // than sql. It is not recommended to attempt any client-side parsing of
+ // `db.statement` just to get this property, but it should be set if it is
+ // provided by the library being instrumented. If the operation is acting upon an
+ // anonymous table, or more than one table, this value MUST NOT be set.
+ DBCassandraTableKey = attribute.Key("db.cassandra.table")
+ // Whether or not the query is idempotent.
+ //
+ // Type: boolean
+ // Required: No
+ // Stability: stable
+ DBCassandraIdempotenceKey = attribute.Key("db.cassandra.idempotence")
+ // The number of times a query was speculatively executed. Not set or `0` if the
+ // query was not executed speculatively.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 0, 2
+ DBCassandraSpeculativeExecutionCountKey = attribute.Key("db.cassandra.speculative_execution_count")
+ // The ID of the coordinating node for a query.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'be13faa2-8574-4d71-926d-27f16cf8a7af'
+ DBCassandraCoordinatorIDKey = attribute.Key("db.cassandra.coordinator.id")
+ // The data center of the coordinating node for a query.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'us-west-2'
+ DBCassandraCoordinatorDCKey = attribute.Key("db.cassandra.coordinator.dc")
+)
+
+var (
+ // all
+ DBCassandraConsistencyLevelAll = DBCassandraConsistencyLevelKey.String("all")
+ // each_quorum
+ DBCassandraConsistencyLevelEachQuorum = DBCassandraConsistencyLevelKey.String("each_quorum")
+ // quorum
+ DBCassandraConsistencyLevelQuorum = DBCassandraConsistencyLevelKey.String("quorum")
+ // local_quorum
+ DBCassandraConsistencyLevelLocalQuorum = DBCassandraConsistencyLevelKey.String("local_quorum")
+ // one
+ DBCassandraConsistencyLevelOne = DBCassandraConsistencyLevelKey.String("one")
+ // two
+ DBCassandraConsistencyLevelTwo = DBCassandraConsistencyLevelKey.String("two")
+ // three
+ DBCassandraConsistencyLevelThree = DBCassandraConsistencyLevelKey.String("three")
+ // local_one
+ DBCassandraConsistencyLevelLocalOne = DBCassandraConsistencyLevelKey.String("local_one")
+ // any
+ DBCassandraConsistencyLevelAny = DBCassandraConsistencyLevelKey.String("any")
+ // serial
+ DBCassandraConsistencyLevelSerial = DBCassandraConsistencyLevelKey.String("serial")
+ // local_serial
+ DBCassandraConsistencyLevelLocalSerial = DBCassandraConsistencyLevelKey.String("local_serial")
+)
+
+// Call-level attributes for Apache HBase
+const (
+ // The [HBase namespace](https://hbase.apache.org/book.html#_namespace) being
+ // accessed. To be used instead of the generic `db.name` attribute.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'default'
+ DBHBaseNamespaceKey = attribute.Key("db.hbase.namespace")
+)
+
+// Call-level attributes for Redis
+const (
+ // The index of the database being accessed as used in the [`SELECT`
+ // command](https://redis.io/commands/select), provided as an integer. To be used
+ // instead of the generic `db.name` attribute.
+ //
+ // Type: int
+ // Required: Required, if other than the default database (`0`).
+ // Stability: stable
+ // Examples: 0, 1, 15
+ DBRedisDBIndexKey = attribute.Key("db.redis.database_index")
+)
+
+// Call-level attributes for MongoDB
+const (
+ // The collection being accessed within the database stated in `db.name`.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'customers', 'products'
+ DBMongoDBCollectionKey = attribute.Key("db.mongodb.collection")
+)
+
+// Call-level attrbiutes for SQL databases
+const (
+ // The name of the primary table that the operation is acting upon, including the
+ // schema name (if applicable).
+ //
+ // Type: string
+ // Required: Recommended if available.
+ // Stability: stable
+ // Examples: 'public.users', 'customers'
+ // Note: It is not recommended to attempt any client-side parsing of
+ // `db.statement` just to get this property, but it should be set if it is
+ // provided by the library being instrumented. If the operation is acting upon an
+ // anonymous table, or more than one table, this value MUST NOT be set.
+ DBSQLTableKey = attribute.Key("db.sql.table")
+)
+
+// This document defines the attributes used to report a single exception associated with a span.
+const (
+ // The type of the exception (its fully-qualified class name, if applicable). The
+ // dynamic type of the exception should be preferred over the static type in
+ // languages that support it.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'java.net.ConnectException', 'OSError'
+ ExceptionTypeKey = attribute.Key("exception.type")
+ // The exception message.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Division by zero', "Can't convert 'int' object to str implicitly"
+ ExceptionMessageKey = attribute.Key("exception.message")
+ // A stacktrace as a string in the natural representation for the language
+ // runtime. The representation is to be determined and documented by each language
+ // SIG.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Exception in thread "main" java.lang.RuntimeException: Test
+ // exception\\n at '
+ // 'com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at '
+ // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at '
+ // 'com.example.GenerateTrace.main(GenerateTrace.java:5)'
+ ExceptionStacktraceKey = attribute.Key("exception.stacktrace")
+ // SHOULD be set to true if the exception event is recorded at a point where it is
+ // known that the exception is escaping the scope of the span.
+ //
+ // Type: boolean
+ // Required: No
+ // Stability: stable
+ // Note: An exception is considered to have escaped (or left) the scope of a span,
+ // if that span is ended while the exception is still logically "in flight".
+ // This may be actually "in flight" in some languages (e.g. if the exception
+ // is passed to a Context manager's `__exit__` method in Python) but will
+ // usually be caught at the point of recording the exception in most languages.
+
+ // It is usually not possible to determine at the point where an exception is
+ // thrown
+ // whether it will escape the scope of a span.
+ // However, it is trivial to know that an exception
+ // will escape, if one checks for an active exception just before ending the span,
+ // as done in the [example above](#exception-end-example).
+
+ // It follows that an exception may still escape the scope of the span
+ // even if the `exception.escaped` attribute was not set or set to false,
+ // since the event might have been recorded at a time where it was not
+ // clear whether the exception will escape.
+ ExceptionEscapedKey = attribute.Key("exception.escaped")
+)
+
+// This semantic convention describes an instance of a function that runs without provisioning or managing of servers (also known as serverless functions or Function as a Service (FaaS)) with spans.
+const (
+ // Type of the trigger on which the function is executed.
+ //
+ // Type: Enum
+ // Required: On FaaS instances, faas.trigger MUST be set on incoming invocations.
+ // Clients invoking FaaS instances MUST set `faas.trigger` on outgoing
+ // invocations, if it is known to the client. This is, for example, not the case,
+ // when the transport layer is abstracted in a FaaS client framework without
+ // access to its configuration.
+ // Stability: stable
+ FaaSTriggerKey = attribute.Key("faas.trigger")
+ // The execution ID of the current function execution.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28'
+ FaaSExecutionKey = attribute.Key("faas.execution")
+)
+
+var (
+ // A response to some data source operation such as a database or filesystem read/write
+ FaaSTriggerDatasource = FaaSTriggerKey.String("datasource")
+ // To provide an answer to an inbound HTTP request
+ FaaSTriggerHTTP = FaaSTriggerKey.String("http")
+ // A function is set to be executed when messages are sent to a messaging system
+ FaaSTriggerPubsub = FaaSTriggerKey.String("pubsub")
+ // A function is scheduled to be executed regularly
+ FaaSTriggerTimer = FaaSTriggerKey.String("timer")
+ // If none of the others apply
+ FaaSTriggerOther = FaaSTriggerKey.String("other")
+)
+
+// Semantic Convention for FaaS triggered as a response to some data source operation such as a database or filesystem read/write.
+const (
+ // The name of the source on which the triggering operation was performed. For
+ // example, in Cloud Storage or S3 corresponds to the bucket name, and in Cosmos
+ // DB to the database name.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'myBucketName', 'myDBName'
+ FaaSDocumentCollectionKey = attribute.Key("faas.document.collection")
+ // Describes the type of the operation that was performed on the data.
+ //
+ // Type: Enum
+ // Required: Always
+ // Stability: stable
+ FaaSDocumentOperationKey = attribute.Key("faas.document.operation")
+ // A string containing the time when the data was accessed in the [ISO
+ // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format expressed
+ // in [UTC](https://www.w3.org/TR/NOTE-datetime).
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: '2020-01-23T13:47:06Z'
+ FaaSDocumentTimeKey = attribute.Key("faas.document.time")
+ // The document name/table subjected to the operation. For example, in Cloud
+ // Storage or S3 is the name of the file, and in Cosmos DB the table name.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'myFile.txt', 'myTableName'
+ FaaSDocumentNameKey = attribute.Key("faas.document.name")
+)
+
+var (
+ // When a new object is created
+ FaaSDocumentOperationInsert = FaaSDocumentOperationKey.String("insert")
+ // When an object is modified
+ FaaSDocumentOperationEdit = FaaSDocumentOperationKey.String("edit")
+ // When an object is deleted
+ FaaSDocumentOperationDelete = FaaSDocumentOperationKey.String("delete")
+)
+
+// Semantic Convention for FaaS scheduled to be executed regularly.
+const (
+ // A string containing the function invocation time in the [ISO
+ // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format expressed
+ // in [UTC](https://www.w3.org/TR/NOTE-datetime).
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: '2020-01-23T13:47:06Z'
+ FaaSTimeKey = attribute.Key("faas.time")
+ // A string containing the schedule period as [Cron Expression](https://docs.oracl
+ // e.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '0/5 * * * ? *'
+ FaaSCronKey = attribute.Key("faas.cron")
+)
+
+// Contains additional attributes for incoming FaaS spans.
+const (
+ // A boolean that is true if the serverless function is executed for the first
+ // time (aka cold-start).
+ //
+ // Type: boolean
+ // Required: No
+ // Stability: stable
+ FaaSColdstartKey = attribute.Key("faas.coldstart")
+)
+
+// Contains additional attributes for outgoing FaaS spans.
+const (
+ // The name of the invoked function.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'my-function'
+ // Note: SHOULD be equal to the `faas.name` resource attribute of the invoked
+ // function.
+ FaaSInvokedNameKey = attribute.Key("faas.invoked_name")
+ // The cloud provider of the invoked function.
+ //
+ // Type: Enum
+ // Required: Always
+ // Stability: stable
+ // Examples: 'aws'
+ // Note: SHOULD be equal to the `cloud.provider` resource attribute of the invoked
+ // function.
+ FaaSInvokedProviderKey = attribute.Key("faas.invoked_provider")
+ // The cloud region of the invoked function.
+ //
+ // Type: string
+ // Required: For some cloud providers, like AWS or GCP, the region in which a
+ // function is hosted is essential to uniquely identify the function and also part
+ // of its endpoint. Since it's part of the endpoint being called, the region is
+ // always known to clients. In these cases, `faas.invoked_region` MUST be set
+ // accordingly. If the region is unknown to the client or not required for
+ // identifying the invoked function, setting `faas.invoked_region` is optional.
+ // Stability: stable
+ // Examples: 'eu-central-1'
+ // Note: SHOULD be equal to the `cloud.region` resource attribute of the invoked
+ // function.
+ FaaSInvokedRegionKey = attribute.Key("faas.invoked_region")
+)
+
+var (
+ // Amazon Web Services
+ FaaSInvokedProviderAWS = FaaSInvokedProviderKey.String("aws")
+ // Microsoft Azure
+ FaaSInvokedProviderAzure = FaaSInvokedProviderKey.String("azure")
+ // Google Cloud Platform
+ FaaSInvokedProviderGCP = FaaSInvokedProviderKey.String("gcp")
+)
+
+// These attributes may be used for any network related operation.
+const (
+ // Transport protocol used. See note below.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ // Examples: 'ip_tcp'
+ NetTransportKey = attribute.Key("net.transport")
+ // Remote address of the peer (dotted decimal for IPv4 or
+ // [RFC5952](https://tools.ietf.org/html/rfc5952) for IPv6)
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '127.0.0.1'
+ NetPeerIPKey = attribute.Key("net.peer.ip")
+ // Remote port number.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 80, 8080, 443
+ NetPeerPortKey = attribute.Key("net.peer.port")
+ // Remote hostname or similar, see note below.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'example.com'
+ NetPeerNameKey = attribute.Key("net.peer.name")
+ // Like `net.peer.ip` but for the host IP. Useful in case of a multi-IP host.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '192.168.0.1'
+ NetHostIPKey = attribute.Key("net.host.ip")
+ // Like `net.peer.port` but for the host port.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 35555
+ NetHostPortKey = attribute.Key("net.host.port")
+ // Local hostname or similar, see note below.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'localhost'
+ NetHostNameKey = attribute.Key("net.host.name")
+)
+
+var (
+ // ip_tcp
+ NetTransportTCP = NetTransportKey.String("ip_tcp")
+ // ip_udp
+ NetTransportUDP = NetTransportKey.String("ip_udp")
+ // Another IP-based protocol
+ NetTransportIP = NetTransportKey.String("ip")
+ // Unix Domain socket. See below
+ NetTransportUnix = NetTransportKey.String("unix")
+ // Named or anonymous pipe. See note below
+ NetTransportPipe = NetTransportKey.String("pipe")
+ // In-process communication
+ NetTransportInProc = NetTransportKey.String("inproc")
+ // Something else (non IP-based)
+ NetTransportOther = NetTransportKey.String("other")
+)
+
+// Operations that access some remote service.
+const (
+ // The [`service.name`](../../resource/semantic_conventions/README.md#service) of
+ // the remote service. SHOULD be equal to the actual `service.name` resource
+ // attribute of the remote service if any.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'AuthTokenCache'
+ PeerServiceKey = attribute.Key("peer.service")
+)
+
+// These attributes may be used for any operation with an authenticated and/or authorized enduser.
+const (
+ // Username or client_id extracted from the access token or
+ // [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header in the
+ // inbound request from outside the system.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'username'
+ EnduserIDKey = attribute.Key("enduser.id")
+ // Actual/assumed role the client is making the request under extracted from token
+ // or application security context.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'admin'
+ EnduserRoleKey = attribute.Key("enduser.role")
+ // Scopes or granted authorities the client currently possesses extracted from
+ // token or application security context. The value would come from the scope
+ // associated with an [OAuth 2.0 Access
+ // Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute value
+ // in a [SAML 2.0 Assertion](http://docs.oasis-
+ // open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'read:message, write:files'
+ EnduserScopeKey = attribute.Key("enduser.scope")
+)
+
+// These attributes may be used for any operation to store information about a thread that started a span.
+const (
+ // Current "managed" thread ID (as opposed to OS thread ID).
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 42
+ ThreadIDKey = attribute.Key("thread.id")
+ // Current thread name.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'main'
+ ThreadNameKey = attribute.Key("thread.name")
+)
+
+// These attributes allow to report this unit of code and therefore to provide more context about the span.
+const (
+ // The method or function name, or equivalent (usually rightmost part of the code
+ // unit's name).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'serveRequest'
+ CodeFunctionKey = attribute.Key("code.function")
+ // The "namespace" within which `code.function` is defined. Usually the qualified
+ // class or module name, such that `code.namespace` + some separator +
+ // `code.function` form a unique identifier for the code unit.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'com.example.MyHTTPService'
+ CodeNamespaceKey = attribute.Key("code.namespace")
+ // The source code file name that identifies the code unit as uniquely as possible
+ // (preferably an absolute file path).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '/usr/local/MyApplication/content_root/app/index.php'
+ CodeFilepathKey = attribute.Key("code.filepath")
+ // The line number in `code.filepath` best representing the operation. It SHOULD
+ // point within the code unit named in `code.function`.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 42
+ CodeLineNumberKey = attribute.Key("code.lineno")
+)
+
+// This document defines semantic conventions for HTTP client and server Spans.
+const (
+ // HTTP request method.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'GET', 'POST', 'HEAD'
+ HTTPMethodKey = attribute.Key("http.method")
+ // Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`.
+ // Usually the fragment is not transmitted over HTTP, but if it is known, it
+ // should be included nevertheless.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv'
+ // Note: `http.url` MUST NOT contain credentials passed via URL in form of
+ // `https://username:password@www.example.com/`. In such case the attribute's
+ // value should be `https://www.example.com/`.
+ HTTPURLKey = attribute.Key("http.url")
+ // The full request target as passed in a HTTP request line or equivalent.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '/path/12314/?q=ddds#123'
+ HTTPTargetKey = attribute.Key("http.target")
+ // The value of the [HTTP host
+ // header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is
+ // empty or not present, this attribute should be the same.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'www.example.org'
+ HTTPHostKey = attribute.Key("http.host")
+ // The URI scheme identifying the used protocol.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'http', 'https'
+ HTTPSchemeKey = attribute.Key("http.scheme")
+ // [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).
+ //
+ // Type: int
+ // Required: If and only if one was received/sent.
+ // Stability: stable
+ // Examples: 200
+ HTTPStatusCodeKey = attribute.Key("http.status_code")
+ // Kind of HTTP protocol used.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ // Examples: '1.0'
+ // Note: If `net.transport` is not specified, it can be assumed to be `IP.TCP`
+ // except if `http.flavor` is `QUIC`, in which case `IP.UDP` is assumed.
+ HTTPFlavorKey = attribute.Key("http.flavor")
+ // Value of the [HTTP User-
+ // Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the
+ // client.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'CERN-LineMode/2.15 libwww/2.17b3'
+ HTTPUserAgentKey = attribute.Key("http.user_agent")
+ // The size of the request payload body in bytes. This is the number of bytes
+ // transferred excluding headers and is often, but not always, present as the
+ // [Content-Length](https://tools.ietf.org/html/rfc7230#section-3.3.2) header. For
+ // requests using transport encoding, this should be the compressed size.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 3495
+ HTTPRequestContentLengthKey = attribute.Key("http.request_content_length")
+ // The size of the uncompressed request payload body after transport decoding. Not
+ // set if transport encoding not used.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 5493
+ HTTPRequestContentLengthUncompressedKey = attribute.Key("http.request_content_length_uncompressed")
+ // The size of the response payload body in bytes. This is the number of bytes
+ // transferred excluding headers and is often, but not always, present as the
+ // [Content-Length](https://tools.ietf.org/html/rfc7230#section-3.3.2) header. For
+ // requests using transport encoding, this should be the compressed size.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 3495
+ HTTPResponseContentLengthKey = attribute.Key("http.response_content_length")
+ // The size of the uncompressed response payload body after transport decoding.
+ // Not set if transport encoding not used.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 5493
+ HTTPResponseContentLengthUncompressedKey = attribute.Key("http.response_content_length_uncompressed")
+)
+
+var (
+ // HTTP 1.0
+ HTTPFlavorHTTP10 = HTTPFlavorKey.String("1.0")
+ // HTTP 1.1
+ HTTPFlavorHTTP11 = HTTPFlavorKey.String("1.1")
+ // HTTP 2
+ HTTPFlavorHTTP20 = HTTPFlavorKey.String("2.0")
+ // SPDY protocol
+ HTTPFlavorSPDY = HTTPFlavorKey.String("SPDY")
+ // QUIC protocol
+ HTTPFlavorQUIC = HTTPFlavorKey.String("QUIC")
+)
+
+// Semantic Convention for HTTP Server
+const (
+ // The primary server name of the matched virtual host. This should be obtained
+ // via configuration. If no such configuration can be obtained, this attribute
+ // MUST NOT be set ( `net.host.name` should be used instead).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'example.com'
+ // Note: `http.url` is usually not readily available on the server side but would
+ // have to be assembled in a cumbersome and sometimes lossy process from other
+ // information (see e.g. open-telemetry/opentelemetry-python/pull/148). It is thus
+ // preferred to supply the raw data that is available.
+ HTTPServerNameKey = attribute.Key("http.server_name")
+ // The matched route (path template).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '/users/:userID?'
+ HTTPRouteKey = attribute.Key("http.route")
+ // The IP address of the original client behind all proxies, if known (e.g. from
+ // [X-Forwarded-For](https://developer.mozilla.org/en-
+ // US/docs/Web/HTTP/Headers/X-Forwarded-For)).
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '83.164.160.102'
+ // Note: This is not necessarily the same as `net.peer.ip`, which would identify
+ // the network-level peer, which may be a proxy.
+ HTTPClientIPKey = attribute.Key("http.client_ip")
+)
+
+// Attributes that exist for multiple DynamoDB request types.
+const (
+ // The keys in the `RequestItems` object field.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: 'Users', 'Cats'
+ AWSDynamoDBTableNamesKey = attribute.Key("aws.dynamodb.table_names")
+ // The JSON-serialized value of each item in the `ConsumedCapacity` response
+ // field.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: '{ "CapacityUnits": number, "GlobalSecondaryIndexes": { "string" : {
+ // "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits":
+ // number } }, "LocalSecondaryIndexes": { "string" : { "CapacityUnits": number,
+ // "ReadCapacityUnits": number, "WriteCapacityUnits": number } },
+ // "ReadCapacityUnits": number, "Table": { "CapacityUnits": number,
+ // "ReadCapacityUnits": number, "WriteCapacityUnits": number }, "TableName":
+ // "string", "WriteCapacityUnits": number }'
+ AWSDynamoDBConsumedCapacityKey = attribute.Key("aws.dynamodb.consumed_capacity")
+ // The JSON-serialized value of the `ItemCollectionMetrics` response field.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '{ "string" : [ { "ItemCollectionKey": { "string" : { "B": blob,
+ // "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { "string" :
+ // "AttributeValue" }, "N": "string", "NS": [ "string" ], "NULL": boolean, "S":
+ // "string", "SS": [ "string" ] } }, "SizeEstimateRangeGB": [ number ] } ] }'
+ AWSDynamoDBItemCollectionMetricsKey = attribute.Key("aws.dynamodb.item_collection_metrics")
+ // The value of the `ProvisionedThroughput.ReadCapacityUnits` request parameter.
+ //
+ // Type: double
+ // Required: No
+ // Stability: stable
+ // Examples: 1.0, 2.0
+ AWSDynamoDBProvisionedReadCapacityKey = attribute.Key("aws.dynamodb.provisioned_read_capacity")
+ // The value of the `ProvisionedThroughput.WriteCapacityUnits` request parameter.
+ //
+ // Type: double
+ // Required: No
+ // Stability: stable
+ // Examples: 1.0, 2.0
+ AWSDynamoDBProvisionedWriteCapacityKey = attribute.Key("aws.dynamodb.provisioned_write_capacity")
+ // The value of the `ConsistentRead` request parameter.
+ //
+ // Type: boolean
+ // Required: No
+ // Stability: stable
+ AWSDynamoDBConsistentReadKey = attribute.Key("aws.dynamodb.consistent_read")
+ // The value of the `ProjectionExpression` request parameter.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Title', 'Title, Price, Color', 'Title, Description, RelatedItems,
+ // ProductReviews'
+ AWSDynamoDBProjectionKey = attribute.Key("aws.dynamodb.projection")
+ // The value of the `Limit` request parameter.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 10
+ AWSDynamoDBLimitKey = attribute.Key("aws.dynamodb.limit")
+ // The value of the `AttributesToGet` request parameter.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: 'lives', 'id'
+ AWSDynamoDBAttributesToGetKey = attribute.Key("aws.dynamodb.attributes_to_get")
+ // The value of the `IndexName` request parameter.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'name_to_group'
+ AWSDynamoDBIndexNameKey = attribute.Key("aws.dynamodb.index_name")
+ // The value of the `Select` request parameter.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'ALL_ATTRIBUTES', 'COUNT'
+ AWSDynamoDBSelectKey = attribute.Key("aws.dynamodb.select")
+)
+
+// DynamoDB.CreateTable
+const (
+ // The JSON-serialized value of each item of the `GlobalSecondaryIndexes` request
+ // field
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: '{ "IndexName": "string", "KeySchema": [ { "AttributeName": "string",
+ // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ],
+ // "ProjectionType": "string" }, "ProvisionedThroughput": { "ReadCapacityUnits":
+ // number, "WriteCapacityUnits": number } }'
+ AWSDynamoDBGlobalSecondaryIndexesKey = attribute.Key("aws.dynamodb.global_secondary_indexes")
+ // The JSON-serialized value of each item of the `LocalSecondaryIndexes` request
+ // field.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: '{ "IndexARN": "string", "IndexName": "string", "IndexSizeBytes":
+ // number, "ItemCount": number, "KeySchema": [ { "AttributeName": "string",
+ // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ],
+ // "ProjectionType": "string" } }'
+ AWSDynamoDBLocalSecondaryIndexesKey = attribute.Key("aws.dynamodb.local_secondary_indexes")
+)
+
+// DynamoDB.ListTables
+const (
+ // The value of the `ExclusiveStartTableName` request parameter.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Users', 'CatsTable'
+ AWSDynamoDBExclusiveStartTableKey = attribute.Key("aws.dynamodb.exclusive_start_table")
+ // The the number of items in the `TableNames` response parameter.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 20
+ AWSDynamoDBTableCountKey = attribute.Key("aws.dynamodb.table_count")
+)
+
+// DynamoDB.Query
+const (
+ // The value of the `ScanIndexForward` request parameter.
+ //
+ // Type: boolean
+ // Required: No
+ // Stability: stable
+ AWSDynamoDBScanForwardKey = attribute.Key("aws.dynamodb.scan_forward")
+)
+
+// DynamoDB.Scan
+const (
+ // The value of the `Segment` request parameter.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 10
+ AWSDynamoDBSegmentKey = attribute.Key("aws.dynamodb.segment")
+ // The value of the `TotalSegments` request parameter.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 100
+ AWSDynamoDBTotalSegmentsKey = attribute.Key("aws.dynamodb.total_segments")
+ // The value of the `Count` response parameter.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 10
+ AWSDynamoDBCountKey = attribute.Key("aws.dynamodb.count")
+ // The value of the `ScannedCount` response parameter.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 50
+ AWSDynamoDBScannedCountKey = attribute.Key("aws.dynamodb.scanned_count")
+)
+
+// DynamoDB.UpdateTable
+const (
+ // The JSON-serialized value of each item in the `AttributeDefinitions` request
+ // field.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: '{ "AttributeName": "string", "AttributeType": "string" }'
+ AWSDynamoDBAttributeDefinitionsKey = attribute.Key("aws.dynamodb.attribute_definitions")
+ // The JSON-serialized value of each item in the the `GlobalSecondaryIndexUpdates`
+ // request field.
+ //
+ // Type: string[]
+ // Required: No
+ // Stability: stable
+ // Examples: '{ "Create": { "IndexName": "string", "KeySchema": [ {
+ // "AttributeName": "string", "KeyType": "string" } ], "Projection": {
+ // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" },
+ // "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits":
+ // number } }'
+ AWSDynamoDBGlobalSecondaryIndexUpdatesKey = attribute.Key("aws.dynamodb.global_secondary_index_updates")
+)
+
+// This document defines the attributes used in messaging systems.
+const (
+ // A string identifying the messaging system.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'kafka', 'rabbitmq', 'activemq', 'AmazonSQS'
+ MessagingSystemKey = attribute.Key("messaging.system")
+ // The message destination name. This might be equal to the span name but is
+ // required nevertheless.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'MyQueue', 'MyTopic'
+ MessagingDestinationKey = attribute.Key("messaging.destination")
+ // The kind of message destination
+ //
+ // Type: Enum
+ // Required: Required only if the message destination is either a `queue` or
+ // `topic`.
+ // Stability: stable
+ MessagingDestinationKindKey = attribute.Key("messaging.destination_kind")
+ // A boolean that is true if the message destination is temporary.
+ //
+ // Type: boolean
+ // Required: If missing, it is assumed to be false.
+ // Stability: stable
+ MessagingTempDestinationKey = attribute.Key("messaging.temp_destination")
+ // The name of the transport protocol.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'AMQP', 'MQTT'
+ MessagingProtocolKey = attribute.Key("messaging.protocol")
+ // The version of the transport protocol.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '0.9.1'
+ MessagingProtocolVersionKey = attribute.Key("messaging.protocol_version")
+ // Connection string.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'tibjmsnaming://localhost:7222',
+ // 'https://queue.amazonaws.com/80398EXAMPLE/MyQueue'
+ MessagingURLKey = attribute.Key("messaging.url")
+ // A value used by the messaging system as an identifier for the message,
+ // represented as a string.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '452a7c7c7c7048c2f887f61572b18fc2'
+ MessagingMessageIDKey = attribute.Key("messaging.message_id")
+ // The [conversation ID](#conversations) identifying the conversation to which the
+ // message belongs, represented as a string. Sometimes called "Correlation ID".
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'MyConversationID'
+ MessagingConversationIDKey = attribute.Key("messaging.conversation_id")
+ // The (uncompressed) size of the message payload in bytes. Also use this
+ // attribute if it is unknown whether the compressed or uncompressed payload size
+ // is reported.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 2738
+ MessagingMessagePayloadSizeBytesKey = attribute.Key("messaging.message_payload_size_bytes")
+ // The compressed size of the message payload in bytes.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 2048
+ MessagingMessagePayloadCompressedSizeBytesKey = attribute.Key("messaging.message_payload_compressed_size_bytes")
+)
+
+var (
+ // A message sent to a queue
+ MessagingDestinationKindQueue = MessagingDestinationKindKey.String("queue")
+ // A message sent to a topic
+ MessagingDestinationKindTopic = MessagingDestinationKindKey.String("topic")
+)
+
+// Semantic convention for a consumer of messages received from a messaging system
+const (
+ // A string identifying the kind of message consumption as defined in the
+ // [Operation names](#operation-names) section above. If the operation is "send",
+ // this attribute MUST NOT be set, since the operation can be inferred from the
+ // span kind in that case.
+ //
+ // Type: Enum
+ // Required: No
+ // Stability: stable
+ MessagingOperationKey = attribute.Key("messaging.operation")
+)
+
+var (
+ // receive
+ MessagingOperationReceive = MessagingOperationKey.String("receive")
+ // process
+ MessagingOperationProcess = MessagingOperationKey.String("process")
+)
+
+// Attributes for RabbitMQ
+const (
+ // RabbitMQ message routing key.
+ //
+ // Type: string
+ // Required: Unless it is empty.
+ // Stability: stable
+ // Examples: 'myKey'
+ MessagingRabbitmqRoutingKeyKey = attribute.Key("messaging.rabbitmq.routing_key")
+)
+
+// Attributes for Apache Kafka
+const (
+ // Message keys in Kafka are used for grouping alike messages to ensure they're
+ // processed on the same partition. They differ from `messaging.message_id` in
+ // that they're not unique. If the key is `null`, the attribute MUST NOT be set.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'myKey'
+ // Note: If the key type is not string, it's string representation has to be
+ // supplied for the attribute. If the key has no unambiguous, canonical string
+ // form, don't include its value.
+ MessagingKafkaMessageKeyKey = attribute.Key("messaging.kafka.message_key")
+ // Name of the Kafka Consumer Group that is handling the message. Only applies to
+ // consumers, not producers.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'my-group'
+ MessagingKafkaConsumerGroupKey = attribute.Key("messaging.kafka.consumer_group")
+ // Client ID for the Consumer or Producer that is handling the message.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'client-5'
+ MessagingKafkaClientIDKey = attribute.Key("messaging.kafka.client_id")
+ // Partition the message is sent to.
+ //
+ // Type: int
+ // Required: No
+ // Stability: stable
+ // Examples: 2
+ MessagingKafkaPartitionKey = attribute.Key("messaging.kafka.partition")
+ // A boolean that is true if the message is a tombstone.
+ //
+ // Type: boolean
+ // Required: If missing, it is assumed to be false.
+ // Stability: stable
+ MessagingKafkaTombstoneKey = attribute.Key("messaging.kafka.tombstone")
+)
+
+// This document defines semantic conventions for remote procedure calls.
+const (
+ // A string identifying the remoting system.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'grpc', 'java_rmi', 'wcf'
+ RPCSystemKey = attribute.Key("rpc.system")
+ // The full name of the service being called, including its package name, if
+ // applicable.
+ //
+ // Type: string
+ // Required: No, but recommended
+ // Stability: stable
+ // Examples: 'myservice.EchoService'
+ RPCServiceKey = attribute.Key("rpc.service")
+ // The name of the method being called, must be equal to the $method part in the
+ // span name.
+ //
+ // Type: string
+ // Required: No, but recommended
+ // Stability: stable
+ // Examples: 'exampleMethod'
+ RPCMethodKey = attribute.Key("rpc.method")
+)
+
+// Tech-specific attributes for gRPC.
+const (
+ // The [numeric status
+ // code](https://github.com/grpc/grpc/blob/v1.33.2/doc/statuscodes.md) of the gRPC
+ // request.
+ //
+ // Type: Enum
+ // Required: Always
+ // Stability: stable
+ // Examples: 0, 1, 16
+ RPCGRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
+)
+
+var (
+ // OK
+ RPCGRPCStatusCodeOk = RPCGRPCStatusCodeKey.Int(0)
+ // CANCELLED
+ RPCGRPCStatusCodeCancelled = RPCGRPCStatusCodeKey.Int(1)
+ // UNKNOWN
+ RPCGRPCStatusCodeUnknown = RPCGRPCStatusCodeKey.Int(2)
+ // INVALID_ARGUMENT
+ RPCGRPCStatusCodeInvalidArgument = RPCGRPCStatusCodeKey.Int(3)
+ // DEADLINE_EXCEEDED
+ RPCGRPCStatusCodeDeadlineExceeded = RPCGRPCStatusCodeKey.Int(4)
+ // NOT_FOUND
+ RPCGRPCStatusCodeNotFound = RPCGRPCStatusCodeKey.Int(5)
+ // ALREADY_EXISTS
+ RPCGRPCStatusCodeAlreadyExists = RPCGRPCStatusCodeKey.Int(6)
+ // PERMISSION_DENIED
+ RPCGRPCStatusCodePermissionDenied = RPCGRPCStatusCodeKey.Int(7)
+ // RESOURCE_EXHAUSTED
+ RPCGRPCStatusCodeResourceExhausted = RPCGRPCStatusCodeKey.Int(8)
+ // FAILED_PRECONDITION
+ RPCGRPCStatusCodeFailedPrecondition = RPCGRPCStatusCodeKey.Int(9)
+ // ABORTED
+ RPCGRPCStatusCodeAborted = RPCGRPCStatusCodeKey.Int(10)
+ // OUT_OF_RANGE
+ RPCGRPCStatusCodeOutOfRange = RPCGRPCStatusCodeKey.Int(11)
+ // UNIMPLEMENTED
+ RPCGRPCStatusCodeUnimplemented = RPCGRPCStatusCodeKey.Int(12)
+ // INTERNAL
+ RPCGRPCStatusCodeInternal = RPCGRPCStatusCodeKey.Int(13)
+ // UNAVAILABLE
+ RPCGRPCStatusCodeUnavailable = RPCGRPCStatusCodeKey.Int(14)
+ // DATA_LOSS
+ RPCGRPCStatusCodeDataLoss = RPCGRPCStatusCodeKey.Int(15)
+ // UNAUTHENTICATED
+ RPCGRPCStatusCodeUnauthenticated = RPCGRPCStatusCodeKey.Int(16)
+)
+
+// Tech-specific attributes for [JSON RPC](https://www.jsonrpc.org/).
+const (
+ // Protocol version as in `jsonrpc` property of request/response. Since JSON-RPC
+ // 1.0 does not specify this, the value can be omitted.
+ //
+ // Type: string
+ // Required: If missing, it is assumed to be "1.0".
+ // Stability: stable
+ // Examples: '2.0', '1.0'
+ RPCJsonrpcVersionKey = attribute.Key("rpc.jsonrpc.version")
+ // `method` property from request. Unlike `rpc.method`, this may not relate to the
+ // actual method being called. Useful for client-side traces since client does not
+ // know what will be called on the server.
+ //
+ // Type: string
+ // Required: Always
+ // Stability: stable
+ // Examples: 'users.create', 'get_users'
+ RPCJsonrpcMethodKey = attribute.Key("rpc.jsonrpc.method")
+ // `id` property of request or response. Since protocol allows id to be int,
+ // string, `null` or missing (for notifications), value is expected to be cast to
+ // string for simplicity. Use empty string in case of `null` value. Omit entirely
+ // if this is a notification.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: '10', 'request-7', ''
+ RPCJsonrpcRequestIDKey = attribute.Key("rpc.jsonrpc.request_id")
+ // `error.code` property of response if it is an error response.
+ //
+ // Type: int
+ // Required: If missing, response is assumed to be successful.
+ // Stability: stable
+ // Examples: -32700, 100
+ RPCJsonrpcErrorCodeKey = attribute.Key("rpc.jsonrpc.error_code")
+ // `error.message` property of response if it is an error response.
+ //
+ // Type: string
+ // Required: No
+ // Stability: stable
+ // Examples: 'Parse error', 'User already exists'
+ RPCJsonrpcErrorMessageKey = attribute.Key("rpc.jsonrpc.error_message")
+)
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
index 4f506f8791..199c21d27a 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build go1.7 && amd64 && gc && !purego
+//go:build amd64 && gc && !purego
package blake2b
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
index 353bb7cac5..9ae8206c20 100644
--- a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build go1.7 && amd64 && gc && !purego
+//go:build amd64 && gc && !purego
#include "textflag.h"
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
deleted file mode 100644
index 1d0770abba..0000000000
--- a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 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.
-
-//go:build !go1.7 && amd64 && gc && !purego
-
-package blake2b
-
-import "golang.org/x/sys/cpu"
-
-func init() {
- useSSE4 = cpu.X86.HasSSE41
-}
-
-//go:noescape
-func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
-
-func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
- if useSSE4 {
- hashBlocksSSE4(h, c, flag, blocks)
- } else {
- hashBlocksGeneric(h, c, flag, blocks)
- }
-}
diff --git a/vendor/golang.org/x/crypto/blake2b/register.go b/vendor/golang.org/x/crypto/blake2b/register.go
index d9fcac3a4d..54e446e1d2 100644
--- a/vendor/golang.org/x/crypto/blake2b/register.go
+++ b/vendor/golang.org/x/crypto/blake2b/register.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build go1.9
-
package blake2b
import (
diff --git a/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go
deleted file mode 100644
index d33c8890fc..0000000000
--- a/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2019 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.
-
-//go:build !go1.13
-
-package poly1305
-
-// Generic fallbacks for the math/bits intrinsics, copied from
-// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had
-// variable time fallbacks until Go 1.13.
-
-func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
- sum = x + y + carry
- carryOut = ((x & y) | ((x | y) &^ sum)) >> 63
- return
-}
-
-func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
- diff = x - y - borrow
- borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63
- return
-}
-
-func bitsMul64(x, y uint64) (hi, lo uint64) {
- const mask32 = 1<<32 - 1
- x0 := x & mask32
- x1 := x >> 32
- y0 := y & mask32
- y1 := y >> 32
- w0 := x0 * y0
- t := x1*y0 + w0>>32
- w1 := t & mask32
- w2 := t >> 32
- w1 += x0 * y1
- hi = x1*y1 + w2 + w1>>32
- lo = x * y
- return
-}
diff --git a/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go
deleted file mode 100644
index 495c1fa697..0000000000
--- a/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2019 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.
-
-//go:build go1.13
-
-package poly1305
-
-import "math/bits"
-
-func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
- return bits.Add64(x, y, carry)
-}
-
-func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
- return bits.Sub64(x, y, borrow)
-}
-
-func bitsMul64(x, y uint64) (hi, lo uint64) {
- return bits.Mul64(x, y)
-}
diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go
index e041da5ea3..ec2202bd7d 100644
--- a/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go
+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go
@@ -7,7 +7,10 @@
package poly1305
-import "encoding/binary"
+import (
+ "encoding/binary"
+ "math/bits"
+)
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag
// for a 64 bytes message is approximately
@@ -114,13 +117,13 @@ type uint128 struct {
}
func mul64(a, b uint64) uint128 {
- hi, lo := bitsMul64(a, b)
+ hi, lo := bits.Mul64(a, b)
return uint128{lo, hi}
}
func add128(a, b uint128) uint128 {
- lo, c := bitsAdd64(a.lo, b.lo, 0)
- hi, c := bitsAdd64(a.hi, b.hi, c)
+ lo, c := bits.Add64(a.lo, b.lo, 0)
+ hi, c := bits.Add64(a.hi, b.hi, c)
if c != 0 {
panic("poly1305: unexpected overflow")
}
@@ -155,8 +158,8 @@ func updateGeneric(state *macState, msg []byte) {
// hide leading zeroes. For full chunks, that's 1 << 128, so we can just
// add 1 to the most significant (2¹²⁸) limb, h2.
if len(msg) >= TagSize {
- h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
- h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
+ h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
+ h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
h2 += c + 1
msg = msg[TagSize:]
@@ -165,8 +168,8 @@ func updateGeneric(state *macState, msg []byte) {
copy(buf[:], msg)
buf[len(msg)] = 1
- h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
- h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
+ h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
+ h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
h2 += c
msg = nil
@@ -219,9 +222,9 @@ func updateGeneric(state *macState, msg []byte) {
m3 := h2r1
t0 := m0.lo
- t1, c := bitsAdd64(m1.lo, m0.hi, 0)
- t2, c := bitsAdd64(m2.lo, m1.hi, c)
- t3, _ := bitsAdd64(m3.lo, m2.hi, c)
+ t1, c := bits.Add64(m1.lo, m0.hi, 0)
+ t2, c := bits.Add64(m2.lo, m1.hi, c)
+ t3, _ := bits.Add64(m3.lo, m2.hi, c)
// Now we have the result as 4 64-bit limbs, and we need to reduce it
// modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do
@@ -243,14 +246,14 @@ func updateGeneric(state *macState, msg []byte) {
// To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c.
- h0, c = bitsAdd64(h0, cc.lo, 0)
- h1, c = bitsAdd64(h1, cc.hi, c)
+ h0, c = bits.Add64(h0, cc.lo, 0)
+ h1, c = bits.Add64(h1, cc.hi, c)
h2 += c
cc = shiftRightBy2(cc)
- h0, c = bitsAdd64(h0, cc.lo, 0)
- h1, c = bitsAdd64(h1, cc.hi, c)
+ h0, c = bits.Add64(h0, cc.lo, 0)
+ h1, c = bits.Add64(h1, cc.hi, c)
h2 += c
// h2 is at most 3 + 1 + 1 = 5, making the whole of h at most
@@ -287,9 +290,9 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
// in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the
// result if the subtraction underflows, and t otherwise.
- hMinusP0, b := bitsSub64(h0, p0, 0)
- hMinusP1, b := bitsSub64(h1, p1, b)
- _, b = bitsSub64(h2, p2, b)
+ hMinusP0, b := bits.Sub64(h0, p0, 0)
+ hMinusP1, b := bits.Sub64(h1, p1, b)
+ _, b = bits.Sub64(h2, p2, b)
// h = h if h < p else h - p
h0 = select64(b, h0, hMinusP0)
@@ -301,8 +304,8 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
//
// by just doing a wide addition with the 128 low bits of h and discarding
// the overflow.
- h0, c := bitsAdd64(h0, s[0], 0)
- h1, _ = bitsAdd64(h1, s[1], c)
+ h0, c := bits.Add64(h0, s[0], 0)
+ h1, _ = bits.Add64(h1, s[1], c)
binary.LittleEndian.PutUint64(out[0:8], h0)
binary.LittleEndian.PutUint64(out[8:16], h1)
diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s
index d2ca5deeb9..b3c1699bff 100644
--- a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s
+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s
@@ -19,15 +19,14 @@
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
MULLD r0, h0, t0; \
- MULLD r0, h1, t4; \
MULHDU r0, h0, t1; \
+ MULLD r0, h1, t4; \
MULHDU r0, h1, t5; \
ADDC t4, t1, t1; \
MULLD r0, h2, t2; \
- ADDZE t5; \
MULHDU r1, h0, t4; \
MULLD r1, h0, h0; \
- ADD t5, t2, t2; \
+ ADDE t5, t2, t2; \
ADDC h0, t1, t1; \
MULLD h2, r1, t3; \
ADDZE t4, h0; \
@@ -37,13 +36,11 @@
ADDE t5, t3, t3; \
ADDC h0, t2, t2; \
MOVD $-4, t4; \
- MOVD t0, h0; \
- MOVD t1, h1; \
ADDZE t3; \
- ANDCC $3, t2, h2; \
- AND t2, t4, t0; \
+ RLDICL $0, t2, $62, h2; \
+ AND t2, t4, h0; \
ADDC t0, h0, h0; \
- ADDE t3, h1, h1; \
+ ADDE t3, t1, h1; \
SLD $62, t3, t4; \
SRD $2, t2; \
ADDZE h2; \
@@ -75,6 +72,7 @@ TEXT ·update(SB), $0-32
loop:
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
+ PCALIGN $16
multiply:
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
ADD $-16, R5
diff --git a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s
index 8fb26aebb2..1f53938861 100644
--- a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s
+++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s
@@ -319,9 +319,9 @@
MOVQ rDi, _si(oState); \
MOVQ rDo, _so(oState) \
-// func keccakF1600(state *[25]uint64)
+// func keccakF1600(a *[25]uint64)
TEXT ·keccakF1600(SB), 0, $200-8
- MOVQ state+0(FP), rpState
+ MOVQ a+0(FP), rpState
// Convert the user state into an internal state
NOTQ _be(rpState)
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
index c0834c00df..cc0bb7ab64 100644
--- a/vendor/golang.org/x/crypto/ssh/channel.go
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
@@ -187,9 +187,11 @@ type channel struct {
pending *buffer
extPending *buffer
- // windowMu protects myWindow, the flow-control window.
- windowMu sync.Mutex
- myWindow uint32
+ // windowMu protects myWindow, the flow-control window, and myConsumed,
+ // the number of bytes consumed since we last increased myWindow
+ windowMu sync.Mutex
+ myWindow uint32
+ myConsumed uint32
// writeMu serializes calls to mux.conn.writePacket() and
// protects sentClose and packetPool. This mutex must be
@@ -332,14 +334,24 @@ func (ch *channel) handleData(packet []byte) error {
return nil
}
-func (c *channel) adjustWindow(n uint32) error {
+func (c *channel) adjustWindow(adj uint32) error {
c.windowMu.Lock()
- // Since myWindow is managed on our side, and can never exceed
- // the initial window setting, we don't worry about overflow.
- c.myWindow += uint32(n)
+ // Since myConsumed and myWindow are managed on our side, and can never
+ // exceed the initial window setting, we don't worry about overflow.
+ c.myConsumed += adj
+ var sendAdj uint32
+ if (channelWindowSize-c.myWindow > 3*c.maxIncomingPayload) ||
+ (c.myWindow < channelWindowSize/2) {
+ sendAdj = c.myConsumed
+ c.myConsumed = 0
+ c.myWindow += sendAdj
+ }
c.windowMu.Unlock()
+ if sendAdj == 0 {
+ return nil
+ }
return c.sendMessage(windowAdjustMsg{
- AdditionalBytes: uint32(n),
+ AdditionalBytes: sendAdj,
})
}
diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go
index bdc356cbdf..fd8c49749e 100644
--- a/vendor/golang.org/x/crypto/ssh/client.go
+++ b/vendor/golang.org/x/crypto/ssh/client.go
@@ -82,7 +82,7 @@ func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan
if err := conn.clientHandshake(addr, &fullConf); err != nil {
c.Close()
- return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
+ return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %w", err)
}
conn.mux = newMux(conn.transport)
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 49bbba7692..56cdc7c21c 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -35,6 +35,16 @@ type keyingTransport interface {
// direction will be effected if a msgNewKeys message is sent
// or received.
prepareKeyChange(*algorithms, *kexResult) error
+
+ // setStrictMode sets the strict KEX mode, notably triggering
+ // sequence number resets on sending or receiving msgNewKeys.
+ // If the sequence number is already > 1 when setStrictMode
+ // is called, an error is returned.
+ setStrictMode() error
+
+ // setInitialKEXDone indicates to the transport that the initial key exchange
+ // was completed
+ setInitialKEXDone()
}
// handshakeTransport implements rekeying on top of a keyingTransport
@@ -100,6 +110,10 @@ type handshakeTransport struct {
// The session ID or nil if first kex did not complete yet.
sessionID []byte
+
+ // strictMode indicates if the other side of the handshake indicated
+ // that we should be following the strict KEX protocol restrictions.
+ strictMode bool
}
type pendingKex struct {
@@ -209,7 +223,10 @@ func (t *handshakeTransport) readLoop() {
close(t.incoming)
break
}
- if p[0] == msgIgnore || p[0] == msgDebug {
+ // If this is the first kex, and strict KEX mode is enabled,
+ // we don't ignore any messages, as they may be used to manipulate
+ // the packet sequence numbers.
+ if !(t.sessionID == nil && t.strictMode) && (p[0] == msgIgnore || p[0] == msgDebug) {
continue
}
t.incoming <- p
@@ -441,6 +458,11 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
return successPacket, nil
}
+const (
+ kexStrictClient = "kex-strict-c-v00@openssh.com"
+ kexStrictServer = "kex-strict-s-v00@openssh.com"
+)
+
// sendKexInit sends a key change message.
func (t *handshakeTransport) sendKexInit() error {
t.mu.Lock()
@@ -454,7 +476,6 @@ func (t *handshakeTransport) sendKexInit() error {
}
msg := &kexInitMsg{
- KexAlgos: t.config.KeyExchanges,
CiphersClientServer: t.config.Ciphers,
CiphersServerClient: t.config.Ciphers,
MACsClientServer: t.config.MACs,
@@ -464,6 +485,13 @@ func (t *handshakeTransport) sendKexInit() error {
}
io.ReadFull(rand.Reader, msg.Cookie[:])
+ // We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm,
+ // and possibly to add the ext-info extension algorithm. Since the slice may be the
+ // user owned KeyExchanges, we create our own slice in order to avoid using user
+ // owned memory by mistake.
+ msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+2) // room for kex-strict and ext-info
+ msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
+
isServer := len(t.hostKeys) > 0
if isServer {
for _, k := range t.hostKeys {
@@ -488,17 +516,24 @@ func (t *handshakeTransport) sendKexInit() error {
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
}
}
+
+ if t.sessionID == nil {
+ msg.KexAlgos = append(msg.KexAlgos, kexStrictServer)
+ }
} else {
msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
// As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what
// algorithms the server supports for public key authentication. See RFC
// 8308, Section 2.1.
+ //
+ // We also send the strict KEX mode extension algorithm, in order to opt
+ // into the strict KEX mode.
if firstKeyExchange := t.sessionID == nil; firstKeyExchange {
- msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1)
- msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
msg.KexAlgos = append(msg.KexAlgos, "ext-info-c")
+ msg.KexAlgos = append(msg.KexAlgos, kexStrictClient)
}
+
}
packet := Marshal(msg)
@@ -604,6 +639,13 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
return err
}
+ if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) {
+ t.strictMode = true
+ if err := t.conn.setStrictMode(); err != nil {
+ return err
+ }
+ }
+
// We don't send FirstKexFollows, but we handle receiving it.
//
// RFC 4253 section 7 defines the kex and the agreement method for
@@ -679,6 +721,12 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
return unexpectedMessageError(msgNewKeys, packet[0])
}
+ if firstKeyExchange {
+ // Indicates to the transport that the first key exchange is completed
+ // after receiving SSH_MSG_NEWKEYS.
+ t.conn.setInitialKEXDone()
+ }
+
return nil
}
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 7f0c236a9a..c2dfe3268c 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -213,6 +213,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
} else {
for _, algo := range fullConf.PublicKeyAuthAlgorithms {
if !contains(supportedPubKeyAuthAlgos, algo) {
+ c.Close()
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
}
}
@@ -220,6 +221,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
// Check if the config contains any unsupported key exchanges
for _, kex := range fullConf.KeyExchanges {
if _, ok := serverForbiddenKexAlgos[kex]; ok {
+ c.Close()
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
index da015801ea..0424d2d37c 100644
--- a/vendor/golang.org/x/crypto/ssh/transport.go
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -49,6 +49,9 @@ type transport struct {
rand io.Reader
isClient bool
io.Closer
+
+ strictMode bool
+ initialKEXDone bool
}
// packetCipher represents a combination of SSH encryption/MAC
@@ -74,6 +77,18 @@ type connectionState struct {
pendingKeyChange chan packetCipher
}
+func (t *transport) setStrictMode() error {
+ if t.reader.seqNum != 1 {
+ return errors.New("ssh: sequence number != 1 when strict KEX mode requested")
+ }
+ t.strictMode = true
+ return nil
+}
+
+func (t *transport) setInitialKEXDone() {
+ t.initialKEXDone = true
+}
+
// prepareKeyChange sets up key material for a keychange. The key changes in
// both directions are triggered by reading and writing a msgNewKey packet
// respectively.
@@ -112,11 +127,12 @@ func (t *transport) printPacket(p []byte, write bool) {
// Read and decrypt next packet.
func (t *transport) readPacket() (p []byte, err error) {
for {
- p, err = t.reader.readPacket(t.bufReader)
+ p, err = t.reader.readPacket(t.bufReader, t.strictMode)
if err != nil {
break
}
- if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
+ // in strict mode we pass through DEBUG and IGNORE packets only during the initial KEX
+ if len(p) == 0 || (t.strictMode && !t.initialKEXDone) || (p[0] != msgIgnore && p[0] != msgDebug) {
break
}
}
@@ -127,7 +143,7 @@ func (t *transport) readPacket() (p []byte, err error) {
return p, err
}
-func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
+func (s *connectionState) readPacket(r *bufio.Reader, strictMode bool) ([]byte, error) {
packet, err := s.packetCipher.readCipherPacket(s.seqNum, r)
s.seqNum++
if err == nil && len(packet) == 0 {
@@ -140,6 +156,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
select {
case cipher := <-s.pendingKeyChange:
s.packetCipher = cipher
+ if strictMode {
+ s.seqNum = 0
+ }
default:
return nil, errors.New("ssh: got bogus newkeys message")
}
@@ -170,10 +189,10 @@ func (t *transport) writePacket(packet []byte) error {
if debugTransport {
t.printPacket(packet, true)
}
- return t.writer.writePacket(t.bufWriter, t.rand, packet)
+ return t.writer.writePacket(t.bufWriter, t.rand, packet, t.strictMode)
}
-func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
+func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte, strictMode bool) error {
changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet)
@@ -188,6 +207,9 @@ func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []
select {
case cipher := <-s.pendingKeyChange:
s.packetCipher = cipher
+ if strictMode {
+ s.seqNum = 0
+ }
default:
panic("ssh: no key material for msgNewKeys")
}
diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go
index de67f938a1..3c57880d69 100644
--- a/vendor/golang.org/x/net/html/token.go
+++ b/vendor/golang.org/x/net/html/token.go
@@ -910,9 +910,6 @@ func (z *Tokenizer) readTagAttrKey() {
return
}
switch c {
- case ' ', '\n', '\r', '\t', '\f', '/':
- z.pendingAttr[0].end = z.raw.end - 1
- return
case '=':
if z.pendingAttr[0].start+1 == z.raw.end {
// WHATWG 13.2.5.32, if we see an equals sign before the attribute name
@@ -920,7 +917,9 @@ func (z *Tokenizer) readTagAttrKey() {
continue
}
fallthrough
- case '>':
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ // WHATWG 13.2.5.33 Attribute name state
+ // We need to reconsume the char in the after attribute name state to support the / character
z.raw.end--
z.pendingAttr[0].end = z.raw.end
return
@@ -939,6 +938,11 @@ func (z *Tokenizer) readTagAttrVal() {
if z.err != nil {
return
}
+ if c == '/' {
+ // WHATWG 13.2.5.34 After attribute name state
+ // U+002F SOLIDUS (/) - Switch to the self-closing start tag state.
+ return
+ }
if c != '=' {
z.raw.end--
return
diff --git a/vendor/golang.org/x/net/http/httpproxy/proxy.go b/vendor/golang.org/x/net/http/httpproxy/proxy.go
index c3bd9a1eeb..6404aaf157 100644
--- a/vendor/golang.org/x/net/http/httpproxy/proxy.go
+++ b/vendor/golang.org/x/net/http/httpproxy/proxy.go
@@ -149,10 +149,7 @@ func parseProxy(proxy string) (*url.URL, error) {
}
proxyURL, err := url.Parse(proxy)
- if err != nil ||
- (proxyURL.Scheme != "http" &&
- proxyURL.Scheme != "https" &&
- proxyURL.Scheme != "socks5") {
+ if err != nil || proxyURL.Scheme == "" || proxyURL.Host == "" {
// proxy was bogus. Try prepending "http://" to it and
// see if that parses correctly. If not, we fall
// through and complain about the original one.
diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go
index c1f6b90dc3..43557ab7e9 100644
--- a/vendor/golang.org/x/net/http2/frame.go
+++ b/vendor/golang.org/x/net/http2/frame.go
@@ -1510,13 +1510,12 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
}
func (fr *Framer) maxHeaderStringLen() int {
- v := fr.maxHeaderListSize()
- if uint32(int(v)) == v {
- return int(v)
+ v := int(fr.maxHeaderListSize())
+ if v < 0 {
+ // If maxHeaderListSize overflows an int, use no limit (0).
+ return 0
}
- // They had a crazy big number for MaxHeaderBytes anyway,
- // so give them unlimited header lengths:
- return 0
+ return v
}
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
@@ -1565,6 +1564,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
if size > remainSize {
hdec.SetEmitEnabled(false)
mh.Truncated = true
+ remainSize = 0
return
}
remainSize -= size
@@ -1577,6 +1577,36 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
var hc headersOrContinuation = hf
for {
frag := hc.HeaderBlockFragment()
+
+ // Avoid parsing large amounts of headers that we will then discard.
+ // If the sender exceeds the max header list size by too much,
+ // skip parsing the fragment and close the connection.
+ //
+ // "Too much" is either any CONTINUATION frame after we've already
+ // exceeded the max header list size (in which case remainSize is 0),
+ // or a frame whose encoded size is more than twice the remaining
+ // header list bytes we're willing to accept.
+ if int64(len(frag)) > int64(2*remainSize) {
+ if VerboseLogs {
+ log.Printf("http2: header list too large")
+ }
+ // It would be nice to send a RST_STREAM before sending the GOAWAY,
+ // but the structure of the server's frame writer makes this difficult.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+
+ // Also close the connection after any CONTINUATION frame following an
+ // invalid header, since we stop tracking the size of the headers after
+ // an invalid one.
+ if invalid != nil {
+ if VerboseLogs {
+ log.Printf("http2: invalid header: %v", invalid)
+ }
+ // It would be nice to send a RST_STREAM before sending the GOAWAY,
+ // but the structure of the server's frame writer makes this difficult.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+
if _, err := hdec.Write(frag); err != nil {
return nil, ConnectionError(ErrCodeCompression)
}
diff --git a/vendor/golang.org/x/net/http2/pipe.go b/vendor/golang.org/x/net/http2/pipe.go
index 684d984fd9..3b9f06b962 100644
--- a/vendor/golang.org/x/net/http2/pipe.go
+++ b/vendor/golang.org/x/net/http2/pipe.go
@@ -77,7 +77,10 @@ func (p *pipe) Read(d []byte) (n int, err error) {
}
}
-var errClosedPipeWrite = errors.New("write on closed buffer")
+var (
+ errClosedPipeWrite = errors.New("write on closed buffer")
+ errUninitializedPipeWrite = errors.New("write on uninitialized buffer")
+)
// Write copies bytes from p into the buffer and wakes a reader.
// It is an error to write more data than the buffer can hold.
@@ -91,6 +94,12 @@ func (p *pipe) Write(d []byte) (n int, err error) {
if p.err != nil || p.breakErr != nil {
return 0, errClosedPipeWrite
}
+ // pipe.setBuffer is never invoked, leaving the buffer uninitialized.
+ // We shouldn't try to write to an uninitialized pipe,
+ // but returning an error is better than panicking.
+ if p.b == nil {
+ return 0, errUninitializedPipeWrite
+ }
return p.b.Write(d)
}
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
index ae94c6408d..ce2e8b40ee 100644
--- a/vendor/golang.org/x/net/http2/server.go
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -124,6 +124,7 @@ type Server struct {
// IdleTimeout specifies how long until idle clients should be
// closed with a GOAWAY frame. PING frames are not considered
// activity for the purposes of IdleTimeout.
+ // If zero or negative, there is no timeout.
IdleTimeout time.Duration
// MaxUploadBufferPerConnection is the size of the initial flow
@@ -434,7 +435,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
// passes the connection off to us with the deadline already set.
// Write deadlines are set per stream in serverConn.newStream.
// Disarm the net.Conn write deadline here.
- if sc.hs.WriteTimeout != 0 {
+ if sc.hs.WriteTimeout > 0 {
sc.conn.SetWriteDeadline(time.Time{})
}
@@ -924,7 +925,7 @@ func (sc *serverConn) serve() {
sc.setConnState(http.StateActive)
sc.setConnState(http.StateIdle)
- if sc.srv.IdleTimeout != 0 {
+ if sc.srv.IdleTimeout > 0 {
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
defer sc.idleTimer.Stop()
}
@@ -1637,7 +1638,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
delete(sc.streams, st.id)
if len(sc.streams) == 0 {
sc.setConnState(http.StateIdle)
- if sc.srv.IdleTimeout != 0 {
+ if sc.srv.IdleTimeout > 0 {
sc.idleTimer.Reset(sc.srv.IdleTimeout)
}
if h1ServerKeepAlivesDisabled(sc.hs) {
@@ -2017,7 +2018,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// similar to how the http1 server works. Here it's
// technically more like the http1 Server's ReadHeaderTimeout
// (in Go 1.8), though. That's a more sane option anyway.
- if sc.hs.ReadTimeout != 0 {
+ if sc.hs.ReadTimeout > 0 {
sc.conn.SetReadDeadline(time.Time{})
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
}
@@ -2038,7 +2039,7 @@ func (sc *serverConn) upgradeRequest(req *http.Request) {
// Disable any read deadline set by the net/http package
// prior to the upgrade.
- if sc.hs.ReadTimeout != 0 {
+ if sc.hs.ReadTimeout > 0 {
sc.conn.SetReadDeadline(time.Time{})
}
@@ -2116,7 +2117,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
st.flow.conn = &sc.flow // link to conn-level counter
st.flow.add(sc.initialStreamSendWindowSize)
st.inflow.init(sc.srv.initialStreamRecvWindowSize())
- if sc.hs.WriteTimeout != 0 {
+ if sc.hs.WriteTimeout > 0 {
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
}
diff --git a/vendor/golang.org/x/net/http2/testsync.go b/vendor/golang.org/x/net/http2/testsync.go
new file mode 100644
index 0000000000..61075bd16d
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/testsync.go
@@ -0,0 +1,331 @@
+// Copyright 2024 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 http2
+
+import (
+ "context"
+ "sync"
+ "time"
+)
+
+// testSyncHooks coordinates goroutines in tests.
+//
+// For example, a call to ClientConn.RoundTrip involves several goroutines, including:
+// - the goroutine running RoundTrip;
+// - the clientStream.doRequest goroutine, which writes the request; and
+// - the clientStream.readLoop goroutine, which reads the response.
+//
+// Using testSyncHooks, a test can start a RoundTrip and identify when all these goroutines
+// are blocked waiting for some condition such as reading the Request.Body or waiting for
+// flow control to become available.
+//
+// The testSyncHooks also manage timers and synthetic time in tests.
+// This permits us to, for example, start a request and cause it to time out waiting for
+// response headers without resorting to time.Sleep calls.
+type testSyncHooks struct {
+ // active/inactive act as a mutex and condition variable.
+ //
+ // - neither chan contains a value: testSyncHooks is locked.
+ // - active contains a value: unlocked, and at least one goroutine is not blocked
+ // - inactive contains a value: unlocked, and all goroutines are blocked
+ active chan struct{}
+ inactive chan struct{}
+
+ // goroutine counts
+ total int // total goroutines
+ condwait map[*sync.Cond]int // blocked in sync.Cond.Wait
+ blocked []*testBlockedGoroutine // otherwise blocked
+
+ // fake time
+ now time.Time
+ timers []*fakeTimer
+
+ // Transport testing: Report various events.
+ newclientconn func(*ClientConn)
+ newstream func(*clientStream)
+}
+
+// testBlockedGoroutine is a blocked goroutine.
+type testBlockedGoroutine struct {
+ f func() bool // blocked until f returns true
+ ch chan struct{} // closed when unblocked
+}
+
+func newTestSyncHooks() *testSyncHooks {
+ h := &testSyncHooks{
+ active: make(chan struct{}, 1),
+ inactive: make(chan struct{}, 1),
+ condwait: map[*sync.Cond]int{},
+ }
+ h.inactive <- struct{}{}
+ h.now = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
+ return h
+}
+
+// lock acquires the testSyncHooks mutex.
+func (h *testSyncHooks) lock() {
+ select {
+ case <-h.active:
+ case <-h.inactive:
+ }
+}
+
+// waitInactive waits for all goroutines to become inactive.
+func (h *testSyncHooks) waitInactive() {
+ for {
+ <-h.inactive
+ if !h.unlock() {
+ break
+ }
+ }
+}
+
+// unlock releases the testSyncHooks mutex.
+// It reports whether any goroutines are active.
+func (h *testSyncHooks) unlock() (active bool) {
+ // Look for a blocked goroutine which can be unblocked.
+ blocked := h.blocked[:0]
+ unblocked := false
+ for _, b := range h.blocked {
+ if !unblocked && b.f() {
+ unblocked = true
+ close(b.ch)
+ } else {
+ blocked = append(blocked, b)
+ }
+ }
+ h.blocked = blocked
+
+ // Count goroutines blocked on condition variables.
+ condwait := 0
+ for _, count := range h.condwait {
+ condwait += count
+ }
+
+ if h.total > condwait+len(blocked) {
+ h.active <- struct{}{}
+ return true
+ } else {
+ h.inactive <- struct{}{}
+ return false
+ }
+}
+
+// goRun starts a new goroutine.
+func (h *testSyncHooks) goRun(f func()) {
+ h.lock()
+ h.total++
+ h.unlock()
+ go func() {
+ defer func() {
+ h.lock()
+ h.total--
+ h.unlock()
+ }()
+ f()
+ }()
+}
+
+// blockUntil indicates that a goroutine is blocked waiting for some condition to become true.
+// It waits until f returns true before proceeding.
+//
+// Example usage:
+//
+// h.blockUntil(func() bool {
+// // Is the context done yet?
+// select {
+// case <-ctx.Done():
+// default:
+// return false
+// }
+// return true
+// })
+// // Wait for the context to become done.
+// <-ctx.Done()
+//
+// The function f passed to blockUntil must be non-blocking and idempotent.
+func (h *testSyncHooks) blockUntil(f func() bool) {
+ if f() {
+ return
+ }
+ ch := make(chan struct{})
+ h.lock()
+ h.blocked = append(h.blocked, &testBlockedGoroutine{
+ f: f,
+ ch: ch,
+ })
+ h.unlock()
+ <-ch
+}
+
+// broadcast is sync.Cond.Broadcast.
+func (h *testSyncHooks) condBroadcast(cond *sync.Cond) {
+ h.lock()
+ delete(h.condwait, cond)
+ h.unlock()
+ cond.Broadcast()
+}
+
+// broadcast is sync.Cond.Wait.
+func (h *testSyncHooks) condWait(cond *sync.Cond) {
+ h.lock()
+ h.condwait[cond]++
+ h.unlock()
+}
+
+// newTimer creates a new fake timer.
+func (h *testSyncHooks) newTimer(d time.Duration) timer {
+ h.lock()
+ defer h.unlock()
+ t := &fakeTimer{
+ hooks: h,
+ when: h.now.Add(d),
+ c: make(chan time.Time),
+ }
+ h.timers = append(h.timers, t)
+ return t
+}
+
+// afterFunc creates a new fake AfterFunc timer.
+func (h *testSyncHooks) afterFunc(d time.Duration, f func()) timer {
+ h.lock()
+ defer h.unlock()
+ t := &fakeTimer{
+ hooks: h,
+ when: h.now.Add(d),
+ f: f,
+ }
+ h.timers = append(h.timers, t)
+ return t
+}
+
+func (h *testSyncHooks) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
+ ctx, cancel := context.WithCancel(ctx)
+ t := h.afterFunc(d, cancel)
+ return ctx, func() {
+ t.Stop()
+ cancel()
+ }
+}
+
+func (h *testSyncHooks) timeUntilEvent() time.Duration {
+ h.lock()
+ defer h.unlock()
+ var next time.Time
+ for _, t := range h.timers {
+ if next.IsZero() || t.when.Before(next) {
+ next = t.when
+ }
+ }
+ if d := next.Sub(h.now); d > 0 {
+ return d
+ }
+ return 0
+}
+
+// advance advances time and causes synthetic timers to fire.
+func (h *testSyncHooks) advance(d time.Duration) {
+ h.lock()
+ defer h.unlock()
+ h.now = h.now.Add(d)
+ timers := h.timers[:0]
+ for _, t := range h.timers {
+ t := t // remove after go.mod depends on go1.22
+ t.mu.Lock()
+ switch {
+ case t.when.After(h.now):
+ timers = append(timers, t)
+ case t.when.IsZero():
+ // stopped timer
+ default:
+ t.when = time.Time{}
+ if t.c != nil {
+ close(t.c)
+ }
+ if t.f != nil {
+ h.total++
+ go func() {
+ defer func() {
+ h.lock()
+ h.total--
+ h.unlock()
+ }()
+ t.f()
+ }()
+ }
+ }
+ t.mu.Unlock()
+ }
+ h.timers = timers
+}
+
+// A timer wraps a time.Timer, or a synthetic equivalent in tests.
+// Unlike time.Timer, timer is single-use: The timer channel is closed when the timer expires.
+type timer interface {
+ C() <-chan time.Time
+ Stop() bool
+ Reset(d time.Duration) bool
+}
+
+// timeTimer implements timer using real time.
+type timeTimer struct {
+ t *time.Timer
+ c chan time.Time
+}
+
+// newTimeTimer creates a new timer using real time.
+func newTimeTimer(d time.Duration) timer {
+ ch := make(chan time.Time)
+ t := time.AfterFunc(d, func() {
+ close(ch)
+ })
+ return &timeTimer{t, ch}
+}
+
+// newTimeAfterFunc creates an AfterFunc timer using real time.
+func newTimeAfterFunc(d time.Duration, f func()) timer {
+ return &timeTimer{
+ t: time.AfterFunc(d, f),
+ }
+}
+
+func (t timeTimer) C() <-chan time.Time { return t.c }
+func (t timeTimer) Stop() bool { return t.t.Stop() }
+func (t timeTimer) Reset(d time.Duration) bool { return t.t.Reset(d) }
+
+// fakeTimer implements timer using fake time.
+type fakeTimer struct {
+ hooks *testSyncHooks
+
+ mu sync.Mutex
+ when time.Time // when the timer will fire
+ c chan time.Time // closed when the timer fires; mutually exclusive with f
+ f func() // called when the timer fires; mutually exclusive with c
+}
+
+func (t *fakeTimer) C() <-chan time.Time { return t.c }
+
+func (t *fakeTimer) Stop() bool {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ stopped := t.when.IsZero()
+ t.when = time.Time{}
+ return stopped
+}
+
+func (t *fakeTimer) Reset(d time.Duration) bool {
+ if t.c != nil || t.f == nil {
+ panic("fakeTimer only supports Reset on AfterFunc timers")
+ }
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.hooks.lock()
+ defer t.hooks.unlock()
+ active := !t.when.IsZero()
+ t.when = t.hooks.now.Add(d)
+ if !active {
+ t.hooks.timers = append(t.hooks.timers, t)
+ }
+ return active
+}
diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go
index df578b86c6..ce375c8c75 100644
--- a/vendor/golang.org/x/net/http2/transport.go
+++ b/vendor/golang.org/x/net/http2/transport.go
@@ -147,6 +147,12 @@ type Transport struct {
// waiting for their turn.
StrictMaxConcurrentStreams bool
+ // IdleConnTimeout is the maximum amount of time an idle
+ // (keep-alive) connection will remain idle before closing
+ // itself.
+ // Zero means no limit.
+ IdleConnTimeout time.Duration
+
// ReadIdleTimeout is the timeout after which a health check using ping
// frame will be carried out if no frame is received on the connection.
// Note that a ping response will is considered a received frame, so if
@@ -178,6 +184,8 @@ type Transport struct {
connPoolOnce sync.Once
connPoolOrDef ClientConnPool // non-nil version of ConnPool
+
+ syncHooks *testSyncHooks
}
func (t *Transport) maxHeaderListSize() uint32 {
@@ -302,7 +310,7 @@ type ClientConn struct {
readerErr error // set before readerDone is closed
idleTimeout time.Duration // or 0 for never
- idleTimer *time.Timer
+ idleTimer timer
mu sync.Mutex // guards following
cond *sync.Cond // hold mu; broadcast on flow/closed changes
@@ -344,6 +352,60 @@ type ClientConn struct {
werr error // first write error that has occurred
hbuf bytes.Buffer // HPACK encoder writes into this
henc *hpack.Encoder
+
+ syncHooks *testSyncHooks // can be nil
+}
+
+// Hook points used for testing.
+// Outside of tests, cc.syncHooks is nil and these all have minimal implementations.
+// Inside tests, see the testSyncHooks function docs.
+
+// goRun starts a new goroutine.
+func (cc *ClientConn) goRun(f func()) {
+ if cc.syncHooks != nil {
+ cc.syncHooks.goRun(f)
+ return
+ }
+ go f()
+}
+
+// condBroadcast is cc.cond.Broadcast.
+func (cc *ClientConn) condBroadcast() {
+ if cc.syncHooks != nil {
+ cc.syncHooks.condBroadcast(cc.cond)
+ }
+ cc.cond.Broadcast()
+}
+
+// condWait is cc.cond.Wait.
+func (cc *ClientConn) condWait() {
+ if cc.syncHooks != nil {
+ cc.syncHooks.condWait(cc.cond)
+ }
+ cc.cond.Wait()
+}
+
+// newTimer creates a new time.Timer, or a synthetic timer in tests.
+func (cc *ClientConn) newTimer(d time.Duration) timer {
+ if cc.syncHooks != nil {
+ return cc.syncHooks.newTimer(d)
+ }
+ return newTimeTimer(d)
+}
+
+// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
+func (cc *ClientConn) afterFunc(d time.Duration, f func()) timer {
+ if cc.syncHooks != nil {
+ return cc.syncHooks.afterFunc(d, f)
+ }
+ return newTimeAfterFunc(d, f)
+}
+
+func (cc *ClientConn) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
+ if cc.syncHooks != nil {
+ return cc.syncHooks.contextWithTimeout(ctx, d)
+ }
+ return context.WithTimeout(ctx, d)
}
// clientStream is the state for a single HTTP/2 stream. One of these
@@ -425,7 +487,7 @@ func (cs *clientStream) abortStreamLocked(err error) {
// TODO(dneil): Clean up tests where cs.cc.cond is nil.
if cs.cc.cond != nil {
// Wake up writeRequestBody if it is waiting on flow control.
- cs.cc.cond.Broadcast()
+ cs.cc.condBroadcast()
}
}
@@ -435,7 +497,7 @@ func (cs *clientStream) abortRequestBodyWrite() {
defer cc.mu.Unlock()
if cs.reqBody != nil && cs.reqBodyClosed == nil {
cs.closeReqBodyLocked()
- cc.cond.Broadcast()
+ cc.condBroadcast()
}
}
@@ -445,10 +507,10 @@ func (cs *clientStream) closeReqBodyLocked() {
}
cs.reqBodyClosed = make(chan struct{})
reqBodyClosed := cs.reqBodyClosed
- go func() {
+ cs.cc.goRun(func() {
cs.reqBody.Close()
close(reqBodyClosed)
- }()
+ })
}
type stickyErrWriter struct {
@@ -537,15 +599,6 @@ func authorityAddr(scheme string, authority string) (addr string) {
return net.JoinHostPort(host, port)
}
-var retryBackoffHook func(time.Duration) *time.Timer
-
-func backoffNewTimer(d time.Duration) *time.Timer {
- if retryBackoffHook != nil {
- return retryBackoffHook(d)
- }
- return time.NewTimer(d)
-}
-
// RoundTripOpt is like RoundTrip, but takes options.
func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
@@ -573,13 +626,27 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
backoff := float64(uint(1) << (uint(retry) - 1))
backoff += backoff * (0.1 * mathrand.Float64())
d := time.Second * time.Duration(backoff)
- timer := backoffNewTimer(d)
+ var tm timer
+ if t.syncHooks != nil {
+ tm = t.syncHooks.newTimer(d)
+ t.syncHooks.blockUntil(func() bool {
+ select {
+ case <-tm.C():
+ case <-req.Context().Done():
+ default:
+ return false
+ }
+ return true
+ })
+ } else {
+ tm = newTimeTimer(d)
+ }
select {
- case <-timer.C:
+ case <-tm.C():
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
continue
case <-req.Context().Done():
- timer.Stop()
+ tm.Stop()
err = req.Context().Err()
}
}
@@ -658,6 +725,9 @@ func canRetryError(err error) bool {
}
func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
+ if t.syncHooks != nil {
+ return t.newClientConn(nil, singleUse, t.syncHooks)
+ }
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
@@ -666,7 +736,7 @@ func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse b
if err != nil {
return nil, err
}
- return t.newClientConn(tconn, singleUse)
+ return t.newClientConn(tconn, singleUse, nil)
}
func (t *Transport) newTLSConfig(host string) *tls.Config {
@@ -732,10 +802,10 @@ func (t *Transport) maxEncoderHeaderTableSize() uint32 {
}
func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
- return t.newClientConn(c, t.disableKeepAlives())
+ return t.newClientConn(c, t.disableKeepAlives(), nil)
}
-func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
+func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHooks) (*ClientConn, error) {
cc := &ClientConn{
t: t,
tconn: c,
@@ -750,10 +820,15 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
wantSettingsAck: true,
pings: make(map[[8]byte]chan struct{}),
reqHeaderMu: make(chan struct{}, 1),
+ syncHooks: hooks,
+ }
+ if hooks != nil {
+ hooks.newclientconn(cc)
+ c = cc.tconn
}
if d := t.idleConnTimeout(); d != 0 {
cc.idleTimeout = d
- cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
+ cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout)
}
if VerboseLogs {
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
@@ -818,7 +893,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
return nil, cc.werr
}
- go cc.readLoop()
+ cc.goRun(cc.readLoop)
return cc, nil
}
@@ -826,7 +901,7 @@ func (cc *ClientConn) healthCheck() {
pingTimeout := cc.t.pingTimeout()
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
// trigger the healthCheck again if there is no frame received.
- ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
+ ctx, cancel := cc.contextWithTimeout(context.Background(), pingTimeout)
defer cancel()
cc.vlogf("http2: Transport sending health check")
err := cc.Ping(ctx)
@@ -1056,7 +1131,7 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
// Wait for all in-flight streams to complete or connection to close
done := make(chan struct{})
cancelled := false // guarded by cc.mu
- go func() {
+ cc.goRun(func() {
cc.mu.Lock()
defer cc.mu.Unlock()
for {
@@ -1068,9 +1143,9 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
if cancelled {
break
}
- cc.cond.Wait()
+ cc.condWait()
}
- }()
+ })
shutdownEnterWaitStateHook()
select {
case <-done:
@@ -1080,7 +1155,7 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
cc.mu.Lock()
// Free the goroutine above
cancelled = true
- cc.cond.Broadcast()
+ cc.condBroadcast()
cc.mu.Unlock()
return ctx.Err()
}
@@ -1118,7 +1193,7 @@ func (cc *ClientConn) closeForError(err error) {
for _, cs := range cc.streams {
cs.abortStreamLocked(err)
}
- cc.cond.Broadcast()
+ cc.condBroadcast()
cc.mu.Unlock()
cc.closeConn()
}
@@ -1215,6 +1290,10 @@ func (cc *ClientConn) decrStreamReservationsLocked() {
}
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
+ return cc.roundTrip(req, nil)
+}
+
+func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) (*http.Response, error) {
ctx := req.Context()
cs := &clientStream{
cc: cc,
@@ -1229,9 +1308,23 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
respHeaderRecv: make(chan struct{}),
donec: make(chan struct{}),
}
- go cs.doRequest(req)
+ cc.goRun(func() {
+ cs.doRequest(req)
+ })
waitDone := func() error {
+ if cc.syncHooks != nil {
+ cc.syncHooks.blockUntil(func() bool {
+ select {
+ case <-cs.donec:
+ case <-ctx.Done():
+ case <-cs.reqCancel:
+ default:
+ return false
+ }
+ return true
+ })
+ }
select {
case <-cs.donec:
return nil
@@ -1292,7 +1385,24 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
return err
}
+ if streamf != nil {
+ streamf(cs)
+ }
+
for {
+ if cc.syncHooks != nil {
+ cc.syncHooks.blockUntil(func() bool {
+ select {
+ case <-cs.respHeaderRecv:
+ case <-cs.abort:
+ case <-ctx.Done():
+ case <-cs.reqCancel:
+ default:
+ return false
+ }
+ return true
+ })
+ }
select {
case <-cs.respHeaderRecv:
return handleResponseHeaders()
@@ -1348,6 +1458,21 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
if cc.reqHeaderMu == nil {
panic("RoundTrip on uninitialized ClientConn") // for tests
}
+ var newStreamHook func(*clientStream)
+ if cc.syncHooks != nil {
+ newStreamHook = cc.syncHooks.newstream
+ cc.syncHooks.blockUntil(func() bool {
+ select {
+ case cc.reqHeaderMu <- struct{}{}:
+ <-cc.reqHeaderMu
+ case <-cs.reqCancel:
+ case <-ctx.Done():
+ default:
+ return false
+ }
+ return true
+ })
+ }
select {
case cc.reqHeaderMu <- struct{}{}:
case <-cs.reqCancel:
@@ -1372,6 +1497,10 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
}
cc.mu.Unlock()
+ if newStreamHook != nil {
+ newStreamHook(cs)
+ }
+
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
if !cc.t.disableCompression() &&
req.Header.Get("Accept-Encoding") == "" &&
@@ -1452,15 +1581,30 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
var respHeaderTimer <-chan time.Time
var respHeaderRecv chan struct{}
if d := cc.responseHeaderTimeout(); d != 0 {
- timer := time.NewTimer(d)
+ timer := cc.newTimer(d)
defer timer.Stop()
- respHeaderTimer = timer.C
+ respHeaderTimer = timer.C()
respHeaderRecv = cs.respHeaderRecv
}
// Wait until the peer half-closes its end of the stream,
// or until the request is aborted (via context, error, or otherwise),
// whichever comes first.
for {
+ if cc.syncHooks != nil {
+ cc.syncHooks.blockUntil(func() bool {
+ select {
+ case <-cs.peerClosed:
+ case <-respHeaderTimer:
+ case <-respHeaderRecv:
+ case <-cs.abort:
+ case <-ctx.Done():
+ case <-cs.reqCancel:
+ default:
+ return false
+ }
+ return true
+ })
+ }
select {
case <-cs.peerClosed:
return nil
@@ -1609,7 +1753,7 @@ func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
return nil
}
cc.pendingRequests++
- cc.cond.Wait()
+ cc.condWait()
cc.pendingRequests--
select {
case <-cs.abort:
@@ -1871,8 +2015,24 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
cs.flow.take(take)
return take, nil
}
- cc.cond.Wait()
+ cc.condWait()
+ }
+}
+
+func validateHeaders(hdrs http.Header) string {
+ for k, vv := range hdrs {
+ if !httpguts.ValidHeaderFieldName(k) {
+ return fmt.Sprintf("name %q", k)
+ }
+ for _, v := range vv {
+ if !httpguts.ValidHeaderFieldValue(v) {
+ // Don't include the value in the error,
+ // because it may be sensitive.
+ return fmt.Sprintf("value for header %q", k)
+ }
+ }
}
+ return ""
}
var errNilRequestURL = errors.New("http2: Request.URI is nil")
@@ -1912,19 +2072,14 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
}
}
- // Check for any invalid headers and return an error before we
+ // Check for any invalid headers+trailers and return an error before we
// potentially pollute our hpack state. (We want to be able to
// continue to reuse the hpack encoder for future requests)
- for k, vv := range req.Header {
- if !httpguts.ValidHeaderFieldName(k) {
- return nil, fmt.Errorf("invalid HTTP header name %q", k)
- }
- for _, v := range vv {
- if !httpguts.ValidHeaderFieldValue(v) {
- // Don't include the value in the error, because it may be sensitive.
- return nil, fmt.Errorf("invalid HTTP header value for header %q", k)
- }
- }
+ if err := validateHeaders(req.Header); err != "" {
+ return nil, fmt.Errorf("invalid HTTP header %s", err)
+ }
+ if err := validateHeaders(req.Trailer); err != "" {
+ return nil, fmt.Errorf("invalid HTTP trailer %s", err)
}
enumerateHeaders := func(f func(name, value string)) {
@@ -2143,7 +2298,7 @@ func (cc *ClientConn) forgetStreamID(id uint32) {
}
// Wake up writeRequestBody via clientStream.awaitFlowControl and
// wake up RoundTrip if there is a pending request.
- cc.cond.Broadcast()
+ cc.condBroadcast()
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
@@ -2231,7 +2386,7 @@ func (rl *clientConnReadLoop) cleanup() {
cs.abortStreamLocked(err)
}
}
- cc.cond.Broadcast()
+ cc.condBroadcast()
cc.mu.Unlock()
}
@@ -2266,10 +2421,9 @@ func (rl *clientConnReadLoop) run() error {
cc := rl.cc
gotSettings := false
readIdleTimeout := cc.t.ReadIdleTimeout
- var t *time.Timer
+ var t timer
if readIdleTimeout != 0 {
- t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
- defer t.Stop()
+ t = cc.afterFunc(readIdleTimeout, cc.healthCheck)
}
for {
f, err := cc.fr.ReadFrame()
@@ -2684,7 +2838,7 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
})
return nil
}
- if !cs.firstByte {
+ if !cs.pastHeaders {
cc.logf("protocol error: received DATA before a HEADERS frame")
rl.endStreamError(cs, StreamError{
StreamID: f.StreamID,
@@ -2867,7 +3021,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
for _, cs := range cc.streams {
cs.flow.add(delta)
}
- cc.cond.Broadcast()
+ cc.condBroadcast()
cc.initialWindowSize = s.Val
case SettingHeaderTableSize:
@@ -2911,9 +3065,18 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
fl = &cs.flow
}
if !fl.add(int32(f.Increment)) {
+ // For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR
+ if cs != nil {
+ rl.endStreamError(cs, StreamError{
+ StreamID: f.StreamID,
+ Code: ErrCodeFlowControl,
+ })
+ return nil
+ }
+
return ConnectionError(ErrCodeFlowControl)
}
- cc.cond.Broadcast()
+ cc.condBroadcast()
return nil
}
@@ -2955,24 +3118,38 @@ func (cc *ClientConn) Ping(ctx context.Context) error {
}
cc.mu.Unlock()
}
- errc := make(chan error, 1)
- go func() {
+ var pingError error
+ errc := make(chan struct{})
+ cc.goRun(func() {
cc.wmu.Lock()
defer cc.wmu.Unlock()
- if err := cc.fr.WritePing(false, p); err != nil {
- errc <- err
+ if pingError = cc.fr.WritePing(false, p); pingError != nil {
+ close(errc)
return
}
- if err := cc.bw.Flush(); err != nil {
- errc <- err
+ if pingError = cc.bw.Flush(); pingError != nil {
+ close(errc)
return
}
- }()
+ })
+ if cc.syncHooks != nil {
+ cc.syncHooks.blockUntil(func() bool {
+ select {
+ case <-c:
+ case <-errc:
+ case <-ctx.Done():
+ case <-cc.readerDone:
+ default:
+ return false
+ }
+ return true
+ })
+ }
select {
case <-c:
return nil
- case err := <-errc:
- return err
+ case <-errc:
+ return pingError
case <-ctx.Done():
return ctx.Err()
case <-cc.readerDone:
@@ -3141,9 +3318,17 @@ func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, err
}
func (t *Transport) idleConnTimeout() time.Duration {
+ // to keep things backwards compatible, we use non-zero values of
+ // IdleConnTimeout, followed by using the IdleConnTimeout on the underlying
+ // http1 transport, followed by 0
+ if t.IdleConnTimeout != 0 {
+ return t.IdleConnTimeout
+ }
+
if t.t1 != nil {
return t.t1.IdleConnTimeout
}
+
return 0
}
diff --git a/vendor/golang.org/x/net/websocket/client.go b/vendor/golang.org/x/net/websocket/client.go
index 69a4ac7eef..1e64157f3e 100644
--- a/vendor/golang.org/x/net/websocket/client.go
+++ b/vendor/golang.org/x/net/websocket/client.go
@@ -6,10 +6,12 @@ package websocket
import (
"bufio"
+ "context"
"io"
"net"
"net/http"
"net/url"
+ "time"
)
// DialError is an error that occurs while dialling a websocket server.
@@ -79,28 +81,59 @@ func parseAuthority(location *url.URL) string {
// DialConfig opens a new client connection to a WebSocket with a config.
func DialConfig(config *Config) (ws *Conn, err error) {
- var client net.Conn
+ return config.DialContext(context.Background())
+}
+
+// DialContext opens a new client connection to a WebSocket, with context support for timeouts/cancellation.
+func (config *Config) DialContext(ctx context.Context) (*Conn, error) {
if config.Location == nil {
return nil, &DialError{config, ErrBadWebSocketLocation}
}
if config.Origin == nil {
return nil, &DialError{config, ErrBadWebSocketOrigin}
}
+
dialer := config.Dialer
if dialer == nil {
dialer = &net.Dialer{}
}
- client, err = dialWithDialer(dialer, config)
- if err != nil {
- goto Error
- }
- ws, err = NewClient(config, client)
+
+ client, err := dialWithDialer(ctx, dialer, config)
if err != nil {
- client.Close()
- goto Error
+ return nil, &DialError{config, err}
}
- return
-Error:
- return nil, &DialError{config, err}
+ // Cleanup the connection if we fail to create the websocket successfully
+ success := false
+ defer func() {
+ if !success {
+ _ = client.Close()
+ }
+ }()
+
+ var ws *Conn
+ var wsErr error
+ doneConnecting := make(chan struct{})
+ go func() {
+ defer close(doneConnecting)
+ ws, err = NewClient(config, client)
+ if err != nil {
+ wsErr = &DialError{config, err}
+ }
+ }()
+
+ // The websocket.NewClient() function can block indefinitely, make sure that we
+ // respect the deadlines specified by the context.
+ select {
+ case <-ctx.Done():
+ // Force the pending operations to fail, terminating the pending connection attempt
+ _ = client.SetDeadline(time.Now())
+ <-doneConnecting // Wait for the goroutine that tries to establish the connection to finish
+ return nil, &DialError{config, ctx.Err()}
+ case <-doneConnecting:
+ if wsErr == nil {
+ success = true // Disarm the deferred connection cleanup
+ }
+ return ws, wsErr
+ }
}
diff --git a/vendor/golang.org/x/net/websocket/dial.go b/vendor/golang.org/x/net/websocket/dial.go
index 2dab943a48..8a2d83c473 100644
--- a/vendor/golang.org/x/net/websocket/dial.go
+++ b/vendor/golang.org/x/net/websocket/dial.go
@@ -5,18 +5,23 @@
package websocket
import (
+ "context"
"crypto/tls"
"net"
)
-func dialWithDialer(dialer *net.Dialer, config *Config) (conn net.Conn, err error) {
+func dialWithDialer(ctx context.Context, dialer *net.Dialer, config *Config) (conn net.Conn, err error) {
switch config.Location.Scheme {
case "ws":
- conn, err = dialer.Dial("tcp", parseAuthority(config.Location))
+ conn, err = dialer.DialContext(ctx, "tcp", parseAuthority(config.Location))
case "wss":
- conn, err = tls.DialWithDialer(dialer, "tcp", parseAuthority(config.Location), config.TlsConfig)
+ tlsDialer := &tls.Dialer{
+ NetDialer: dialer,
+ Config: config.TlsConfig,
+ }
+ conn, err = tlsDialer.DialContext(ctx, "tcp", parseAuthority(config.Location))
default:
err = ErrBadScheme
}
diff --git a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
deleted file mode 100644
index 2459d069f7..0000000000
--- a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2014 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 clientcredentials implements the OAuth2.0 "client credentials" token flow,
-// also known as the "two-legged OAuth 2.0".
-//
-// This should be used when the client is acting on its own behalf or when the client
-// is the resource owner. It may also be used when requesting access to protected
-// resources based on an authorization previously arranged with the authorization
-// server.
-//
-// See https://tools.ietf.org/html/rfc6749#section-4.4
-package clientcredentials // import "golang.org/x/oauth2/clientcredentials"
-
-import (
- "context"
- "fmt"
- "net/http"
- "net/url"
- "strings"
-
- "golang.org/x/oauth2"
- "golang.org/x/oauth2/internal"
-)
-
-// Config describes a 2-legged OAuth2 flow, with both the
-// client application information and the server's endpoint URLs.
-type Config struct {
- // ClientID is the application's ID.
- ClientID string
-
- // ClientSecret is the application's secret.
- ClientSecret string
-
- // TokenURL is the resource server's token endpoint
- // URL. This is a constant specific to each server.
- TokenURL string
-
- // Scope specifies optional requested permissions.
- Scopes []string
-
- // EndpointParams specifies additional parameters for requests to the token endpoint.
- EndpointParams url.Values
-
- // AuthStyle optionally specifies how the endpoint wants the
- // client ID & client secret sent. The zero value means to
- // auto-detect.
- AuthStyle oauth2.AuthStyle
-
- // authStyleCache caches which auth style to use when Endpoint.AuthStyle is
- // the zero value (AuthStyleAutoDetect).
- authStyleCache internal.LazyAuthStyleCache
-}
-
-// Token uses client credentials to retrieve a token.
-//
-// The provided context optionally controls which HTTP client is used. See the oauth2.HTTPClient variable.
-func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) {
- return c.TokenSource(ctx).Token()
-}
-
-// Client returns an HTTP client using the provided token.
-// The token will auto-refresh as necessary.
-//
-// The provided context optionally controls which HTTP client
-// is returned. See the oauth2.HTTPClient variable.
-//
-// The returned Client and its Transport should not be modified.
-func (c *Config) Client(ctx context.Context) *http.Client {
- return oauth2.NewClient(ctx, c.TokenSource(ctx))
-}
-
-// TokenSource returns a TokenSource that returns t until t expires,
-// automatically refreshing it as necessary using the provided context and the
-// client ID and client secret.
-//
-// Most users will use Config.Client instead.
-func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
- source := &tokenSource{
- ctx: ctx,
- conf: c,
- }
- return oauth2.ReuseTokenSource(nil, source)
-}
-
-type tokenSource struct {
- ctx context.Context
- conf *Config
-}
-
-// Token refreshes the token by using a new client credentials request.
-// tokens received this way do not include a refresh token
-func (c *tokenSource) Token() (*oauth2.Token, error) {
- v := url.Values{
- "grant_type": {"client_credentials"},
- }
- if len(c.conf.Scopes) > 0 {
- v.Set("scope", strings.Join(c.conf.Scopes, " "))
- }
- for k, p := range c.conf.EndpointParams {
- // Allow grant_type to be overridden to allow interoperability with
- // non-compliant implementations.
- if _, ok := v[k]; ok && k != "grant_type" {
- return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k)
- }
- v[k] = p
- }
-
- tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v, internal.AuthStyle(c.conf.AuthStyle), c.conf.authStyleCache.Get())
- if err != nil {
- if rErr, ok := err.(*internal.RetrieveError); ok {
- return nil, (*oauth2.RetrieveError)(rErr)
- }
- return nil, err
- }
- t := &oauth2.Token{
- AccessToken: tk.AccessToken,
- TokenType: tk.TokenType,
- RefreshToken: tk.RefreshToken,
- Expiry: tk.Expiry,
- }
- return t.WithExtra(tk.Raw), nil
-}
diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go
index 4756ad5f79..8fa707aa4b 100644
--- a/vendor/golang.org/x/sys/cpu/cpu.go
+++ b/vendor/golang.org/x/sys/cpu/cpu.go
@@ -103,6 +103,7 @@ var ARM64 struct {
HasASIMDDP bool // Advanced SIMD double precision instruction set
HasSHA512 bool // SHA512 hardware implementation
HasSVE bool // Scalable Vector Extensions
+ HasSVE2 bool // Scalable Vector Extensions 2
HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32
_ CacheLinePad
}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go
index f3eb993bf2..0e27a21e1f 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go
@@ -28,6 +28,7 @@ func initOptions() {
{Name: "sm3", Feature: &ARM64.HasSM3},
{Name: "sm4", Feature: &ARM64.HasSM4},
{Name: "sve", Feature: &ARM64.HasSVE},
+ {Name: "sve2", Feature: &ARM64.HasSVE2},
{Name: "crc32", Feature: &ARM64.HasCRC32},
{Name: "atomics", Feature: &ARM64.HasATOMICS},
{Name: "asimdhp", Feature: &ARM64.HasASIMDHP},
@@ -164,6 +165,15 @@ func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) {
switch extractBits(pfr0, 32, 35) {
case 1:
ARM64.HasSVE = true
+
+ parseARM64SVERegister(getzfr0())
+ }
+}
+
+func parseARM64SVERegister(zfr0 uint64) {
+ switch extractBits(zfr0, 0, 3) {
+ case 1:
+ ARM64.HasSVE2 = true
}
}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_arm64.s
index fcb9a38882..22cc99844a 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_arm64.s
+++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.s
@@ -29,3 +29,11 @@ TEXT ·getpfr0(SB),NOSPLIT,$0-8
WORD $0xd5380400
MOVD R0, ret+0(FP)
RET
+
+// func getzfr0() uint64
+TEXT ·getzfr0(SB),NOSPLIT,$0-8
+ // get SVE Feature Register 0 into x0
+ // mrs x0, ID_AA64ZFR0_EL1 = d5380480
+ WORD $0xd5380480
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
index a8acd3e328..6ac6e1efb2 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go
@@ -9,3 +9,4 @@ package cpu
func getisar0() uint64
func getisar1() uint64
func getpfr0() uint64
+func getzfr0() uint64
diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go
index a968b80fa6..3d386d0fc2 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go
@@ -35,6 +35,8 @@ const (
hwcap_SHA512 = 1 << 21
hwcap_SVE = 1 << 22
hwcap_ASIMDFHM = 1 << 23
+
+ hwcap2_SVE2 = 1 << 1
)
// linuxKernelCanEmulateCPUID reports whether we're running
@@ -104,6 +106,9 @@ func doinit() {
ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512)
ARM64.HasSVE = isSet(hwCap, hwcap_SVE)
ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM)
+
+ // HWCAP2 feature bits
+ ARM64.HasSVE2 = isSet(hwCap2, hwcap2_SVE2)
}
func isSet(hwc uint, value uint) bool {
diff --git a/vendor/golang.org/x/sys/unix/aliases.go b/vendor/golang.org/x/sys/unix/aliases.go
index e7d3df4bd3..b0e4198575 100644
--- a/vendor/golang.org/x/sys/unix/aliases.go
+++ b/vendor/golang.org/x/sys/unix/aliases.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
package unix
diff --git a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s
index 2f67ba86d5..813dfad7d2 100644
--- a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s
+++ b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s
@@ -9,9 +9,11 @@
#define PSALAA 1208(R0)
#define GTAB64(x) 80(x)
#define LCA64(x) 88(x)
+#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
#define CAA(x) 8(x)
-#define EDCHPXV(x) 1016(x) // in the CAA
-#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
+#define CEECAATHDID(x) 976(x) // in the CAA
+#define EDCHPXV(x) 1016(x) // in the CAA
+#define GOCB(x) 1104(x) // in the CAA
// SS_*, where x=SAVSTACK_ASYNC
#define SS_LE(x) 0(x)
@@ -19,405 +21,362 @@
#define SS_ERRNO(x) 16(x)
#define SS_ERRNOJR(x) 20(x)
-#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6
+// Function Descriptor Offsets
+#define __errno 0x156*16
+#define __err2ad 0x16C*16
-TEXT ·clearErrno(SB),NOSPLIT,$0-0
- BL addrerrno<>(SB)
- MOVD $0, 0(R3)
+// Call Instructions
+#define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6
+#define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD
+#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE
+
+DATA zosLibVec<>(SB)/8, $0
+GLOBL zosLibVec<>(SB), NOPTR, $8
+
+TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
+ MOVW PSALAA, R8
+ MOVD LCA64(R8), R8
+ MOVD CAA(R8), R8
+ MOVD EDCHPXV(R8), R8
+ MOVD R8, zosLibVec<>(SB)
+ RET
+
+TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD zosLibVec<>(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·clearErrno(SB), NOSPLIT, $0-0
+ BL addrerrno<>(SB)
+ MOVD $0, 0(R3)
RET
// Returns the address of errno in R3.
-TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0
+TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
// Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
+ MOVW PSALAA, R8
+ MOVD LCA64(R8), R8
// Get __errno FuncDesc.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- ADD $(0x156*16), R9
- LMG 0(R9), R5, R6
+ MOVD CAA(R8), R9
+ MOVD EDCHPXV(R9), R9
+ ADD $(__errno), R9
+ LMG 0(R9), R5, R6
// Switch to saved LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
+ MOVD SAVSTACK_ASYNC(R8), R9
+ MOVD 0(R9), R4
+ MOVD $0, 0(R9)
// Call __errno function.
LE_CALL
NOPH
// Switch back to Go stack.
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
+ XOR R0, R0 // Restore R0 to $0.
+ MOVD R4, 0(R9) // Save stack pointer.
RET
-TEXT ·syscall_syscall(SB),NOSPLIT,$0-56
- BL runtime·entersyscall(SB)
- MOVD a1+8(FP), R1
- MOVD a2+16(FP), R2
- MOVD a3+24(FP), R3
+// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
+TEXT ·svcCall(SB), NOSPLIT, $0
+ BL runtime·save_g(SB) // Save g and stack pointer
+ MOVW PSALAA, R8
+ MOVD LCA64(R8), R8
+ MOVD SAVSTACK_ASYNC(R8), R9
+ MOVD R15, 0(R9)
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
+ MOVD argv+8(FP), R1 // Move function arguments into registers
+ MOVD dsa+16(FP), g
+ MOVD fnptr+0(FP), R15
- // Get function.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- MOVD trap+0(FP), R5
- SLD $4, R5
- ADD R5, R9
- LMG 0(R9), R5, R6
+ BYTE $0x0D // Branch to function
+ BYTE $0xEF
- // Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
+ BL runtime·load_g(SB) // Restore g and stack pointer
+ MOVW PSALAA, R8
+ MOVD LCA64(R8), R8
+ MOVD SAVSTACK_ASYNC(R8), R9
+ MOVD 0(R9), R15
- // Call function.
- LE_CALL
- NOPH
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
-
- MOVD R3, r1+32(FP)
- MOVD R0, r2+40(FP)
- MOVD R0, err+48(FP)
- MOVW R3, R4
- CMP R4, $-1
- BNE done
- BL addrerrno<>(SB)
- MOVWZ 0(R3), R3
- MOVD R3, err+48(FP)
-done:
- BL runtime·exitsyscall(SB)
RET
-TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56
- MOVD a1+8(FP), R1
- MOVD a2+16(FP), R2
- MOVD a3+24(FP), R3
-
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
-
- // Get function.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- MOVD trap+0(FP), R5
- SLD $4, R5
- ADD R5, R9
- LMG 0(R9), R5, R6
+// func svcLoad(name *byte) unsafe.Pointer
+TEXT ·svcLoad(SB), NOSPLIT, $0
+ MOVD R15, R2 // Save go stack pointer
+ MOVD name+0(FP), R0 // Move SVC args into registers
+ MOVD $0x80000000, R1
+ MOVD $0, R15
+ SVC_LOAD
+ MOVW R15, R3 // Save return code from SVC
+ MOVD R2, R15 // Restore go stack pointer
+ CMP R3, $0 // Check SVC return code
+ BNE error
+
+ MOVD $-2, R3 // Reset last bit of entry point to zero
+ AND R0, R3
+ MOVD R3, ret+8(FP) // Return entry point returned by SVC
+ CMP R0, R3 // Check if last bit of entry point was set
+ BNE done
+
+ MOVD R15, R2 // Save go stack pointer
+ MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
+ SVC_DELETE
+ MOVD R2, R15 // Restore go stack pointer
- // Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
+error:
+ MOVD $0, ret+8(FP) // Return 0 on failure
- // Call function.
- LE_CALL
- NOPH
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
-
- MOVD R3, r1+32(FP)
- MOVD R0, r2+40(FP)
- MOVD R0, err+48(FP)
- MOVW R3, R4
- CMP R4, $-1
- BNE done
- BL addrerrno<>(SB)
- MOVWZ 0(R3), R3
- MOVD R3, err+48(FP)
done:
+ XOR R0, R0 // Reset r0 to 0
RET
-TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80
- BL runtime·entersyscall(SB)
- MOVD a1+8(FP), R1
- MOVD a2+16(FP), R2
- MOVD a3+24(FP), R3
+// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
+TEXT ·svcUnload(SB), NOSPLIT, $0
+ MOVD R15, R2 // Save go stack pointer
+ MOVD name+0(FP), R0 // Move SVC args into registers
+ MOVD fnptr+8(FP), R15
+ SVC_DELETE
+ XOR R0, R0 // Reset r0 to 0
+ MOVD R15, R1 // Save SVC return code
+ MOVD R2, R15 // Restore go stack pointer
+ MOVD R1, ret+16(FP) // Return SVC return code
+ RET
+// func gettid() uint64
+TEXT ·gettid(SB), NOSPLIT, $0
// Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
+ MOVW PSALAA, R8
+ MOVD LCA64(R8), R8
- // Get function.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- MOVD trap+0(FP), R5
- SLD $4, R5
- ADD R5, R9
- LMG 0(R9), R5, R6
+ // Get CEECAATHDID
+ MOVD CAA(R8), R9
+ MOVD CEECAATHDID(R9), R9
+ MOVD R9, ret+0(FP)
- // Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
-
- // Fill in parameter list.
- MOVD a4+32(FP), R12
- MOVD R12, (2176+24)(R4)
- MOVD a5+40(FP), R12
- MOVD R12, (2176+32)(R4)
- MOVD a6+48(FP), R12
- MOVD R12, (2176+40)(R4)
-
- // Call function.
- LE_CALL
- NOPH
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
-
- MOVD R3, r1+56(FP)
- MOVD R0, r2+64(FP)
- MOVD R0, err+72(FP)
- MOVW R3, R4
- CMP R4, $-1
- BNE done
- BL addrerrno<>(SB)
- MOVWZ 0(R3), R3
- MOVD R3, err+72(FP)
-done:
- BL runtime·exitsyscall(SB)
RET
-TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80
- MOVD a1+8(FP), R1
- MOVD a2+16(FP), R2
- MOVD a3+24(FP), R3
-
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
-
- // Get function.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- MOVD trap+0(FP), R5
- SLD $4, R5
- ADD R5, R9
- LMG 0(R9), R5, R6
+//
+// Call LE function, if the return is -1
+// errno and errno2 is retrieved
+//
+TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0
+ MOVW PSALAA, R8
+ MOVD LCA64(R8), R8
+ MOVD CAA(R8), R9
+ MOVD g, GOCB(R9)
// Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
-
- // Fill in parameter list.
- MOVD a4+32(FP), R12
- MOVD R12, (2176+24)(R4)
- MOVD a5+40(FP), R12
- MOVD R12, (2176+32)(R4)
- MOVD a6+48(FP), R12
- MOVD R12, (2176+40)(R4)
-
- // Call function.
- LE_CALL
+ MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
+ MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
+
+ MOVD parms_base+8(FP), R7 // R7 -> argument array
+ MOVD parms_len+16(FP), R8 // R8 number of arguments
+
+ // arg 1 ---> R1
+ CMP R8, $0
+ BEQ docall
+ SUB $1, R8
+ MOVD 0(R7), R1
+
+ // arg 2 ---> R2
+ CMP R8, $0
+ BEQ docall
+ SUB $1, R8
+ ADD $8, R7
+ MOVD 0(R7), R2
+
+ // arg 3 --> R3
+ CMP R8, $0
+ BEQ docall
+ SUB $1, R8
+ ADD $8, R7
+ MOVD 0(R7), R3
+
+ CMP R8, $0
+ BEQ docall
+ MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
+
+repeat:
+ ADD $8, R7
+ MOVD 0(R7), R0 // advance arg pointer by 8 byte
+ ADD $8, R6 // advance LE argument address by 8 byte
+ MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
+ SUB $1, R8
+ CMP R8, $0
+ BNE repeat
+
+docall:
+ MOVD funcdesc+0(FP), R8 // R8-> function descriptor
+ LMG 0(R8), R5, R6
+ MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
+ LE_CALL // balr R7, R6 (return #1)
+ NOPH
+ MOVD R3, ret+32(FP)
+ CMP R3, $-1 // compare result to -1
+ BNE done
+
+ // retrieve errno and errno2
+ MOVD zosLibVec<>(SB), R8
+ ADD $(__errno), R8
+ LMG 0(R8), R5, R6
+ LE_CALL // balr R7, R6 __errno (return #3)
NOPH
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
-
- MOVD R3, r1+56(FP)
- MOVD R0, r2+64(FP)
- MOVD R0, err+72(FP)
- MOVW R3, R4
- CMP R4, $-1
- BNE done
- BL ·rrno<>(SB)
- MOVWZ 0(R3), R3
- MOVD R3, err+72(FP)
+ MOVWZ 0(R3), R3
+ MOVD R3, err+48(FP)
+ MOVD zosLibVec<>(SB), R8
+ ADD $(__err2ad), R8
+ LMG 0(R8), R5, R6
+ LE_CALL // balr R7, R6 __err2ad (return #2)
+ NOPH
+ MOVW (R3), R2 // retrieve errno2
+ MOVD R2, errno2+40(FP) // store in return area
+
done:
+ MOVD R4, 0(R9) // Save stack pointer.
RET
-TEXT ·syscall_syscall9(SB),NOSPLIT,$0
- BL runtime·entersyscall(SB)
- MOVD a1+8(FP), R1
- MOVD a2+16(FP), R2
- MOVD a3+24(FP), R3
-
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
-
- // Get function.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- MOVD trap+0(FP), R5
- SLD $4, R5
- ADD R5, R9
- LMG 0(R9), R5, R6
+//
+// Call LE function, if the return is 0
+// errno and errno2 is retrieved
+//
+TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0
+ MOVW PSALAA, R8
+ MOVD LCA64(R8), R8
+ MOVD CAA(R8), R9
+ MOVD g, GOCB(R9)
// Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
-
- // Fill in parameter list.
- MOVD a4+32(FP), R12
- MOVD R12, (2176+24)(R4)
- MOVD a5+40(FP), R12
- MOVD R12, (2176+32)(R4)
- MOVD a6+48(FP), R12
- MOVD R12, (2176+40)(R4)
- MOVD a7+56(FP), R12
- MOVD R12, (2176+48)(R4)
- MOVD a8+64(FP), R12
- MOVD R12, (2176+56)(R4)
- MOVD a9+72(FP), R12
- MOVD R12, (2176+64)(R4)
-
- // Call function.
- LE_CALL
+ MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
+ MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
+
+ MOVD parms_base+8(FP), R7 // R7 -> argument array
+ MOVD parms_len+16(FP), R8 // R8 number of arguments
+
+ // arg 1 ---> R1
+ CMP R8, $0
+ BEQ docall
+ SUB $1, R8
+ MOVD 0(R7), R1
+
+ // arg 2 ---> R2
+ CMP R8, $0
+ BEQ docall
+ SUB $1, R8
+ ADD $8, R7
+ MOVD 0(R7), R2
+
+ // arg 3 --> R3
+ CMP R8, $0
+ BEQ docall
+ SUB $1, R8
+ ADD $8, R7
+ MOVD 0(R7), R3
+
+ CMP R8, $0
+ BEQ docall
+ MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
+
+repeat:
+ ADD $8, R7
+ MOVD 0(R7), R0 // advance arg pointer by 8 byte
+ ADD $8, R6 // advance LE argument address by 8 byte
+ MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
+ SUB $1, R8
+ CMP R8, $0
+ BNE repeat
+
+docall:
+ MOVD funcdesc+0(FP), R8 // R8-> function descriptor
+ LMG 0(R8), R5, R6
+ MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
+ LE_CALL // balr R7, R6 (return #1)
NOPH
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
-
- MOVD R3, r1+80(FP)
- MOVD R0, r2+88(FP)
- MOVD R0, err+96(FP)
- MOVW R3, R4
- CMP R4, $-1
- BNE done
- BL addrerrno<>(SB)
- MOVWZ 0(R3), R3
- MOVD R3, err+96(FP)
-done:
- BL runtime·exitsyscall(SB)
- RET
-
-TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0
- MOVD a1+8(FP), R1
- MOVD a2+16(FP), R2
- MOVD a3+24(FP), R3
-
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
-
- // Get function.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- MOVD trap+0(FP), R5
- SLD $4, R5
- ADD R5, R9
- LMG 0(R9), R5, R6
-
- // Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
-
- // Fill in parameter list.
- MOVD a4+32(FP), R12
- MOVD R12, (2176+24)(R4)
- MOVD a5+40(FP), R12
- MOVD R12, (2176+32)(R4)
- MOVD a6+48(FP), R12
- MOVD R12, (2176+40)(R4)
- MOVD a7+56(FP), R12
- MOVD R12, (2176+48)(R4)
- MOVD a8+64(FP), R12
- MOVD R12, (2176+56)(R4)
- MOVD a9+72(FP), R12
- MOVD R12, (2176+64)(R4)
-
- // Call function.
- LE_CALL
+ MOVD R3, ret+32(FP)
+ CMP R3, $0 // compare result to 0
+ BNE done
+
+ // retrieve errno and errno2
+ MOVD zosLibVec<>(SB), R8
+ ADD $(__errno), R8
+ LMG 0(R8), R5, R6
+ LE_CALL // balr R7, R6 __errno (return #3)
NOPH
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
-
- MOVD R3, r1+80(FP)
- MOVD R0, r2+88(FP)
- MOVD R0, err+96(FP)
- MOVW R3, R4
- CMP R4, $-1
- BNE done
- BL addrerrno<>(SB)
- MOVWZ 0(R3), R3
- MOVD R3, err+96(FP)
-done:
- RET
-
-// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
-TEXT ·svcCall(SB),NOSPLIT,$0
- BL runtime·save_g(SB) // Save g and stack pointer
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD R15, 0(R9)
-
- MOVD argv+8(FP), R1 // Move function arguments into registers
- MOVD dsa+16(FP), g
- MOVD fnptr+0(FP), R15
-
- BYTE $0x0D // Branch to function
- BYTE $0xEF
-
- BL runtime·load_g(SB) // Restore g and stack pointer
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R15
-
- RET
-
-// func svcLoad(name *byte) unsafe.Pointer
-TEXT ·svcLoad(SB),NOSPLIT,$0
- MOVD R15, R2 // Save go stack pointer
- MOVD name+0(FP), R0 // Move SVC args into registers
- MOVD $0x80000000, R1
- MOVD $0, R15
- BYTE $0x0A // SVC 08 LOAD
- BYTE $0x08
- MOVW R15, R3 // Save return code from SVC
- MOVD R2, R15 // Restore go stack pointer
- CMP R3, $0 // Check SVC return code
- BNE error
-
- MOVD $-2, R3 // Reset last bit of entry point to zero
- AND R0, R3
- MOVD R3, addr+8(FP) // Return entry point returned by SVC
- CMP R0, R3 // Check if last bit of entry point was set
- BNE done
-
- MOVD R15, R2 // Save go stack pointer
- MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
- BYTE $0x0A // SVC 09 DELETE
- BYTE $0x09
- MOVD R2, R15 // Restore go stack pointer
+ MOVWZ 0(R3), R3
+ MOVD R3, err+48(FP)
+ MOVD zosLibVec<>(SB), R8
+ ADD $(__err2ad), R8
+ LMG 0(R8), R5, R6
+ LE_CALL // balr R7, R6 __err2ad (return #2)
+ NOPH
+ MOVW (R3), R2 // retrieve errno2
+ MOVD R2, errno2+40(FP) // store in return area
+ XOR R2, R2
+ MOVWZ R2, (R3) // clear errno2
-error:
- MOVD $0, addr+8(FP) // Return 0 on failure
done:
- XOR R0, R0 // Reset r0 to 0
+ MOVD R4, 0(R9) // Save stack pointer.
RET
-// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
-TEXT ·svcUnload(SB),NOSPLIT,$0
- MOVD R15, R2 // Save go stack pointer
- MOVD name+0(FP), R0 // Move SVC args into registers
- MOVD addr+8(FP), R15
- BYTE $0x0A // SVC 09
- BYTE $0x09
- XOR R0, R0 // Reset r0 to 0
- MOVD R15, R1 // Save SVC return code
- MOVD R2, R15 // Restore go stack pointer
- MOVD R1, rc+0(FP) // Return SVC return code
+//
+// function to test if a pointer can be safely dereferenced (content read)
+// return 0 for succces
+//
+TEXT ·ptrtest(SB), NOSPLIT, $0-16
+ MOVD arg+0(FP), R10 // test pointer in R10
+
+ // set up R2 to point to CEECAADMC
+ BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
+ BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
+ BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
+ BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
+ BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
+ BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
+
+ // set up R5 to point to the "shunt" path which set 1 to R3 (failure)
+ BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
+ BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
+ BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
+
+ // if r3 is not zero (failed) then branch to finish
+ BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
+ BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
+
+ // stomic store shunt address in R5 into CEECAADMC
+ BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
+
+ // now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above
+ BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10)
+
+ // finish here, restore 0 into CEECAADMC
+ BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
+ BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
+ MOVD R3, ret+8(FP) // result in R3
RET
-// func gettid() uint64
-TEXT ·gettid(SB), NOSPLIT, $0
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
-
- // Get CEECAATHDID
- MOVD CAA(R8), R9
- MOVD 0x3D0(R9), R9
- MOVD R9, ret+0(FP)
-
+//
+// function to test if a untptr can be loaded from a pointer
+// return 1: the 8-byte content
+// 2: 0 for success, 1 for failure
+//
+// func safeload(ptr uintptr) ( value uintptr, error uintptr)
+TEXT ·safeload(SB), NOSPLIT, $0-24
+ MOVD ptr+0(FP), R10 // test pointer in R10
+ MOVD $0x0, R6
+ BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
+ BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
+ BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
+ BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
+ BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
+ BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
+ BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
+ BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
+ BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
+ BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
+ BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
+ BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
+ BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10)
+ BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
+ BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
+ MOVD R6, value+8(FP) // result in R6
+ MOVD R3, error+16(FP) // error in R3
RET
diff --git a/vendor/golang.org/x/sys/unix/bpxsvc_zos.go b/vendor/golang.org/x/sys/unix/bpxsvc_zos.go
new file mode 100644
index 0000000000..39d647d863
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/bpxsvc_zos.go
@@ -0,0 +1,657 @@
+// Copyright 2024 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.
+
+//go:build zos
+
+package unix
+
+import (
+ "bytes"
+ "fmt"
+ "unsafe"
+)
+
+//go:noescape
+func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
+
+//go:noescape
+func A2e([]byte)
+
+//go:noescape
+func E2a([]byte)
+
+const (
+ BPX4STA = 192 // stat
+ BPX4FST = 104 // fstat
+ BPX4LST = 132 // lstat
+ BPX4OPN = 156 // open
+ BPX4CLO = 72 // close
+ BPX4CHR = 500 // chattr
+ BPX4FCR = 504 // fchattr
+ BPX4LCR = 1180 // lchattr
+ BPX4CTW = 492 // cond_timed_wait
+ BPX4GTH = 1056 // __getthent
+ BPX4PTQ = 412 // pthread_quiesc
+ BPX4PTR = 320 // ptrace
+)
+
+const (
+ //options
+ //byte1
+ BPX_OPNFHIGH = 0x80
+ //byte2
+ BPX_OPNFEXEC = 0x80
+ //byte3
+ BPX_O_NOLARGEFILE = 0x08
+ BPX_O_LARGEFILE = 0x04
+ BPX_O_ASYNCSIG = 0x02
+ BPX_O_SYNC = 0x01
+ //byte4
+ BPX_O_CREXCL = 0xc0
+ BPX_O_CREAT = 0x80
+ BPX_O_EXCL = 0x40
+ BPX_O_NOCTTY = 0x20
+ BPX_O_TRUNC = 0x10
+ BPX_O_APPEND = 0x08
+ BPX_O_NONBLOCK = 0x04
+ BPX_FNDELAY = 0x04
+ BPX_O_RDWR = 0x03
+ BPX_O_RDONLY = 0x02
+ BPX_O_WRONLY = 0x01
+ BPX_O_ACCMODE = 0x03
+ BPX_O_GETFL = 0x0f
+
+ //mode
+ // byte1 (file type)
+ BPX_FT_DIR = 1
+ BPX_FT_CHARSPEC = 2
+ BPX_FT_REGFILE = 3
+ BPX_FT_FIFO = 4
+ BPX_FT_SYMLINK = 5
+ BPX_FT_SOCKET = 6
+ //byte3
+ BPX_S_ISUID = 0x08
+ BPX_S_ISGID = 0x04
+ BPX_S_ISVTX = 0x02
+ BPX_S_IRWXU1 = 0x01
+ BPX_S_IRUSR = 0x01
+ //byte4
+ BPX_S_IRWXU2 = 0xc0
+ BPX_S_IWUSR = 0x80
+ BPX_S_IXUSR = 0x40
+ BPX_S_IRWXG = 0x38
+ BPX_S_IRGRP = 0x20
+ BPX_S_IWGRP = 0x10
+ BPX_S_IXGRP = 0x08
+ BPX_S_IRWXOX = 0x07
+ BPX_S_IROTH = 0x04
+ BPX_S_IWOTH = 0x02
+ BPX_S_IXOTH = 0x01
+
+ CW_INTRPT = 1
+ CW_CONDVAR = 32
+ CW_TIMEOUT = 64
+
+ PGTHA_NEXT = 2
+ PGTHA_CURRENT = 1
+ PGTHA_FIRST = 0
+ PGTHA_LAST = 3
+ PGTHA_PROCESS = 0x80
+ PGTHA_CONTTY = 0x40
+ PGTHA_PATH = 0x20
+ PGTHA_COMMAND = 0x10
+ PGTHA_FILEDATA = 0x08
+ PGTHA_THREAD = 0x04
+ PGTHA_PTAG = 0x02
+ PGTHA_COMMANDLONG = 0x01
+ PGTHA_THREADFAST = 0x80
+ PGTHA_FILEPATH = 0x40
+ PGTHA_THDSIGMASK = 0x20
+ // thread quiece mode
+ QUIESCE_TERM int32 = 1
+ QUIESCE_FORCE int32 = 2
+ QUIESCE_QUERY int32 = 3
+ QUIESCE_FREEZE int32 = 4
+ QUIESCE_UNFREEZE int32 = 5
+ FREEZE_THIS_THREAD int32 = 6
+ FREEZE_EXIT int32 = 8
+ QUIESCE_SRB int32 = 9
+)
+
+type Pgtha struct {
+ Pid uint32 // 0
+ Tid0 uint32 // 4
+ Tid1 uint32
+ Accesspid byte // C
+ Accesstid byte // D
+ Accessasid uint16 // E
+ Loginname [8]byte // 10
+ Flag1 byte // 18
+ Flag1b2 byte // 19
+}
+
+type Bpxystat_t struct { // DSECT BPXYSTAT
+ St_id [4]uint8 // 0
+ St_length uint16 // 0x4
+ St_version uint16 // 0x6
+ St_mode uint32 // 0x8
+ St_ino uint32 // 0xc
+ St_dev uint32 // 0x10
+ St_nlink uint32 // 0x14
+ St_uid uint32 // 0x18
+ St_gid uint32 // 0x1c
+ St_size uint64 // 0x20
+ St_atime uint32 // 0x28
+ St_mtime uint32 // 0x2c
+ St_ctime uint32 // 0x30
+ St_rdev uint32 // 0x34
+ St_auditoraudit uint32 // 0x38
+ St_useraudit uint32 // 0x3c
+ St_blksize uint32 // 0x40
+ St_createtime uint32 // 0x44
+ St_auditid [4]uint32 // 0x48
+ St_res01 uint32 // 0x58
+ Ft_ccsid uint16 // 0x5c
+ Ft_flags uint16 // 0x5e
+ St_res01a [2]uint32 // 0x60
+ St_res02 uint32 // 0x68
+ St_blocks uint32 // 0x6c
+ St_opaque [3]uint8 // 0x70
+ St_visible uint8 // 0x73
+ St_reftime uint32 // 0x74
+ St_fid uint64 // 0x78
+ St_filefmt uint8 // 0x80
+ St_fspflag2 uint8 // 0x81
+ St_res03 [2]uint8 // 0x82
+ St_ctimemsec uint32 // 0x84
+ St_seclabel [8]uint8 // 0x88
+ St_res04 [4]uint8 // 0x90
+ // end of version 1
+ _ uint32 // 0x94
+ St_atime64 uint64 // 0x98
+ St_mtime64 uint64 // 0xa0
+ St_ctime64 uint64 // 0xa8
+ St_createtime64 uint64 // 0xb0
+ St_reftime64 uint64 // 0xb8
+ _ uint64 // 0xc0
+ St_res05 [16]uint8 // 0xc8
+ // end of version 2
+}
+
+type BpxFilestatus struct {
+ Oflag1 byte
+ Oflag2 byte
+ Oflag3 byte
+ Oflag4 byte
+}
+
+type BpxMode struct {
+ Ftype byte
+ Mode1 byte
+ Mode2 byte
+ Mode3 byte
+}
+
+// Thr attribute structure for extended attributes
+type Bpxyatt_t struct { // DSECT BPXYATT
+ Att_id [4]uint8
+ Att_version uint16
+ Att_res01 [2]uint8
+ Att_setflags1 uint8
+ Att_setflags2 uint8
+ Att_setflags3 uint8
+ Att_setflags4 uint8
+ Att_mode uint32
+ Att_uid uint32
+ Att_gid uint32
+ Att_opaquemask [3]uint8
+ Att_visblmaskres uint8
+ Att_opaque [3]uint8
+ Att_visibleres uint8
+ Att_size_h uint32
+ Att_size_l uint32
+ Att_atime uint32
+ Att_mtime uint32
+ Att_auditoraudit uint32
+ Att_useraudit uint32
+ Att_ctime uint32
+ Att_reftime uint32
+ // end of version 1
+ Att_filefmt uint8
+ Att_res02 [3]uint8
+ Att_filetag uint32
+ Att_res03 [8]uint8
+ // end of version 2
+ Att_atime64 uint64
+ Att_mtime64 uint64
+ Att_ctime64 uint64
+ Att_reftime64 uint64
+ Att_seclabel [8]uint8
+ Att_ver3res02 [8]uint8
+ // end of version 3
+}
+
+func BpxOpen(name string, options *BpxFilestatus, mode *BpxMode) (rv int32, rc int32, rn int32) {
+ if len(name) < 1024 {
+ var namebuf [1024]byte
+ sz := int32(copy(namebuf[:], name))
+ A2e(namebuf[:sz])
+ var parms [7]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&sz)
+ parms[1] = unsafe.Pointer(&namebuf[0])
+ parms[2] = unsafe.Pointer(options)
+ parms[3] = unsafe.Pointer(mode)
+ parms[4] = unsafe.Pointer(&rv)
+ parms[5] = unsafe.Pointer(&rc)
+ parms[6] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4OPN)
+ return rv, rc, rn
+ }
+ return -1, -1, -1
+}
+
+func BpxClose(fd int32) (rv int32, rc int32, rn int32) {
+ var parms [4]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&fd)
+ parms[1] = unsafe.Pointer(&rv)
+ parms[2] = unsafe.Pointer(&rc)
+ parms[3] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4CLO)
+ return rv, rc, rn
+}
+
+func BpxFileFStat(fd int32, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
+ st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
+ st.St_version = 2
+ stat_sz := uint32(unsafe.Sizeof(*st))
+ var parms [6]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&fd)
+ parms[1] = unsafe.Pointer(&stat_sz)
+ parms[2] = unsafe.Pointer(st)
+ parms[3] = unsafe.Pointer(&rv)
+ parms[4] = unsafe.Pointer(&rc)
+ parms[5] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4FST)
+ return rv, rc, rn
+}
+
+func BpxFileStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
+ if len(name) < 1024 {
+ var namebuf [1024]byte
+ sz := int32(copy(namebuf[:], name))
+ A2e(namebuf[:sz])
+ st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
+ st.St_version = 2
+ stat_sz := uint32(unsafe.Sizeof(*st))
+ var parms [7]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&sz)
+ parms[1] = unsafe.Pointer(&namebuf[0])
+ parms[2] = unsafe.Pointer(&stat_sz)
+ parms[3] = unsafe.Pointer(st)
+ parms[4] = unsafe.Pointer(&rv)
+ parms[5] = unsafe.Pointer(&rc)
+ parms[6] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4STA)
+ return rv, rc, rn
+ }
+ return -1, -1, -1
+}
+
+func BpxFileLStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
+ if len(name) < 1024 {
+ var namebuf [1024]byte
+ sz := int32(copy(namebuf[:], name))
+ A2e(namebuf[:sz])
+ st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
+ st.St_version = 2
+ stat_sz := uint32(unsafe.Sizeof(*st))
+ var parms [7]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&sz)
+ parms[1] = unsafe.Pointer(&namebuf[0])
+ parms[2] = unsafe.Pointer(&stat_sz)
+ parms[3] = unsafe.Pointer(st)
+ parms[4] = unsafe.Pointer(&rv)
+ parms[5] = unsafe.Pointer(&rc)
+ parms[6] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4LST)
+ return rv, rc, rn
+ }
+ return -1, -1, -1
+}
+
+func BpxChattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
+ if len(path) >= 1024 {
+ return -1, -1, -1
+ }
+ var namebuf [1024]byte
+ sz := int32(copy(namebuf[:], path))
+ A2e(namebuf[:sz])
+ attr_sz := uint32(unsafe.Sizeof(*attr))
+ var parms [7]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&sz)
+ parms[1] = unsafe.Pointer(&namebuf[0])
+ parms[2] = unsafe.Pointer(&attr_sz)
+ parms[3] = unsafe.Pointer(attr)
+ parms[4] = unsafe.Pointer(&rv)
+ parms[5] = unsafe.Pointer(&rc)
+ parms[6] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4CHR)
+ return rv, rc, rn
+}
+
+func BpxLchattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
+ if len(path) >= 1024 {
+ return -1, -1, -1
+ }
+ var namebuf [1024]byte
+ sz := int32(copy(namebuf[:], path))
+ A2e(namebuf[:sz])
+ attr_sz := uint32(unsafe.Sizeof(*attr))
+ var parms [7]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&sz)
+ parms[1] = unsafe.Pointer(&namebuf[0])
+ parms[2] = unsafe.Pointer(&attr_sz)
+ parms[3] = unsafe.Pointer(attr)
+ parms[4] = unsafe.Pointer(&rv)
+ parms[5] = unsafe.Pointer(&rc)
+ parms[6] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4LCR)
+ return rv, rc, rn
+}
+
+func BpxFchattr(fd int32, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
+ attr_sz := uint32(unsafe.Sizeof(*attr))
+ var parms [6]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&fd)
+ parms[1] = unsafe.Pointer(&attr_sz)
+ parms[2] = unsafe.Pointer(attr)
+ parms[3] = unsafe.Pointer(&rv)
+ parms[4] = unsafe.Pointer(&rc)
+ parms[5] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4FCR)
+ return rv, rc, rn
+}
+
+func BpxCondTimedWait(sec uint32, nsec uint32, events uint32, secrem *uint32, nsecrem *uint32) (rv int32, rc int32, rn int32) {
+ var parms [8]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&sec)
+ parms[1] = unsafe.Pointer(&nsec)
+ parms[2] = unsafe.Pointer(&events)
+ parms[3] = unsafe.Pointer(secrem)
+ parms[4] = unsafe.Pointer(nsecrem)
+ parms[5] = unsafe.Pointer(&rv)
+ parms[6] = unsafe.Pointer(&rc)
+ parms[7] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4CTW)
+ return rv, rc, rn
+}
+func BpxGetthent(in *Pgtha, outlen *uint32, out unsafe.Pointer) (rv int32, rc int32, rn int32) {
+ var parms [7]unsafe.Pointer
+ inlen := uint32(26) // nothing else will work. Go says Pgtha is 28-byte because of alignment, but Pgtha is "packed" and must be 26-byte
+ parms[0] = unsafe.Pointer(&inlen)
+ parms[1] = unsafe.Pointer(&in)
+ parms[2] = unsafe.Pointer(outlen)
+ parms[3] = unsafe.Pointer(&out)
+ parms[4] = unsafe.Pointer(&rv)
+ parms[5] = unsafe.Pointer(&rc)
+ parms[6] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4GTH)
+ return rv, rc, rn
+}
+func ZosJobname() (jobname string, err error) {
+ var pgtha Pgtha
+ pgtha.Pid = uint32(Getpid())
+ pgtha.Accesspid = PGTHA_CURRENT
+ pgtha.Flag1 = PGTHA_PROCESS
+ var out [256]byte
+ var outlen uint32
+ outlen = 256
+ rv, rc, rn := BpxGetthent(&pgtha, &outlen, unsafe.Pointer(&out[0]))
+ if rv == 0 {
+ gthc := []byte{0x87, 0xa3, 0x88, 0x83} // 'gthc' in ebcdic
+ ix := bytes.Index(out[:], gthc)
+ if ix == -1 {
+ err = fmt.Errorf("BPX4GTH: gthc return data not found")
+ return
+ }
+ jn := out[ix+80 : ix+88] // we didn't declare Pgthc, but jobname is 8-byte at offset 80
+ E2a(jn)
+ jobname = string(bytes.TrimRight(jn, " "))
+
+ } else {
+ err = fmt.Errorf("BPX4GTH: rc=%d errno=%d reason=code=0x%x", rv, rc, rn)
+ }
+ return
+}
+func Bpx4ptq(code int32, data string) (rv int32, rc int32, rn int32) {
+ var userdata [8]byte
+ var parms [5]unsafe.Pointer
+ copy(userdata[:], data+" ")
+ A2e(userdata[:])
+ parms[0] = unsafe.Pointer(&code)
+ parms[1] = unsafe.Pointer(&userdata[0])
+ parms[2] = unsafe.Pointer(&rv)
+ parms[3] = unsafe.Pointer(&rc)
+ parms[4] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4PTQ)
+ return rv, rc, rn
+}
+
+const (
+ PT_TRACE_ME = 0 // Debug this process
+ PT_READ_I = 1 // Read a full word
+ PT_READ_D = 2 // Read a full word
+ PT_READ_U = 3 // Read control info
+ PT_WRITE_I = 4 //Write a full word
+ PT_WRITE_D = 5 //Write a full word
+ PT_CONTINUE = 7 //Continue the process
+ PT_KILL = 8 //Terminate the process
+ PT_READ_GPR = 11 // Read GPR, CR, PSW
+ PT_READ_FPR = 12 // Read FPR
+ PT_READ_VR = 13 // Read VR
+ PT_WRITE_GPR = 14 // Write GPR, CR, PSW
+ PT_WRITE_FPR = 15 // Write FPR
+ PT_WRITE_VR = 16 // Write VR
+ PT_READ_BLOCK = 17 // Read storage
+ PT_WRITE_BLOCK = 19 // Write storage
+ PT_READ_GPRH = 20 // Read GPRH
+ PT_WRITE_GPRH = 21 // Write GPRH
+ PT_REGHSET = 22 // Read all GPRHs
+ PT_ATTACH = 30 // Attach to a process
+ PT_DETACH = 31 // Detach from a process
+ PT_REGSET = 32 // Read all GPRs
+ PT_REATTACH = 33 // Reattach to a process
+ PT_LDINFO = 34 // Read loader info
+ PT_MULTI = 35 // Multi process mode
+ PT_LD64INFO = 36 // RMODE64 Info Area
+ PT_BLOCKREQ = 40 // Block request
+ PT_THREAD_INFO = 60 // Read thread info
+ PT_THREAD_MODIFY = 61
+ PT_THREAD_READ_FOCUS = 62
+ PT_THREAD_WRITE_FOCUS = 63
+ PT_THREAD_HOLD = 64
+ PT_THREAD_SIGNAL = 65
+ PT_EXPLAIN = 66
+ PT_EVENTS = 67
+ PT_THREAD_INFO_EXTENDED = 68
+ PT_REATTACH2 = 71
+ PT_CAPTURE = 72
+ PT_UNCAPTURE = 73
+ PT_GET_THREAD_TCB = 74
+ PT_GET_ALET = 75
+ PT_SWAPIN = 76
+ PT_EXTENDED_EVENT = 98
+ PT_RECOVER = 99 // Debug a program check
+ PT_GPR0 = 0 // General purpose register 0
+ PT_GPR1 = 1 // General purpose register 1
+ PT_GPR2 = 2 // General purpose register 2
+ PT_GPR3 = 3 // General purpose register 3
+ PT_GPR4 = 4 // General purpose register 4
+ PT_GPR5 = 5 // General purpose register 5
+ PT_GPR6 = 6 // General purpose register 6
+ PT_GPR7 = 7 // General purpose register 7
+ PT_GPR8 = 8 // General purpose register 8
+ PT_GPR9 = 9 // General purpose register 9
+ PT_GPR10 = 10 // General purpose register 10
+ PT_GPR11 = 11 // General purpose register 11
+ PT_GPR12 = 12 // General purpose register 12
+ PT_GPR13 = 13 // General purpose register 13
+ PT_GPR14 = 14 // General purpose register 14
+ PT_GPR15 = 15 // General purpose register 15
+ PT_FPR0 = 16 // Floating point register 0
+ PT_FPR1 = 17 // Floating point register 1
+ PT_FPR2 = 18 // Floating point register 2
+ PT_FPR3 = 19 // Floating point register 3
+ PT_FPR4 = 20 // Floating point register 4
+ PT_FPR5 = 21 // Floating point register 5
+ PT_FPR6 = 22 // Floating point register 6
+ PT_FPR7 = 23 // Floating point register 7
+ PT_FPR8 = 24 // Floating point register 8
+ PT_FPR9 = 25 // Floating point register 9
+ PT_FPR10 = 26 // Floating point register 10
+ PT_FPR11 = 27 // Floating point register 11
+ PT_FPR12 = 28 // Floating point register 12
+ PT_FPR13 = 29 // Floating point register 13
+ PT_FPR14 = 30 // Floating point register 14
+ PT_FPR15 = 31 // Floating point register 15
+ PT_FPC = 32 // Floating point control register
+ PT_PSW = 40 // PSW
+ PT_PSW0 = 40 // Left half of the PSW
+ PT_PSW1 = 41 // Right half of the PSW
+ PT_CR0 = 42 // Control register 0
+ PT_CR1 = 43 // Control register 1
+ PT_CR2 = 44 // Control register 2
+ PT_CR3 = 45 // Control register 3
+ PT_CR4 = 46 // Control register 4
+ PT_CR5 = 47 // Control register 5
+ PT_CR6 = 48 // Control register 6
+ PT_CR7 = 49 // Control register 7
+ PT_CR8 = 50 // Control register 8
+ PT_CR9 = 51 // Control register 9
+ PT_CR10 = 52 // Control register 10
+ PT_CR11 = 53 // Control register 11
+ PT_CR12 = 54 // Control register 12
+ PT_CR13 = 55 // Control register 13
+ PT_CR14 = 56 // Control register 14
+ PT_CR15 = 57 // Control register 15
+ PT_GPRH0 = 58 // GP High register 0
+ PT_GPRH1 = 59 // GP High register 1
+ PT_GPRH2 = 60 // GP High register 2
+ PT_GPRH3 = 61 // GP High register 3
+ PT_GPRH4 = 62 // GP High register 4
+ PT_GPRH5 = 63 // GP High register 5
+ PT_GPRH6 = 64 // GP High register 6
+ PT_GPRH7 = 65 // GP High register 7
+ PT_GPRH8 = 66 // GP High register 8
+ PT_GPRH9 = 67 // GP High register 9
+ PT_GPRH10 = 68 // GP High register 10
+ PT_GPRH11 = 69 // GP High register 11
+ PT_GPRH12 = 70 // GP High register 12
+ PT_GPRH13 = 71 // GP High register 13
+ PT_GPRH14 = 72 // GP High register 14
+ PT_GPRH15 = 73 // GP High register 15
+ PT_VR0 = 74 // Vector register 0
+ PT_VR1 = 75 // Vector register 1
+ PT_VR2 = 76 // Vector register 2
+ PT_VR3 = 77 // Vector register 3
+ PT_VR4 = 78 // Vector register 4
+ PT_VR5 = 79 // Vector register 5
+ PT_VR6 = 80 // Vector register 6
+ PT_VR7 = 81 // Vector register 7
+ PT_VR8 = 82 // Vector register 8
+ PT_VR9 = 83 // Vector register 9
+ PT_VR10 = 84 // Vector register 10
+ PT_VR11 = 85 // Vector register 11
+ PT_VR12 = 86 // Vector register 12
+ PT_VR13 = 87 // Vector register 13
+ PT_VR14 = 88 // Vector register 14
+ PT_VR15 = 89 // Vector register 15
+ PT_VR16 = 90 // Vector register 16
+ PT_VR17 = 91 // Vector register 17
+ PT_VR18 = 92 // Vector register 18
+ PT_VR19 = 93 // Vector register 19
+ PT_VR20 = 94 // Vector register 20
+ PT_VR21 = 95 // Vector register 21
+ PT_VR22 = 96 // Vector register 22
+ PT_VR23 = 97 // Vector register 23
+ PT_VR24 = 98 // Vector register 24
+ PT_VR25 = 99 // Vector register 25
+ PT_VR26 = 100 // Vector register 26
+ PT_VR27 = 101 // Vector register 27
+ PT_VR28 = 102 // Vector register 28
+ PT_VR29 = 103 // Vector register 29
+ PT_VR30 = 104 // Vector register 30
+ PT_VR31 = 105 // Vector register 31
+ PT_PSWG = 106 // PSWG
+ PT_PSWG0 = 106 // Bytes 0-3
+ PT_PSWG1 = 107 // Bytes 4-7
+ PT_PSWG2 = 108 // Bytes 8-11 (IA high word)
+ PT_PSWG3 = 109 // Bytes 12-15 (IA low word)
+)
+
+func Bpx4ptr(request int32, pid int32, addr unsafe.Pointer, data unsafe.Pointer, buffer unsafe.Pointer) (rv int32, rc int32, rn int32) {
+ var parms [8]unsafe.Pointer
+ parms[0] = unsafe.Pointer(&request)
+ parms[1] = unsafe.Pointer(&pid)
+ parms[2] = unsafe.Pointer(&addr)
+ parms[3] = unsafe.Pointer(&data)
+ parms[4] = unsafe.Pointer(&buffer)
+ parms[5] = unsafe.Pointer(&rv)
+ parms[6] = unsafe.Pointer(&rc)
+ parms[7] = unsafe.Pointer(&rn)
+ bpxcall(parms[:], BPX4PTR)
+ return rv, rc, rn
+}
+
+func copyU8(val uint8, dest []uint8) int {
+ if len(dest) < 1 {
+ return 0
+ }
+ dest[0] = val
+ return 1
+}
+
+func copyU8Arr(src, dest []uint8) int {
+ if len(dest) < len(src) {
+ return 0
+ }
+ for i, v := range src {
+ dest[i] = v
+ }
+ return len(src)
+}
+
+func copyU16(val uint16, dest []uint16) int {
+ if len(dest) < 1 {
+ return 0
+ }
+ dest[0] = val
+ return 1
+}
+
+func copyU32(val uint32, dest []uint32) int {
+ if len(dest) < 1 {
+ return 0
+ }
+ dest[0] = val
+ return 1
+}
+
+func copyU32Arr(src, dest []uint32) int {
+ if len(dest) < len(src) {
+ return 0
+ }
+ for i, v := range src {
+ dest[i] = v
+ }
+ return len(src)
+}
+
+func copyU64(val uint64, dest []uint64) int {
+ if len(dest) < 1 {
+ return 0
+ }
+ dest[0] = val
+ return 1
+}
diff --git a/vendor/golang.org/x/sys/unix/bpxsvc_zos.s b/vendor/golang.org/x/sys/unix/bpxsvc_zos.s
new file mode 100644
index 0000000000..4bd4a17982
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/bpxsvc_zos.s
@@ -0,0 +1,192 @@
+// Copyright 2024 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.
+
+#include "go_asm.h"
+#include "textflag.h"
+
+// function to call USS assembly language services
+//
+// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bit64env.htm
+//
+// arg1 unsafe.Pointer array that ressembles an OS PLIST
+//
+// arg2 function offset as in
+// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bpx2cr_List_of_offsets.htm
+//
+// func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
+
+TEXT ·bpxcall(SB), NOSPLIT|NOFRAME, $0
+ MOVD plist_base+0(FP), R1 // r1 points to plist
+ MOVD bpx_offset+24(FP), R2 // r2 offset to BPX vector table
+ MOVD R14, R7 // save r14
+ MOVD R15, R8 // save r15
+ MOVWZ 16(R0), R9
+ MOVWZ 544(R9), R9
+ MOVWZ 24(R9), R9 // call vector in r9
+ ADD R2, R9 // add offset to vector table
+ MOVWZ (R9), R9 // r9 points to entry point
+ BYTE $0x0D // BL R14,R9 --> basr r14,r9
+ BYTE $0xE9 // clobbers 0,1,14,15
+ MOVD R8, R15 // restore 15
+ JMP R7 // return via saved return address
+
+// func A2e(arr [] byte)
+// code page conversion from 819 to 1047
+TEXT ·A2e(SB), NOSPLIT|NOFRAME, $0
+ MOVD arg_base+0(FP), R2 // pointer to arry of characters
+ MOVD arg_len+8(FP), R3 // count
+ XOR R0, R0
+ XOR R1, R1
+ BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
+
+ // ASCII -> EBCDIC conversion table:
+ BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
+ BYTE $0x37; BYTE $0x2d; BYTE $0x2e; BYTE $0x2f
+ BYTE $0x16; BYTE $0x05; BYTE $0x15; BYTE $0x0b
+ BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
+ BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
+ BYTE $0x3c; BYTE $0x3d; BYTE $0x32; BYTE $0x26
+ BYTE $0x18; BYTE $0x19; BYTE $0x3f; BYTE $0x27
+ BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
+ BYTE $0x40; BYTE $0x5a; BYTE $0x7f; BYTE $0x7b
+ BYTE $0x5b; BYTE $0x6c; BYTE $0x50; BYTE $0x7d
+ BYTE $0x4d; BYTE $0x5d; BYTE $0x5c; BYTE $0x4e
+ BYTE $0x6b; BYTE $0x60; BYTE $0x4b; BYTE $0x61
+ BYTE $0xf0; BYTE $0xf1; BYTE $0xf2; BYTE $0xf3
+ BYTE $0xf4; BYTE $0xf5; BYTE $0xf6; BYTE $0xf7
+ BYTE $0xf8; BYTE $0xf9; BYTE $0x7a; BYTE $0x5e
+ BYTE $0x4c; BYTE $0x7e; BYTE $0x6e; BYTE $0x6f
+ BYTE $0x7c; BYTE $0xc1; BYTE $0xc2; BYTE $0xc3
+ BYTE $0xc4; BYTE $0xc5; BYTE $0xc6; BYTE $0xc7
+ BYTE $0xc8; BYTE $0xc9; BYTE $0xd1; BYTE $0xd2
+ BYTE $0xd3; BYTE $0xd4; BYTE $0xd5; BYTE $0xd6
+ BYTE $0xd7; BYTE $0xd8; BYTE $0xd9; BYTE $0xe2
+ BYTE $0xe3; BYTE $0xe4; BYTE $0xe5; BYTE $0xe6
+ BYTE $0xe7; BYTE $0xe8; BYTE $0xe9; BYTE $0xad
+ BYTE $0xe0; BYTE $0xbd; BYTE $0x5f; BYTE $0x6d
+ BYTE $0x79; BYTE $0x81; BYTE $0x82; BYTE $0x83
+ BYTE $0x84; BYTE $0x85; BYTE $0x86; BYTE $0x87
+ BYTE $0x88; BYTE $0x89; BYTE $0x91; BYTE $0x92
+ BYTE $0x93; BYTE $0x94; BYTE $0x95; BYTE $0x96
+ BYTE $0x97; BYTE $0x98; BYTE $0x99; BYTE $0xa2
+ BYTE $0xa3; BYTE $0xa4; BYTE $0xa5; BYTE $0xa6
+ BYTE $0xa7; BYTE $0xa8; BYTE $0xa9; BYTE $0xc0
+ BYTE $0x4f; BYTE $0xd0; BYTE $0xa1; BYTE $0x07
+ BYTE $0x20; BYTE $0x21; BYTE $0x22; BYTE $0x23
+ BYTE $0x24; BYTE $0x25; BYTE $0x06; BYTE $0x17
+ BYTE $0x28; BYTE $0x29; BYTE $0x2a; BYTE $0x2b
+ BYTE $0x2c; BYTE $0x09; BYTE $0x0a; BYTE $0x1b
+ BYTE $0x30; BYTE $0x31; BYTE $0x1a; BYTE $0x33
+ BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x08
+ BYTE $0x38; BYTE $0x39; BYTE $0x3a; BYTE $0x3b
+ BYTE $0x04; BYTE $0x14; BYTE $0x3e; BYTE $0xff
+ BYTE $0x41; BYTE $0xaa; BYTE $0x4a; BYTE $0xb1
+ BYTE $0x9f; BYTE $0xb2; BYTE $0x6a; BYTE $0xb5
+ BYTE $0xbb; BYTE $0xb4; BYTE $0x9a; BYTE $0x8a
+ BYTE $0xb0; BYTE $0xca; BYTE $0xaf; BYTE $0xbc
+ BYTE $0x90; BYTE $0x8f; BYTE $0xea; BYTE $0xfa
+ BYTE $0xbe; BYTE $0xa0; BYTE $0xb6; BYTE $0xb3
+ BYTE $0x9d; BYTE $0xda; BYTE $0x9b; BYTE $0x8b
+ BYTE $0xb7; BYTE $0xb8; BYTE $0xb9; BYTE $0xab
+ BYTE $0x64; BYTE $0x65; BYTE $0x62; BYTE $0x66
+ BYTE $0x63; BYTE $0x67; BYTE $0x9e; BYTE $0x68
+ BYTE $0x74; BYTE $0x71; BYTE $0x72; BYTE $0x73
+ BYTE $0x78; BYTE $0x75; BYTE $0x76; BYTE $0x77
+ BYTE $0xac; BYTE $0x69; BYTE $0xed; BYTE $0xee
+ BYTE $0xeb; BYTE $0xef; BYTE $0xec; BYTE $0xbf
+ BYTE $0x80; BYTE $0xfd; BYTE $0xfe; BYTE $0xfb
+ BYTE $0xfc; BYTE $0xba; BYTE $0xae; BYTE $0x59
+ BYTE $0x44; BYTE $0x45; BYTE $0x42; BYTE $0x46
+ BYTE $0x43; BYTE $0x47; BYTE $0x9c; BYTE $0x48
+ BYTE $0x54; BYTE $0x51; BYTE $0x52; BYTE $0x53
+ BYTE $0x58; BYTE $0x55; BYTE $0x56; BYTE $0x57
+ BYTE $0x8c; BYTE $0x49; BYTE $0xcd; BYTE $0xce
+ BYTE $0xcb; BYTE $0xcf; BYTE $0xcc; BYTE $0xe1
+ BYTE $0x70; BYTE $0xdd; BYTE $0xde; BYTE $0xdb
+ BYTE $0xdc; BYTE $0x8d; BYTE $0x8e; BYTE $0xdf
+
+retry:
+ WORD $0xB9931022 // TROO 2,2,b'0001'
+ BVS retry
+ RET
+
+// func e2a(arr [] byte)
+// code page conversion from 1047 to 819
+TEXT ·E2a(SB), NOSPLIT|NOFRAME, $0
+ MOVD arg_base+0(FP), R2 // pointer to arry of characters
+ MOVD arg_len+8(FP), R3 // count
+ XOR R0, R0
+ XOR R1, R1
+ BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
+
+ // EBCDIC -> ASCII conversion table:
+ BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
+ BYTE $0x9c; BYTE $0x09; BYTE $0x86; BYTE $0x7f
+ BYTE $0x97; BYTE $0x8d; BYTE $0x8e; BYTE $0x0b
+ BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
+ BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
+ BYTE $0x9d; BYTE $0x0a; BYTE $0x08; BYTE $0x87
+ BYTE $0x18; BYTE $0x19; BYTE $0x92; BYTE $0x8f
+ BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
+ BYTE $0x80; BYTE $0x81; BYTE $0x82; BYTE $0x83
+ BYTE $0x84; BYTE $0x85; BYTE $0x17; BYTE $0x1b
+ BYTE $0x88; BYTE $0x89; BYTE $0x8a; BYTE $0x8b
+ BYTE $0x8c; BYTE $0x05; BYTE $0x06; BYTE $0x07
+ BYTE $0x90; BYTE $0x91; BYTE $0x16; BYTE $0x93
+ BYTE $0x94; BYTE $0x95; BYTE $0x96; BYTE $0x04
+ BYTE $0x98; BYTE $0x99; BYTE $0x9a; BYTE $0x9b
+ BYTE $0x14; BYTE $0x15; BYTE $0x9e; BYTE $0x1a
+ BYTE $0x20; BYTE $0xa0; BYTE $0xe2; BYTE $0xe4
+ BYTE $0xe0; BYTE $0xe1; BYTE $0xe3; BYTE $0xe5
+ BYTE $0xe7; BYTE $0xf1; BYTE $0xa2; BYTE $0x2e
+ BYTE $0x3c; BYTE $0x28; BYTE $0x2b; BYTE $0x7c
+ BYTE $0x26; BYTE $0xe9; BYTE $0xea; BYTE $0xeb
+ BYTE $0xe8; BYTE $0xed; BYTE $0xee; BYTE $0xef
+ BYTE $0xec; BYTE $0xdf; BYTE $0x21; BYTE $0x24
+ BYTE $0x2a; BYTE $0x29; BYTE $0x3b; BYTE $0x5e
+ BYTE $0x2d; BYTE $0x2f; BYTE $0xc2; BYTE $0xc4
+ BYTE $0xc0; BYTE $0xc1; BYTE $0xc3; BYTE $0xc5
+ BYTE $0xc7; BYTE $0xd1; BYTE $0xa6; BYTE $0x2c
+ BYTE $0x25; BYTE $0x5f; BYTE $0x3e; BYTE $0x3f
+ BYTE $0xf8; BYTE $0xc9; BYTE $0xca; BYTE $0xcb
+ BYTE $0xc8; BYTE $0xcd; BYTE $0xce; BYTE $0xcf
+ BYTE $0xcc; BYTE $0x60; BYTE $0x3a; BYTE $0x23
+ BYTE $0x40; BYTE $0x27; BYTE $0x3d; BYTE $0x22
+ BYTE $0xd8; BYTE $0x61; BYTE $0x62; BYTE $0x63
+ BYTE $0x64; BYTE $0x65; BYTE $0x66; BYTE $0x67
+ BYTE $0x68; BYTE $0x69; BYTE $0xab; BYTE $0xbb
+ BYTE $0xf0; BYTE $0xfd; BYTE $0xfe; BYTE $0xb1
+ BYTE $0xb0; BYTE $0x6a; BYTE $0x6b; BYTE $0x6c
+ BYTE $0x6d; BYTE $0x6e; BYTE $0x6f; BYTE $0x70
+ BYTE $0x71; BYTE $0x72; BYTE $0xaa; BYTE $0xba
+ BYTE $0xe6; BYTE $0xb8; BYTE $0xc6; BYTE $0xa4
+ BYTE $0xb5; BYTE $0x7e; BYTE $0x73; BYTE $0x74
+ BYTE $0x75; BYTE $0x76; BYTE $0x77; BYTE $0x78
+ BYTE $0x79; BYTE $0x7a; BYTE $0xa1; BYTE $0xbf
+ BYTE $0xd0; BYTE $0x5b; BYTE $0xde; BYTE $0xae
+ BYTE $0xac; BYTE $0xa3; BYTE $0xa5; BYTE $0xb7
+ BYTE $0xa9; BYTE $0xa7; BYTE $0xb6; BYTE $0xbc
+ BYTE $0xbd; BYTE $0xbe; BYTE $0xdd; BYTE $0xa8
+ BYTE $0xaf; BYTE $0x5d; BYTE $0xb4; BYTE $0xd7
+ BYTE $0x7b; BYTE $0x41; BYTE $0x42; BYTE $0x43
+ BYTE $0x44; BYTE $0x45; BYTE $0x46; BYTE $0x47
+ BYTE $0x48; BYTE $0x49; BYTE $0xad; BYTE $0xf4
+ BYTE $0xf6; BYTE $0xf2; BYTE $0xf3; BYTE $0xf5
+ BYTE $0x7d; BYTE $0x4a; BYTE $0x4b; BYTE $0x4c
+ BYTE $0x4d; BYTE $0x4e; BYTE $0x4f; BYTE $0x50
+ BYTE $0x51; BYTE $0x52; BYTE $0xb9; BYTE $0xfb
+ BYTE $0xfc; BYTE $0xf9; BYTE $0xfa; BYTE $0xff
+ BYTE $0x5c; BYTE $0xf7; BYTE $0x53; BYTE $0x54
+ BYTE $0x55; BYTE $0x56; BYTE $0x57; BYTE $0x58
+ BYTE $0x59; BYTE $0x5a; BYTE $0xb2; BYTE $0xd4
+ BYTE $0xd6; BYTE $0xd2; BYTE $0xd3; BYTE $0xd5
+ BYTE $0x30; BYTE $0x31; BYTE $0x32; BYTE $0x33
+ BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x37
+ BYTE $0x38; BYTE $0x39; BYTE $0xb3; BYTE $0xdb
+ BYTE $0xdc; BYTE $0xd9; BYTE $0xda; BYTE $0x9f
+
+retry:
+ WORD $0xB9931022 // TROO 2,2,b'0001'
+ BVS retry
+ RET
diff --git a/vendor/golang.org/x/sys/unix/epoll_zos.go b/vendor/golang.org/x/sys/unix/epoll_zos.go
deleted file mode 100644
index 7753fddea8..0000000000
--- a/vendor/golang.org/x/sys/unix/epoll_zos.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2020 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.
-
-//go:build zos && s390x
-
-package unix
-
-import (
- "sync"
-)
-
-// This file simulates epoll on z/OS using poll.
-
-// Analogous to epoll_event on Linux.
-// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove?
-type EpollEvent struct {
- Events uint32
- Fd int32
- Pad int32
-}
-
-const (
- EPOLLERR = 0x8
- EPOLLHUP = 0x10
- EPOLLIN = 0x1
- EPOLLMSG = 0x400
- EPOLLOUT = 0x4
- EPOLLPRI = 0x2
- EPOLLRDBAND = 0x80
- EPOLLRDNORM = 0x40
- EPOLLWRBAND = 0x200
- EPOLLWRNORM = 0x100
- EPOLL_CTL_ADD = 0x1
- EPOLL_CTL_DEL = 0x2
- EPOLL_CTL_MOD = 0x3
- // The following constants are part of the epoll API, but represent
- // currently unsupported functionality on z/OS.
- // EPOLL_CLOEXEC = 0x80000
- // EPOLLET = 0x80000000
- // EPOLLONESHOT = 0x40000000
- // EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis
- // EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode
- // EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability
-)
-
-// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL
-// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16).
-
-// epToPollEvt converts epoll event field to poll equivalent.
-// In epoll, Events is a 32-bit field, while poll uses 16 bits.
-func epToPollEvt(events uint32) int16 {
- var ep2p = map[uint32]int16{
- EPOLLIN: POLLIN,
- EPOLLOUT: POLLOUT,
- EPOLLHUP: POLLHUP,
- EPOLLPRI: POLLPRI,
- EPOLLERR: POLLERR,
- }
-
- var pollEvts int16 = 0
- for epEvt, pEvt := range ep2p {
- if (events & epEvt) != 0 {
- pollEvts |= pEvt
- }
- }
-
- return pollEvts
-}
-
-// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields.
-func pToEpollEvt(revents int16) uint32 {
- var p2ep = map[int16]uint32{
- POLLIN: EPOLLIN,
- POLLOUT: EPOLLOUT,
- POLLHUP: EPOLLHUP,
- POLLPRI: EPOLLPRI,
- POLLERR: EPOLLERR,
- }
-
- var epollEvts uint32 = 0
- for pEvt, epEvt := range p2ep {
- if (revents & pEvt) != 0 {
- epollEvts |= epEvt
- }
- }
-
- return epollEvts
-}
-
-// Per-process epoll implementation.
-type epollImpl struct {
- mu sync.Mutex
- epfd2ep map[int]*eventPoll
- nextEpfd int
-}
-
-// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances.
-// On Linux, this is an in-kernel data structure accessed through a fd.
-type eventPoll struct {
- mu sync.Mutex
- fds map[int]*EpollEvent
-}
-
-// epoll impl for this process.
-var impl epollImpl = epollImpl{
- epfd2ep: make(map[int]*eventPoll),
- nextEpfd: 0,
-}
-
-func (e *epollImpl) epollcreate(size int) (epfd int, err error) {
- e.mu.Lock()
- defer e.mu.Unlock()
- epfd = e.nextEpfd
- e.nextEpfd++
-
- e.epfd2ep[epfd] = &eventPoll{
- fds: make(map[int]*EpollEvent),
- }
- return epfd, nil
-}
-
-func (e *epollImpl) epollcreate1(flag int) (fd int, err error) {
- return e.epollcreate(4)
-}
-
-func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) {
- e.mu.Lock()
- defer e.mu.Unlock()
-
- ep, ok := e.epfd2ep[epfd]
- if !ok {
-
- return EBADF
- }
-
- switch op {
- case EPOLL_CTL_ADD:
- // TODO(neeilan): When we make epfds and fds disjoint, detect epoll
- // loops here (instances watching each other) and return ELOOP.
- if _, ok := ep.fds[fd]; ok {
- return EEXIST
- }
- ep.fds[fd] = event
- case EPOLL_CTL_MOD:
- if _, ok := ep.fds[fd]; !ok {
- return ENOENT
- }
- ep.fds[fd] = event
- case EPOLL_CTL_DEL:
- if _, ok := ep.fds[fd]; !ok {
- return ENOENT
- }
- delete(ep.fds, fd)
-
- }
- return nil
-}
-
-// Must be called while holding ep.mu
-func (ep *eventPoll) getFds() []int {
- fds := make([]int, len(ep.fds))
- for fd := range ep.fds {
- fds = append(fds, fd)
- }
- return fds
-}
-
-func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait
- ep, ok := e.epfd2ep[epfd]
-
- if !ok {
- e.mu.Unlock()
- return 0, EBADF
- }
-
- pollfds := make([]PollFd, 4)
- for fd, epollevt := range ep.fds {
- pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)})
- }
- e.mu.Unlock()
-
- n, err = Poll(pollfds, msec)
- if err != nil {
- return n, err
- }
-
- i := 0
- for _, pFd := range pollfds {
- if pFd.Revents != 0 {
- events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)}
- i++
- }
-
- if i == n {
- break
- }
- }
-
- return n, nil
-}
-
-func EpollCreate(size int) (fd int, err error) {
- return impl.epollcreate(size)
-}
-
-func EpollCreate1(flag int) (fd int, err error) {
- return impl.epollcreate1(flag)
-}
-
-func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
- return impl.epollctl(epfd, op, fd, event)
-}
-
-// Because EpollWait mutates events, the caller is expected to coordinate
-// concurrent access if calling with the same epfd from multiple goroutines.
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
- return impl.epollwait(epfd, events, msec)
-}
diff --git a/vendor/golang.org/x/sys/unix/fstatfs_zos.go b/vendor/golang.org/x/sys/unix/fstatfs_zos.go
deleted file mode 100644
index c8bde601e7..0000000000
--- a/vendor/golang.org/x/sys/unix/fstatfs_zos.go
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2020 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.
-
-//go:build zos && s390x
-
-package unix
-
-import (
- "unsafe"
-)
-
-// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
-
-func Fstatfs(fd int, stat *Statfs_t) (err error) {
- var stat_v Statvfs_t
- err = Fstatvfs(fd, &stat_v)
- if err == nil {
- // populate stat
- stat.Type = 0
- stat.Bsize = stat_v.Bsize
- stat.Blocks = stat_v.Blocks
- stat.Bfree = stat_v.Bfree
- stat.Bavail = stat_v.Bavail
- stat.Files = stat_v.Files
- stat.Ffree = stat_v.Ffree
- stat.Fsid = stat_v.Fsid
- stat.Namelen = stat_v.Namemax
- stat.Frsize = stat_v.Frsize
- stat.Flags = stat_v.Flag
- for passn := 0; passn < 5; passn++ {
- switch passn {
- case 0:
- err = tryGetmntent64(stat)
- break
- case 1:
- err = tryGetmntent128(stat)
- break
- case 2:
- err = tryGetmntent256(stat)
- break
- case 3:
- err = tryGetmntent512(stat)
- break
- case 4:
- err = tryGetmntent1024(stat)
- break
- default:
- break
- }
- //proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
- if err == nil || err != nil && err != ERANGE {
- break
- }
- }
- }
- return err
-}
-
-func tryGetmntent64(stat *Statfs_t) (err error) {
- var mnt_ent_buffer struct {
- header W_Mnth
- filesys_info [64]W_Mntent
- }
- var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
- fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
- if err != nil {
- return err
- }
- err = ERANGE //return ERANGE if no match is found in this batch
- for i := 0; i < fs_count; i++ {
- if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
- stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
- err = nil
- break
- }
- }
- return err
-}
-
-func tryGetmntent128(stat *Statfs_t) (err error) {
- var mnt_ent_buffer struct {
- header W_Mnth
- filesys_info [128]W_Mntent
- }
- var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
- fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
- if err != nil {
- return err
- }
- err = ERANGE //return ERANGE if no match is found in this batch
- for i := 0; i < fs_count; i++ {
- if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
- stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
- err = nil
- break
- }
- }
- return err
-}
-
-func tryGetmntent256(stat *Statfs_t) (err error) {
- var mnt_ent_buffer struct {
- header W_Mnth
- filesys_info [256]W_Mntent
- }
- var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
- fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
- if err != nil {
- return err
- }
- err = ERANGE //return ERANGE if no match is found in this batch
- for i := 0; i < fs_count; i++ {
- if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
- stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
- err = nil
- break
- }
- }
- return err
-}
-
-func tryGetmntent512(stat *Statfs_t) (err error) {
- var mnt_ent_buffer struct {
- header W_Mnth
- filesys_info [512]W_Mntent
- }
- var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
- fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
- if err != nil {
- return err
- }
- err = ERANGE //return ERANGE if no match is found in this batch
- for i := 0; i < fs_count; i++ {
- if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
- stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
- err = nil
- break
- }
- }
- return err
-}
-
-func tryGetmntent1024(stat *Statfs_t) (err error) {
- var mnt_ent_buffer struct {
- header W_Mnth
- filesys_info [1024]W_Mntent
- }
- var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
- fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
- if err != nil {
- return err
- }
- err = ERANGE //return ERANGE if no match is found in this batch
- for i := 0; i < fs_count; i++ {
- if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
- stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
- err = nil
- break
- }
- }
- return err
-}
diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh
index 6202638bae..fdcaa974d2 100644
--- a/vendor/golang.org/x/sys/unix/mkerrors.sh
+++ b/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -248,6 +248,7 @@ struct ltchars {
#include
#include
#include
+#include
#include
#include
#include
@@ -283,10 +284,6 @@ struct ltchars {
#include
#endif
-#ifndef MSG_FASTOPEN
-#define MSG_FASTOPEN 0x20000000
-#endif
-
#ifndef PTRACE_GETREGS
#define PTRACE_GETREGS 0xc
#endif
@@ -295,14 +292,6 @@ struct ltchars {
#define PTRACE_SETREGS 0xd
#endif
-#ifndef SOL_NETLINK
-#define SOL_NETLINK 270
-#endif
-
-#ifndef SOL_SMC
-#define SOL_SMC 286
-#endif
-
#ifdef SOL_BLUETOOTH
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
// but it is already in bluetooth_linux.go
@@ -319,10 +308,23 @@ struct ltchars {
#undef TIPC_WAIT_FOREVER
#define TIPC_WAIT_FOREVER 0xffffffff
-// Copied from linux/l2tp.h
-// Including linux/l2tp.h here causes conflicts between linux/in.h
-// and netinet/in.h included via net/route.h above.
-#define IPPROTO_L2TP 115
+// Copied from linux/netfilter/nf_nat.h
+// Including linux/netfilter/nf_nat.h here causes conflicts between linux/in.h
+// and netinet/in.h.
+#define NF_NAT_RANGE_MAP_IPS (1 << 0)
+#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1)
+#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)
+#define NF_NAT_RANGE_PERSISTENT (1 << 3)
+#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
+#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
+#define NF_NAT_RANGE_NETMAP (1 << 6)
+#define NF_NAT_RANGE_PROTO_RANDOM_ALL \
+ (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+#define NF_NAT_RANGE_MASK \
+ (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \
+ NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \
+ NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | \
+ NF_NAT_RANGE_NETMAP)
// Copied from linux/hid.h.
// Keep in sync with the size of the referenced fields.
@@ -582,7 +584,7 @@ ccflags="$@"
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
$2 ~ /^KEYCTL_/ ||
$2 ~ /^PERF_/ ||
- $2 ~ /^SECCOMP_MODE_/ ||
+ $2 ~ /^SECCOMP_/ ||
$2 ~ /^SEEK_/ ||
$2 ~ /^SCHED_/ ||
$2 ~ /^SPLICE_/ ||
@@ -603,6 +605,9 @@ ccflags="$@"
$2 ~ /^FSOPT_/ ||
$2 ~ /^WDIO[CFS]_/ ||
$2 ~ /^NFN/ ||
+ $2 !~ /^NFT_META_IIFTYPE/ &&
+ $2 ~ /^NFT_/ ||
+ $2 ~ /^NF_NAT_/ ||
$2 ~ /^XDP_/ ||
$2 ~ /^RWF_/ ||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
diff --git a/vendor/golang.org/x/sys/unix/mmap_nomremap.go b/vendor/golang.org/x/sys/unix/mmap_nomremap.go
index 4b68e59780..7f602ffd26 100644
--- a/vendor/golang.org/x/sys/unix/mmap_nomremap.go
+++ b/vendor/golang.org/x/sys/unix/mmap_nomremap.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris
+//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos
package unix
diff --git a/vendor/golang.org/x/sys/unix/pagesize_unix.go b/vendor/golang.org/x/sys/unix/pagesize_unix.go
index 4d0a3430ed..0482408d7c 100644
--- a/vendor/golang.org/x/sys/unix/pagesize_unix.go
+++ b/vendor/golang.org/x/sys/unix/pagesize_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
// For Unix, get the pagesize from the runtime.
diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go
index 130398b6b7..b903c00604 100644
--- a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go
+++ b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build darwin
+//go:build darwin || zos
package unix
diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_zos.go b/vendor/golang.org/x/sys/unix/sockcmsg_zos.go
new file mode 100644
index 0000000000..3e53dbc028
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/sockcmsg_zos.go
@@ -0,0 +1,58 @@
+// Copyright 2024 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.
+
+// Socket control messages
+
+package unix
+
+import "unsafe"
+
+// UnixCredentials encodes credentials into a socket control message
+// for sending to another process. This can be used for
+// authentication.
+func UnixCredentials(ucred *Ucred) []byte {
+ b := make([]byte, CmsgSpace(SizeofUcred))
+ h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+ h.Level = SOL_SOCKET
+ h.Type = SCM_CREDENTIALS
+ h.SetLen(CmsgLen(SizeofUcred))
+ *(*Ucred)(h.data(0)) = *ucred
+ return b
+}
+
+// ParseUnixCredentials decodes a socket control message that contains
+// credentials in a Ucred structure. To receive such a message, the
+// SO_PASSCRED option must be enabled on the socket.
+func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
+ if m.Header.Level != SOL_SOCKET {
+ return nil, EINVAL
+ }
+ if m.Header.Type != SCM_CREDENTIALS {
+ return nil, EINVAL
+ }
+ ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
+ return &ucred, nil
+}
+
+// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO.
+func PktInfo4(info *Inet4Pktinfo) []byte {
+ b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
+ h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+ h.Level = SOL_IP
+ h.Type = IP_PKTINFO
+ h.SetLen(CmsgLen(SizeofInet4Pktinfo))
+ *(*Inet4Pktinfo)(h.data(0)) = *info
+ return b
+}
+
+// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO.
+func PktInfo6(info *Inet6Pktinfo) []byte {
+ b := make([]byte, CmsgSpace(SizeofInet6Pktinfo))
+ h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
+ h.Level = SOL_IPV6
+ h.Type = IPV6_PKTINFO
+ h.SetLen(CmsgLen(SizeofInet6Pktinfo))
+ *(*Inet6Pktinfo)(h.data(0)) = *info
+ return b
+}
diff --git a/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s b/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s
new file mode 100644
index 0000000000..3c4f33cb6a
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s
@@ -0,0 +1,75 @@
+// Copyright 2024 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.
+
+//go:build zos && s390x && gc
+
+#include "textflag.h"
+
+// provide the address of function variable to be fixed up.
+
+TEXT ·getPipe2Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Pipe2(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_FlockAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Flock(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_GetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Getxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_NanosleepAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Nanosleep(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_SetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Setxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_Wait4Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Wait4(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_MountAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Mount(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_UnmountAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Unmount(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_UtimesNanoAtAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·UtimesNanoAt(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_UtimesNanoAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·UtimesNano(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_MkfifoatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Mkfifoat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_ChtagAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Chtag(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+TEXT ·get_ReadlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Readlinkat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go
index 16dc699379..2f0fa76e4f 100644
--- a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go
+++ b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build darwin && go1.12
+//go:build darwin
package unix
diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go
index 64d1bb4dba..2b57e0f73b 100644
--- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go
+++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go
@@ -13,6 +13,7 @@
package unix
import (
+ "errors"
"sync"
"unsafe"
)
@@ -169,25 +170,26 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
func Uname(uname *Utsname) error {
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
n := unsafe.Sizeof(uname.Sysname)
- if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
+ // Suppress ENOMEM errors to be compatible with the C library __xuname() implementation.
+ if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
n = unsafe.Sizeof(uname.Nodename)
- if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
+ if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
n = unsafe.Sizeof(uname.Release)
- if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
+ if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
mib = []_C_int{CTL_KERN, KERN_VERSION}
n = unsafe.Sizeof(uname.Version)
- if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
+ if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
@@ -205,7 +207,7 @@ func Uname(uname *Utsname) error {
mib = []_C_int{CTL_HW, HW_MACHINE}
n = unsafe.Sizeof(uname.Machine)
- if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
+ if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err
}
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go
index 0f85e29e62..5682e2628a 100644
--- a/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -1849,6 +1849,105 @@ func Dup2(oldfd, newfd int) error {
//sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error)
//sys Fsopen(fsName string, flags int) (fd int, err error)
//sys Fspick(dirfd int, pathName string, flags int) (fd int, err error)
+
+//sys fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error)
+
+func fsconfigCommon(fd int, cmd uint, key string, value *byte, aux int) (err error) {
+ var keyp *byte
+ if keyp, err = BytePtrFromString(key); err != nil {
+ return
+ }
+ return fsconfig(fd, cmd, keyp, value, aux)
+}
+
+// FsconfigSetFlag is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_SET_FLAG.
+//
+// fd is the filesystem context to act upon.
+// key the parameter key to set.
+func FsconfigSetFlag(fd int, key string) (err error) {
+ return fsconfigCommon(fd, FSCONFIG_SET_FLAG, key, nil, 0)
+}
+
+// FsconfigSetString is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_SET_STRING.
+//
+// fd is the filesystem context to act upon.
+// key the parameter key to set.
+// value is the parameter value to set.
+func FsconfigSetString(fd int, key string, value string) (err error) {
+ var valuep *byte
+ if valuep, err = BytePtrFromString(value); err != nil {
+ return
+ }
+ return fsconfigCommon(fd, FSCONFIG_SET_STRING, key, valuep, 0)
+}
+
+// FsconfigSetBinary is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_SET_BINARY.
+//
+// fd is the filesystem context to act upon.
+// key the parameter key to set.
+// value is the parameter value to set.
+func FsconfigSetBinary(fd int, key string, value []byte) (err error) {
+ if len(value) == 0 {
+ return EINVAL
+ }
+ return fsconfigCommon(fd, FSCONFIG_SET_BINARY, key, &value[0], len(value))
+}
+
+// FsconfigSetPath is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_SET_PATH.
+//
+// fd is the filesystem context to act upon.
+// key the parameter key to set.
+// path is a non-empty path for specified key.
+// atfd is a file descriptor at which to start lookup from or AT_FDCWD.
+func FsconfigSetPath(fd int, key string, path string, atfd int) (err error) {
+ var valuep *byte
+ if valuep, err = BytePtrFromString(path); err != nil {
+ return
+ }
+ return fsconfigCommon(fd, FSCONFIG_SET_PATH, key, valuep, atfd)
+}
+
+// FsconfigSetPathEmpty is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_SET_PATH_EMPTY. The same as
+// FconfigSetPath but with AT_PATH_EMPTY implied.
+func FsconfigSetPathEmpty(fd int, key string, path string, atfd int) (err error) {
+ var valuep *byte
+ if valuep, err = BytePtrFromString(path); err != nil {
+ return
+ }
+ return fsconfigCommon(fd, FSCONFIG_SET_PATH_EMPTY, key, valuep, atfd)
+}
+
+// FsconfigSetFd is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_SET_FD.
+//
+// fd is the filesystem context to act upon.
+// key the parameter key to set.
+// value is a file descriptor to be assigned to specified key.
+func FsconfigSetFd(fd int, key string, value int) (err error) {
+ return fsconfigCommon(fd, FSCONFIG_SET_FD, key, nil, value)
+}
+
+// FsconfigCreate is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_CMD_CREATE.
+//
+// fd is the filesystem context to act upon.
+func FsconfigCreate(fd int) (err error) {
+ return fsconfig(fd, FSCONFIG_CMD_CREATE, nil, nil, 0)
+}
+
+// FsconfigReconfigure is equivalent to fsconfig(2) called
+// with cmd == FSCONFIG_CMD_RECONFIGURE.
+//
+// fd is the filesystem context to act upon.
+func FsconfigReconfigure(fd int) (err error) {
+ return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0)
+}
+
//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
//sysnb Getpgid(pid int) (pgid int, err error)
diff --git a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
index b473038c61..312ae6ac1d 100644
--- a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
@@ -4,11 +4,21 @@
//go:build zos && s390x
+// Many of the following syscalls are not available on all versions of z/OS.
+// Some missing calls have legacy implementations/simulations but others
+// will be missing completely. To achieve consistent failing behaviour on
+// legacy systems, we first test the function pointer via a safeloading
+// mechanism to see if the function exists on a given system. Then execution
+// is branched to either continue the function call, or return an error.
+
package unix
import (
"bytes"
"fmt"
+ "os"
+ "reflect"
+ "regexp"
"runtime"
"sort"
"strings"
@@ -17,17 +27,205 @@ import (
"unsafe"
)
+//go:noescape
+func initZosLibVec()
+
+//go:noescape
+func GetZosLibVec() uintptr
+
+func init() {
+ initZosLibVec()
+ r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACE\x00"))[0])))
+ if r0 != 0 {
+ n, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0)
+ ZosTraceLevel = int(n)
+ r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACEFD\x00"))[0])))
+ if r0 != 0 {
+ fd, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0)
+ f := os.NewFile(fd, "zostracefile")
+ if f != nil {
+ ZosTracefile = f
+ }
+ }
+
+ }
+}
+
+//go:noescape
+func CallLeFuncWithErr(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno)
+
+//go:noescape
+func CallLeFuncWithPtrReturn(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno)
+
+// -------------------------------
+// pointer validity test
+// good pointer returns 0
+// bad pointer returns 1
+//
+//go:nosplit
+func ptrtest(uintptr) uint64
+
+// Load memory at ptr location with error handling if the location is invalid
+//
+//go:noescape
+func safeload(ptr uintptr) (value uintptr, error uintptr)
+
const (
- O_CLOEXEC = 0 // Dummy value (not supported).
- AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX
+ entrypointLocationOffset = 8 // From function descriptor
+
+ xplinkEyecatcher = 0x00c300c500c500f1 // ".C.E.E.1"
+ eyecatcherOffset = 16 // From function entrypoint (negative)
+ ppa1LocationOffset = 8 // From function entrypoint (negative)
+
+ nameLenOffset = 0x14 // From PPA1 start
+ nameOffset = 0x16 // From PPA1 start
)
-func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
-func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
-func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
-func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
-func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
-func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
+func getPpaOffset(funcptr uintptr) int64 {
+ entrypoint, err := safeload(funcptr + entrypointLocationOffset)
+ if err != 0 {
+ return -1
+ }
+
+ // XPLink functions have ".C.E.E.1" as the first 8 bytes (EBCDIC)
+ val, err := safeload(entrypoint - eyecatcherOffset)
+ if err != 0 {
+ return -1
+ }
+ if val != xplinkEyecatcher {
+ return -1
+ }
+
+ ppaoff, err := safeload(entrypoint - ppa1LocationOffset)
+ if err != 0 {
+ return -1
+ }
+
+ ppaoff >>= 32
+ return int64(ppaoff)
+}
+
+//-------------------------------
+// function descriptor pointer validity test
+// good pointer returns 0
+// bad pointer returns 1
+
+// TODO: currently mksyscall_zos_s390x.go generate empty string for funcName
+// have correct funcName pass to the funcptrtest function
+func funcptrtest(funcptr uintptr, funcName string) uint64 {
+ entrypoint, err := safeload(funcptr + entrypointLocationOffset)
+ if err != 0 {
+ return 1
+ }
+
+ ppaoff := getPpaOffset(funcptr)
+ if ppaoff == -1 {
+ return 1
+ }
+
+ // PPA1 offset value is from the start of the entire function block, not the entrypoint
+ ppa1 := (entrypoint - eyecatcherOffset) + uintptr(ppaoff)
+
+ nameLen, err := safeload(ppa1 + nameLenOffset)
+ if err != 0 {
+ return 1
+ }
+
+ nameLen >>= 48
+ if nameLen > 128 {
+ return 1
+ }
+
+ // no function name input to argument end here
+ if funcName == "" {
+ return 0
+ }
+
+ var funcname [128]byte
+ for i := 0; i < int(nameLen); i += 8 {
+ v, err := safeload(ppa1 + nameOffset + uintptr(i))
+ if err != 0 {
+ return 1
+ }
+ funcname[i] = byte(v >> 56)
+ funcname[i+1] = byte(v >> 48)
+ funcname[i+2] = byte(v >> 40)
+ funcname[i+3] = byte(v >> 32)
+ funcname[i+4] = byte(v >> 24)
+ funcname[i+5] = byte(v >> 16)
+ funcname[i+6] = byte(v >> 8)
+ funcname[i+7] = byte(v)
+ }
+
+ runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l
+ []uintptr{uintptr(unsafe.Pointer(&funcname[0])), nameLen})
+
+ name := string(funcname[:nameLen])
+ if name != funcName {
+ return 1
+ }
+
+ return 0
+}
+
+// For detection of capabilities on a system.
+// Is function descriptor f a valid function?
+func isValidLeFunc(f uintptr) error {
+ ret := funcptrtest(f, "")
+ if ret != 0 {
+ return fmt.Errorf("Bad pointer, not an LE function ")
+ }
+ return nil
+}
+
+// Retrieve function name from descriptor
+func getLeFuncName(f uintptr) (string, error) {
+ // assume it has been checked, only check ppa1 validity here
+ entry := ((*[2]uintptr)(unsafe.Pointer(f)))[1]
+ preamp := ((*[4]uint32)(unsafe.Pointer(entry - eyecatcherOffset)))
+
+ offsetPpa1 := preamp[2]
+ if offsetPpa1 > 0x0ffff {
+ return "", fmt.Errorf("PPA1 offset seems too big 0x%x\n", offsetPpa1)
+ }
+
+ ppa1 := uintptr(unsafe.Pointer(preamp)) + uintptr(offsetPpa1)
+ res := ptrtest(ppa1)
+ if res != 0 {
+ return "", fmt.Errorf("PPA1 address not valid")
+ }
+
+ size := *(*uint16)(unsafe.Pointer(ppa1 + nameLenOffset))
+ if size > 128 {
+ return "", fmt.Errorf("Function name seems too long, length=%d\n", size)
+ }
+
+ var name [128]byte
+ funcname := (*[128]byte)(unsafe.Pointer(ppa1 + nameOffset))
+ copy(name[0:size], funcname[0:size])
+
+ runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l
+ []uintptr{uintptr(unsafe.Pointer(&name[0])), uintptr(size)})
+
+ return string(name[:size]), nil
+}
+
+// Check z/OS version
+func zosLeVersion() (version, release uint32) {
+ p1 := (*(*uintptr)(unsafe.Pointer(uintptr(1208)))) >> 32
+ p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 88)))
+ p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 8)))
+ p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 984)))
+ vrm := *(*uint32)(unsafe.Pointer(p1 + 80))
+ version = (vrm & 0x00ff0000) >> 16
+ release = (vrm & 0x0000ff00) >> 8
+ return
+}
+
+// returns a zos C FILE * for stdio fd 0, 1, 2
+func ZosStdioFilep(fd int32) uintptr {
+ return uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(uint64(*(*uint32)(unsafe.Pointer(uintptr(1208)))) + 80))) + uint64((fd+2)<<3))))))))
+}
func copyStat(stat *Stat_t, statLE *Stat_LE_t) {
stat.Dev = uint64(statLE.Dev)
@@ -65,6 +263,21 @@ func (d *Dirent) NameString() string {
}
}
+func DecodeData(dest []byte, sz int, val uint64) {
+ for i := 0; i < sz; i++ {
+ dest[sz-1-i] = byte((val >> (uint64(i * 8))) & 0xff)
+ }
+}
+
+func EncodeData(data []byte) uint64 {
+ var value uint64
+ sz := len(data)
+ for i := 0; i < sz; i++ {
+ value |= uint64(data[i]) << uint64(((sz - i - 1) * 8))
+ }
+ return value
+}
+
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL
@@ -74,7 +287,9 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
- sa.raw.Addr = sa.Addr
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
}
@@ -88,7 +303,9 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
- sa.raw.Addr = sa.Addr
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
}
@@ -146,7 +363,9 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
- sa.Addr = pp.Addr
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i]
+ }
return sa, nil
case AF_INET6:
@@ -155,7 +374,9 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
- sa.Addr = pp.Addr
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i]
+ }
return sa, nil
}
return nil, EAFNOSUPPORT
@@ -177,6 +398,43 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
return
}
+func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
+ var rsa RawSockaddrAny
+ var len _Socklen = SizeofSockaddrAny
+ nfd, err = accept4(fd, &rsa, &len, flags)
+ if err != nil {
+ return
+ }
+ if len > SizeofSockaddrAny {
+ panic("RawSockaddrAny too small")
+ }
+ // TODO(neeilan): Remove 0 in call
+ sa, err = anyToSockaddr(0, &rsa)
+ if err != nil {
+ Close(nfd)
+ nfd = 0
+ }
+ return
+}
+
+func Ctermid() (tty string, err error) {
+ var termdev [1025]byte
+ runtime.EnterSyscall()
+ r0, err2, err1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___CTERMID_A<<4, uintptr(unsafe.Pointer(&termdev[0])))
+ runtime.ExitSyscall()
+ if r0 == 0 {
+ return "", fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2)
+ }
+ s := string(termdev[:])
+ idx := strings.Index(s, string(rune(0)))
+ if idx == -1 {
+ tty = s
+ } else {
+ tty = s[:idx]
+ }
+ return
+}
+
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
@@ -190,10 +448,16 @@ func (cmsg *Cmsghdr) SetLen(length int) {
}
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
+//sys Flistxattr(fd int, dest []byte) (sz int, err error) = SYS___FLISTXATTR_A
+//sys Fremovexattr(fd int, attr string) (err error) = SYS___FREMOVEXATTR_A
//sys read(fd int, p []byte) (n int, err error)
//sys write(fd int, p []byte) (n int, err error)
+//sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) = SYS___FGETXATTR_A
+//sys Fsetxattr(fd int, attr string, data []byte, flag int) (err error) = SYS___FSETXATTR_A
+
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A
+//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = SYS___ACCEPT4_A
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
@@ -204,6 +468,7 @@ func (cmsg *Cmsghdr) SetLen(length int) {
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A
+//sys Removexattr(path string, attr string) (err error) = SYS___REMOVEXATTR_A
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A
@@ -212,6 +477,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
//sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
//sys ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL
//sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL
+//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) = SYS_SHMAT
+//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) = SYS_SHMCTL64
+//sys shmdt(addr uintptr) (err error) = SYS_SHMDT
+//sys shmget(key int, size int, flag int) (id int, err error) = SYS_SHMGET
//sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A
//sys Chdir(path string) (err error) = SYS___CHDIR_A
@@ -220,14 +489,31 @@ func (cmsg *Cmsghdr) SetLen(length int) {
//sys Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A
//sys Dup(oldfd int) (fd int, err error)
//sys Dup2(oldfd int, newfd int) (err error)
+//sys Dup3(oldfd int, newfd int, flags int) (err error) = SYS_DUP3
+//sys Dirfd(dirp uintptr) (fd int, err error) = SYS_DIRFD
+//sys EpollCreate(size int) (fd int, err error) = SYS_EPOLL_CREATE
+//sys EpollCreate1(flags int) (fd int, err error) = SYS_EPOLL_CREATE1
+//sys EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) = SYS_EPOLL_CTL
+//sys EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) = SYS_EPOLL_PWAIT
+//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_WAIT
//sys Errno2() (er2 int) = SYS___ERRNO2
-//sys Err2ad() (eadd *int) = SYS___ERR2AD
+//sys Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD
//sys Exit(code int)
+//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FACCESSAT_A
+
+func Faccessat2(dirfd int, path string, mode uint32, flags int) (err error) {
+ return Faccessat(dirfd, path, mode, flags)
+}
+
//sys Fchdir(fd int) (err error)
//sys Fchmod(fd int, mode uint32) (err error)
+//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FCHMODAT_A
//sys Fchown(fd int, uid int, gid int) (err error)
+//sys Fchownat(fd int, path string, uid int, gid int, flags int) (err error) = SYS___FCHOWNAT_A
//sys FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL
+//sys Fdatasync(fd int) (err error) = SYS_FDATASYNC
//sys fstat(fd int, stat *Stat_LE_t) (err error)
+//sys fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) = SYS___FSTATAT_A
func Fstat(fd int, stat *Stat_t) (err error) {
var statLE Stat_LE_t
@@ -236,28 +522,208 @@ func Fstat(fd int, stat *Stat_t) (err error) {
return
}
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+ var statLE Stat_LE_t
+ err = fstatat(dirfd, path, &statLE, flags)
+ copyStat(stat, &statLE)
+ return
+}
+
+func impl_Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(dest) > 0 {
+ _p2 = unsafe.Pointer(&dest[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)))
+ sz = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_GetxattrAddr() *(func(path string, attr string, dest []byte) (sz int, err error))
+
+var Getxattr = enter_Getxattr
+
+func enter_Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+ funcref := get_GetxattrAddr()
+ if validGetxattr() {
+ *funcref = impl_Getxattr
+ } else {
+ *funcref = error_Getxattr
+ }
+ return (*funcref)(path, attr, dest)
+}
+
+func error_Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+ return -1, ENOSYS
+}
+
+func validGetxattr() bool {
+ if funcptrtest(GetZosLibVec()+SYS___GETXATTR_A<<4, "") == 0 {
+ if name, err := getLeFuncName(GetZosLibVec() + SYS___GETXATTR_A<<4); err == nil {
+ return name == "__getxattr_a"
+ }
+ }
+ return false
+}
+
+//sys Lgetxattr(link string, attr string, dest []byte) (sz int, err error) = SYS___LGETXATTR_A
+//sys Lsetxattr(path string, attr string, data []byte, flags int) (err error) = SYS___LSETXATTR_A
+
+func impl_Setxattr(path string, attr string, data []byte, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(data) > 0 {
+ _p2 = unsafe.Pointer(&data[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_SetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error))
+
+var Setxattr = enter_Setxattr
+
+func enter_Setxattr(path string, attr string, data []byte, flags int) (err error) {
+ funcref := get_SetxattrAddr()
+ if validSetxattr() {
+ *funcref = impl_Setxattr
+ } else {
+ *funcref = error_Setxattr
+ }
+ return (*funcref)(path, attr, data, flags)
+}
+
+func error_Setxattr(path string, attr string, data []byte, flags int) (err error) {
+ return ENOSYS
+}
+
+func validSetxattr() bool {
+ if funcptrtest(GetZosLibVec()+SYS___SETXATTR_A<<4, "") == 0 {
+ if name, err := getLeFuncName(GetZosLibVec() + SYS___SETXATTR_A<<4); err == nil {
+ return name == "__setxattr_a"
+ }
+ }
+ return false
+}
+
+//sys Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS
//sys Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS
//sys Fsync(fd int) (err error)
+//sys Futimes(fd int, tv []Timeval) (err error) = SYS_FUTIMES
+//sys Futimesat(dirfd int, path string, tv []Timeval) (err error) = SYS___FUTIMESAT_A
//sys Ftruncate(fd int, length int64) (err error)
-//sys Getpagesize() (pgsize int) = SYS_GETPAGESIZE
+//sys Getrandom(buf []byte, flags int) (n int, err error) = SYS_GETRANDOM
+//sys InotifyInit() (fd int, err error) = SYS_INOTIFY_INIT
+//sys InotifyInit1(flags int) (fd int, err error) = SYS_INOTIFY_INIT1
+//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) = SYS___INOTIFY_ADD_WATCH_A
+//sys InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) = SYS_INOTIFY_RM_WATCH
+//sys Listxattr(path string, dest []byte) (sz int, err error) = SYS___LISTXATTR_A
+//sys Llistxattr(path string, dest []byte) (sz int, err error) = SYS___LLISTXATTR_A
+//sys Lremovexattr(path string, attr string) (err error) = SYS___LREMOVEXATTR_A
+//sys Lutimes(path string, tv []Timeval) (err error) = SYS___LUTIMES_A
//sys Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT
//sys Msync(b []byte, flags int) (err error) = SYS_MSYNC
+//sys Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) = SYS___CONSOLE2
+
+// Pipe2 begin
+
+//go:nosplit
+func getPipe2Addr() *(func([]int, int) error)
+
+var Pipe2 = pipe2Enter
+
+func pipe2Enter(p []int, flags int) (err error) {
+ if funcptrtest(GetZosLibVec()+SYS_PIPE2<<4, "") == 0 {
+ *getPipe2Addr() = pipe2Impl
+ } else {
+ *getPipe2Addr() = pipe2Error
+ }
+ return (*getPipe2Addr())(p, flags)
+}
+
+func pipe2Impl(p []int, flags int) (err error) {
+ var pp [2]_C_int
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE2<<4, uintptr(unsafe.Pointer(&pp[0])), uintptr(flags))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ } else {
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ }
+ return
+}
+func pipe2Error(p []int, flags int) (err error) {
+ return fmt.Errorf("Pipe2 is not available on this system")
+}
+
+// Pipe2 end
+
//sys Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL
+
+func Readdir(dir uintptr) (dirent *Dirent, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_A<<4, uintptr(dir))
+ runtime.ExitSyscall()
+ dirent = (*Dirent)(unsafe.Pointer(r0))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//sys Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) = SYS___READDIR_R_A
+//sys Statfs(path string, buf *Statfs_t) (err error) = SYS___STATFS_A
+//sys Syncfs(fd int) (err error) = SYS_SYNCFS
//sys Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES
//sys W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT
//sys W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A
//sys mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A
-//sys unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A
+//sys unmount_LE(filesystem string, mtm int) (err error) = SYS___UMOUNT_A
//sys Chroot(path string) (err error) = SYS___CHROOT_A
//sys Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT
-//sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A
+//sysnb Uname(buf *Utsname) (err error) = SYS_____OSNAME_A
+//sys Unshare(flags int) (err error) = SYS_UNSHARE
func Ptsname(fd int) (name string, err error) {
- r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0)
- name = u2s(unsafe.Pointer(r0))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___PTSNAME_A<<4, uintptr(fd))
+ runtime.ExitSyscall()
+ if r0 == 0 {
+ err = errnoErr2(e1, e2)
+ } else {
+ name = u2s(unsafe.Pointer(r0))
}
return
}
@@ -272,13 +738,19 @@ func u2s(cstr unsafe.Pointer) string {
}
func Close(fd int) (err error) {
- _, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd))
+ runtime.ExitSyscall()
for i := 0; e1 == EAGAIN && i < 10; i++ {
- _, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0)
- _, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+ runtime.EnterSyscall()
+ CallLeFuncWithErr(GetZosLibVec()+SYS_USLEEP<<4, uintptr(10))
+ runtime.ExitSyscall()
+ runtime.EnterSyscall()
+ r0, e2, e1 = CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd))
+ runtime.ExitSyscall()
}
- if e1 != 0 {
- err = errnoErr(e1)
+ if r0 != 0 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -288,9 +760,15 @@ func Madvise(b []byte, advice int) (err error) {
return
}
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
+ return mapper.Mmap(fd, offset, length, prot, flags)
+}
+
+func Munmap(b []byte) (err error) {
+ return mapper.Munmap(b)
+}
+
//sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
-//sysnb Getegid() (egid int)
-//sysnb Geteuid() (uid int)
//sysnb Getgid() (gid int)
//sysnb Getpid() (pid int)
//sysnb Getpgid(pid int) (pgid int, err error) = SYS_GETPGID
@@ -317,11 +795,14 @@ func Getrusage(who int, rusage *Rusage) (err error) {
return
}
+//sys Getegid() (egid int) = SYS_GETEGID
+//sys Geteuid() (euid int) = SYS_GETEUID
//sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID
//sysnb Getuid() (uid int)
//sysnb Kill(pid int, sig Signal) (err error)
//sys Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A
//sys Link(path string, link string) (err error) = SYS___LINK_A
+//sys Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) = SYS___LINKAT_A
//sys Listen(s int, n int) (err error)
//sys lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A
@@ -332,15 +813,150 @@ func Lstat(path string, stat *Stat_t) (err error) {
return
}
+// for checking symlinks begins with $VERSION/ $SYSNAME/ $SYSSYMR/ $SYSSYMA/
+func isSpecialPath(path []byte) (v bool) {
+ var special = [4][8]byte{
+ [8]byte{'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'},
+ [8]byte{'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'},
+ [8]byte{'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'},
+ [8]byte{'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}}
+
+ var i, j int
+ for i = 0; i < len(special); i++ {
+ for j = 0; j < len(special[i]); j++ {
+ if path[j] != special[i][j] {
+ break
+ }
+ }
+ if j == len(special[i]) {
+ return true
+ }
+ }
+ return false
+}
+
+func realpath(srcpath string, abspath []byte) (pathlen int, errno int) {
+ var source [1024]byte
+ copy(source[:], srcpath)
+ source[len(srcpath)] = 0
+ ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___REALPATH_A<<4, //__realpath_a()
+ []uintptr{uintptr(unsafe.Pointer(&source[0])),
+ uintptr(unsafe.Pointer(&abspath[0]))})
+ if ret != 0 {
+ index := bytes.IndexByte(abspath[:], byte(0))
+ if index != -1 {
+ return index, 0
+ }
+ } else {
+ errptr := (*int)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) //__errno()
+ return 0, *errptr
+ }
+ return 0, 245 // EBADDATA 245
+}
+
+func Readlink(path string, buf []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(buf) > 0 {
+ _p1 = unsafe.Pointer(&buf[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ n = int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___READLINK_A<<4,
+ []uintptr{uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))}))
+ runtime.KeepAlive(unsafe.Pointer(_p0))
+ if n == -1 {
+ value := *(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{})))
+ err = errnoErr(Errno(value))
+ } else {
+ if buf[0] == '$' {
+ if isSpecialPath(buf[1:9]) {
+ cnt, err1 := realpath(path, buf)
+ if err1 == 0 {
+ n = cnt
+ }
+ }
+ }
+ }
+ return
+}
+
+func impl_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(buf) > 0 {
+ _p1 = unsafe.Pointer(&buf[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
+ runtime.ExitSyscall()
+ n = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ return n, err
+ } else {
+ if buf[0] == '$' {
+ if isSpecialPath(buf[1:9]) {
+ cnt, err1 := realpath(path, buf)
+ if err1 == 0 {
+ n = cnt
+ }
+ }
+ }
+ }
+ return
+}
+
+//go:nosplit
+func get_ReadlinkatAddr() *(func(dirfd int, path string, buf []byte) (n int, err error))
+
+var Readlinkat = enter_Readlinkat
+
+func enter_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
+ funcref := get_ReadlinkatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___READLINKAT_A<<4, "") == 0 {
+ *funcref = impl_Readlinkat
+ } else {
+ *funcref = error_Readlinkat
+ }
+ return (*funcref)(dirfd, path, buf)
+}
+
+func error_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
+ n = -1
+ err = ENOSYS
+ return
+}
+
//sys Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A
+//sys Mkdirat(dirfd int, path string, mode uint32) (err error) = SYS___MKDIRAT_A
//sys Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A
//sys Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A
+//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) = SYS___MKNODAT_A
+//sys PivotRoot(newroot string, oldroot string) (err error) = SYS___PIVOT_ROOT_A
//sys Pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
-//sys Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A
+//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) = SYS___PRCTL_A
+//sysnb Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT
//sys Rename(from string, to string) (err error) = SYS___RENAME_A
+//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) = SYS___RENAMEAT_A
+//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) = SYS___RENAMEAT2_A
//sys Rmdir(path string) (err error) = SYS___RMDIR_A
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
+//sys Setegid(egid int) (err error) = SYS_SETEGID
+//sys Seteuid(euid int) (err error) = SYS_SETEUID
+//sys Sethostname(p []byte) (err error) = SYS___SETHOSTNAME_A
+//sys Setns(fd int, nstype int) (err error) = SYS_SETNS
//sys Setpriority(which int, who int, prio int) (err error)
//sysnb Setpgid(pid int, pgid int) (err error) = SYS_SETPGID
//sysnb Setrlimit(resource int, lim *Rlimit) (err error)
@@ -360,32 +976,57 @@ func Stat(path string, sta *Stat_t) (err error) {
}
//sys Symlink(path string, link string) (err error) = SYS___SYMLINK_A
+//sys Symlinkat(oldPath string, dirfd int, newPath string) (err error) = SYS___SYMLINKAT_A
//sys Sync() = SYS_SYNC
//sys Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A
//sys Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR
//sys Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR
//sys Umask(mask int) (oldmask int)
//sys Unlink(path string) (err error) = SYS___UNLINK_A
+//sys Unlinkat(dirfd int, path string, flags int) (err error) = SYS___UNLINKAT_A
//sys Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A
//sys open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A
func Open(path string, mode int, perm uint32) (fd int, err error) {
+ if mode&O_ACCMODE == 0 {
+ mode |= O_RDONLY
+ }
return open(path, mode, perm)
}
-func Mkfifoat(dirfd int, path string, mode uint32) (err error) {
- wd, err := Getwd()
- if err != nil {
- return err
+//sys openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) = SYS___OPENAT_A
+
+func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+ if flags&O_ACCMODE == 0 {
+ flags |= O_RDONLY
}
+ return openat(dirfd, path, flags, mode)
+}
- if err := Fchdir(dirfd); err != nil {
- return err
+//sys openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) = SYS___OPENAT2_A
+
+func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) {
+ if how.Flags&O_ACCMODE == 0 {
+ how.Flags |= O_RDONLY
}
- defer Chdir(wd)
+ return openat2(dirfd, path, how, SizeofOpenHow)
+}
- return Mkfifo(path, mode)
+func ZosFdToPath(dirfd int) (path string, err error) {
+ var buffer [1024]byte
+ runtime.EnterSyscall()
+ ret, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_IOCTL<<4, uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0])))
+ runtime.ExitSyscall()
+ if ret == 0 {
+ zb := bytes.IndexByte(buffer[:], 0)
+ if zb == -1 {
+ zb = len(buffer)
+ }
+ CallLeFuncWithErr(GetZosLibVec()+SYS___E2A_L<<4, uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb))
+ return string(buffer[:zb]), nil
+ }
+ return "", errnoErr2(e1, e2)
}
//sys remove(path string) (err error)
@@ -403,10 +1044,12 @@ func Getcwd(buf []byte) (n int, err error) {
} else {
p = unsafe.Pointer(&_zero)
}
- _, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___GETCWD_A<<4, uintptr(p), uintptr(len(buf)))
+ runtime.ExitSyscall()
n = clen(buf) + 1
- if e != 0 {
- err = errnoErr(e)
+ if r0 == 0 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -520,9 +1163,41 @@ func (w WaitStatus) StopSignal() Signal {
func (w WaitStatus) TrapCause() int { return -1 }
+//sys waitid(idType int, id int, info *Siginfo, options int) (err error)
+
+func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) {
+ return waitid(idType, id, info, options)
+}
+
//sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error)
-func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+func impl_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAIT4<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)))
+ runtime.ExitSyscall()
+ wpid = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_Wait4Addr() *(func(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error))
+
+var Wait4 = enter_Wait4
+
+func enter_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+ funcref := get_Wait4Addr()
+ if funcptrtest(GetZosLibVec()+SYS_WAIT4<<4, "") == 0 {
+ *funcref = impl_Wait4
+ } else {
+ *funcref = legacyWait4
+ }
+ return (*funcref)(pid, wstatus, options, rusage)
+}
+
+func legacyWait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
// TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want.
// At the moment rusage will not be touched.
var status _C_int
@@ -571,23 +1246,62 @@ func Pipe(p []int) (err error) {
}
var pp [2]_C_int
err = pipe(&pp)
- if err == nil {
- p[0] = int(pp[0])
- p[1] = int(pp[1])
- }
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
return
}
//sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A
func Utimes(path string, tv []Timeval) (err error) {
+ if tv == nil {
+ return utimes(path, nil)
+ }
if len(tv) != 2 {
return EINVAL
}
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
-func UtimesNano(path string, ts []Timespec) error {
+//sys utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) = SYS___UTIMENSAT_A
+
+func validUtimensat() bool {
+ if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 {
+ if name, err := getLeFuncName(GetZosLibVec() + SYS___UTIMENSAT_A<<4); err == nil {
+ return name == "__utimensat_a"
+ }
+ }
+ return false
+}
+
+// Begin UtimesNano
+
+//go:nosplit
+func get_UtimesNanoAddr() *(func(path string, ts []Timespec) (err error))
+
+var UtimesNano = enter_UtimesNano
+
+func enter_UtimesNano(path string, ts []Timespec) (err error) {
+ funcref := get_UtimesNanoAddr()
+ if validUtimensat() {
+ *funcref = utimesNanoImpl
+ } else {
+ *funcref = legacyUtimesNano
+ }
+ return (*funcref)(path, ts)
+}
+
+func utimesNanoImpl(path string, ts []Timespec) (err error) {
+ if ts == nil {
+ return utimensat(AT_FDCWD, path, nil, 0)
+ }
+ if len(ts) != 2 {
+ return EINVAL
+ }
+ return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
+}
+
+func legacyUtimesNano(path string, ts []Timespec) (err error) {
if len(ts) != 2 {
return EINVAL
}
@@ -600,6 +1314,70 @@ func UtimesNano(path string, ts []Timespec) error {
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
+// End UtimesNano
+
+// Begin UtimesNanoAt
+
+//go:nosplit
+func get_UtimesNanoAtAddr() *(func(dirfd int, path string, ts []Timespec, flags int) (err error))
+
+var UtimesNanoAt = enter_UtimesNanoAt
+
+func enter_UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) {
+ funcref := get_UtimesNanoAtAddr()
+ if validUtimensat() {
+ *funcref = utimesNanoAtImpl
+ } else {
+ *funcref = legacyUtimesNanoAt
+ }
+ return (*funcref)(dirfd, path, ts, flags)
+}
+
+func utimesNanoAtImpl(dirfd int, path string, ts []Timespec, flags int) (err error) {
+ if ts == nil {
+ return utimensat(dirfd, path, nil, flags)
+ }
+ if len(ts) != 2 {
+ return EINVAL
+ }
+ return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
+}
+
+func legacyUtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) {
+ if path[0] != '/' {
+ dirPath, err := ZosFdToPath(dirfd)
+ if err != nil {
+ return err
+ }
+ path = dirPath + "/" + path
+ }
+ if flags == AT_SYMLINK_NOFOLLOW {
+ if len(ts) != 2 {
+ return EINVAL
+ }
+
+ if ts[0].Nsec >= 5e8 {
+ ts[0].Sec++
+ }
+ ts[0].Nsec = 0
+ if ts[1].Nsec >= 5e8 {
+ ts[1].Sec++
+ }
+ ts[1].Nsec = 0
+
+ // Not as efficient as it could be because Timespec and
+ // Timeval have different types in the different OSes
+ tv := []Timeval{
+ NsecToTimeval(TimespecToNsec(ts[0])),
+ NsecToTimeval(TimespecToNsec(ts[1])),
+ }
+ return Lutimes(path, tv)
+ }
+ return UtimesNano(path, ts)
+}
+
+// End UtimesNanoAt
+
func Getsockname(fd int) (sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
@@ -1186,67 +1964,46 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
return n, nil
}
-func Opendir(name string) (uintptr, error) {
- p, err := BytePtrFromString(name)
- if err != nil {
- return 0, err
- }
- dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0)
- runtime.KeepAlive(unsafe.Pointer(p))
- if e != 0 {
- err = errnoErr(e)
- }
- return dir, err
-}
-
-// clearsyscall.Errno resets the errno value to 0.
-func clearErrno()
-
-func Readdir(dir uintptr) (*Dirent, error) {
- var ent Dirent
- var res uintptr
- // __readdir_r_a returns errno at the end of the directory stream, rather than 0.
- // Therefore to avoid false positives we clear errno before calling it.
-
- // TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall"
- //clearsyscall.Errno() // TODO(mundaym): check pre-emption rules.
-
- e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res)))
- var err error
- if e != 0 {
- err = errnoErr(Errno(e))
- }
- if res == 0 {
- return nil, err
- }
- return &ent, err
-}
-
-func readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) {
- r0, _, e1 := syscall_syscall(SYS___READDIR_R_A, dirp, uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
- if int64(r0) == -1 {
- err = errnoErr(Errno(e1))
+func Opendir(name string) (uintptr, error) {
+ p, err := BytePtrFromString(name)
+ if err != nil {
+ return 0, err
}
- return
+ err = nil
+ runtime.EnterSyscall()
+ dir, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___OPENDIR_A<<4, uintptr(unsafe.Pointer(p)))
+ runtime.ExitSyscall()
+ runtime.KeepAlive(unsafe.Pointer(p))
+ if dir == 0 {
+ err = errnoErr2(e1, e2)
+ }
+ return dir, err
}
+// clearsyscall.Errno resets the errno value to 0.
+func clearErrno()
+
func Closedir(dir uintptr) error {
- _, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0)
- if e != 0 {
- return errnoErr(e)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSEDIR<<4, dir)
+ runtime.ExitSyscall()
+ if r0 != 0 {
+ return errnoErr2(e1, e2)
}
return nil
}
func Seekdir(dir uintptr, pos int) {
- _, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0)
+ runtime.EnterSyscall()
+ CallLeFuncWithErr(GetZosLibVec()+SYS_SEEKDIR<<4, dir, uintptr(pos))
+ runtime.ExitSyscall()
}
func Telldir(dir uintptr) (int, error) {
- p, _, e := syscall_syscall(SYS_TELLDIR, dir, 0, 0)
+ p, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TELLDIR<<4, dir)
pos := int(p)
- if pos == -1 {
- return pos, errnoErr(e)
+ if int64(p) == -1 {
+ return pos, errnoErr2(e1, e2)
}
return pos, nil
}
@@ -1261,19 +2018,55 @@ func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
*(*int64)(unsafe.Pointer(&flock[4])) = lk.Start
*(*int64)(unsafe.Pointer(&flock[12])) = lk.Len
*(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid
- _, _, errno := syscall_syscall(SYS_FCNTL, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock)))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock)))
+ runtime.ExitSyscall()
lk.Type = *(*int16)(unsafe.Pointer(&flock[0]))
lk.Whence = *(*int16)(unsafe.Pointer(&flock[2]))
lk.Start = *(*int64)(unsafe.Pointer(&flock[4]))
lk.Len = *(*int64)(unsafe.Pointer(&flock[12]))
lk.Pid = *(*int32)(unsafe.Pointer(&flock[20]))
- if errno == 0 {
+ if r0 == 0 {
return nil
}
- return errno
+ return errnoErr2(e1, e2)
+}
+
+func impl_Flock(fd int, how int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FLOCK<<4, uintptr(fd), uintptr(how))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FlockAddr() *(func(fd int, how int) (err error))
+
+var Flock = enter_Flock
+
+func validFlock(fp uintptr) bool {
+ if funcptrtest(GetZosLibVec()+SYS_FLOCK<<4, "") == 0 {
+ if name, err := getLeFuncName(GetZosLibVec() + SYS_FLOCK<<4); err == nil {
+ return name == "flock"
+ }
+ }
+ return false
+}
+
+func enter_Flock(fd int, how int) (err error) {
+ funcref := get_FlockAddr()
+ if validFlock(GetZosLibVec() + SYS_FLOCK<<4) {
+ *funcref = impl_Flock
+ } else {
+ *funcref = legacyFlock
+ }
+ return (*funcref)(fd, how)
}
-func Flock(fd int, how int) error {
+func legacyFlock(fd int, how int) error {
var flock_type int16
var fcntl_cmd int
@@ -1307,41 +2100,51 @@ func Flock(fd int, how int) error {
}
func Mlock(b []byte) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
+ runtime.ExitSyscall()
+ if r0 != 0 {
+ err = errnoErr2(e1, e2)
}
return
}
func Mlock2(b []byte, flags int) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
+ runtime.ExitSyscall()
+ if r0 != 0 {
+ err = errnoErr2(e1, e2)
}
return
}
func Mlockall(flags int) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP)
+ runtime.ExitSyscall()
+ if r0 != 0 {
+ err = errnoErr2(e1, e2)
}
return
}
func Munlock(b []byte) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP)
+ runtime.ExitSyscall()
+ if r0 != 0 {
+ err = errnoErr2(e1, e2)
}
return
}
func Munlockall() (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP)
+ runtime.ExitSyscall()
+ if r0 != 0 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1372,15 +2175,104 @@ func ClockGettime(clockid int32, ts *Timespec) error {
return nil
}
-func Statfs(path string, stat *Statfs_t) (err error) {
- fd, err := open(path, O_RDONLY, 0)
- defer Close(fd)
- if err != nil {
- return err
+// Chtag
+
+//go:nosplit
+func get_ChtagAddr() *(func(path string, ccsid uint64, textbit uint64) error)
+
+var Chtag = enter_Chtag
+
+func enter_Chtag(path string, ccsid uint64, textbit uint64) error {
+ funcref := get_ChtagAddr()
+ if validSetxattr() {
+ *funcref = impl_Chtag
+ } else {
+ *funcref = legacy_Chtag
+ }
+ return (*funcref)(path, ccsid, textbit)
+}
+
+func legacy_Chtag(path string, ccsid uint64, textbit uint64) error {
+ tag := ccsid<<16 | textbit<<15
+ var tag_buff [8]byte
+ DecodeData(tag_buff[:], 8, tag)
+ return Setxattr(path, "filetag", tag_buff[:], XATTR_REPLACE)
+}
+
+func impl_Chtag(path string, ccsid uint64, textbit uint64) error {
+ tag := ccsid<<16 | textbit<<15
+ var tag_buff [4]byte
+ DecodeData(tag_buff[:], 4, tag)
+ return Setxattr(path, "system.filetag", tag_buff[:], XATTR_REPLACE)
+}
+
+// End of Chtag
+
+// Nanosleep
+
+//go:nosplit
+func get_NanosleepAddr() *(func(time *Timespec, leftover *Timespec) error)
+
+var Nanosleep = enter_Nanosleep
+
+func enter_Nanosleep(time *Timespec, leftover *Timespec) error {
+ funcref := get_NanosleepAddr()
+ if funcptrtest(GetZosLibVec()+SYS_NANOSLEEP<<4, "") == 0 {
+ *funcref = impl_Nanosleep
+ } else {
+ *funcref = legacyNanosleep
+ }
+ return (*funcref)(time, leftover)
+}
+
+func impl_Nanosleep(time *Timespec, leftover *Timespec) error {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_NANOSLEEP<<4, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ return errnoErr2(e1, e2)
+ }
+ return nil
+}
+
+func legacyNanosleep(time *Timespec, leftover *Timespec) error {
+ t0 := runtime.Nanotime1()
+ var secrem uint32
+ var nsecrem uint32
+ total := time.Sec*1000000000 + time.Nsec
+ elapsed := runtime.Nanotime1() - t0
+ var rv int32
+ var rc int32
+ var err error
+ // repeatedly sleep for 1 second until less than 1 second left
+ for total-elapsed > 1000000000 {
+ rv, rc, _ = BpxCondTimedWait(uint32(1), uint32(0), uint32(CW_CONDVAR), &secrem, &nsecrem)
+ if rv != 0 && rc != 112 { // 112 is EAGAIN
+ if leftover != nil && rc == 120 { // 120 is EINTR
+ leftover.Sec = int64(secrem)
+ leftover.Nsec = int64(nsecrem)
+ }
+ err = Errno(rc)
+ return err
+ }
+ elapsed = runtime.Nanotime1() - t0
}
- return Fstatfs(fd, stat)
+ // sleep the remainder
+ if total > elapsed {
+ rv, rc, _ = BpxCondTimedWait(uint32(0), uint32(total-elapsed), uint32(CW_CONDVAR), &secrem, &nsecrem)
+ }
+ if leftover != nil && rc == 120 {
+ leftover.Sec = int64(secrem)
+ leftover.Nsec = int64(nsecrem)
+ }
+ if rv != 0 && rc != 112 {
+ err = Errno(rc)
+ }
+ return err
}
+// End of Nanosleep
+
var (
Stdin = 0
Stdout = 1
@@ -1395,6 +2287,9 @@ var (
errENOENT error = syscall.ENOENT
)
+var ZosTraceLevel int
+var ZosTracefile *os.File
+
var (
signalNameMapOnce sync.Once
signalNameMap map[string]syscall.Signal
@@ -1416,6 +2311,56 @@ func errnoErr(e Errno) error {
return e
}
+var reg *regexp.Regexp
+
+// enhanced with zos specific errno2
+func errnoErr2(e Errno, e2 uintptr) error {
+ switch e {
+ case 0:
+ return nil
+ case EAGAIN:
+ return errEAGAIN
+ /*
+ Allow the retrieval of errno2 for EINVAL and ENOENT on zos
+ case EINVAL:
+ return errEINVAL
+ case ENOENT:
+ return errENOENT
+ */
+ }
+ if ZosTraceLevel > 0 {
+ var name string
+ if reg == nil {
+ reg = regexp.MustCompile("(^unix\\.[^/]+$|.*\\/unix\\.[^/]+$)")
+ }
+ i := 1
+ pc, file, line, ok := runtime.Caller(i)
+ if ok {
+ name = runtime.FuncForPC(pc).Name()
+ }
+ for ok && reg.MatchString(runtime.FuncForPC(pc).Name()) {
+ i += 1
+ pc, file, line, ok = runtime.Caller(i)
+ }
+ if ok {
+ if ZosTracefile == nil {
+ ZosConsolePrintf("From %s:%d\n", file, line)
+ ZosConsolePrintf("%s: %s (errno2=0x%x)\n", name, e.Error(), e2)
+ } else {
+ fmt.Fprintf(ZosTracefile, "From %s:%d\n", file, line)
+ fmt.Fprintf(ZosTracefile, "%s: %s (errno2=0x%x)\n", name, e.Error(), e2)
+ }
+ } else {
+ if ZosTracefile == nil {
+ ZosConsolePrintf("%s (errno2=0x%x)\n", e.Error(), e2)
+ } else {
+ fmt.Fprintf(ZosTracefile, "%s (errno2=0x%x)\n", e.Error(), e2)
+ }
+ }
+ }
+ return e
+}
+
// ErrnoName returns the error name for error number e.
func ErrnoName(e Errno) string {
i := sort.Search(len(errorList), func(i int) bool {
@@ -1474,6 +2419,9 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d
return nil, EINVAL
}
+ // Set __MAP_64 by default
+ flags |= __MAP_64
+
// Map the requested memory.
addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
if errno != nil {
@@ -1778,83 +2726,170 @@ func Exec(argv0 string, argv []string, envv []string) error {
return syscall.Exec(argv0, argv, envv)
}
-func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
+func Getag(path string) (ccsid uint16, flag uint16, err error) {
+ var val [8]byte
+ sz, err := Getxattr(path, "ccsid", val[:])
+ if err != nil {
+ return
+ }
+ ccsid = uint16(EncodeData(val[0:sz]))
+ sz, err = Getxattr(path, "flags", val[:])
+ if err != nil {
+ return
+ }
+ flag = uint16(EncodeData(val[0:sz]) >> 15)
+ return
+}
+
+// Mount begin
+func impl_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(source)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(target)
+ if err != nil {
+ return
+ }
+ var _p2 *byte
+ _p2, err = BytePtrFromString(fstype)
+ if err != nil {
+ return
+ }
+ var _p3 *byte
+ _p3, err = BytePtrFromString(data)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT1_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(_p3)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_MountAddr() *(func(source string, target string, fstype string, flags uintptr, data string) (err error))
+
+var Mount = enter_Mount
+
+func enter_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
+ funcref := get_MountAddr()
+ if validMount() {
+ *funcref = impl_Mount
+ } else {
+ *funcref = legacyMount
+ }
+ return (*funcref)(source, target, fstype, flags, data)
+}
+
+func legacyMount(source string, target string, fstype string, flags uintptr, data string) (err error) {
if needspace := 8 - len(fstype); needspace <= 0 {
- fstype = fstype[:8]
+ fstype = fstype[0:8]
} else {
- fstype += " "[:needspace]
+ fstype += " "[0:needspace]
}
return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data)
}
-func Unmount(name string, mtm int) (err error) {
+func validMount() bool {
+ if funcptrtest(GetZosLibVec()+SYS___MOUNT1_A<<4, "") == 0 {
+ if name, err := getLeFuncName(GetZosLibVec() + SYS___MOUNT1_A<<4); err == nil {
+ return name == "__mount1_a"
+ }
+ }
+ return false
+}
+
+// Mount end
+
+// Unmount begin
+func impl_Unmount(target string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(target)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT2_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_UnmountAddr() *(func(target string, flags int) (err error))
+
+var Unmount = enter_Unmount
+
+func enter_Unmount(target string, flags int) (err error) {
+ funcref := get_UnmountAddr()
+ if funcptrtest(GetZosLibVec()+SYS___UMOUNT2_A<<4, "") == 0 {
+ *funcref = impl_Unmount
+ } else {
+ *funcref = legacyUnmount
+ }
+ return (*funcref)(target, flags)
+}
+
+func legacyUnmount(name string, mtm int) (err error) {
// mountpoint is always a full path and starts with a '/'
// check if input string is not a mountpoint but a filesystem name
if name[0] != '/' {
- return unmount(name, mtm)
+ return unmount_LE(name, mtm)
}
// treat name as mountpoint
b2s := func(arr []byte) string {
- nulli := bytes.IndexByte(arr, 0)
- if nulli == -1 {
- return string(arr)
- } else {
- return string(arr[:nulli])
+ var str string
+ for i := 0; i < len(arr); i++ {
+ if arr[i] == 0 {
+ str = string(arr[:i])
+ break
+ }
}
+ return str
}
var buffer struct {
header W_Mnth
fsinfo [64]W_Mntent
}
- fsCount, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
- if err != nil {
- return err
- }
- if fsCount == 0 {
- return EINVAL
- }
- for i := 0; i < fsCount; i++ {
- if b2s(buffer.fsinfo[i].Mountpoint[:]) == name {
- err = unmount(b2s(buffer.fsinfo[i].Fsname[:]), mtm)
- break
+ fs_count, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
+ if err == nil {
+ err = EINVAL
+ for i := 0; i < fs_count; i++ {
+ if b2s(buffer.fsinfo[i].Mountpoint[:]) == name {
+ err = unmount_LE(b2s(buffer.fsinfo[i].Fsname[:]), mtm)
+ break
+ }
}
+ } else if fs_count == 0 {
+ err = EINVAL
}
return err
}
-func fdToPath(dirfd int) (path string, err error) {
- var buffer [1024]byte
- // w_ctrl()
- ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4,
- []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))})
- if ret == 0 {
- zb := bytes.IndexByte(buffer[:], 0)
- if zb == -1 {
- zb = len(buffer)
- }
- // __e2a_l()
- runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4,
- []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)})
- return string(buffer[:zb]), nil
- }
- // __errno()
- errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4,
- []uintptr{}))))
- // __errno2()
- errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4,
- []uintptr{}))
- // strerror_r()
- ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4,
- []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024})
- if ret == 0 {
- zb := bytes.IndexByte(buffer[:], 0)
- if zb == -1 {
- zb = len(buffer)
- }
- return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2)
- } else {
- return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2)
+// Unmount end
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ reclen, ok := direntReclen(buf)
+ if !ok {
+ return 0, false
}
+ return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
}
func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) {
@@ -1896,7 +2931,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
}
// Get path from fd to avoid unavailable call (fdopendir)
- path, err := fdToPath(fd)
+ path, err := ZosFdToPath(fd)
if err != nil {
return 0, err
}
@@ -1910,7 +2945,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
for {
var entryLE direntLE
var entrypLE *direntLE
- e := readdir_r(d, &entryLE, &entrypLE)
+ e := Readdir_r(d, &entryLE, &entrypLE)
if e != nil {
return n, e
}
@@ -1956,23 +2991,127 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
return n, nil
}
-func ReadDirent(fd int, buf []byte) (n int, err error) {
- var base = (*uintptr)(unsafe.Pointer(new(uint64)))
- return Getdirentries(fd, buf, base)
+func Err2ad() (eadd *int) {
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERR2AD<<4)
+ eadd = (*int)(unsafe.Pointer(r0))
+ return
}
-func direntIno(buf []byte) (uint64, bool) {
- return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
+func ZosConsolePrintf(format string, v ...interface{}) (int, error) {
+ type __cmsg struct {
+ _ uint16
+ _ [2]uint8
+ __msg_length uint32
+ __msg uintptr
+ _ [4]uint8
+ }
+ msg := fmt.Sprintf(format, v...)
+ strptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&msg)).Data)
+ len := (*reflect.StringHeader)(unsafe.Pointer(&msg)).Len
+ cmsg := __cmsg{__msg_length: uint32(len), __msg: uintptr(strptr)}
+ cmd := uint32(0)
+ runtime.EnterSyscall()
+ rc, err2, err1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____CONSOLE_A<<4, uintptr(unsafe.Pointer(&cmsg)), 0, uintptr(unsafe.Pointer(&cmd)))
+ runtime.ExitSyscall()
+ if rc != 0 {
+ return 0, fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2)
+ }
+ return 0, nil
+}
+func ZosStringToEbcdicBytes(str string, nullterm bool) (ebcdicBytes []byte) {
+ if nullterm {
+ ebcdicBytes = []byte(str + "\x00")
+ } else {
+ ebcdicBytes = []byte(str)
+ }
+ A2e(ebcdicBytes)
+ return
+}
+func ZosEbcdicBytesToString(b []byte, trimRight bool) (str string) {
+ res := make([]byte, len(b))
+ copy(res, b)
+ E2a(res)
+ if trimRight {
+ str = string(bytes.TrimRight(res, " \x00"))
+ } else {
+ str = string(res)
+ }
+ return
}
-func direntReclen(buf []byte) (uint64, bool) {
- return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+func fdToPath(dirfd int) (path string, err error) {
+ var buffer [1024]byte
+ // w_ctrl()
+ ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4,
+ []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))})
+ if ret == 0 {
+ zb := bytes.IndexByte(buffer[:], 0)
+ if zb == -1 {
+ zb = len(buffer)
+ }
+ // __e2a_l()
+ runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4,
+ []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)})
+ return string(buffer[:zb]), nil
+ }
+ // __errno()
+ errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4,
+ []uintptr{}))))
+ // __errno2()
+ errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4,
+ []uintptr{}))
+ // strerror_r()
+ ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4,
+ []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024})
+ if ret == 0 {
+ zb := bytes.IndexByte(buffer[:], 0)
+ if zb == -1 {
+ zb = len(buffer)
+ }
+ return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2)
+ } else {
+ return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2)
+ }
}
-func direntNamlen(buf []byte) (uint64, bool) {
- reclen, ok := direntReclen(buf)
- if !ok {
- return 0, false
+func impl_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
}
- return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFOAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_MkfifoatAddr() *(func(dirfd int, path string, mode uint32) (err error))
+
+var Mkfifoat = enter_Mkfifoat
+
+func enter_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
+ funcref := get_MkfifoatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___MKFIFOAT_A<<4, "") == 0 {
+ *funcref = impl_Mkfifoat
+ } else {
+ *funcref = legacy_Mkfifoat
+ }
+ return (*funcref)(dirfd, path, mode)
+}
+
+func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
+ dirname, err := ZosFdToPath(dirfd)
+ if err != nil {
+ return err
+ }
+ return Mkfifo(dirname+"/"+path, mode)
}
+
+//sys Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT
+//sys Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT
+//sys Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT
diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/vendor/golang.org/x/sys/unix/sysvshm_unix.go
index 79a84f18b4..672d6b0a88 100644
--- a/vendor/golang.org/x/sys/unix/sysvshm_unix.go
+++ b/vendor/golang.org/x/sys/unix/sysvshm_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (darwin && !ios) || linux
+//go:build (darwin && !ios) || linux || zos
package unix
diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go
index 9eb0db664c..8b7977a28c 100644
--- a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go
+++ b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build darwin && !ios
+//go:build (darwin && !ios) || zos
package unix
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go
index c73cfe2f10..93a38a97d9 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -491,6 +491,7 @@ const (
BPF_F_REPLACE = 0x4
BPF_F_SLEEPABLE = 0x10
BPF_F_STRICT_ALIGNMENT = 0x1
+ BPF_F_TEST_REG_INVARIANTS = 0x80
BPF_F_TEST_RND_HI32 = 0x4
BPF_F_TEST_RUN_ON_CPU = 0x1
BPF_F_TEST_STATE_FREQ = 0x8
@@ -1697,6 +1698,7 @@ const (
KEXEC_ARCH_S390 = 0x160000
KEXEC_ARCH_SH = 0x2a0000
KEXEC_ARCH_X86_64 = 0x3e0000
+ KEXEC_FILE_DEBUG = 0x8
KEXEC_FILE_NO_INITRAMFS = 0x4
KEXEC_FILE_ON_CRASH = 0x2
KEXEC_FILE_UNLOAD = 0x1
@@ -1785,6 +1787,8 @@ const (
LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20
LANDLOCK_ACCESS_FS_TRUNCATE = 0x4000
LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2
+ LANDLOCK_ACCESS_NET_BIND_TCP = 0x1
+ LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2
LANDLOCK_CREATE_RULESET_VERSION = 0x1
LINUX_REBOOT_CMD_CAD_OFF = 0x0
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
@@ -1896,6 +1900,7 @@ const (
MNT_DETACH = 0x2
MNT_EXPIRE = 0x4
MNT_FORCE = 0x1
+ MNT_ID_REQ_SIZE_VER0 = 0x18
MODULE_INIT_COMPRESSED_FILE = 0x4
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
MODULE_INIT_IGNORE_VERMAGIC = 0x2
@@ -2127,6 +2132,60 @@ const (
NFNL_SUBSYS_QUEUE = 0x3
NFNL_SUBSYS_ULOG = 0x4
NFS_SUPER_MAGIC = 0x6969
+ NFT_CHAIN_FLAGS = 0x7
+ NFT_CHAIN_MAXNAMELEN = 0x100
+ NFT_CT_MAX = 0x17
+ NFT_DATA_RESERVED_MASK = 0xffffff00
+ NFT_DATA_VALUE_MAXLEN = 0x40
+ NFT_EXTHDR_OP_MAX = 0x4
+ NFT_FIB_RESULT_MAX = 0x3
+ NFT_INNER_MASK = 0xf
+ NFT_LOGLEVEL_MAX = 0x8
+ NFT_NAME_MAXLEN = 0x100
+ NFT_NG_MAX = 0x1
+ NFT_OBJECT_CONNLIMIT = 0x5
+ NFT_OBJECT_COUNTER = 0x1
+ NFT_OBJECT_CT_EXPECT = 0x9
+ NFT_OBJECT_CT_HELPER = 0x3
+ NFT_OBJECT_CT_TIMEOUT = 0x7
+ NFT_OBJECT_LIMIT = 0x4
+ NFT_OBJECT_MAX = 0xa
+ NFT_OBJECT_QUOTA = 0x2
+ NFT_OBJECT_SECMARK = 0x8
+ NFT_OBJECT_SYNPROXY = 0xa
+ NFT_OBJECT_TUNNEL = 0x6
+ NFT_OBJECT_UNSPEC = 0x0
+ NFT_OBJ_MAXNAMELEN = 0x100
+ NFT_OSF_MAXGENRELEN = 0x10
+ NFT_QUEUE_FLAG_BYPASS = 0x1
+ NFT_QUEUE_FLAG_CPU_FANOUT = 0x2
+ NFT_QUEUE_FLAG_MASK = 0x3
+ NFT_REG32_COUNT = 0x10
+ NFT_REG32_SIZE = 0x4
+ NFT_REG_MAX = 0x4
+ NFT_REG_SIZE = 0x10
+ NFT_REJECT_ICMPX_MAX = 0x3
+ NFT_RT_MAX = 0x4
+ NFT_SECMARK_CTX_MAXLEN = 0x100
+ NFT_SET_MAXNAMELEN = 0x100
+ NFT_SOCKET_MAX = 0x3
+ NFT_TABLE_F_MASK = 0x3
+ NFT_TABLE_MAXNAMELEN = 0x100
+ NFT_TRACETYPE_MAX = 0x3
+ NFT_TUNNEL_F_MASK = 0x7
+ NFT_TUNNEL_MAX = 0x1
+ NFT_TUNNEL_MODE_MAX = 0x2
+ NFT_USERDATA_MAXLEN = 0x100
+ NFT_XFRM_KEY_MAX = 0x6
+ NF_NAT_RANGE_MAP_IPS = 0x1
+ NF_NAT_RANGE_MASK = 0x7f
+ NF_NAT_RANGE_NETMAP = 0x40
+ NF_NAT_RANGE_PERSISTENT = 0x8
+ NF_NAT_RANGE_PROTO_OFFSET = 0x20
+ NF_NAT_RANGE_PROTO_RANDOM = 0x4
+ NF_NAT_RANGE_PROTO_RANDOM_ALL = 0x14
+ NF_NAT_RANGE_PROTO_RANDOM_FULLY = 0x10
+ NF_NAT_RANGE_PROTO_SPECIFIED = 0x2
NILFS_SUPER_MAGIC = 0x3434
NL0 = 0x0
NL1 = 0x100
@@ -2246,6 +2305,7 @@ const (
PERF_AUX_FLAG_PARTIAL = 0x4
PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00
PERF_AUX_FLAG_TRUNCATED = 0x1
+ PERF_BRANCH_ENTRY_INFO_BITS_MAX = 0x21
PERF_BR_ARM64_DEBUG_DATA = 0x7
PERF_BR_ARM64_DEBUG_EXIT = 0x5
PERF_BR_ARM64_DEBUG_HALT = 0x4
@@ -2411,6 +2471,7 @@ const (
PR_MCE_KILL_GET = 0x22
PR_MCE_KILL_LATE = 0x0
PR_MCE_KILL_SET = 0x1
+ PR_MDWE_NO_INHERIT = 0x2
PR_MDWE_REFUSE_EXEC_GAIN = 0x1
PR_MPX_DISABLE_MANAGEMENT = 0x2c
PR_MPX_ENABLE_MANAGEMENT = 0x2b
@@ -2615,8 +2676,9 @@ const (
RTAX_FEATURES = 0xc
RTAX_FEATURE_ALLFRAG = 0x8
RTAX_FEATURE_ECN = 0x1
- RTAX_FEATURE_MASK = 0xf
+ RTAX_FEATURE_MASK = 0x1f
RTAX_FEATURE_SACK = 0x2
+ RTAX_FEATURE_TCP_USEC_TS = 0x10
RTAX_FEATURE_TIMESTAMP = 0x4
RTAX_HOPLIMIT = 0xa
RTAX_INITCWND = 0xb
@@ -2859,9 +2921,38 @@ const (
SCM_RIGHTS = 0x1
SCM_TIMESTAMP = 0x1d
SC_LOG_FLUSH = 0x100000
+ SECCOMP_ADDFD_FLAG_SEND = 0x2
+ SECCOMP_ADDFD_FLAG_SETFD = 0x1
+ SECCOMP_FILTER_FLAG_LOG = 0x2
+ SECCOMP_FILTER_FLAG_NEW_LISTENER = 0x8
+ SECCOMP_FILTER_FLAG_SPEC_ALLOW = 0x4
+ SECCOMP_FILTER_FLAG_TSYNC = 0x1
+ SECCOMP_FILTER_FLAG_TSYNC_ESRCH = 0x10
+ SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV = 0x20
+ SECCOMP_GET_ACTION_AVAIL = 0x2
+ SECCOMP_GET_NOTIF_SIZES = 0x3
+ SECCOMP_IOCTL_NOTIF_RECV = 0xc0502100
+ SECCOMP_IOCTL_NOTIF_SEND = 0xc0182101
+ SECCOMP_IOC_MAGIC = '!'
SECCOMP_MODE_DISABLED = 0x0
SECCOMP_MODE_FILTER = 0x2
SECCOMP_MODE_STRICT = 0x1
+ SECCOMP_RET_ACTION = 0x7fff0000
+ SECCOMP_RET_ACTION_FULL = 0xffff0000
+ SECCOMP_RET_ALLOW = 0x7fff0000
+ SECCOMP_RET_DATA = 0xffff
+ SECCOMP_RET_ERRNO = 0x50000
+ SECCOMP_RET_KILL = 0x0
+ SECCOMP_RET_KILL_PROCESS = 0x80000000
+ SECCOMP_RET_KILL_THREAD = 0x0
+ SECCOMP_RET_LOG = 0x7ffc0000
+ SECCOMP_RET_TRACE = 0x7ff00000
+ SECCOMP_RET_TRAP = 0x30000
+ SECCOMP_RET_USER_NOTIF = 0x7fc00000
+ SECCOMP_SET_MODE_FILTER = 0x1
+ SECCOMP_SET_MODE_STRICT = 0x0
+ SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP = 0x1
+ SECCOMP_USER_NOTIF_FLAG_CONTINUE = 0x1
SECRETMEM_MAGIC = 0x5345434d
SECURITYFS_MAGIC = 0x73636673
SEEK_CUR = 0x1
@@ -3021,6 +3112,7 @@ const (
SOL_TIPC = 0x10f
SOL_TLS = 0x11a
SOL_UDP = 0x11
+ SOL_VSOCK = 0x11f
SOL_X25 = 0x106
SOL_XDP = 0x11b
SOMAXCONN = 0x1000
@@ -3080,6 +3172,7 @@ const (
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MNT_ID = 0x1000
+ STATX_MNT_ID_UNIQUE = 0x4000
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
@@ -3474,12 +3567,16 @@ const (
XDP_RX_RING = 0x2
XDP_SHARED_UMEM = 0x1
XDP_STATISTICS = 0x7
+ XDP_TXMD_FLAGS_CHECKSUM = 0x2
+ XDP_TXMD_FLAGS_TIMESTAMP = 0x1
+ XDP_TX_METADATA = 0x2
XDP_TX_RING = 0x3
XDP_UMEM_COMPLETION_RING = 0x6
XDP_UMEM_FILL_RING = 0x5
XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000
XDP_UMEM_PGOFF_FILL_RING = 0x100000000
XDP_UMEM_REG = 0x4
+ XDP_UMEM_TX_SW_CSUM = 0x2
XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1
XDP_USE_NEED_WAKEUP = 0x8
XDP_USE_SG = 0x10
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
index 4920821cf3..42ff8c3c1b 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
@@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
index a0c1e41127..dca436004f 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
@@ -282,6 +282,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
index c63985560f..5cca668ac3 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
@@ -288,6 +288,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
index 47cc62e25c..d8cae6d153 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
@@ -278,6 +278,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
index 27ac4a09e2..28e39afdcb 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
@@ -275,6 +275,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
index 54694642a5..cd66e92cb4 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
@@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
index 3adb81d758..c1595eba78 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
@@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
index 2dfe98f0d1..ee9456b0da 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
@@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
index f5398f84f0..8cfca81e1b 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
@@ -281,6 +281,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x80
SIOCATMARK = 0x40047307
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
index c54f152d68..60b0deb3af 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
@@ -336,6 +336,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
index 76057dc72f..f90aa7281b 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
@@ -340,6 +340,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
index e0c3725e2b..ba9e015033 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
@@ -340,6 +340,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
index 18f2813ed5..07cdfd6e9f 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
@@ -272,6 +272,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
index 11619d4ec8..2f1dd214a7 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
@@ -344,6 +344,9 @@ const (
SCM_TIMESTAMPNS = 0x23
SCM_TXTIME = 0x3d
SCM_WIFI_STATUS = 0x29
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104
SFD_CLOEXEC = 0x80000
SFD_NONBLOCK = 0x800
SIOCATMARK = 0x8905
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
index 396d994da7..f40519d901 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
@@ -335,6 +335,9 @@ const (
SCM_TIMESTAMPNS = 0x21
SCM_TXTIME = 0x3f
SCM_WIFI_STATUS = 0x25
+ SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103
+ SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102
+ SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104
SFD_CLOEXEC = 0x400000
SFD_NONBLOCK = 0x4000
SF_FP = 0x38
diff --git a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go
index 4dfd2e051d..da08b2ab3d 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go
@@ -10,41 +10,99 @@
package unix
const (
- BRKINT = 0x0001
- CLOCK_MONOTONIC = 0x1
- CLOCK_PROCESS_CPUTIME_ID = 0x2
- CLOCK_REALTIME = 0x0
- CLOCK_THREAD_CPUTIME_ID = 0x3
- CS8 = 0x0030
- CSIZE = 0x0030
- ECHO = 0x00000008
- ECHONL = 0x00000001
- FD_CLOEXEC = 0x01
- FD_CLOFORK = 0x02
- FNDELAY = 0x04
- F_CLOSFD = 9
- F_CONTROL_CVT = 13
- F_DUPFD = 0
- F_DUPFD2 = 8
- F_GETFD = 1
- F_GETFL = 259
- F_GETLK = 5
- F_GETOWN = 10
- F_OK = 0x0
- F_RDLCK = 1
- F_SETFD = 2
- F_SETFL = 4
- F_SETLK = 6
- F_SETLKW = 7
- F_SETOWN = 11
- F_SETTAG = 12
- F_UNLCK = 3
- F_WRLCK = 2
- FSTYPE_ZFS = 0xe9 //"Z"
- FSTYPE_HFS = 0xc8 //"H"
- FSTYPE_NFS = 0xd5 //"N"
- FSTYPE_TFS = 0xe3 //"T"
- FSTYPE_AUTOMOUNT = 0xc1 //"A"
+ BRKINT = 0x0001
+ CLOCAL = 0x1
+ CLOCK_MONOTONIC = 0x1
+ CLOCK_PROCESS_CPUTIME_ID = 0x2
+ CLOCK_REALTIME = 0x0
+ CLOCK_THREAD_CPUTIME_ID = 0x3
+ CLONE_NEWIPC = 0x08000000
+ CLONE_NEWNET = 0x40000000
+ CLONE_NEWNS = 0x00020000
+ CLONE_NEWPID = 0x20000000
+ CLONE_NEWUTS = 0x04000000
+ CLONE_PARENT = 0x00008000
+ CS8 = 0x0030
+ CSIZE = 0x0030
+ ECHO = 0x00000008
+ ECHONL = 0x00000001
+ EFD_SEMAPHORE = 0x00002000
+ EFD_CLOEXEC = 0x00001000
+ EFD_NONBLOCK = 0x00000004
+ EPOLL_CLOEXEC = 0x00001000
+ EPOLL_CTL_ADD = 0
+ EPOLL_CTL_MOD = 1
+ EPOLL_CTL_DEL = 2
+ EPOLLRDNORM = 0x0001
+ EPOLLRDBAND = 0x0002
+ EPOLLIN = 0x0003
+ EPOLLOUT = 0x0004
+ EPOLLWRBAND = 0x0008
+ EPOLLPRI = 0x0010
+ EPOLLERR = 0x0020
+ EPOLLHUP = 0x0040
+ EPOLLEXCLUSIVE = 0x20000000
+ EPOLLONESHOT = 0x40000000
+ FD_CLOEXEC = 0x01
+ FD_CLOFORK = 0x02
+ FD_SETSIZE = 0x800
+ FNDELAY = 0x04
+ F_CLOSFD = 9
+ F_CONTROL_CVT = 13
+ F_DUPFD = 0
+ F_DUPFD2 = 8
+ F_GETFD = 1
+ F_GETFL = 259
+ F_GETLK = 5
+ F_GETOWN = 10
+ F_OK = 0x0
+ F_RDLCK = 1
+ F_SETFD = 2
+ F_SETFL = 4
+ F_SETLK = 6
+ F_SETLKW = 7
+ F_SETOWN = 11
+ F_SETTAG = 12
+ F_UNLCK = 3
+ F_WRLCK = 2
+ FSTYPE_ZFS = 0xe9 //"Z"
+ FSTYPE_HFS = 0xc8 //"H"
+ FSTYPE_NFS = 0xd5 //"N"
+ FSTYPE_TFS = 0xe3 //"T"
+ FSTYPE_AUTOMOUNT = 0xc1 //"A"
+ GRND_NONBLOCK = 1
+ GRND_RANDOM = 2
+ HUPCL = 0x0100 // Hang up on last close
+ IN_CLOEXEC = 0x00001000
+ IN_NONBLOCK = 0x00000004
+ IN_ACCESS = 0x00000001
+ IN_MODIFY = 0x00000002
+ IN_ATTRIB = 0x00000004
+ IN_CLOSE_WRITE = 0x00000008
+ IN_CLOSE_NOWRITE = 0x00000010
+ IN_OPEN = 0x00000020
+ IN_MOVED_FROM = 0x00000040
+ IN_MOVED_TO = 0x00000080
+ IN_CREATE = 0x00000100
+ IN_DELETE = 0x00000200
+ IN_DELETE_SELF = 0x00000400
+ IN_MOVE_SELF = 0x00000800
+ IN_UNMOUNT = 0x00002000
+ IN_Q_OVERFLOW = 0x00004000
+ IN_IGNORED = 0x00008000
+ IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
+ IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO)
+ IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB |
+ IN_CLOSE | IN_OPEN | IN_MOVE |
+ IN_CREATE | IN_DELETE | IN_DELETE_SELF |
+ IN_MOVE_SELF)
+ IN_ONLYDIR = 0x01000000
+ IN_DONT_FOLLOW = 0x02000000
+ IN_EXCL_UNLINK = 0x04000000
+ IN_MASK_CREATE = 0x10000000
+ IN_MASK_ADD = 0x20000000
+ IN_ISDIR = 0x40000000
+ IN_ONESHOT = 0x80000000
IP6F_MORE_FRAG = 0x0001
IP6F_OFF_MASK = 0xfff8
IP6F_RESERVED_MASK = 0x0006
@@ -152,10 +210,18 @@ const (
IP_PKTINFO = 101
IP_RECVPKTINFO = 102
IP_TOS = 2
- IP_TTL = 3
+ IP_TTL = 14
IP_UNBLOCK_SOURCE = 11
+ ICMP6_FILTER = 1
+ MCAST_INCLUDE = 0
+ MCAST_EXCLUDE = 1
+ MCAST_JOIN_GROUP = 40
+ MCAST_LEAVE_GROUP = 41
+ MCAST_JOIN_SOURCE_GROUP = 42
+ MCAST_LEAVE_SOURCE_GROUP = 43
+ MCAST_BLOCK_SOURCE = 44
+ MCAST_UNBLOCK_SOURCE = 46
ICANON = 0x0010
- ICMP6_FILTER = 0x26
ICRNL = 0x0002
IEXTEN = 0x0020
IGNBRK = 0x0004
@@ -165,10 +231,10 @@ const (
ISTRIP = 0x0080
IXON = 0x0200
IXOFF = 0x0100
- LOCK_SH = 0x1 // Not exist on zOS
- LOCK_EX = 0x2 // Not exist on zOS
- LOCK_NB = 0x4 // Not exist on zOS
- LOCK_UN = 0x8 // Not exist on zOS
+ LOCK_SH = 0x1
+ LOCK_EX = 0x2
+ LOCK_NB = 0x4
+ LOCK_UN = 0x8
POLLIN = 0x0003
POLLOUT = 0x0004
POLLPRI = 0x0010
@@ -182,15 +248,29 @@ const (
MAP_PRIVATE = 0x1 // changes are private
MAP_SHARED = 0x2 // changes are shared
MAP_FIXED = 0x4 // place exactly
- MCAST_JOIN_GROUP = 40
- MCAST_LEAVE_GROUP = 41
- MCAST_JOIN_SOURCE_GROUP = 42
- MCAST_LEAVE_SOURCE_GROUP = 43
- MCAST_BLOCK_SOURCE = 44
- MCAST_UNBLOCK_SOURCE = 45
+ __MAP_MEGA = 0x8
+ __MAP_64 = 0x10
+ MAP_ANON = 0x20
+ MAP_ANONYMOUS = 0x20
MS_SYNC = 0x1 // msync - synchronous writes
MS_ASYNC = 0x2 // asynchronous writes
MS_INVALIDATE = 0x4 // invalidate mappings
+ MS_BIND = 0x00001000
+ MS_MOVE = 0x00002000
+ MS_NOSUID = 0x00000002
+ MS_PRIVATE = 0x00040000
+ MS_REC = 0x00004000
+ MS_REMOUNT = 0x00008000
+ MS_RDONLY = 0x00000001
+ MS_UNBINDABLE = 0x00020000
+ MNT_DETACH = 0x00000004
+ ZOSDSFS_SUPER_MAGIC = 0x44534653 // zOS DSFS
+ NFS_SUPER_MAGIC = 0x6969 // NFS
+ NSFS_MAGIC = 0x6e736673 // PROCNS
+ PROC_SUPER_MAGIC = 0x9fa0 // proc FS
+ ZOSTFS_SUPER_MAGIC = 0x544653 // zOS TFS
+ ZOSUFS_SUPER_MAGIC = 0x554653 // zOS UFS
+ ZOSZFS_SUPER_MAGIC = 0x5A4653 // zOS ZFS
MTM_RDONLY = 0x80000000
MTM_RDWR = 0x40000000
MTM_UMOUNT = 0x10000000
@@ -205,13 +285,20 @@ const (
MTM_REMOUNT = 0x00000100
MTM_NOSECURITY = 0x00000080
NFDBITS = 0x20
+ ONLRET = 0x0020 // NL performs CR function
O_ACCMODE = 0x03
O_APPEND = 0x08
O_ASYNCSIG = 0x0200
O_CREAT = 0x80
+ O_DIRECT = 0x00002000
+ O_NOFOLLOW = 0x00004000
+ O_DIRECTORY = 0x00008000
+ O_PATH = 0x00080000
+ O_CLOEXEC = 0x00001000
O_EXCL = 0x40
O_GETFL = 0x0F
O_LARGEFILE = 0x0400
+ O_NDELAY = 0x4
O_NONBLOCK = 0x04
O_RDONLY = 0x02
O_RDWR = 0x03
@@ -248,6 +335,7 @@ const (
AF_IUCV = 17
AF_LAT = 14
AF_LINK = 18
+ AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX
AF_MAX = 30
AF_NBS = 7
AF_NDD = 23
@@ -285,15 +373,33 @@ const (
RLIMIT_AS = 5
RLIMIT_NOFILE = 6
RLIMIT_MEMLIMIT = 7
+ RLIMIT_MEMLOCK = 0x8
RLIM_INFINITY = 2147483647
+ SCHED_FIFO = 0x2
+ SCM_CREDENTIALS = 0x2
SCM_RIGHTS = 0x01
SF_CLOSE = 0x00000002
SF_REUSE = 0x00000001
+ SHM_RND = 0x2
+ SHM_RDONLY = 0x1
+ SHMLBA = 0x1000
+ IPC_STAT = 0x3
+ IPC_SET = 0x2
+ IPC_RMID = 0x1
+ IPC_PRIVATE = 0x0
+ IPC_CREAT = 0x1000000
+ __IPC_MEGA = 0x4000000
+ __IPC_SHAREAS = 0x20000000
+ __IPC_BELOWBAR = 0x10000000
+ IPC_EXCL = 0x2000000
+ __IPC_GIGA = 0x8000000
SHUT_RD = 0
SHUT_RDWR = 2
SHUT_WR = 1
+ SOCK_CLOEXEC = 0x00001000
SOCK_CONN_DGRAM = 6
SOCK_DGRAM = 2
+ SOCK_NONBLOCK = 0x800
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
@@ -378,8 +484,6 @@ const (
S_IFMST = 0x00FF0000
TCP_KEEPALIVE = 0x8
TCP_NODELAY = 0x1
- TCP_INFO = 0xb
- TCP_USER_TIMEOUT = 0x1
TIOCGWINSZ = 0x4008a368
TIOCSWINSZ = 0x8008a367
TIOCSBRK = 0x2000a77b
@@ -427,7 +531,10 @@ const (
VSUSP = 9
VTIME = 10
WCONTINUED = 0x4
+ WEXITED = 0x8
WNOHANG = 0x1
+ WNOWAIT = 0x20
+ WSTOPPED = 0x10
WUNTRACED = 0x2
_BPX_SWAP = 1
_BPX_NONSWAP = 2
@@ -452,8 +559,28 @@ const (
MADV_FREE = 15 // for Linux compatibility -- no zos semantics
MADV_WIPEONFORK = 16 // for Linux compatibility -- no zos semantics
MADV_KEEPONFORK = 17 // for Linux compatibility -- no zos semantics
- AT_SYMLINK_NOFOLLOW = 1 // for Unix compatibility -- no zos semantics
- AT_FDCWD = 2 // for Unix compatibility -- no zos semantics
+ AT_SYMLINK_FOLLOW = 0x400
+ AT_SYMLINK_NOFOLLOW = 0x100
+ XATTR_CREATE = 0x1
+ XATTR_REPLACE = 0x2
+ P_PID = 0
+ P_PGID = 1
+ P_ALL = 2
+ PR_SET_NAME = 15
+ PR_GET_NAME = 16
+ PR_SET_NO_NEW_PRIVS = 38
+ PR_GET_NO_NEW_PRIVS = 39
+ PR_SET_DUMPABLE = 4
+ PR_GET_DUMPABLE = 3
+ PR_SET_PDEATHSIG = 1
+ PR_GET_PDEATHSIG = 2
+ PR_SET_CHILD_SUBREAPER = 36
+ PR_GET_CHILD_SUBREAPER = 37
+ AT_FDCWD = -100
+ AT_EACCESS = 0x200
+ AT_EMPTY_PATH = 0x1000
+ AT_REMOVEDIR = 0x200
+ RENAME_NOREPLACE = 1 << 0
)
const (
@@ -476,6 +603,7 @@ const (
EMLINK = Errno(125)
ENAMETOOLONG = Errno(126)
ENFILE = Errno(127)
+ ENOATTR = Errno(265)
ENODEV = Errno(128)
ENOENT = Errno(129)
ENOEXEC = Errno(130)
@@ -700,7 +828,7 @@ var errorList = [...]struct {
{145, "EDC5145I", "The parameter list is too long, or the message to receive was too large for the buffer."},
{146, "EDC5146I", "Too many levels of symbolic links."},
{147, "EDC5147I", "Illegal byte sequence."},
- {148, "", ""},
+ {148, "EDC5148I", "The named attribute or data not available."},
{149, "EDC5149I", "Value Overflow Error."},
{150, "EDC5150I", "UNIX System Services is not active."},
{151, "EDC5151I", "Dynamic allocation error."},
@@ -743,6 +871,7 @@ var errorList = [...]struct {
{259, "EDC5259I", "A CUN_RS_NO_CONVERSION error was issued by Unicode Services."},
{260, "EDC5260I", "A CUN_RS_TABLE_NOT_ALIGNED error was issued by Unicode Services."},
{262, "EDC5262I", "An iconv() function encountered an unexpected error while using Unicode Services."},
+ {265, "EDC5265I", "The named attribute not available."},
{1000, "EDC8000I", "A bad socket-call constant was found in the IUCV header."},
{1001, "EDC8001I", "An error was found in the IUCV header."},
{1002, "EDC8002I", "A socket descriptor is out of range."},
diff --git a/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s b/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s
new file mode 100644
index 0000000000..b77ff5db90
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s
@@ -0,0 +1,364 @@
+// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+//go:build zos && s390x
+#include "textflag.h"
+
+// provide the address of function variable to be fixed up.
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Flistxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Fremovexattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Fgetxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Fsetxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_accept4Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·accept4(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_RemovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Removexattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_Dup3Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Dup3(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_DirfdAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Dirfd(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_EpollCreateAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·EpollCreate(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_EpollCreate1Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·EpollCreate1(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_EpollCtlAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·EpollCtl(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_EpollPwaitAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·EpollPwait(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_EpollWaitAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·EpollWait(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_EventfdAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Eventfd(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FaccessatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Faccessat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FchmodatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Fchmodat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FchownatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Fchownat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FdatasyncAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Fdatasync(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_fstatatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·fstatat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_LgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Lgetxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_LsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Lsetxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FstatfsAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Fstatfs(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FutimesAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Futimes(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_FutimesatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Futimesat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_GetrandomAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Getrandom(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_InotifyInitAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·InotifyInit(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_InotifyInit1Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·InotifyInit1(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_InotifyAddWatchAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·InotifyAddWatch(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_InotifyRmWatchAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·InotifyRmWatch(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_ListxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Listxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_LlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Llistxattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_LremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Lremovexattr(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_LutimesAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Lutimes(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_StatfsAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Statfs(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_SyncfsAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Syncfs(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_UnshareAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Unshare(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_LinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Linkat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_MkdiratAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Mkdirat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_MknodatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Mknodat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_PivotRootAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·PivotRoot(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_PrctlAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Prctl(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_PrlimitAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Prlimit(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_RenameatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Renameat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_Renameat2Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Renameat2(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_SethostnameAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Sethostname(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_SetnsAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Setns(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_SymlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Symlinkat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_UnlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·Unlinkat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_openatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·openat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_openat2Addr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·openat2(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+TEXT ·get_utimensatAddr(SB), NOSPLIT|NOFRAME, $0-8
+ MOVD $·utimensat(SB), R8
+ MOVD R8, ret+0(FP)
+ RET
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go
index 1488d27128..87d8612a1d 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go
@@ -906,6 +906,16 @@ func Fspick(dirfd int, pathName string, flags int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) {
+ _, _, e1 := Syscall6(SYS_FSCONFIG, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(value)), uintptr(aux), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func Getdents(fd int, buf []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go
index a1d061597c..9dc42410b7 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go
@@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
var libc_unveil_trampoline_addr uintptr
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
-
-
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go
index 5b2a740977..0d3a0751cd 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go
@@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
var libc_unveil_trampoline_addr uintptr
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
-
-
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go
index f6eda1344a..c39f7776db 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go
@@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
var libc_unveil_trampoline_addr uintptr
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
-
-
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go
index 55df20ae9d..57571d072f 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go
@@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
var libc_unveil_trampoline_addr uintptr
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
-
-
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go
index 8c1155cbc0..e62963e67e 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go
@@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
var libc_unveil_trampoline_addr uintptr
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
-
-
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go
index 7cc80c58d9..00831354c8 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go
@@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
var libc_unveil_trampoline_addr uintptr
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
-
-
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go
index 0688737f49..79029ed584 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go
@@ -2297,5 +2297,3 @@ func unveil(path *byte, flags *byte) (err error) {
var libc_unveil_trampoline_addr uintptr
//go:cgo_import_dynamic libc_unveil unveil "libc.so"
-
-
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go
index 94f0112383..7ccf66b7ee 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go
@@ -1,4 +1,4 @@
-// go run mksyscall.go -tags zos,s390x syscall_zos_s390x.go
+// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s
// Code generated by the command above; see README.md. DO NOT EDIT.
//go:build zos && s390x
@@ -6,17 +6,100 @@
package unix
import (
+ "runtime"
+ "syscall"
"unsafe"
)
+var _ syscall.Errno
+
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fcntl(fd int, cmd int, arg int) (val int, err error) {
- r0, _, e1 := syscall_syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg))
+ runtime.ExitSyscall()
val = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Flistxattr(fd int, dest []byte) (sz int, err error) {
+ var _p0 unsafe.Pointer
+ if len(dest) > 0 {
+ _p0 = unsafe.Pointer(&dest[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FLISTXATTR_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(dest)))
+ runtime.ExitSyscall()
+ sz = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FlistxattrAddr() *(func(fd int, dest []byte) (sz int, err error))
+
+var Flistxattr = enter_Flistxattr
+
+func enter_Flistxattr(fd int, dest []byte) (sz int, err error) {
+ funcref := get_FlistxattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FLISTXATTR_A<<4, "") == 0 {
+ *funcref = impl_Flistxattr
+ } else {
+ *funcref = error_Flistxattr
+ }
+ return (*funcref)(fd, dest)
+}
+
+func error_Flistxattr(fd int, dest []byte) (sz int, err error) {
+ sz = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Fremovexattr(fd int, attr string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FremovexattrAddr() *(func(fd int, attr string) (err error))
+
+var Fremovexattr = enter_Fremovexattr
+
+func enter_Fremovexattr(fd int, attr string) (err error) {
+ funcref := get_FremovexattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, "") == 0 {
+ *funcref = impl_Fremovexattr
+ } else {
+ *funcref = error_Fremovexattr
}
+ return (*funcref)(fd, attr)
+}
+
+func error_Fremovexattr(fd int, attr string) (err error) {
+ err = ENOSYS
return
}
@@ -29,10 +112,12 @@ func read(fd int, p []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := syscall_syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_READ<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ runtime.ExitSyscall()
n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -46,31 +131,159 @@ func write(fd int, p []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := syscall_syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+ runtime.ExitSyscall()
n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(dest) > 0 {
+ _p1 = unsafe.Pointer(&dest[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FGETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+ runtime.ExitSyscall()
+ sz = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FgetxattrAddr() *(func(fd int, attr string, dest []byte) (sz int, err error))
+
+var Fgetxattr = enter_Fgetxattr
+
+func enter_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
+ funcref := get_FgetxattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FGETXATTR_A<<4, "") == 0 {
+ *funcref = impl_Fgetxattr
+ } else {
+ *funcref = error_Fgetxattr
+ }
+ return (*funcref)(fd, attr, dest)
+}
+
+func error_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
+ sz = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(data) > 0 {
+ _p1 = unsafe.Pointer(&data[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(data)), uintptr(flag))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FsetxattrAddr() *(func(fd int, attr string, data []byte, flag int) (err error))
+
+var Fsetxattr = enter_Fsetxattr
+
+func enter_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) {
+ funcref := get_FsetxattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FSETXATTR_A<<4, "") == 0 {
+ *funcref = impl_Fsetxattr
+ } else {
+ *funcref = error_Fsetxattr
}
+ return (*funcref)(fd, attr, data, flag)
+}
+
+func error_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
- r0, _, e1 := syscall_syscall(SYS___ACCEPT_A, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT4_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags))
+ runtime.ExitSyscall()
fd = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_accept4Addr() *(func(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error))
+
+var accept4 = enter_accept4
+
+func enter_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+ funcref := get_accept4Addr()
+ if funcptrtest(GetZosLibVec()+SYS___ACCEPT4_A<<4, "") == 0 {
+ *funcref = impl_accept4
+ } else {
+ *funcref = error_accept4
}
+ return (*funcref)(s, rsa, addrlen, flags)
+}
+
+func error_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
- _, _, e1 := syscall_syscall(SYS___BIND_A, uintptr(s), uintptr(addr), uintptr(addrlen))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___BIND_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -78,9 +291,11 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
- _, _, e1 := syscall_syscall(SYS___CONNECT_A, uintptr(s), uintptr(addr), uintptr(addrlen))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONNECT_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -88,10 +303,10 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getgroups(n int, list *_Gid_t) (nn int, err error) {
- r0, _, e1 := syscall_rawsyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list)))
nn = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -99,9 +314,9 @@ func getgroups(n int, list *_Gid_t) (nn int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setgroups(n int, list *_Gid_t) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -109,9 +324,11 @@ func setgroups(n int, list *_Gid_t) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
- _, _, e1 := syscall_syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -119,9 +336,11 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
- _, _, e1 := syscall_syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -129,10 +348,10 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func socket(domain int, typ int, proto int) (fd int, err error) {
- r0, _, e1 := syscall_rawsyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKET<<4, uintptr(domain), uintptr(typ), uintptr(proto))
fd = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -140,9 +359,9 @@ func socket(domain int, typ int, proto int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
- _, _, e1 := syscall_rawsyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKETPAIR<<4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -150,9 +369,9 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS___GETPEERNAME_A, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETPEERNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -160,10 +379,52 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS___GETSOCKNAME_A, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETSOCKNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Removexattr(path string, attr string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_RemovexattrAddr() *(func(path string, attr string) (err error))
+
+var Removexattr = enter_Removexattr
+
+func enter_Removexattr(path string, attr string) (err error) {
+ funcref := get_RemovexattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, "") == 0 {
+ *funcref = impl_Removexattr
+ } else {
+ *funcref = error_Removexattr
}
+ return (*funcref)(path, attr)
+}
+
+func error_Removexattr(path string, attr string) (err error) {
+ err = ENOSYS
return
}
@@ -176,10 +437,12 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := syscall_syscall6(SYS___RECVFROM_A, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVFROM_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+ runtime.ExitSyscall()
n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -193,9 +456,11 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
} else {
_p0 = unsafe.Pointer(&_zero)
}
- _, _, e1 := syscall_syscall6(SYS___SENDTO_A, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDTO_A<<4, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -203,10 +468,12 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
- r0, _, e1 := syscall_syscall(SYS___RECVMSG_A, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ runtime.ExitSyscall()
n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -214,10 +481,12 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
- r0, _, e1 := syscall_syscall(SYS___SENDMSG_A, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+ runtime.ExitSyscall()
n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -225,10 +494,12 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
- r0, _, e1 := syscall_syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MMAP<<4, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos))
+ runtime.ExitSyscall()
ret = uintptr(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -236,9 +507,11 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func munmap(addr uintptr, length uintptr) (err error) {
- _, _, e1 := syscall_syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MUNMAP<<4, uintptr(addr), uintptr(length))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -246,9 +519,11 @@ func munmap(addr uintptr, length uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctl(fd int, req int, arg uintptr) (err error) {
- _, _, e1 := syscall_syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -256,9 +531,62 @@ func ioctl(fd int, req int, arg uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
- _, _, e1 := syscall_syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMAT<<4, uintptr(id), uintptr(addr), uintptr(flag))
+ runtime.ExitSyscall()
+ ret = uintptr(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMCTL64<<4, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf)))
+ runtime.ExitSyscall()
+ result = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func shmdt(addr uintptr) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMDT<<4, uintptr(addr))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func shmget(key int, size int, flag int) (id int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMGET<<4, uintptr(key), uintptr(size), uintptr(flag))
+ runtime.ExitSyscall()
+ id = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -271,9 +599,11 @@ func Access(path string, mode uint32) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___ACCESS_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCESS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -286,9 +616,11 @@ func Chdir(path string) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___CHDIR_A, uintptr(unsafe.Pointer(_p0)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHDIR_A<<4, uintptr(unsafe.Pointer(_p0)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -301,9 +633,11 @@ func Chown(path string, uid int, gid int) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___CHOWN_A, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -316,9 +650,11 @@ func Chmod(path string, mode uint32) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___CHMOD_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHMOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -331,10 +667,12 @@ func Creat(path string, mode uint32) (fd int, err error) {
if err != nil {
return
}
- r0, _, e1 := syscall_syscall(SYS___CREAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CREAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ runtime.ExitSyscall()
fd = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -342,10 +680,12 @@ func Creat(path string, mode uint32) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup(oldfd int) (fd int, err error) {
- r0, _, e1 := syscall_syscall(SYS_DUP, uintptr(oldfd), 0, 0)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP<<4, uintptr(oldfd))
+ runtime.ExitSyscall()
fd = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -353,617 +693,2216 @@ func Dup(oldfd int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
- _, _, e1 := syscall_syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP2<<4, uintptr(oldfd), uintptr(newfd))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Errno2() (er2 int) {
- uer2, _, _ := syscall_syscall(SYS___ERRNO2, 0, 0, 0)
- er2 = int(uer2)
+func impl_Dup3(oldfd int, newfd int, flags int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP3<<4, uintptr(oldfd), uintptr(newfd), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_Dup3Addr() *(func(oldfd int, newfd int, flags int) (err error))
-func Err2ad() (eadd *int) {
- ueadd, _, _ := syscall_syscall(SYS___ERR2AD, 0, 0, 0)
- eadd = (*int)(unsafe.Pointer(ueadd))
- return
-}
+var Dup3 = enter_Dup3
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func enter_Dup3(oldfd int, newfd int, flags int) (err error) {
+ funcref := get_Dup3Addr()
+ if funcptrtest(GetZosLibVec()+SYS_DUP3<<4, "") == 0 {
+ *funcref = impl_Dup3
+ } else {
+ *funcref = error_Dup3
+ }
+ return (*funcref)(oldfd, newfd, flags)
+}
-func Exit(code int) {
- syscall_syscall(SYS_EXIT, uintptr(code), 0, 0)
+func error_Dup3(oldfd int, newfd int, flags int) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Fchdir(fd int) (err error) {
- _, _, e1 := syscall_syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_Dirfd(dirp uintptr) (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DIRFD<<4, uintptr(dirp))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_DirfdAddr() *(func(dirp uintptr) (fd int, err error))
-func Fchmod(fd int, mode uint32) (err error) {
- _, _, e1 := syscall_syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+var Dirfd = enter_Dirfd
+
+func enter_Dirfd(dirp uintptr) (fd int, err error) {
+ funcref := get_DirfdAddr()
+ if funcptrtest(GetZosLibVec()+SYS_DIRFD<<4, "") == 0 {
+ *funcref = impl_Dirfd
+ } else {
+ *funcref = error_Dirfd
}
+ return (*funcref)(dirp)
+}
+
+func error_Dirfd(dirp uintptr) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Fchown(fd int, uid int, gid int) (err error) {
- _, _, e1 := syscall_syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_EpollCreate(size int) (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE<<4, uintptr(size))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_EpollCreateAddr() *(func(size int) (fd int, err error))
-func FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) {
- r0, _, e1 := syscall_syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
- retval = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+var EpollCreate = enter_EpollCreate
+
+func enter_EpollCreate(size int) (fd int, err error) {
+ funcref := get_EpollCreateAddr()
+ if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE<<4, "") == 0 {
+ *funcref = impl_EpollCreate
+ } else {
+ *funcref = error_EpollCreate
}
+ return (*funcref)(size)
+}
+
+func error_EpollCreate(size int) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func fstat(fd int, stat *Stat_LE_t) (err error) {
- _, _, e1 := syscall_syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_EpollCreate1(flags int) (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, uintptr(flags))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_EpollCreate1Addr() *(func(flags int) (fd int, err error))
-func Fstatvfs(fd int, stat *Statvfs_t) (err error) {
- _, _, e1 := syscall_syscall(SYS_FSTATVFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+var EpollCreate1 = enter_EpollCreate1
+
+func enter_EpollCreate1(flags int) (fd int, err error) {
+ funcref := get_EpollCreate1Addr()
+ if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, "") == 0 {
+ *funcref = impl_EpollCreate1
+ } else {
+ *funcref = error_EpollCreate1
}
+ return (*funcref)(flags)
+}
+
+func error_EpollCreate1(flags int) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Fsync(fd int) (err error) {
- _, _, e1 := syscall_syscall(SYS_FSYNC, uintptr(fd), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CTL<<4, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_EpollCtlAddr() *(func(epfd int, op int, fd int, event *EpollEvent) (err error))
-func Ftruncate(fd int, length int64) (err error) {
- _, _, e1 := syscall_syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+var EpollCtl = enter_EpollCtl
+
+func enter_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+ funcref := get_EpollCtlAddr()
+ if funcptrtest(GetZosLibVec()+SYS_EPOLL_CTL<<4, "") == 0 {
+ *funcref = impl_EpollCtl
+ } else {
+ *funcref = error_EpollCtl
}
- return
+ return (*funcref)(epfd, op, fd, event)
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Getpagesize() (pgsize int) {
- r0, _, _ := syscall_syscall(SYS_GETPAGESIZE, 0, 0, 0)
- pgsize = int(r0)
+func error_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Mprotect(b []byte, prot int) (err error) {
+func impl_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) {
var _p0 unsafe.Pointer
- if len(b) > 0 {
- _p0 = unsafe.Pointer(&b[0])
+ if len(events) > 0 {
+ _p0 = unsafe.Pointer(&events[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
- _, _, e1 := syscall_syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), uintptr(unsafe.Pointer(sigmask)))
+ runtime.ExitSyscall()
+ n = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_EpollPwaitAddr() *(func(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error))
-func Msync(b []byte, flags int) (err error) {
- var _p0 unsafe.Pointer
- if len(b) > 0 {
- _p0 = unsafe.Pointer(&b[0])
+var EpollPwait = enter_EpollPwait
+
+func enter_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) {
+ funcref := get_EpollPwaitAddr()
+ if funcptrtest(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, "") == 0 {
+ *funcref = impl_EpollPwait
} else {
- _p0 = unsafe.Pointer(&_zero)
- }
- _, _, e1 := syscall_syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags))
- if e1 != 0 {
- err = errnoErr(e1)
+ *funcref = error_EpollPwait
}
+ return (*funcref)(epfd, events, msec, sigmask)
+}
+
+func error_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) {
+ n = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Poll(fds []PollFd, timeout int) (n int, err error) {
+func impl_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
var _p0 unsafe.Pointer
- if len(fds) > 0 {
- _p0 = unsafe.Pointer(&fds[0])
+ if len(events) > 0 {
+ _p0 = unsafe.Pointer(&events[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := syscall_syscall(SYS_POLL, uintptr(_p0), uintptr(len(fds)), uintptr(timeout))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_WAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec))
+ runtime.ExitSyscall()
n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_EpollWaitAddr() *(func(epfd int, events []EpollEvent, msec int) (n int, err error))
-func Times(tms *Tms) (ticks uintptr, err error) {
- r0, _, e1 := syscall_syscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
- ticks = uintptr(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+var EpollWait = enter_EpollWait
+
+func enter_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+ funcref := get_EpollWaitAddr()
+ if funcptrtest(GetZosLibVec()+SYS_EPOLL_WAIT<<4, "") == 0 {
+ *funcref = impl_EpollWait
+ } else {
+ *funcref = error_EpollWait
}
+ return (*funcref)(epfd, events, msec)
+}
+
+func error_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+ n = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func W_Getmntent(buff *byte, size int) (lastsys int, err error) {
- r0, _, e1 := syscall_syscall(SYS_W_GETMNTENT, uintptr(unsafe.Pointer(buff)), uintptr(size), 0)
- lastsys = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
+func Errno2() (er2 int) {
+ runtime.EnterSyscall()
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERRNO2<<4)
+ runtime.ExitSyscall()
+ er2 = int(r0)
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func W_Getmntent_A(buff *byte, size int) (lastsys int, err error) {
- r0, _, e1 := syscall_syscall(SYS___W_GETMNTENT_A, uintptr(unsafe.Pointer(buff)), uintptr(size), 0)
- lastsys = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_Eventfd(initval uint, flags int) (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EVENTFD<<4, uintptr(initval), uintptr(flags))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
+//go:nosplit
+func get_EventfdAddr() *(func(initval uint, flags int) (fd int, err error))
+
+var Eventfd = enter_Eventfd
+
+func enter_Eventfd(initval uint, flags int) (fd int, err error) {
+ funcref := get_EventfdAddr()
+ if funcptrtest(GetZosLibVec()+SYS_EVENTFD<<4, "") == 0 {
+ *funcref = impl_Eventfd
+ } else {
+ *funcref = error_Eventfd
+ }
+ return (*funcref)(initval, flags)
+}
+
+func error_Eventfd(initval uint, flags int) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
+ return
+}
+
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) {
+func Exit(code int) {
+ runtime.EnterSyscall()
+ CallLeFuncWithErr(GetZosLibVec()+SYS_EXIT<<4, uintptr(code))
+ runtime.ExitSyscall()
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
- var _p1 *byte
- _p1, err = BytePtrFromString(filesystem)
- if err != nil {
- return
- }
- var _p2 *byte
- _p2, err = BytePtrFromString(fstype)
- if err != nil {
- return
- }
- var _p3 *byte
- _p3, err = BytePtrFromString(parm)
- if err != nil {
- return
- }
- _, _, e1 := syscall_syscall6(SYS___MOUNT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(mtm), uintptr(parmlen), uintptr(unsafe.Pointer(_p3)))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FACCESSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_FaccessatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error))
-func unmount(filesystem string, mtm int) (err error) {
+var Faccessat = enter_Faccessat
+
+func enter_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+ funcref := get_FaccessatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FACCESSAT_A<<4, "") == 0 {
+ *funcref = impl_Faccessat
+ } else {
+ *funcref = error_Faccessat
+ }
+ return (*funcref)(dirfd, path, mode, flags)
+}
+
+func error_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHDIR<<4, uintptr(fd))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHMOD<<4, uintptr(fd), uintptr(mode))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
var _p0 *byte
- _p0, err = BytePtrFromString(filesystem)
+ _p0, err = BytePtrFromString(path)
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___UMOUNT_A, uintptr(unsafe.Pointer(_p0)), uintptr(mtm), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHMODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FchmodatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error))
+
+var Fchmodat = enter_Fchmodat
+
+func enter_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+ funcref := get_FchmodatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FCHMODAT_A<<4, "") == 0 {
+ *funcref = impl_Fchmodat
+ } else {
+ *funcref = error_Fchmodat
+ }
+ return (*funcref)(dirfd, path, mode, flags)
+}
+
+func error_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHOWN<<4, uintptr(fd), uintptr(uid), uintptr(gid))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Chroot(path string) (err error) {
+func impl_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___CHROOT_A, uintptr(unsafe.Pointer(_p0)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHOWNAT_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FchownatAddr() *(func(fd int, path string, uid int, gid int, flags int) (err error))
+
+var Fchownat = enter_Fchownat
+
+func enter_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) {
+ funcref := get_FchownatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FCHOWNAT_A<<4, "") == 0 {
+ *funcref = impl_Fchownat
+ } else {
+ *funcref = error_Fchownat
}
+ return (*funcref)(fd, path, uid, gid, flags)
+}
+
+func error_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Uname(buf *Utsname) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS___UNAME_A, uintptr(unsafe.Pointer(buf)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+func FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg))
+ runtime.ExitSyscall()
+ retval = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Gethostname(buf []byte) (err error) {
+func impl_Fdatasync(fd int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FDATASYNC<<4, uintptr(fd))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FdatasyncAddr() *(func(fd int) (err error))
+
+var Fdatasync = enter_Fdatasync
+
+func enter_Fdatasync(fd int) (err error) {
+ funcref := get_FdatasyncAddr()
+ if funcptrtest(GetZosLibVec()+SYS_FDATASYNC<<4, "") == 0 {
+ *funcref = impl_Fdatasync
+ } else {
+ *funcref = error_Fdatasync
+ }
+ return (*funcref)(fd)
+}
+
+func error_Fdatasync(fd int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fstat(fd int, stat *Stat_LE_t) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTAT<<4, uintptr(fd), uintptr(unsafe.Pointer(stat)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSTATAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_fstatatAddr() *(func(dirfd int, path string, stat *Stat_LE_t, flags int) (err error))
+
+var fstatat = enter_fstatat
+
+func enter_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) {
+ funcref := get_fstatatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FSTATAT_A<<4, "") == 0 {
+ *funcref = impl_fstatat
+ } else {
+ *funcref = error_fstatat
+ }
+ return (*funcref)(dirfd, path, stat, flags)
+}
+
+func error_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(link)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(dest) > 0 {
+ _p2 = unsafe.Pointer(&dest[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LGETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)))
+ runtime.ExitSyscall()
+ sz = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_LgetxattrAddr() *(func(link string, attr string, dest []byte) (sz int, err error))
+
+var Lgetxattr = enter_Lgetxattr
+
+func enter_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
+ funcref := get_LgetxattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___LGETXATTR_A<<4, "") == 0 {
+ *funcref = impl_Lgetxattr
+ } else {
+ *funcref = error_Lgetxattr
+ }
+ return (*funcref)(link, attr, dest)
+}
+
+func error_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
+ sz = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Lsetxattr(path string, attr string, data []byte, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ var _p2 unsafe.Pointer
+ if len(data) > 0 {
+ _p2 = unsafe.Pointer(&data[0])
+ } else {
+ _p2 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_LsetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error))
+
+var Lsetxattr = enter_Lsetxattr
+
+func enter_Lsetxattr(path string, attr string, data []byte, flags int) (err error) {
+ funcref := get_LsetxattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___LSETXATTR_A<<4, "") == 0 {
+ *funcref = impl_Lsetxattr
+ } else {
+ *funcref = error_Lsetxattr
+ }
+ return (*funcref)(path, attr, data, flags)
+}
+
+func error_Lsetxattr(path string, attr string, data []byte, flags int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Fstatfs(fd int, buf *Statfs_t) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATFS<<4, uintptr(fd), uintptr(unsafe.Pointer(buf)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FstatfsAddr() *(func(fd int, buf *Statfs_t) (err error))
+
+var Fstatfs = enter_Fstatfs
+
+func enter_Fstatfs(fd int, buf *Statfs_t) (err error) {
+ funcref := get_FstatfsAddr()
+ if funcptrtest(GetZosLibVec()+SYS_FSTATFS<<4, "") == 0 {
+ *funcref = impl_Fstatfs
+ } else {
+ *funcref = error_Fstatfs
+ }
+ return (*funcref)(fd, buf)
+}
+
+func error_Fstatfs(fd int, buf *Statfs_t) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstatvfs(fd int, stat *Statvfs_t) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATVFS<<4, uintptr(fd), uintptr(unsafe.Pointer(stat)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSYNC<<4, uintptr(fd))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Futimes(fd int, tv []Timeval) (err error) {
var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
+ if len(tv) > 0 {
+ _p0 = unsafe.Pointer(&tv[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
- _, _, e1 := syscall_syscall(SYS___GETHOSTNAME_A, uintptr(_p0), uintptr(len(buf)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FUTIMES<<4, uintptr(fd), uintptr(_p0), uintptr(len(tv)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_FutimesAddr() *(func(fd int, tv []Timeval) (err error))
-func Getegid() (egid int) {
- r0, _, _ := syscall_rawsyscall(SYS_GETEGID, 0, 0, 0)
- egid = int(r0)
+var Futimes = enter_Futimes
+
+func enter_Futimes(fd int, tv []Timeval) (err error) {
+ funcref := get_FutimesAddr()
+ if funcptrtest(GetZosLibVec()+SYS_FUTIMES<<4, "") == 0 {
+ *funcref = impl_Futimes
+ } else {
+ *funcref = error_Futimes
+ }
+ return (*funcref)(fd, tv)
+}
+
+func error_Futimes(fd int, tv []Timeval) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Geteuid() (uid int) {
- r0, _, _ := syscall_rawsyscall(SYS_GETEUID, 0, 0, 0)
- uid = int(r0)
+func impl_Futimesat(dirfd int, path string, tv []Timeval) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(tv) > 0 {
+ _p1 = unsafe.Pointer(&tv[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FUTIMESAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_FutimesatAddr() *(func(dirfd int, path string, tv []Timeval) (err error))
+
+var Futimesat = enter_Futimesat
+
+func enter_Futimesat(dirfd int, path string, tv []Timeval) (err error) {
+ funcref := get_FutimesatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___FUTIMESAT_A<<4, "") == 0 {
+ *funcref = impl_Futimesat
+ } else {
+ *funcref = error_Futimesat
+ }
+ return (*funcref)(dirfd, path, tv)
+}
+
+func error_Futimesat(dirfd int, path string, tv []Timeval) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getgid() (gid int) {
- r0, _, _ := syscall_rawsyscall(SYS_GETGID, 0, 0, 0)
- gid = int(r0)
+func Ftruncate(fd int, length int64) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FTRUNCATE<<4, uintptr(fd), uintptr(length))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getpid() (pid int) {
- r0, _, _ := syscall_rawsyscall(SYS_GETPID, 0, 0, 0)
- pid = int(r0)
+func impl_Getrandom(buf []byte, flags int) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRANDOM<<4, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
+ runtime.ExitSyscall()
+ n = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_GetrandomAddr() *(func(buf []byte, flags int) (n int, err error))
+
+var Getrandom = enter_Getrandom
+
+func enter_Getrandom(buf []byte, flags int) (n int, err error) {
+ funcref := get_GetrandomAddr()
+ if funcptrtest(GetZosLibVec()+SYS_GETRANDOM<<4, "") == 0 {
+ *funcref = impl_Getrandom
+ } else {
+ *funcref = error_Getrandom
+ }
+ return (*funcref)(buf, flags)
+}
+
+func error_Getrandom(buf []byte, flags int) (n int, err error) {
+ n = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getpgid(pid int) (pgid int, err error) {
- r0, _, e1 := syscall_rawsyscall(SYS_GETPGID, uintptr(pid), 0, 0)
- pgid = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_InotifyInit() (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_INOTIFY_INIT<<4)
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_InotifyInitAddr() *(func() (fd int, err error))
+
+var InotifyInit = enter_InotifyInit
+
+func enter_InotifyInit() (fd int, err error) {
+ funcref := get_InotifyInitAddr()
+ if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT<<4, "") == 0 {
+ *funcref = impl_InotifyInit
+ } else {
+ *funcref = error_InotifyInit
}
+ return (*funcref)()
+}
+
+func error_InotifyInit() (fd int, err error) {
+ fd = -1
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getppid() (pid int) {
- r0, _, _ := syscall_rawsyscall(SYS_GETPPID, 0, 0, 0)
- pid = int(r0)
+func impl_InotifyInit1(flags int) (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, uintptr(flags))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_InotifyInit1Addr() *(func(flags int) (fd int, err error))
+
+var InotifyInit1 = enter_InotifyInit1
+
+func enter_InotifyInit1(flags int) (fd int, err error) {
+ funcref := get_InotifyInit1Addr()
+ if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, "") == 0 {
+ *funcref = impl_InotifyInit1
+ } else {
+ *funcref = error_InotifyInit1
+ }
+ return (*funcref)(flags)
+}
+
+func error_InotifyInit1(flags int) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(pathname)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
+ runtime.ExitSyscall()
+ watchdesc = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_InotifyAddWatchAddr() *(func(fd int, pathname string, mask uint32) (watchdesc int, err error))
+
+var InotifyAddWatch = enter_InotifyAddWatch
+
+func enter_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
+ funcref := get_InotifyAddWatchAddr()
+ if funcptrtest(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, "") == 0 {
+ *funcref = impl_InotifyAddWatch
+ } else {
+ *funcref = error_InotifyAddWatch
+ }
+ return (*funcref)(fd, pathname, mask)
+}
+
+func error_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
+ watchdesc = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, uintptr(fd), uintptr(watchdesc))
+ runtime.ExitSyscall()
+ success = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_InotifyRmWatchAddr() *(func(fd int, watchdesc uint32) (success int, err error))
+
+var InotifyRmWatch = enter_InotifyRmWatch
+
+func enter_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+ funcref := get_InotifyRmWatchAddr()
+ if funcptrtest(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, "") == 0 {
+ *funcref = impl_InotifyRmWatch
+ } else {
+ *funcref = error_InotifyRmWatch
+ }
+ return (*funcref)(fd, watchdesc)
+}
+
+func error_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+ success = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Listxattr(path string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(dest) > 0 {
+ _p1 = unsafe.Pointer(&dest[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+ runtime.ExitSyscall()
+ sz = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_ListxattrAddr() *(func(path string, dest []byte) (sz int, err error))
+
+var Listxattr = enter_Listxattr
+
+func enter_Listxattr(path string, dest []byte) (sz int, err error) {
+ funcref := get_ListxattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___LISTXATTR_A<<4, "") == 0 {
+ *funcref = impl_Listxattr
+ } else {
+ *funcref = error_Listxattr
+ }
+ return (*funcref)(path, dest)
+}
+
+func error_Listxattr(path string, dest []byte) (sz int, err error) {
+ sz = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Llistxattr(path string, dest []byte) (sz int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(dest) > 0 {
+ _p1 = unsafe.Pointer(&dest[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LLISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+ runtime.ExitSyscall()
+ sz = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_LlistxattrAddr() *(func(path string, dest []byte) (sz int, err error))
+
+var Llistxattr = enter_Llistxattr
+
+func enter_Llistxattr(path string, dest []byte) (sz int, err error) {
+ funcref := get_LlistxattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___LLISTXATTR_A<<4, "") == 0 {
+ *funcref = impl_Llistxattr
+ } else {
+ *funcref = error_Llistxattr
+ }
+ return (*funcref)(path, dest)
+}
+
+func error_Llistxattr(path string, dest []byte) (sz int, err error) {
+ sz = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Lremovexattr(path string, attr string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(attr)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_LremovexattrAddr() *(func(path string, attr string) (err error))
+
+var Lremovexattr = enter_Lremovexattr
+
+func enter_Lremovexattr(path string, attr string) (err error) {
+ funcref := get_LremovexattrAddr()
+ if funcptrtest(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, "") == 0 {
+ *funcref = impl_Lremovexattr
+ } else {
+ *funcref = error_Lremovexattr
+ }
+ return (*funcref)(path, attr)
+}
+
+func error_Lremovexattr(path string, attr string) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Lutimes(path string, tv []Timeval) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 unsafe.Pointer
+ if len(tv) > 0 {
+ _p1 = unsafe.Pointer(&tv[0])
+ } else {
+ _p1 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LUTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_LutimesAddr() *(func(path string, tv []Timeval) (err error))
+
+var Lutimes = enter_Lutimes
+
+func enter_Lutimes(path string, tv []Timeval) (err error) {
+ funcref := get_LutimesAddr()
+ if funcptrtest(GetZosLibVec()+SYS___LUTIMES_A<<4, "") == 0 {
+ *funcref = impl_Lutimes
+ } else {
+ *funcref = error_Lutimes
+ }
+ return (*funcref)(path, tv)
+}
+
+func error_Lutimes(path string, tv []Timeval) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MPROTECT<<4, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Msync(b []byte, flags int) (err error) {
+ var _p0 unsafe.Pointer
+ if len(b) > 0 {
+ _p0 = unsafe.Pointer(&b[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MSYNC<<4, uintptr(_p0), uintptr(len(b)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONSOLE2<<4, uintptr(unsafe.Pointer(cmsg)), uintptr(unsafe.Pointer(modstr)), uintptr(unsafe.Pointer(concmd)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Poll(fds []PollFd, timeout int) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(fds) > 0 {
+ _p0 = unsafe.Pointer(&fds[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POLL<<4, uintptr(_p0), uintptr(len(fds)), uintptr(timeout))
+ runtime.ExitSyscall()
+ n = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_R_A<<4, uintptr(dirp), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Statfs(path string, buf *Statfs_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STATFS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_StatfsAddr() *(func(path string, buf *Statfs_t) (err error))
+
+var Statfs = enter_Statfs
+
+func enter_Statfs(path string, buf *Statfs_t) (err error) {
+ funcref := get_StatfsAddr()
+ if funcptrtest(GetZosLibVec()+SYS___STATFS_A<<4, "") == 0 {
+ *funcref = impl_Statfs
+ } else {
+ *funcref = error_Statfs
+ }
+ return (*funcref)(path, buf)
+}
+
+func error_Statfs(path string, buf *Statfs_t) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Syncfs(fd int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SYNCFS<<4, uintptr(fd))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_SyncfsAddr() *(func(fd int) (err error))
+
+var Syncfs = enter_Syncfs
+
+func enter_Syncfs(fd int) (err error) {
+ funcref := get_SyncfsAddr()
+ if funcptrtest(GetZosLibVec()+SYS_SYNCFS<<4, "") == 0 {
+ *funcref = impl_Syncfs
+ } else {
+ *funcref = error_Syncfs
+ }
+ return (*funcref)(fd)
+}
+
+func error_Syncfs(fd int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Times(tms *Tms) (ticks uintptr, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TIMES<<4, uintptr(unsafe.Pointer(tms)))
+ runtime.ExitSyscall()
+ ticks = uintptr(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func W_Getmntent(buff *byte, size int) (lastsys int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_GETMNTENT<<4, uintptr(unsafe.Pointer(buff)), uintptr(size))
+ runtime.ExitSyscall()
+ lastsys = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func W_Getmntent_A(buff *byte, size int) (lastsys int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___W_GETMNTENT_A<<4, uintptr(unsafe.Pointer(buff)), uintptr(size))
+ runtime.ExitSyscall()
+ lastsys = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(filesystem)
+ if err != nil {
+ return
+ }
+ var _p2 *byte
+ _p2, err = BytePtrFromString(fstype)
+ if err != nil {
+ return
+ }
+ var _p3 *byte
+ _p3, err = BytePtrFromString(parm)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(mtm), uintptr(parmlen), uintptr(unsafe.Pointer(_p3)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func unmount_LE(filesystem string, mtm int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(filesystem)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mtm))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHROOT_A<<4, uintptr(unsafe.Pointer(_p0)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SELECT<<4, uintptr(nmsgsfds), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)))
+ runtime.ExitSyscall()
+ ret = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Uname(buf *Utsname) (err error) {
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____OSNAME_A<<4, uintptr(unsafe.Pointer(buf)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Unshare(flags int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNSHARE<<4, uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_UnshareAddr() *(func(flags int) (err error))
+
+var Unshare = enter_Unshare
+
+func enter_Unshare(flags int) (err error) {
+ funcref := get_UnshareAddr()
+ if funcptrtest(GetZosLibVec()+SYS_UNSHARE<<4, "") == 0 {
+ *funcref = impl_Unshare
+ } else {
+ *funcref = error_Unshare
+ }
+ return (*funcref)(flags)
+}
+
+func error_Unshare(flags int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gethostname(buf []byte) (err error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(buf)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETGID<<4)
+ gid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPID<<4)
+ pid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPGID<<4, uintptr(pid))
+ pgid = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (pid int) {
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPPID<<4)
+ pid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPRIORITY<<4, uintptr(which), uintptr(who))
+ runtime.ExitSyscall()
+ prio = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(rlim)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getrusage(who int, rusage *rusage_zos) (err error) {
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRUSAGE<<4, uintptr(who), uintptr(unsafe.Pointer(rusage)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+ runtime.EnterSyscall()
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEGID<<4)
+ runtime.ExitSyscall()
+ egid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (euid int) {
+ runtime.EnterSyscall()
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEUID<<4)
+ runtime.ExitSyscall()
+ euid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getsid(pid int) (sid int, err error) {
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSID<<4, uintptr(pid))
+ sid = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETUID<<4)
+ uid = int(r0)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, sig Signal) (err error) {
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_KILL<<4, uintptr(pid), uintptr(sig))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LCHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Link(path string, link string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(link)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldPath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newPath)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINKAT_A<<4, uintptr(oldDirFd), uintptr(unsafe.Pointer(_p0)), uintptr(newDirFd), uintptr(unsafe.Pointer(_p1)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_LinkatAddr() *(func(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error))
+
+var Linkat = enter_Linkat
+
+func enter_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) {
+ funcref := get_LinkatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___LINKAT_A<<4, "") == 0 {
+ *funcref = impl_Linkat
+ } else {
+ *funcref = error_Linkat
+ }
+ return (*funcref)(oldDirFd, oldPath, newDirFd, newPath, flags)
+}
+
+func error_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, n int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LISTEN<<4, uintptr(s), uintptr(n))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func lstat(path string, stat *Stat_LE_t) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSTAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdir(path string, mode uint32) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Mkdirat(dirfd int, path string, mode uint32) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIRAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_MkdiratAddr() *(func(dirfd int, path string, mode uint32) (err error))
+
+var Mkdirat = enter_Mkdirat
+
+func enter_Mkdirat(dirfd int, path string, mode uint32) (err error) {
+ funcref := get_MkdiratAddr()
+ if funcptrtest(GetZosLibVec()+SYS___MKDIRAT_A<<4, "") == 0 {
+ *funcref = impl_Mkdirat
+ } else {
+ *funcref = error_Mkdirat
+ }
+ return (*funcref)(dirfd, path, mode)
+}
+
+func error_Mkdirat(dirfd int, path string, mode uint32) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkfifo(path string, mode uint32) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFO_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknod(path string, mode uint32, dev int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_MknodatAddr() *(func(dirfd int, path string, mode uint32, dev int) (err error))
+
+var Mknodat = enter_Mknodat
+
+func enter_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+ funcref := get_MknodatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___MKNODAT_A<<4, "") == 0 {
+ *funcref = impl_Mknodat
+ } else {
+ *funcref = error_Mknodat
+ }
+ return (*funcref)(dirfd, path, mode, dev)
+}
+
+func error_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_PivotRoot(newroot string, oldroot string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(newroot)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(oldroot)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_PivotRootAddr() *(func(newroot string, oldroot string) (err error))
+
+var PivotRoot = enter_PivotRoot
+
+func enter_PivotRoot(newroot string, oldroot string) (err error) {
+ funcref := get_PivotRootAddr()
+ if funcptrtest(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, "") == 0 {
+ *funcref = impl_PivotRoot
+ } else {
+ *funcref = error_PivotRoot
+ }
+ return (*funcref)(newroot, oldroot)
+}
+
+func error_PivotRoot(newroot string, oldroot string) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PREAD<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset))
+ runtime.ExitSyscall()
+ n = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getpriority(which int, who int) (prio int, err error) {
- r0, _, e1 := syscall_syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
- prio = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PWRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset))
+ runtime.ExitSyscall()
+ n = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getrlimit(resource int, rlim *Rlimit) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PRCTL_A<<4, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_PrctlAddr() *(func(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error))
-func getrusage(who int, rusage *rusage_zos) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+var Prctl = enter_Prctl
+
+func enter_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) {
+ funcref := get_PrctlAddr()
+ if funcptrtest(GetZosLibVec()+SYS___PRCTL_A<<4, "") == 0 {
+ *funcref = impl_Prctl
+ } else {
+ *funcref = error_Prctl
}
- return
+ return (*funcref)(option, arg2, arg3, arg4, arg5)
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Getsid(pid int) (sid int, err error) {
- r0, _, e1 := syscall_rawsyscall(SYS_GETSID, uintptr(pid), 0, 0)
- sid = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
+func error_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getuid() (uid int) {
- r0, _, _ := syscall_rawsyscall(SYS_GETUID, 0, 0, 0)
- uid = int(r0)
+func impl_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) {
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PRLIMIT<<4, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(newlimit)), uintptr(unsafe.Pointer(old)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_PrlimitAddr() *(func(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error))
-func Kill(pid int, sig Signal) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+var Prlimit = enter_Prlimit
+
+func enter_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) {
+ funcref := get_PrlimitAddr()
+ if funcptrtest(GetZosLibVec()+SYS_PRLIMIT<<4, "") == 0 {
+ *funcref = impl_Prlimit
+ } else {
+ *funcref = error_Prlimit
}
+ return (*funcref)(pid, resource, newlimit, old)
+}
+
+func error_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Lchown(path string, uid int, gid int) (err error) {
+func Rename(from string, to string) (err error) {
var _p0 *byte
- _p0, err = BytePtrFromString(path)
+ _p0, err = BytePtrFromString(from)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(to)
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___LCHOWN_A, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Link(path string, link string) (err error) {
+func impl_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
var _p0 *byte
- _p0, err = BytePtrFromString(path)
+ _p0, err = BytePtrFromString(oldpath)
if err != nil {
return
}
var _p1 *byte
- _p1, err = BytePtrFromString(link)
+ _p1, err = BytePtrFromString(newpath)
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___LINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_RenameatAddr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string) (err error))
-func Listen(s int, n int) (err error) {
- _, _, e1 := syscall_syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+var Renameat = enter_Renameat
+
+func enter_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+ funcref := get_RenameatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___RENAMEAT_A<<4, "") == 0 {
+ *funcref = impl_Renameat
+ } else {
+ *funcref = error_Renameat
}
+ return (*funcref)(olddirfd, oldpath, newdirfd, newpath)
+}
+
+func error_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func lstat(path string, stat *Stat_LE_t) (err error) {
+func impl_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) {
var _p0 *byte
- _p0, err = BytePtrFromString(path)
+ _p0, err = BytePtrFromString(oldpath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newpath)
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___LSTAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT2_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_Renameat2Addr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error))
-func Mkdir(path string, mode uint32) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := syscall_syscall(SYS___MKDIR_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+var Renameat2 = enter_Renameat2
+
+func enter_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) {
+ funcref := get_Renameat2Addr()
+ if funcptrtest(GetZosLibVec()+SYS___RENAMEAT2_A<<4, "") == 0 {
+ *funcref = impl_Renameat2
+ } else {
+ *funcref = error_Renameat2
}
+ return (*funcref)(olddirfd, oldpath, newdirfd, newpath, flags)
+}
+
+func error_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Mkfifo(path string, mode uint32) (err error) {
+func Rmdir(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___MKFIFO_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RMDIR_A<<4, uintptr(unsafe.Pointer(_p0)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Mknod(path string, mode uint32, dev int) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := syscall_syscall(SYS___MKNOD_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev))
- if e1 != 0 {
- err = errnoErr(e1)
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LSEEK<<4, uintptr(fd), uintptr(offset), uintptr(whence))
+ runtime.ExitSyscall()
+ off = int64(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pread(fd int, p []byte, offset int64) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(p) > 0 {
- _p0 = unsafe.Pointer(&p[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
+func Setegid(egid int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEGID<<4, uintptr(egid))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
- r0, _, e1 := syscall_syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seteuid(euid int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEUID<<4, uintptr(euid))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+func impl_Sethostname(p []byte) (err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := syscall_syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(p)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_SethostnameAddr() *(func(p []byte) (err error))
-func Readlink(path string, buf []byte) (n int, err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- var _p1 unsafe.Pointer
- if len(buf) > 0 {
- _p1 = unsafe.Pointer(&buf[0])
+var Sethostname = enter_Sethostname
+
+func enter_Sethostname(p []byte) (err error) {
+ funcref := get_SethostnameAddr()
+ if funcptrtest(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, "") == 0 {
+ *funcref = impl_Sethostname
} else {
- _p1 = unsafe.Pointer(&_zero)
+ *funcref = error_Sethostname
}
- r0, _, e1 := syscall_syscall(SYS___READLINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)))
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
+ return (*funcref)(p)
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Rename(from string, to string) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(from)
- if err != nil {
- return
- }
- var _p1 *byte
- _p1, err = BytePtrFromString(to)
- if err != nil {
- return
- }
- _, _, e1 := syscall_syscall(SYS___RENAME_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
+func error_Sethostname(p []byte) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Rmdir(path string) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := syscall_syscall(SYS___RMDIR_A, uintptr(unsafe.Pointer(_p0)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_Setns(fd int, nstype int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETNS<<4, uintptr(fd), uintptr(nstype))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+//go:nosplit
+func get_SetnsAddr() *(func(fd int, nstype int) (err error))
-func Seek(fd int, offset int64, whence int) (off int64, err error) {
- r0, _, e1 := syscall_syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
- off = int64(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+var Setns = enter_Setns
+
+func enter_Setns(fd int, nstype int) (err error) {
+ funcref := get_SetnsAddr()
+ if funcptrtest(GetZosLibVec()+SYS_SETNS<<4, "") == 0 {
+ *funcref = impl_Setns
+ } else {
+ *funcref = error_Setns
}
+ return (*funcref)(fd, nstype)
+}
+
+func error_Setns(fd int, nstype int) (err error) {
+ err = ENOSYS
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setpriority(which int, who int, prio int) (err error) {
- _, _, e1 := syscall_syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPRIORITY<<4, uintptr(which), uintptr(who), uintptr(prio))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -971,9 +2910,9 @@ func Setpriority(which int, who int, prio int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setpgid(pid int, pgid int) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPGID<<4, uintptr(pid), uintptr(pgid))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -981,9 +2920,9 @@ func Setpgid(pid int, pgid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, lim *Rlimit) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(lim)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(lim)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -991,9 +2930,9 @@ func Setrlimit(resource int, lim *Rlimit) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setregid(rgid int, egid int) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREGID<<4, uintptr(rgid), uintptr(egid))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1001,9 +2940,9 @@ func Setregid(rgid int, egid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setreuid(ruid int, euid int) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREUID<<4, uintptr(ruid), uintptr(euid))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1011,10 +2950,10 @@ func Setreuid(ruid int, euid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setsid() (pid int, err error) {
- r0, _, e1 := syscall_rawsyscall(SYS_SETSID, 0, 0, 0)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_SETSID<<4)
pid = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1022,9 +2961,11 @@ func Setsid() (pid int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setuid(uid int) (err error) {
- _, _, e1 := syscall_syscall(SYS_SETUID, uintptr(uid), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETUID<<4, uintptr(uid))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1032,9 +2973,11 @@ func Setuid(uid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setgid(uid int) (err error) {
- _, _, e1 := syscall_syscall(SYS_SETGID, uintptr(uid), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGID<<4, uintptr(uid))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1042,9 +2985,11 @@ func Setgid(uid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Shutdown(fd int, how int) (err error) {
- _, _, e1 := syscall_syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHUTDOWN<<4, uintptr(fd), uintptr(how))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1057,9 +3002,11 @@ func stat(path string, statLE *Stat_LE_t) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___STAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(statLE)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(statLE)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1077,17 +3024,63 @@ func Symlink(path string, link string) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___SYMLINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Symlinkat(oldPath string, dirfd int, newPath string) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(oldPath)
+ if err != nil {
+ return
+ }
+ var _p1 *byte
+ _p1, err = BytePtrFromString(newPath)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINKAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(dirfd), uintptr(unsafe.Pointer(_p1)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
+//go:nosplit
+func get_SymlinkatAddr() *(func(oldPath string, dirfd int, newPath string) (err error))
+
+var Symlinkat = enter_Symlinkat
+
+func enter_Symlinkat(oldPath string, dirfd int, newPath string) (err error) {
+ funcref := get_SymlinkatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___SYMLINKAT_A<<4, "") == 0 {
+ *funcref = impl_Symlinkat
+ } else {
+ *funcref = error_Symlinkat
+ }
+ return (*funcref)(oldPath, dirfd, newPath)
+}
+
+func error_Symlinkat(oldPath string, dirfd int, newPath string) (err error) {
+ err = ENOSYS
+ return
+}
+
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Sync() {
- syscall_syscall(SYS_SYNC, 0, 0, 0)
+ runtime.EnterSyscall()
+ CallLeFuncWithErr(GetZosLibVec() + SYS_SYNC<<4)
+ runtime.ExitSyscall()
return
}
@@ -1099,9 +3092,11 @@ func Truncate(path string, length int64) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___TRUNCATE_A, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___TRUNCATE_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(length))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1109,9 +3104,11 @@ func Truncate(path string, length int64) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Tcgetattr(fildes int, termptr *Termios) (err error) {
- _, _, e1 := syscall_syscall(SYS_TCGETATTR, uintptr(fildes), uintptr(unsafe.Pointer(termptr)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCGETATTR<<4, uintptr(fildes), uintptr(unsafe.Pointer(termptr)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1119,9 +3116,11 @@ func Tcgetattr(fildes int, termptr *Termios) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Tcsetattr(fildes int, when int, termptr *Termios) (err error) {
- _, _, e1 := syscall_syscall(SYS_TCSETATTR, uintptr(fildes), uintptr(when), uintptr(unsafe.Pointer(termptr)))
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCSETATTR<<4, uintptr(fildes), uintptr(when), uintptr(unsafe.Pointer(termptr)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1129,7 +3128,9 @@ func Tcsetattr(fildes int, when int, termptr *Termios) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Umask(mask int) (oldmask int) {
- r0, _, _ := syscall_syscall(SYS_UMASK, uintptr(mask), 0, 0)
+ runtime.EnterSyscall()
+ r0, _, _ := CallLeFuncWithErr(GetZosLibVec()+SYS_UMASK<<4, uintptr(mask))
+ runtime.ExitSyscall()
oldmask = int(r0)
return
}
@@ -1142,10 +3143,49 @@ func Unlink(path string) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___UNLINK_A, uintptr(unsafe.Pointer(_p0)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINK_A<<4, uintptr(unsafe.Pointer(_p0)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_Unlinkat(dirfd int, path string, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_UnlinkatAddr() *(func(dirfd int, path string, flags int) (err error))
+
+var Unlinkat = enter_Unlinkat
+
+func enter_Unlinkat(dirfd int, path string, flags int) (err error) {
+ funcref := get_UnlinkatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___UNLINKAT_A<<4, "") == 0 {
+ *funcref = impl_Unlinkat
+ } else {
+ *funcref = error_Unlinkat
}
+ return (*funcref)(dirfd, path, flags)
+}
+
+func error_Unlinkat(dirfd int, path string, flags int) (err error) {
+ err = ENOSYS
return
}
@@ -1157,9 +3197,11 @@ func Utime(path string, utim *Utimbuf) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___UTIME_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(utim)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(utim)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1172,11 +3214,91 @@ func open(path string, mode int, perm uint32) (fd int, err error) {
if err != nil {
return
}
- r0, _, e1 := syscall_syscall(SYS___OPEN_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPEN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_openatAddr() *(func(dirfd int, path string, flags int, mode uint32) (fd int, err error))
+
+var openat = enter_openat
+
+func enter_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+ funcref := get_openatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___OPENAT_A<<4, "") == 0 {
+ *funcref = impl_openat
+ } else {
+ *funcref = error_openat
+ }
+ return (*funcref)(dirfd, path, flags, mode)
+}
+
+func error_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func impl_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT2_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(open_how)), uintptr(size))
+ runtime.ExitSyscall()
fd = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_openat2Addr() *(func(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error))
+
+var openat2 = enter_openat2
+
+func enter_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) {
+ funcref := get_openat2Addr()
+ if funcptrtest(GetZosLibVec()+SYS___OPENAT2_A<<4, "") == 0 {
+ *funcref = impl_openat2
+ } else {
+ *funcref = error_openat2
}
+ return (*funcref)(dirfd, path, open_how, size)
+}
+
+func error_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) {
+ fd = -1
+ err = ENOSYS
return
}
@@ -1188,9 +3310,23 @@ func remove(path string) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_REMOVE<<4, uintptr(unsafe.Pointer(_p0)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func waitid(idType int, id int, info *Siginfo, options int) (err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITID<<4, uintptr(idType), uintptr(id), uintptr(unsafe.Pointer(info)), uintptr(options))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1198,10 +3334,12 @@ func remove(path string) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) {
- r0, _, e1 := syscall_syscall(SYS_WAITPID, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options))
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITPID<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options))
+ runtime.ExitSyscall()
wpid = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1209,9 +3347,9 @@ func waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tv *timeval_zos) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETTIMEOFDAY<<4, uintptr(unsafe.Pointer(tv)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1219,9 +3357,9 @@ func gettimeofday(tv *timeval_zos) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]_C_int) (err error) {
- _, _, e1 := syscall_rawsyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE<<4, uintptr(unsafe.Pointer(p)))
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
@@ -1234,20 +3372,87 @@ func utimes(path string, timeval *[2]Timeval) (err error) {
if err != nil {
return
}
- _, _, e1 := syscall_syscall(SYS___UTIMES_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) {
- r0, _, e1 := syscall_syscall6(SYS_SELECT, uintptr(nmsgsfds), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
- ret = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
+func impl_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) {
+ var _p0 *byte
+ _p0, err = BytePtrFromString(path)
+ if err != nil {
+ return
+ }
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMENSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(ts)), uintptr(flags))
+ runtime.ExitSyscall()
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+//go:nosplit
+func get_utimensatAddr() *(func(dirfd int, path string, ts *[2]Timespec, flags int) (err error))
+
+var utimensat = enter_utimensat
+
+func enter_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) {
+ funcref := get_utimensatAddr()
+ if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 {
+ *funcref = impl_utimensat
+ } else {
+ *funcref = error_utimensat
+ }
+ return (*funcref)(dirfd, path, ts, flags)
+}
+
+func error_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) {
+ err = ENOSYS
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Posix_openpt(oflag int) (fd int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POSIX_OPENPT<<4, uintptr(oflag))
+ runtime.ExitSyscall()
+ fd = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Grantpt(fildes int) (rc int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GRANTPT<<4, uintptr(fildes))
+ runtime.ExitSyscall()
+ rc = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unlockpt(fildes int) (rc int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNLOCKPT<<4, uintptr(fildes))
+ runtime.ExitSyscall()
+ rc = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
}
return
}
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go
index fcf3ecbdde..53aef5dc58 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go
@@ -448,4 +448,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
index f56dc2504a..71d524763d 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
@@ -371,4 +371,12 @@ const (
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go
index 974bf24676..c747706131 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go
@@ -412,4 +412,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
index 39a2739e23..f96e214f6d 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
@@ -315,4 +315,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go
index cf9c9d77e1..28425346cf 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go
@@ -309,4 +309,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go
index 10b7362ef4..d0953018da 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go
@@ -432,4 +432,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 4450
SYS_CACHESTAT = 4451
SYS_FCHMODAT2 = 4452
+ SYS_MAP_SHADOW_STACK = 4453
+ SYS_FUTEX_WAKE = 4454
+ SYS_FUTEX_WAIT = 4455
+ SYS_FUTEX_REQUEUE = 4456
+ SYS_STATMOUNT = 4457
+ SYS_LISTMOUNT = 4458
+ SYS_LSM_GET_SELF_ATTR = 4459
+ SYS_LSM_SET_SELF_ATTR = 4460
+ SYS_LSM_LIST_MODULES = 4461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go
index cd4d8b4fd3..295c7f4b81 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go
@@ -362,4 +362,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 5450
SYS_CACHESTAT = 5451
SYS_FCHMODAT2 = 5452
+ SYS_MAP_SHADOW_STACK = 5453
+ SYS_FUTEX_WAKE = 5454
+ SYS_FUTEX_WAIT = 5455
+ SYS_FUTEX_REQUEUE = 5456
+ SYS_STATMOUNT = 5457
+ SYS_LISTMOUNT = 5458
+ SYS_LSM_GET_SELF_ATTR = 5459
+ SYS_LSM_SET_SELF_ATTR = 5460
+ SYS_LSM_LIST_MODULES = 5461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go
index 2c0efca818..d1a9eaca7a 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go
@@ -362,4 +362,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 5450
SYS_CACHESTAT = 5451
SYS_FCHMODAT2 = 5452
+ SYS_MAP_SHADOW_STACK = 5453
+ SYS_FUTEX_WAKE = 5454
+ SYS_FUTEX_WAIT = 5455
+ SYS_FUTEX_REQUEUE = 5456
+ SYS_STATMOUNT = 5457
+ SYS_LISTMOUNT = 5458
+ SYS_LSM_GET_SELF_ATTR = 5459
+ SYS_LSM_SET_SELF_ATTR = 5460
+ SYS_LSM_LIST_MODULES = 5461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go
index a72e31d391..bec157c39f 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go
@@ -432,4 +432,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 4450
SYS_CACHESTAT = 4451
SYS_FCHMODAT2 = 4452
+ SYS_MAP_SHADOW_STACK = 4453
+ SYS_FUTEX_WAKE = 4454
+ SYS_FUTEX_WAIT = 4455
+ SYS_FUTEX_REQUEUE = 4456
+ SYS_STATMOUNT = 4457
+ SYS_LISTMOUNT = 4458
+ SYS_LSM_GET_SELF_ATTR = 4459
+ SYS_LSM_SET_SELF_ATTR = 4460
+ SYS_LSM_LIST_MODULES = 4461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go
index c7d1e37471..7ee7bdc435 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go
@@ -439,4 +439,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go
index f4d4838c87..fad1f25b44 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go
@@ -411,4 +411,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go
index b64f0e5911..7d3e16357d 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go
@@ -411,4 +411,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
index 95711195a0..0ed53ad9f7 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
@@ -316,4 +316,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
index f94e943bc4..2fba04ad50 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
@@ -377,4 +377,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go
index ba0c2bc515..621d00d741 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go
@@ -390,4 +390,13 @@ const (
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
+ SYS_MAP_SHADOW_STACK = 453
+ SYS_FUTEX_WAKE = 454
+ SYS_FUTEX_WAIT = 455
+ SYS_FUTEX_REQUEUE = 456
+ SYS_STATMOUNT = 457
+ SYS_LISTMOUNT = 458
+ SYS_LSM_GET_SELF_ATTR = 459
+ SYS_LSM_SET_SELF_ATTR = 460
+ SYS_LSM_LIST_MODULES = 461
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go
index b2e3085819..5e8c263ca9 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go
@@ -1,2669 +1,2852 @@
-// Copyright 2020 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.
+// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s
+// Code generated by the command above; see README.md. DO NOT EDIT.
//go:build zos && s390x
package unix
-// TODO: auto-generate.
-
const (
- SYS_ACOSD128 = 0xB80
- SYS_ACOSD32 = 0xB7E
- SYS_ACOSD64 = 0xB7F
- SYS_ACOSHD128 = 0xB83
- SYS_ACOSHD32 = 0xB81
- SYS_ACOSHD64 = 0xB82
- SYS_AIO_FSYNC = 0xC69
- SYS_ASCTIME = 0x0AE
- SYS_ASCTIME64 = 0xCD7
- SYS_ASCTIME64_R = 0xCD8
- SYS_ASIND128 = 0xB86
- SYS_ASIND32 = 0xB84
- SYS_ASIND64 = 0xB85
- SYS_ASINHD128 = 0xB89
- SYS_ASINHD32 = 0xB87
- SYS_ASINHD64 = 0xB88
- SYS_ATAN2D128 = 0xB8F
- SYS_ATAN2D32 = 0xB8D
- SYS_ATAN2D64 = 0xB8E
- SYS_ATAND128 = 0xB8C
- SYS_ATAND32 = 0xB8A
- SYS_ATAND64 = 0xB8B
- SYS_ATANHD128 = 0xB92
- SYS_ATANHD32 = 0xB90
- SYS_ATANHD64 = 0xB91
- SYS_BIND2ADDRSEL = 0xD59
- SYS_C16RTOMB = 0xD40
- SYS_C32RTOMB = 0xD41
- SYS_CBRTD128 = 0xB95
- SYS_CBRTD32 = 0xB93
- SYS_CBRTD64 = 0xB94
- SYS_CEILD128 = 0xB98
- SYS_CEILD32 = 0xB96
- SYS_CEILD64 = 0xB97
- SYS_CLEARENV = 0x0C9
- SYS_CLEARERR_UNLOCKED = 0xCA1
- SYS_CLOCK = 0x0AA
- SYS_CLOGL = 0xA00
- SYS_CLRMEMF = 0x0BD
- SYS_CONJ = 0xA03
- SYS_CONJF = 0xA06
- SYS_CONJL = 0xA09
- SYS_COPYSIGND128 = 0xB9E
- SYS_COPYSIGND32 = 0xB9C
- SYS_COPYSIGND64 = 0xB9D
- SYS_COSD128 = 0xBA1
- SYS_COSD32 = 0xB9F
- SYS_COSD64 = 0xBA0
- SYS_COSHD128 = 0xBA4
- SYS_COSHD32 = 0xBA2
- SYS_COSHD64 = 0xBA3
- SYS_CPOW = 0xA0C
- SYS_CPOWF = 0xA0F
- SYS_CPOWL = 0xA12
- SYS_CPROJ = 0xA15
- SYS_CPROJF = 0xA18
- SYS_CPROJL = 0xA1B
- SYS_CREAL = 0xA1E
- SYS_CREALF = 0xA21
- SYS_CREALL = 0xA24
- SYS_CSIN = 0xA27
- SYS_CSINF = 0xA2A
- SYS_CSINH = 0xA30
- SYS_CSINHF = 0xA33
- SYS_CSINHL = 0xA36
- SYS_CSINL = 0xA2D
- SYS_CSNAP = 0x0C5
- SYS_CSQRT = 0xA39
- SYS_CSQRTF = 0xA3C
- SYS_CSQRTL = 0xA3F
- SYS_CTAN = 0xA42
- SYS_CTANF = 0xA45
- SYS_CTANH = 0xA4B
- SYS_CTANHF = 0xA4E
- SYS_CTANHL = 0xA51
- SYS_CTANL = 0xA48
- SYS_CTIME = 0x0AB
- SYS_CTIME64 = 0xCD9
- SYS_CTIME64_R = 0xCDA
- SYS_CTRACE = 0x0C6
- SYS_DIFFTIME = 0x0A7
- SYS_DIFFTIME64 = 0xCDB
- SYS_DLADDR = 0xC82
- SYS_DYNALLOC = 0x0C3
- SYS_DYNFREE = 0x0C2
- SYS_ERFCD128 = 0xBAA
- SYS_ERFCD32 = 0xBA8
- SYS_ERFCD64 = 0xBA9
- SYS_ERFD128 = 0xBA7
- SYS_ERFD32 = 0xBA5
- SYS_ERFD64 = 0xBA6
- SYS_EXP2D128 = 0xBB0
- SYS_EXP2D32 = 0xBAE
- SYS_EXP2D64 = 0xBAF
- SYS_EXPD128 = 0xBAD
- SYS_EXPD32 = 0xBAB
- SYS_EXPD64 = 0xBAC
- SYS_EXPM1D128 = 0xBB3
- SYS_EXPM1D32 = 0xBB1
- SYS_EXPM1D64 = 0xBB2
- SYS_FABSD128 = 0xBB6
- SYS_FABSD32 = 0xBB4
- SYS_FABSD64 = 0xBB5
- SYS_FDELREC_UNLOCKED = 0xCA2
- SYS_FDIMD128 = 0xBB9
- SYS_FDIMD32 = 0xBB7
- SYS_FDIMD64 = 0xBB8
- SYS_FDOPEN_UNLOCKED = 0xCFC
- SYS_FECLEAREXCEPT = 0xAEA
- SYS_FEGETENV = 0xAEB
- SYS_FEGETEXCEPTFLAG = 0xAEC
- SYS_FEGETROUND = 0xAED
- SYS_FEHOLDEXCEPT = 0xAEE
- SYS_FEOF_UNLOCKED = 0xCA3
- SYS_FERAISEEXCEPT = 0xAEF
- SYS_FERROR_UNLOCKED = 0xCA4
- SYS_FESETENV = 0xAF0
- SYS_FESETEXCEPTFLAG = 0xAF1
- SYS_FESETROUND = 0xAF2
- SYS_FETCHEP = 0x0BF
- SYS_FETESTEXCEPT = 0xAF3
- SYS_FEUPDATEENV = 0xAF4
- SYS_FE_DEC_GETROUND = 0xBBA
- SYS_FE_DEC_SETROUND = 0xBBB
- SYS_FFLUSH_UNLOCKED = 0xCA5
- SYS_FGETC_UNLOCKED = 0xC80
- SYS_FGETPOS64 = 0xCEE
- SYS_FGETPOS64_UNLOCKED = 0xCF4
- SYS_FGETPOS_UNLOCKED = 0xCA6
- SYS_FGETS_UNLOCKED = 0xC7C
- SYS_FGETWC_UNLOCKED = 0xCA7
- SYS_FGETWS_UNLOCKED = 0xCA8
- SYS_FILENO_UNLOCKED = 0xCA9
- SYS_FLDATA = 0x0C1
- SYS_FLDATA_UNLOCKED = 0xCAA
- SYS_FLOCATE_UNLOCKED = 0xCAB
- SYS_FLOORD128 = 0xBBE
- SYS_FLOORD32 = 0xBBC
- SYS_FLOORD64 = 0xBBD
- SYS_FMA = 0xA63
- SYS_FMAD128 = 0xBC1
- SYS_FMAD32 = 0xBBF
- SYS_FMAD64 = 0xBC0
- SYS_FMAF = 0xA66
- SYS_FMAL = 0xA69
- SYS_FMAX = 0xA6C
- SYS_FMAXD128 = 0xBC4
- SYS_FMAXD32 = 0xBC2
- SYS_FMAXD64 = 0xBC3
- SYS_FMAXF = 0xA6F
- SYS_FMAXL = 0xA72
- SYS_FMIN = 0xA75
- SYS_FMIND128 = 0xBC7
- SYS_FMIND32 = 0xBC5
- SYS_FMIND64 = 0xBC6
- SYS_FMINF = 0xA78
- SYS_FMINL = 0xA7B
- SYS_FMODD128 = 0xBCA
- SYS_FMODD32 = 0xBC8
- SYS_FMODD64 = 0xBC9
- SYS_FOPEN64 = 0xD49
- SYS_FOPEN64_UNLOCKED = 0xD4A
- SYS_FOPEN_UNLOCKED = 0xCFA
- SYS_FPRINTF_UNLOCKED = 0xCAC
- SYS_FPUTC_UNLOCKED = 0xC81
- SYS_FPUTS_UNLOCKED = 0xC7E
- SYS_FPUTWC_UNLOCKED = 0xCAD
- SYS_FPUTWS_UNLOCKED = 0xCAE
- SYS_FREAD_NOUPDATE = 0xCEC
- SYS_FREAD_NOUPDATE_UNLOCKED = 0xCED
- SYS_FREAD_UNLOCKED = 0xC7B
- SYS_FREEIFADDRS = 0xCE6
- SYS_FREOPEN64 = 0xD4B
- SYS_FREOPEN64_UNLOCKED = 0xD4C
- SYS_FREOPEN_UNLOCKED = 0xCFB
- SYS_FREXPD128 = 0xBCE
- SYS_FREXPD32 = 0xBCC
- SYS_FREXPD64 = 0xBCD
- SYS_FSCANF_UNLOCKED = 0xCAF
- SYS_FSEEK64 = 0xCEF
- SYS_FSEEK64_UNLOCKED = 0xCF5
- SYS_FSEEKO64 = 0xCF0
- SYS_FSEEKO64_UNLOCKED = 0xCF6
- SYS_FSEEKO_UNLOCKED = 0xCB1
- SYS_FSEEK_UNLOCKED = 0xCB0
- SYS_FSETPOS64 = 0xCF1
- SYS_FSETPOS64_UNLOCKED = 0xCF7
- SYS_FSETPOS_UNLOCKED = 0xCB3
- SYS_FTELL64 = 0xCF2
- SYS_FTELL64_UNLOCKED = 0xCF8
- SYS_FTELLO64 = 0xCF3
- SYS_FTELLO64_UNLOCKED = 0xCF9
- SYS_FTELLO_UNLOCKED = 0xCB5
- SYS_FTELL_UNLOCKED = 0xCB4
- SYS_FUPDATE = 0x0B5
- SYS_FUPDATE_UNLOCKED = 0xCB7
- SYS_FWIDE_UNLOCKED = 0xCB8
- SYS_FWPRINTF_UNLOCKED = 0xCB9
- SYS_FWRITE_UNLOCKED = 0xC7A
- SYS_FWSCANF_UNLOCKED = 0xCBA
- SYS_GETDATE64 = 0xD4F
- SYS_GETIFADDRS = 0xCE7
- SYS_GETIPV4SOURCEFILTER = 0xC77
- SYS_GETSOURCEFILTER = 0xC79
- SYS_GETSYNTX = 0x0FD
- SYS_GETS_UNLOCKED = 0xC7D
- SYS_GETTIMEOFDAY64 = 0xD50
- SYS_GETWCHAR_UNLOCKED = 0xCBC
- SYS_GETWC_UNLOCKED = 0xCBB
- SYS_GMTIME = 0x0B0
- SYS_GMTIME64 = 0xCDC
- SYS_GMTIME64_R = 0xCDD
- SYS_HYPOTD128 = 0xBD1
- SYS_HYPOTD32 = 0xBCF
- SYS_HYPOTD64 = 0xBD0
- SYS_ILOGBD128 = 0xBD4
- SYS_ILOGBD32 = 0xBD2
- SYS_ILOGBD64 = 0xBD3
- SYS_ILOGBF = 0xA7E
- SYS_ILOGBL = 0xA81
- SYS_INET6_IS_SRCADDR = 0xD5A
- SYS_ISBLANK = 0x0FE
- SYS_ISWALNUM = 0x0FF
- SYS_LDEXPD128 = 0xBD7
- SYS_LDEXPD32 = 0xBD5
- SYS_LDEXPD64 = 0xBD6
- SYS_LGAMMAD128 = 0xBDA
- SYS_LGAMMAD32 = 0xBD8
- SYS_LGAMMAD64 = 0xBD9
- SYS_LIO_LISTIO = 0xC6A
- SYS_LLRINT = 0xA84
- SYS_LLRINTD128 = 0xBDD
- SYS_LLRINTD32 = 0xBDB
- SYS_LLRINTD64 = 0xBDC
- SYS_LLRINTF = 0xA87
- SYS_LLRINTL = 0xA8A
- SYS_LLROUND = 0xA8D
- SYS_LLROUNDD128 = 0xBE0
- SYS_LLROUNDD32 = 0xBDE
- SYS_LLROUNDD64 = 0xBDF
- SYS_LLROUNDF = 0xA90
- SYS_LLROUNDL = 0xA93
- SYS_LOCALTIM = 0x0B1
- SYS_LOCALTIME = 0x0B1
- SYS_LOCALTIME64 = 0xCDE
- SYS_LOCALTIME64_R = 0xCDF
- SYS_LOG10D128 = 0xBE6
- SYS_LOG10D32 = 0xBE4
- SYS_LOG10D64 = 0xBE5
- SYS_LOG1PD128 = 0xBE9
- SYS_LOG1PD32 = 0xBE7
- SYS_LOG1PD64 = 0xBE8
- SYS_LOG2D128 = 0xBEC
- SYS_LOG2D32 = 0xBEA
- SYS_LOG2D64 = 0xBEB
- SYS_LOGBD128 = 0xBEF
- SYS_LOGBD32 = 0xBED
- SYS_LOGBD64 = 0xBEE
- SYS_LOGBF = 0xA96
- SYS_LOGBL = 0xA99
- SYS_LOGD128 = 0xBE3
- SYS_LOGD32 = 0xBE1
- SYS_LOGD64 = 0xBE2
- SYS_LRINT = 0xA9C
- SYS_LRINTD128 = 0xBF2
- SYS_LRINTD32 = 0xBF0
- SYS_LRINTD64 = 0xBF1
- SYS_LRINTF = 0xA9F
- SYS_LRINTL = 0xAA2
- SYS_LROUNDD128 = 0xBF5
- SYS_LROUNDD32 = 0xBF3
- SYS_LROUNDD64 = 0xBF4
- SYS_LROUNDL = 0xAA5
- SYS_MBLEN = 0x0AF
- SYS_MBRTOC16 = 0xD42
- SYS_MBRTOC32 = 0xD43
- SYS_MEMSET = 0x0A3
- SYS_MKTIME = 0x0AC
- SYS_MKTIME64 = 0xCE0
- SYS_MODFD128 = 0xBF8
- SYS_MODFD32 = 0xBF6
- SYS_MODFD64 = 0xBF7
- SYS_NAN = 0xAA8
- SYS_NAND128 = 0xBFB
- SYS_NAND32 = 0xBF9
- SYS_NAND64 = 0xBFA
- SYS_NANF = 0xAAA
- SYS_NANL = 0xAAC
- SYS_NEARBYINT = 0xAAE
- SYS_NEARBYINTD128 = 0xBFE
- SYS_NEARBYINTD32 = 0xBFC
- SYS_NEARBYINTD64 = 0xBFD
- SYS_NEARBYINTF = 0xAB1
- SYS_NEARBYINTL = 0xAB4
- SYS_NEXTAFTERD128 = 0xC01
- SYS_NEXTAFTERD32 = 0xBFF
- SYS_NEXTAFTERD64 = 0xC00
- SYS_NEXTAFTERF = 0xAB7
- SYS_NEXTAFTERL = 0xABA
- SYS_NEXTTOWARD = 0xABD
- SYS_NEXTTOWARDD128 = 0xC04
- SYS_NEXTTOWARDD32 = 0xC02
- SYS_NEXTTOWARDD64 = 0xC03
- SYS_NEXTTOWARDF = 0xAC0
- SYS_NEXTTOWARDL = 0xAC3
- SYS_NL_LANGINFO = 0x0FC
- SYS_PERROR_UNLOCKED = 0xCBD
- SYS_POSIX_FALLOCATE = 0xCE8
- SYS_POSIX_MEMALIGN = 0xCE9
- SYS_POSIX_OPENPT = 0xC66
- SYS_POWD128 = 0xC07
- SYS_POWD32 = 0xC05
- SYS_POWD64 = 0xC06
- SYS_PRINTF_UNLOCKED = 0xCBE
- SYS_PSELECT = 0xC67
- SYS_PTHREAD_ATTR_GETSTACK = 0xB3E
- SYS_PTHREAD_ATTR_SETSTACK = 0xB3F
- SYS_PTHREAD_SECURITY_APPLID_NP = 0xCE4
- SYS_PUTS_UNLOCKED = 0xC7F
- SYS_PUTWCHAR_UNLOCKED = 0xCC0
- SYS_PUTWC_UNLOCKED = 0xCBF
- SYS_QUANTEXPD128 = 0xD46
- SYS_QUANTEXPD32 = 0xD44
- SYS_QUANTEXPD64 = 0xD45
- SYS_QUANTIZED128 = 0xC0A
- SYS_QUANTIZED32 = 0xC08
- SYS_QUANTIZED64 = 0xC09
- SYS_REMAINDERD128 = 0xC0D
- SYS_REMAINDERD32 = 0xC0B
- SYS_REMAINDERD64 = 0xC0C
- SYS_RESIZE_ALLOC = 0xCEB
- SYS_REWIND_UNLOCKED = 0xCC1
- SYS_RINTD128 = 0xC13
- SYS_RINTD32 = 0xC11
- SYS_RINTD64 = 0xC12
- SYS_RINTF = 0xACB
- SYS_RINTL = 0xACD
- SYS_ROUND = 0xACF
- SYS_ROUNDD128 = 0xC16
- SYS_ROUNDD32 = 0xC14
- SYS_ROUNDD64 = 0xC15
- SYS_ROUNDF = 0xAD2
- SYS_ROUNDL = 0xAD5
- SYS_SAMEQUANTUMD128 = 0xC19
- SYS_SAMEQUANTUMD32 = 0xC17
- SYS_SAMEQUANTUMD64 = 0xC18
- SYS_SCALBLN = 0xAD8
- SYS_SCALBLND128 = 0xC1C
- SYS_SCALBLND32 = 0xC1A
- SYS_SCALBLND64 = 0xC1B
- SYS_SCALBLNF = 0xADB
- SYS_SCALBLNL = 0xADE
- SYS_SCALBND128 = 0xC1F
- SYS_SCALBND32 = 0xC1D
- SYS_SCALBND64 = 0xC1E
- SYS_SCALBNF = 0xAE3
- SYS_SCALBNL = 0xAE6
- SYS_SCANF_UNLOCKED = 0xCC2
- SYS_SCHED_YIELD = 0xB32
- SYS_SETENV = 0x0C8
- SYS_SETIPV4SOURCEFILTER = 0xC76
- SYS_SETSOURCEFILTER = 0xC78
- SYS_SHM_OPEN = 0xC8C
- SYS_SHM_UNLINK = 0xC8D
- SYS_SIND128 = 0xC22
- SYS_SIND32 = 0xC20
- SYS_SIND64 = 0xC21
- SYS_SINHD128 = 0xC25
- SYS_SINHD32 = 0xC23
- SYS_SINHD64 = 0xC24
- SYS_SIZEOF_ALLOC = 0xCEA
- SYS_SOCKATMARK = 0xC68
- SYS_SQRTD128 = 0xC28
- SYS_SQRTD32 = 0xC26
- SYS_SQRTD64 = 0xC27
- SYS_STRCHR = 0x0A0
- SYS_STRCSPN = 0x0A1
- SYS_STRERROR = 0x0A8
- SYS_STRERROR_R = 0xB33
- SYS_STRFTIME = 0x0B2
- SYS_STRLEN = 0x0A9
- SYS_STRPBRK = 0x0A2
- SYS_STRSPN = 0x0A4
- SYS_STRSTR = 0x0A5
- SYS_STRTOD128 = 0xC2B
- SYS_STRTOD32 = 0xC29
- SYS_STRTOD64 = 0xC2A
- SYS_STRTOK = 0x0A6
- SYS_TAND128 = 0xC2E
- SYS_TAND32 = 0xC2C
- SYS_TAND64 = 0xC2D
- SYS_TANHD128 = 0xC31
- SYS_TANHD32 = 0xC2F
- SYS_TANHD64 = 0xC30
- SYS_TGAMMAD128 = 0xC34
- SYS_TGAMMAD32 = 0xC32
- SYS_TGAMMAD64 = 0xC33
- SYS_TIME = 0x0AD
- SYS_TIME64 = 0xCE1
- SYS_TMPFILE64 = 0xD4D
- SYS_TMPFILE64_UNLOCKED = 0xD4E
- SYS_TMPFILE_UNLOCKED = 0xCFD
- SYS_TRUNCD128 = 0xC40
- SYS_TRUNCD32 = 0xC3E
- SYS_TRUNCD64 = 0xC3F
- SYS_UNGETC_UNLOCKED = 0xCC3
- SYS_UNGETWC_UNLOCKED = 0xCC4
- SYS_UNSETENV = 0xB34
- SYS_VFPRINTF_UNLOCKED = 0xCC5
- SYS_VFSCANF_UNLOCKED = 0xCC7
- SYS_VFWPRINTF_UNLOCKED = 0xCC9
- SYS_VFWSCANF_UNLOCKED = 0xCCB
- SYS_VPRINTF_UNLOCKED = 0xCCD
- SYS_VSCANF_UNLOCKED = 0xCCF
- SYS_VWPRINTF_UNLOCKED = 0xCD1
- SYS_VWSCANF_UNLOCKED = 0xCD3
- SYS_WCSTOD128 = 0xC43
- SYS_WCSTOD32 = 0xC41
- SYS_WCSTOD64 = 0xC42
- SYS_WPRINTF_UNLOCKED = 0xCD5
- SYS_WSCANF_UNLOCKED = 0xCD6
- SYS__FLUSHLBF = 0xD68
- SYS__FLUSHLBF_UNLOCKED = 0xD6F
- SYS___ACOSHF_H = 0xA54
- SYS___ACOSHL_H = 0xA55
- SYS___ASINHF_H = 0xA56
- SYS___ASINHL_H = 0xA57
- SYS___ATANPID128 = 0xC6D
- SYS___ATANPID32 = 0xC6B
- SYS___ATANPID64 = 0xC6C
- SYS___CBRTF_H = 0xA58
- SYS___CBRTL_H = 0xA59
- SYS___CDUMP = 0x0C4
- SYS___CLASS = 0xAFA
- SYS___CLASS2 = 0xB99
- SYS___CLASS2D128 = 0xC99
- SYS___CLASS2D32 = 0xC97
- SYS___CLASS2D64 = 0xC98
- SYS___CLASS2F = 0xC91
- SYS___CLASS2F_B = 0xC93
- SYS___CLASS2F_H = 0xC94
- SYS___CLASS2L = 0xC92
- SYS___CLASS2L_B = 0xC95
- SYS___CLASS2L_H = 0xC96
- SYS___CLASS2_B = 0xB9A
- SYS___CLASS2_H = 0xB9B
- SYS___CLASS_B = 0xAFB
- SYS___CLASS_H = 0xAFC
- SYS___CLOGL_B = 0xA01
- SYS___CLOGL_H = 0xA02
- SYS___CLRENV = 0x0C9
- SYS___CLRMF = 0x0BD
- SYS___CODEPAGE_INFO = 0xC64
- SYS___CONJF_B = 0xA07
- SYS___CONJF_H = 0xA08
- SYS___CONJL_B = 0xA0A
- SYS___CONJL_H = 0xA0B
- SYS___CONJ_B = 0xA04
- SYS___CONJ_H = 0xA05
- SYS___COPYSIGN_B = 0xA5A
- SYS___COPYSIGN_H = 0xAF5
- SYS___COSPID128 = 0xC70
- SYS___COSPID32 = 0xC6E
- SYS___COSPID64 = 0xC6F
- SYS___CPOWF_B = 0xA10
- SYS___CPOWF_H = 0xA11
- SYS___CPOWL_B = 0xA13
- SYS___CPOWL_H = 0xA14
- SYS___CPOW_B = 0xA0D
- SYS___CPOW_H = 0xA0E
- SYS___CPROJF_B = 0xA19
- SYS___CPROJF_H = 0xA1A
- SYS___CPROJL_B = 0xA1C
- SYS___CPROJL_H = 0xA1D
- SYS___CPROJ_B = 0xA16
- SYS___CPROJ_H = 0xA17
- SYS___CREALF_B = 0xA22
- SYS___CREALF_H = 0xA23
- SYS___CREALL_B = 0xA25
- SYS___CREALL_H = 0xA26
- SYS___CREAL_B = 0xA1F
- SYS___CREAL_H = 0xA20
- SYS___CSINF_B = 0xA2B
- SYS___CSINF_H = 0xA2C
- SYS___CSINHF_B = 0xA34
- SYS___CSINHF_H = 0xA35
- SYS___CSINHL_B = 0xA37
- SYS___CSINHL_H = 0xA38
- SYS___CSINH_B = 0xA31
- SYS___CSINH_H = 0xA32
- SYS___CSINL_B = 0xA2E
- SYS___CSINL_H = 0xA2F
- SYS___CSIN_B = 0xA28
- SYS___CSIN_H = 0xA29
- SYS___CSNAP = 0x0C5
- SYS___CSQRTF_B = 0xA3D
- SYS___CSQRTF_H = 0xA3E
- SYS___CSQRTL_B = 0xA40
- SYS___CSQRTL_H = 0xA41
- SYS___CSQRT_B = 0xA3A
- SYS___CSQRT_H = 0xA3B
- SYS___CTANF_B = 0xA46
- SYS___CTANF_H = 0xA47
- SYS___CTANHF_B = 0xA4F
- SYS___CTANHF_H = 0xA50
- SYS___CTANHL_B = 0xA52
- SYS___CTANHL_H = 0xA53
- SYS___CTANH_B = 0xA4C
- SYS___CTANH_H = 0xA4D
- SYS___CTANL_B = 0xA49
- SYS___CTANL_H = 0xA4A
- SYS___CTAN_B = 0xA43
- SYS___CTAN_H = 0xA44
- SYS___CTEST = 0x0C7
- SYS___CTRACE = 0x0C6
- SYS___D1TOP = 0xC9B
- SYS___D2TOP = 0xC9C
- SYS___D4TOP = 0xC9D
- SYS___DYNALL = 0x0C3
- SYS___DYNFRE = 0x0C2
- SYS___EXP2F_H = 0xA5E
- SYS___EXP2L_H = 0xA5F
- SYS___EXP2_H = 0xA5D
- SYS___EXPM1F_H = 0xA5B
- SYS___EXPM1L_H = 0xA5C
- SYS___FBUFSIZE = 0xD60
- SYS___FLBF = 0xD62
- SYS___FLDATA = 0x0C1
- SYS___FMAF_B = 0xA67
- SYS___FMAF_H = 0xA68
- SYS___FMAL_B = 0xA6A
- SYS___FMAL_H = 0xA6B
- SYS___FMAXF_B = 0xA70
- SYS___FMAXF_H = 0xA71
- SYS___FMAXL_B = 0xA73
- SYS___FMAXL_H = 0xA74
- SYS___FMAX_B = 0xA6D
- SYS___FMAX_H = 0xA6E
- SYS___FMA_B = 0xA64
- SYS___FMA_H = 0xA65
- SYS___FMINF_B = 0xA79
- SYS___FMINF_H = 0xA7A
- SYS___FMINL_B = 0xA7C
- SYS___FMINL_H = 0xA7D
- SYS___FMIN_B = 0xA76
- SYS___FMIN_H = 0xA77
- SYS___FPENDING = 0xD61
- SYS___FPENDING_UNLOCKED = 0xD6C
- SYS___FPURGE = 0xD69
- SYS___FPURGE_UNLOCKED = 0xD70
- SYS___FP_CAST_D = 0xBCB
- SYS___FREADABLE = 0xD63
- SYS___FREADAHEAD = 0xD6A
- SYS___FREADAHEAD_UNLOCKED = 0xD71
- SYS___FREADING = 0xD65
- SYS___FREADING_UNLOCKED = 0xD6D
- SYS___FSEEK2 = 0xB3C
- SYS___FSETERR = 0xD6B
- SYS___FSETLOCKING = 0xD67
- SYS___FTCHEP = 0x0BF
- SYS___FTELL2 = 0xB3B
- SYS___FUPDT = 0x0B5
- SYS___FWRITABLE = 0xD64
- SYS___FWRITING = 0xD66
- SYS___FWRITING_UNLOCKED = 0xD6E
- SYS___GETCB = 0x0B4
- SYS___GETGRGID1 = 0xD5B
- SYS___GETGRNAM1 = 0xD5C
- SYS___GETTHENT = 0xCE5
- SYS___GETTOD = 0xD3E
- SYS___HYPOTF_H = 0xAF6
- SYS___HYPOTL_H = 0xAF7
- SYS___ILOGBF_B = 0xA7F
- SYS___ILOGBF_H = 0xA80
- SYS___ILOGBL_B = 0xA82
- SYS___ILOGBL_H = 0xA83
- SYS___ISBLANK_A = 0xB2E
- SYS___ISBLNK = 0x0FE
- SYS___ISWBLANK_A = 0xB2F
- SYS___LE_CEEGTJS = 0xD72
- SYS___LE_TRACEBACK = 0xB7A
- SYS___LGAMMAL_H = 0xA62
- SYS___LGAMMA_B_C99 = 0xB39
- SYS___LGAMMA_H_C99 = 0xB38
- SYS___LGAMMA_R_C99 = 0xB3A
- SYS___LLRINTF_B = 0xA88
- SYS___LLRINTF_H = 0xA89
- SYS___LLRINTL_B = 0xA8B
- SYS___LLRINTL_H = 0xA8C
- SYS___LLRINT_B = 0xA85
- SYS___LLRINT_H = 0xA86
- SYS___LLROUNDF_B = 0xA91
- SYS___LLROUNDF_H = 0xA92
- SYS___LLROUNDL_B = 0xA94
- SYS___LLROUNDL_H = 0xA95
- SYS___LLROUND_B = 0xA8E
- SYS___LLROUND_H = 0xA8F
- SYS___LOCALE_CTL = 0xD47
- SYS___LOG1PF_H = 0xA60
- SYS___LOG1PL_H = 0xA61
- SYS___LOGBF_B = 0xA97
- SYS___LOGBF_H = 0xA98
- SYS___LOGBL_B = 0xA9A
- SYS___LOGBL_H = 0xA9B
- SYS___LOGIN_APPLID = 0xCE2
- SYS___LRINTF_B = 0xAA0
- SYS___LRINTF_H = 0xAA1
- SYS___LRINTL_B = 0xAA3
- SYS___LRINTL_H = 0xAA4
- SYS___LRINT_B = 0xA9D
- SYS___LRINT_H = 0xA9E
- SYS___LROUNDF_FIXUP = 0xB31
- SYS___LROUNDL_B = 0xAA6
- SYS___LROUNDL_H = 0xAA7
- SYS___LROUND_FIXUP = 0xB30
- SYS___MOSERVICES = 0xD3D
- SYS___MUST_STAY_CLEAN = 0xB7C
- SYS___NANF_B = 0xAAB
- SYS___NANL_B = 0xAAD
- SYS___NAN_B = 0xAA9
- SYS___NEARBYINTF_B = 0xAB2
- SYS___NEARBYINTF_H = 0xAB3
- SYS___NEARBYINTL_B = 0xAB5
- SYS___NEARBYINTL_H = 0xAB6
- SYS___NEARBYINT_B = 0xAAF
- SYS___NEARBYINT_H = 0xAB0
- SYS___NEXTAFTERF_B = 0xAB8
- SYS___NEXTAFTERF_H = 0xAB9
- SYS___NEXTAFTERL_B = 0xABB
- SYS___NEXTAFTERL_H = 0xABC
- SYS___NEXTTOWARDF_B = 0xAC1
- SYS___NEXTTOWARDF_H = 0xAC2
- SYS___NEXTTOWARDL_B = 0xAC4
- SYS___NEXTTOWARDL_H = 0xAC5
- SYS___NEXTTOWARD_B = 0xABE
- SYS___NEXTTOWARD_H = 0xABF
- SYS___O_ENV = 0xB7D
- SYS___PASSWD_APPLID = 0xCE3
- SYS___PTOD1 = 0xC9E
- SYS___PTOD2 = 0xC9F
- SYS___PTOD4 = 0xCA0
- SYS___REGCOMP_STD = 0x0EA
- SYS___REMAINDERF_H = 0xAC6
- SYS___REMAINDERL_H = 0xAC7
- SYS___REMQUOD128 = 0xC10
- SYS___REMQUOD32 = 0xC0E
- SYS___REMQUOD64 = 0xC0F
- SYS___REMQUOF_H = 0xAC9
- SYS___REMQUOL_H = 0xACA
- SYS___REMQUO_H = 0xAC8
- SYS___RINTF_B = 0xACC
- SYS___RINTL_B = 0xACE
- SYS___ROUNDF_B = 0xAD3
- SYS___ROUNDF_H = 0xAD4
- SYS___ROUNDL_B = 0xAD6
- SYS___ROUNDL_H = 0xAD7
- SYS___ROUND_B = 0xAD0
- SYS___ROUND_H = 0xAD1
- SYS___SCALBLNF_B = 0xADC
- SYS___SCALBLNF_H = 0xADD
- SYS___SCALBLNL_B = 0xADF
- SYS___SCALBLNL_H = 0xAE0
- SYS___SCALBLN_B = 0xAD9
- SYS___SCALBLN_H = 0xADA
- SYS___SCALBNF_B = 0xAE4
- SYS___SCALBNF_H = 0xAE5
- SYS___SCALBNL_B = 0xAE7
- SYS___SCALBNL_H = 0xAE8
- SYS___SCALBN_B = 0xAE1
- SYS___SCALBN_H = 0xAE2
- SYS___SETENV = 0x0C8
- SYS___SINPID128 = 0xC73
- SYS___SINPID32 = 0xC71
- SYS___SINPID64 = 0xC72
- SYS___SMF_RECORD2 = 0xD48
- SYS___STATIC_REINIT = 0xB3D
- SYS___TGAMMAF_H_C99 = 0xB79
- SYS___TGAMMAL_H = 0xAE9
- SYS___TGAMMA_H_C99 = 0xB78
- SYS___TOCSNAME2 = 0xC9A
- SYS_CEIL = 0x01F
- SYS_CHAUDIT = 0x1E0
- SYS_EXP = 0x01A
- SYS_FCHAUDIT = 0x1E1
- SYS_FREXP = 0x01D
- SYS_GETGROUPSBYNAME = 0x1E2
- SYS_GETPWUID = 0x1A0
- SYS_GETUID = 0x1A1
- SYS_ISATTY = 0x1A3
- SYS_KILL = 0x1A4
- SYS_LDEXP = 0x01E
- SYS_LINK = 0x1A5
- SYS_LOG10 = 0x01C
- SYS_LSEEK = 0x1A6
- SYS_LSTAT = 0x1A7
- SYS_MKDIR = 0x1A8
- SYS_MKFIFO = 0x1A9
- SYS_MKNOD = 0x1AA
- SYS_MODF = 0x01B
- SYS_MOUNT = 0x1AB
- SYS_OPEN = 0x1AC
- SYS_OPENDIR = 0x1AD
- SYS_PATHCONF = 0x1AE
- SYS_PAUSE = 0x1AF
- SYS_PIPE = 0x1B0
- SYS_PTHREAD_ATTR_DESTROY = 0x1E7
- SYS_PTHREAD_ATTR_GETDETACHSTATE = 0x1EB
- SYS_PTHREAD_ATTR_GETSTACKSIZE = 0x1E9
- SYS_PTHREAD_ATTR_GETWEIGHT_NP = 0x1ED
- SYS_PTHREAD_ATTR_INIT = 0x1E6
- SYS_PTHREAD_ATTR_SETDETACHSTATE = 0x1EA
- SYS_PTHREAD_ATTR_SETSTACKSIZE = 0x1E8
- SYS_PTHREAD_ATTR_SETWEIGHT_NP = 0x1EC
- SYS_PTHREAD_CANCEL = 0x1EE
- SYS_PTHREAD_CLEANUP_POP = 0x1F0
- SYS_PTHREAD_CLEANUP_PUSH = 0x1EF
- SYS_PTHREAD_CONDATTR_DESTROY = 0x1F2
- SYS_PTHREAD_CONDATTR_INIT = 0x1F1
- SYS_PTHREAD_COND_BROADCAST = 0x1F6
- SYS_PTHREAD_COND_DESTROY = 0x1F4
- SYS_PTHREAD_COND_INIT = 0x1F3
- SYS_PTHREAD_COND_SIGNAL = 0x1F5
- SYS_PTHREAD_COND_TIMEDWAIT = 0x1F8
- SYS_PTHREAD_COND_WAIT = 0x1F7
- SYS_PTHREAD_CREATE = 0x1F9
- SYS_PTHREAD_DETACH = 0x1FA
- SYS_PTHREAD_EQUAL = 0x1FB
- SYS_PTHREAD_EXIT = 0x1E4
- SYS_PTHREAD_GETSPECIFIC = 0x1FC
- SYS_PTHREAD_JOIN = 0x1FD
- SYS_PTHREAD_KEY_CREATE = 0x1FE
- SYS_PTHREAD_KILL = 0x1E5
- SYS_PTHREAD_MUTEXATTR_INIT = 0x1FF
- SYS_READ = 0x1B2
- SYS_READDIR = 0x1B3
- SYS_READLINK = 0x1B4
- SYS_REWINDDIR = 0x1B5
- SYS_RMDIR = 0x1B6
- SYS_SETEGID = 0x1B7
- SYS_SETEUID = 0x1B8
- SYS_SETGID = 0x1B9
- SYS_SETPGID = 0x1BA
- SYS_SETSID = 0x1BB
- SYS_SETUID = 0x1BC
- SYS_SIGACTION = 0x1BD
- SYS_SIGADDSET = 0x1BE
- SYS_SIGDELSET = 0x1BF
- SYS_SIGEMPTYSET = 0x1C0
- SYS_SIGFILLSET = 0x1C1
- SYS_SIGISMEMBER = 0x1C2
- SYS_SIGLONGJMP = 0x1C3
- SYS_SIGPENDING = 0x1C4
- SYS_SIGPROCMASK = 0x1C5
- SYS_SIGSETJMP = 0x1C6
- SYS_SIGSUSPEND = 0x1C7
- SYS_SIGWAIT = 0x1E3
- SYS_SLEEP = 0x1C8
- SYS_STAT = 0x1C9
- SYS_SYMLINK = 0x1CB
- SYS_SYSCONF = 0x1CC
- SYS_TCDRAIN = 0x1CD
- SYS_TCFLOW = 0x1CE
- SYS_TCFLUSH = 0x1CF
- SYS_TCGETATTR = 0x1D0
- SYS_TCGETPGRP = 0x1D1
- SYS_TCSENDBREAK = 0x1D2
- SYS_TCSETATTR = 0x1D3
- SYS_TCSETPGRP = 0x1D4
- SYS_TIMES = 0x1D5
- SYS_TTYNAME = 0x1D6
- SYS_TZSET = 0x1D7
- SYS_UMASK = 0x1D8
- SYS_UMOUNT = 0x1D9
- SYS_UNAME = 0x1DA
- SYS_UNLINK = 0x1DB
- SYS_UTIME = 0x1DC
- SYS_WAIT = 0x1DD
- SYS_WAITPID = 0x1DE
- SYS_WRITE = 0x1DF
- SYS_W_GETPSENT = 0x1B1
- SYS_W_IOCTL = 0x1A2
- SYS_W_STATFS = 0x1CA
- SYS_A64L = 0x2EF
- SYS_BCMP = 0x2B9
- SYS_BCOPY = 0x2BA
- SYS_BZERO = 0x2BB
- SYS_CATCLOSE = 0x2B6
- SYS_CATGETS = 0x2B7
- SYS_CATOPEN = 0x2B8
- SYS_CRYPT = 0x2AC
- SYS_DBM_CLEARERR = 0x2F7
- SYS_DBM_CLOSE = 0x2F8
- SYS_DBM_DELETE = 0x2F9
- SYS_DBM_ERROR = 0x2FA
- SYS_DBM_FETCH = 0x2FB
- SYS_DBM_FIRSTKEY = 0x2FC
- SYS_DBM_NEXTKEY = 0x2FD
- SYS_DBM_OPEN = 0x2FE
- SYS_DBM_STORE = 0x2FF
- SYS_DRAND48 = 0x2B2
- SYS_ENCRYPT = 0x2AD
- SYS_ENDUTXENT = 0x2E1
- SYS_ERAND48 = 0x2B3
- SYS_ERF = 0x02C
- SYS_ERFC = 0x02D
- SYS_FCHDIR = 0x2D9
- SYS_FFS = 0x2BC
- SYS_FMTMSG = 0x2E5
- SYS_FSTATVFS = 0x2B4
- SYS_FTIME = 0x2F5
- SYS_GAMMA = 0x02E
- SYS_GETDATE = 0x2A6
- SYS_GETPAGESIZE = 0x2D8
- SYS_GETTIMEOFDAY = 0x2F6
- SYS_GETUTXENT = 0x2E0
- SYS_GETUTXID = 0x2E2
- SYS_GETUTXLINE = 0x2E3
- SYS_HCREATE = 0x2C6
- SYS_HDESTROY = 0x2C7
- SYS_HSEARCH = 0x2C8
- SYS_HYPOT = 0x02B
- SYS_INDEX = 0x2BD
- SYS_INITSTATE = 0x2C2
- SYS_INSQUE = 0x2CF
- SYS_ISASCII = 0x2ED
- SYS_JRAND48 = 0x2E6
- SYS_L64A = 0x2F0
- SYS_LCONG48 = 0x2EA
- SYS_LFIND = 0x2C9
- SYS_LRAND48 = 0x2E7
- SYS_LSEARCH = 0x2CA
- SYS_MEMCCPY = 0x2D4
- SYS_MRAND48 = 0x2E8
- SYS_NRAND48 = 0x2E9
- SYS_PCLOSE = 0x2D2
- SYS_POPEN = 0x2D1
- SYS_PUTUTXLINE = 0x2E4
- SYS_RANDOM = 0x2C4
- SYS_REMQUE = 0x2D0
- SYS_RINDEX = 0x2BE
- SYS_SEED48 = 0x2EC
- SYS_SETKEY = 0x2AE
- SYS_SETSTATE = 0x2C3
- SYS_SETUTXENT = 0x2DF
- SYS_SRAND48 = 0x2EB
- SYS_SRANDOM = 0x2C5
- SYS_STATVFS = 0x2B5
- SYS_STRCASECMP = 0x2BF
- SYS_STRDUP = 0x2C0
- SYS_STRNCASECMP = 0x2C1
- SYS_SWAB = 0x2D3
- SYS_TDELETE = 0x2CB
- SYS_TFIND = 0x2CC
- SYS_TOASCII = 0x2EE
- SYS_TSEARCH = 0x2CD
- SYS_TWALK = 0x2CE
- SYS_UALARM = 0x2F1
- SYS_USLEEP = 0x2F2
- SYS_WAIT3 = 0x2A7
- SYS_WAITID = 0x2A8
- SYS_Y1 = 0x02A
- SYS___ATOE = 0x2DB
- SYS___ATOE_L = 0x2DC
- SYS___CATTRM = 0x2A9
- SYS___CNVBLK = 0x2AF
- SYS___CRYTRM = 0x2B0
- SYS___DLGHT = 0x2A1
- SYS___ECRTRM = 0x2B1
- SYS___ETOA = 0x2DD
- SYS___ETOA_L = 0x2DE
- SYS___GDTRM = 0x2AA
- SYS___OCLCK = 0x2DA
- SYS___OPARGF = 0x2A2
- SYS___OPERRF = 0x2A5
- SYS___OPINDF = 0x2A4
- SYS___OPOPTF = 0x2A3
- SYS___RNDTRM = 0x2AB
- SYS___SRCTRM = 0x2F4
- SYS___TZONE = 0x2A0
- SYS___UTXTRM = 0x2F3
- SYS_ASIN = 0x03E
- SYS_ISXDIGIT = 0x03B
- SYS_SETLOCAL = 0x03A
- SYS_SETLOCALE = 0x03A
- SYS_SIN = 0x03F
- SYS_TOLOWER = 0x03C
- SYS_TOUPPER = 0x03D
- SYS_ACCEPT_AND_RECV = 0x4F7
- SYS_ATOL = 0x04E
- SYS_CHECKSCH = 0x4BC
- SYS_CHECKSCHENV = 0x4BC
- SYS_CLEARERR = 0x04C
- SYS_CONNECTS = 0x4B5
- SYS_CONNECTSERVER = 0x4B5
- SYS_CONNECTW = 0x4B4
- SYS_CONNECTWORKMGR = 0x4B4
- SYS_CONTINUE = 0x4B3
- SYS_CONTINUEWORKUNIT = 0x4B3
- SYS_COPYSIGN = 0x4C2
- SYS_CREATEWO = 0x4B2
- SYS_CREATEWORKUNIT = 0x4B2
- SYS_DELETEWO = 0x4B9
- SYS_DELETEWORKUNIT = 0x4B9
- SYS_DISCONNE = 0x4B6
- SYS_DISCONNECTSERVER = 0x4B6
- SYS_FEOF = 0x04D
- SYS_FERROR = 0x04A
- SYS_FINITE = 0x4C8
- SYS_GAMMA_R = 0x4E2
- SYS_JOINWORK = 0x4B7
- SYS_JOINWORKUNIT = 0x4B7
- SYS_LEAVEWOR = 0x4B8
- SYS_LEAVEWORKUNIT = 0x4B8
- SYS_LGAMMA_R = 0x4EB
- SYS_MATHERR = 0x4D0
- SYS_PERROR = 0x04F
- SYS_QUERYMET = 0x4BA
- SYS_QUERYMETRICS = 0x4BA
- SYS_QUERYSCH = 0x4BB
- SYS_QUERYSCHENV = 0x4BB
- SYS_REWIND = 0x04B
- SYS_SCALBN = 0x4D4
- SYS_SIGNIFIC = 0x4D5
- SYS_SIGNIFICAND = 0x4D5
- SYS___ACOSH_B = 0x4DA
- SYS___ACOS_B = 0x4D9
- SYS___ASINH_B = 0x4BE
- SYS___ASIN_B = 0x4DB
- SYS___ATAN2_B = 0x4DC
- SYS___ATANH_B = 0x4DD
- SYS___ATAN_B = 0x4BF
- SYS___CBRT_B = 0x4C0
- SYS___CEIL_B = 0x4C1
- SYS___COSH_B = 0x4DE
- SYS___COS_B = 0x4C3
- SYS___DGHT = 0x4A8
- SYS___ENVN = 0x4B0
- SYS___ERFC_B = 0x4C5
- SYS___ERF_B = 0x4C4
- SYS___EXPM1_B = 0x4C6
- SYS___EXP_B = 0x4DF
- SYS___FABS_B = 0x4C7
- SYS___FLOOR_B = 0x4C9
- SYS___FMOD_B = 0x4E0
- SYS___FP_SETMODE = 0x4F8
- SYS___FREXP_B = 0x4CA
- SYS___GAMMA_B = 0x4E1
- SYS___GDRR = 0x4A1
- SYS___HRRNO = 0x4A2
- SYS___HYPOT_B = 0x4E3
- SYS___ILOGB_B = 0x4CB
- SYS___ISNAN_B = 0x4CC
- SYS___J0_B = 0x4E4
- SYS___J1_B = 0x4E6
- SYS___JN_B = 0x4E8
- SYS___LDEXP_B = 0x4CD
- SYS___LGAMMA_B = 0x4EA
- SYS___LOG10_B = 0x4ED
- SYS___LOG1P_B = 0x4CE
- SYS___LOGB_B = 0x4CF
- SYS___LOGIN = 0x4F5
- SYS___LOG_B = 0x4EC
- SYS___MLOCKALL = 0x4B1
- SYS___MODF_B = 0x4D1
- SYS___NEXTAFTER_B = 0x4D2
- SYS___OPENDIR2 = 0x4F3
- SYS___OPEN_STAT = 0x4F6
- SYS___OPND = 0x4A5
- SYS___OPPT = 0x4A6
- SYS___OPRG = 0x4A3
- SYS___OPRR = 0x4A4
- SYS___PID_AFFINITY = 0x4BD
- SYS___POW_B = 0x4EE
- SYS___READDIR2 = 0x4F4
- SYS___REMAINDER_B = 0x4EF
- SYS___RINT_B = 0x4D3
- SYS___SCALB_B = 0x4F0
- SYS___SIGACTIONSET = 0x4FB
- SYS___SIGGM = 0x4A7
- SYS___SINH_B = 0x4F1
- SYS___SIN_B = 0x4D6
- SYS___SQRT_B = 0x4F2
- SYS___TANH_B = 0x4D8
- SYS___TAN_B = 0x4D7
- SYS___TRRNO = 0x4AF
- SYS___TZNE = 0x4A9
- SYS___TZZN = 0x4AA
- SYS___UCREATE = 0x4FC
- SYS___UFREE = 0x4FE
- SYS___UHEAPREPORT = 0x4FF
- SYS___UMALLOC = 0x4FD
- SYS___Y0_B = 0x4E5
- SYS___Y1_B = 0x4E7
- SYS___YN_B = 0x4E9
- SYS_ABORT = 0x05C
- SYS_ASCTIME_R = 0x5E0
- SYS_ATEXIT = 0x05D
- SYS_CONNECTE = 0x5AE
- SYS_CONNECTEXPORTIMPORT = 0x5AE
- SYS_CTIME_R = 0x5E1
- SYS_DN_COMP = 0x5DF
- SYS_DN_EXPAND = 0x5DD
- SYS_DN_SKIPNAME = 0x5DE
- SYS_EXIT = 0x05A
- SYS_EXPORTWO = 0x5A1
- SYS_EXPORTWORKUNIT = 0x5A1
- SYS_EXTRACTW = 0x5A5
- SYS_EXTRACTWORKUNIT = 0x5A5
- SYS_FSEEKO = 0x5C9
- SYS_FTELLO = 0x5C8
- SYS_GETGRGID_R = 0x5E7
- SYS_GETGRNAM_R = 0x5E8
- SYS_GETLOGIN_R = 0x5E9
- SYS_GETPWNAM_R = 0x5EA
- SYS_GETPWUID_R = 0x5EB
- SYS_GMTIME_R = 0x5E2
- SYS_IMPORTWO = 0x5A3
- SYS_IMPORTWORKUNIT = 0x5A3
- SYS_INET_NTOP = 0x5D3
- SYS_INET_PTON = 0x5D4
- SYS_LLABS = 0x5CE
- SYS_LLDIV = 0x5CB
- SYS_LOCALTIME_R = 0x5E3
- SYS_PTHREAD_ATFORK = 0x5ED
- SYS_PTHREAD_ATTR_GETDETACHSTATE_U98 = 0x5FB
- SYS_PTHREAD_ATTR_GETGUARDSIZE = 0x5EE
- SYS_PTHREAD_ATTR_GETSCHEDPARAM = 0x5F9
- SYS_PTHREAD_ATTR_GETSTACKADDR = 0x5EF
- SYS_PTHREAD_ATTR_SETDETACHSTATE_U98 = 0x5FC
- SYS_PTHREAD_ATTR_SETGUARDSIZE = 0x5F0
- SYS_PTHREAD_ATTR_SETSCHEDPARAM = 0x5FA
- SYS_PTHREAD_ATTR_SETSTACKADDR = 0x5F1
- SYS_PTHREAD_CONDATTR_GETPSHARED = 0x5F2
- SYS_PTHREAD_CONDATTR_SETPSHARED = 0x5F3
- SYS_PTHREAD_DETACH_U98 = 0x5FD
- SYS_PTHREAD_GETCONCURRENCY = 0x5F4
- SYS_PTHREAD_GETSPECIFIC_U98 = 0x5FE
- SYS_PTHREAD_KEY_DELETE = 0x5F5
- SYS_PTHREAD_SETCANCELSTATE = 0x5FF
- SYS_PTHREAD_SETCONCURRENCY = 0x5F6
- SYS_PTHREAD_SIGMASK = 0x5F7
- SYS_QUERYENC = 0x5AD
- SYS_QUERYWORKUNITCLASSIFICATION = 0x5AD
- SYS_RAISE = 0x05E
- SYS_RAND_R = 0x5E4
- SYS_READDIR_R = 0x5E6
- SYS_REALLOC = 0x05B
- SYS_RES_INIT = 0x5D8
- SYS_RES_MKQUERY = 0x5D7
- SYS_RES_QUERY = 0x5D9
- SYS_RES_QUERYDOMAIN = 0x5DC
- SYS_RES_SEARCH = 0x5DA
- SYS_RES_SEND = 0x5DB
- SYS_SETJMP = 0x05F
- SYS_SIGQUEUE = 0x5A9
- SYS_STRTOK_R = 0x5E5
- SYS_STRTOLL = 0x5B0
- SYS_STRTOULL = 0x5B1
- SYS_TTYNAME_R = 0x5EC
- SYS_UNDOEXPO = 0x5A2
- SYS_UNDOEXPORTWORKUNIT = 0x5A2
- SYS_UNDOIMPO = 0x5A4
- SYS_UNDOIMPORTWORKUNIT = 0x5A4
- SYS_WCSTOLL = 0x5CC
- SYS_WCSTOULL = 0x5CD
- SYS___ABORT = 0x05C
- SYS___CONSOLE2 = 0x5D2
- SYS___CPL = 0x5A6
- SYS___DISCARDDATA = 0x5F8
- SYS___DSA_PREV = 0x5B2
- SYS___EP_FIND = 0x5B3
- SYS___FP_SWAPMODE = 0x5AF
- SYS___GETUSERID = 0x5AB
- SYS___GET_CPUID = 0x5B9
- SYS___GET_SYSTEM_SETTINGS = 0x5BA
- SYS___IPDOMAINNAME = 0x5AC
- SYS___MAP_INIT = 0x5A7
- SYS___MAP_SERVICE = 0x5A8
- SYS___MOUNT = 0x5AA
- SYS___MSGRCV_TIMED = 0x5B7
- SYS___RES = 0x5D6
- SYS___SEMOP_TIMED = 0x5B8
- SYS___SERVER_THREADS_QUERY = 0x5B4
- SYS_FPRINTF = 0x06D
- SYS_FSCANF = 0x06A
- SYS_PRINTF = 0x06F
- SYS_SETBUF = 0x06B
- SYS_SETVBUF = 0x06C
- SYS_SSCANF = 0x06E
- SYS___CATGETS_A = 0x6C0
- SYS___CHAUDIT_A = 0x6F4
- SYS___CHMOD_A = 0x6E8
- SYS___COLLATE_INIT_A = 0x6AC
- SYS___CREAT_A = 0x6F6
- SYS___CTYPE_INIT_A = 0x6AF
- SYS___DLLLOAD_A = 0x6DF
- SYS___DLLQUERYFN_A = 0x6E0
- SYS___DLLQUERYVAR_A = 0x6E1
- SYS___E2A_L = 0x6E3
- SYS___EXECLE_A = 0x6A0
- SYS___EXECLP_A = 0x6A4
- SYS___EXECVE_A = 0x6C1
- SYS___EXECVP_A = 0x6C2
- SYS___EXECV_A = 0x6B1
- SYS___FPRINTF_A = 0x6FA
- SYS___GETADDRINFO_A = 0x6BF
- SYS___GETNAMEINFO_A = 0x6C4
- SYS___GET_WCTYPE_STD_A = 0x6AE
- SYS___ICONV_OPEN_A = 0x6DE
- SYS___IF_INDEXTONAME_A = 0x6DC
- SYS___IF_NAMETOINDEX_A = 0x6DB
- SYS___ISWCTYPE_A = 0x6B0
- SYS___IS_WCTYPE_STD_A = 0x6B2
- SYS___LOCALECONV_A = 0x6B8
- SYS___LOCALECONV_STD_A = 0x6B9
- SYS___LOCALE_INIT_A = 0x6B7
- SYS___LSTAT_A = 0x6EE
- SYS___LSTAT_O_A = 0x6EF
- SYS___MKDIR_A = 0x6E9
- SYS___MKFIFO_A = 0x6EC
- SYS___MKNOD_A = 0x6F0
- SYS___MONETARY_INIT_A = 0x6BC
- SYS___MOUNT_A = 0x6F1
- SYS___NL_CSINFO_A = 0x6D6
- SYS___NL_LANGINFO_A = 0x6BA
- SYS___NL_LNAGINFO_STD_A = 0x6BB
- SYS___NL_MONINFO_A = 0x6D7
- SYS___NL_NUMINFO_A = 0x6D8
- SYS___NL_RESPINFO_A = 0x6D9
- SYS___NL_TIMINFO_A = 0x6DA
- SYS___NUMERIC_INIT_A = 0x6C6
- SYS___OPEN_A = 0x6F7
- SYS___PRINTF_A = 0x6DD
- SYS___RESP_INIT_A = 0x6C7
- SYS___RPMATCH_A = 0x6C8
- SYS___RPMATCH_C_A = 0x6C9
- SYS___RPMATCH_STD_A = 0x6CA
- SYS___SETLOCALE_A = 0x6F9
- SYS___SPAWNP_A = 0x6C5
- SYS___SPAWN_A = 0x6C3
- SYS___SPRINTF_A = 0x6FB
- SYS___STAT_A = 0x6EA
- SYS___STAT_O_A = 0x6EB
- SYS___STRCOLL_STD_A = 0x6A1
- SYS___STRFMON_A = 0x6BD
- SYS___STRFMON_STD_A = 0x6BE
- SYS___STRFTIME_A = 0x6CC
- SYS___STRFTIME_STD_A = 0x6CD
- SYS___STRPTIME_A = 0x6CE
- SYS___STRPTIME_STD_A = 0x6CF
- SYS___STRXFRM_A = 0x6A2
- SYS___STRXFRM_C_A = 0x6A3
- SYS___STRXFRM_STD_A = 0x6A5
- SYS___SYNTAX_INIT_A = 0x6D4
- SYS___TIME_INIT_A = 0x6CB
- SYS___TOD_INIT_A = 0x6D5
- SYS___TOWLOWER_A = 0x6B3
- SYS___TOWLOWER_STD_A = 0x6B4
- SYS___TOWUPPER_A = 0x6B5
- SYS___TOWUPPER_STD_A = 0x6B6
- SYS___UMOUNT_A = 0x6F2
- SYS___VFPRINTF_A = 0x6FC
- SYS___VPRINTF_A = 0x6FD
- SYS___VSPRINTF_A = 0x6FE
- SYS___VSWPRINTF_A = 0x6FF
- SYS___WCSCOLL_A = 0x6A6
- SYS___WCSCOLL_C_A = 0x6A7
- SYS___WCSCOLL_STD_A = 0x6A8
- SYS___WCSFTIME_A = 0x6D0
- SYS___WCSFTIME_STD_A = 0x6D1
- SYS___WCSXFRM_A = 0x6A9
- SYS___WCSXFRM_C_A = 0x6AA
- SYS___WCSXFRM_STD_A = 0x6AB
- SYS___WCTYPE_A = 0x6AD
- SYS___W_GETMNTENT_A = 0x6F5
- SYS_____CCSIDTYPE_A = 0x6E6
- SYS_____CHATTR_A = 0x6E2
- SYS_____CSNAMETYPE_A = 0x6E7
- SYS_____OPEN_STAT_A = 0x6ED
- SYS_____SPAWN2_A = 0x6D2
- SYS_____SPAWNP2_A = 0x6D3
- SYS_____TOCCSID_A = 0x6E4
- SYS_____TOCSNAME_A = 0x6E5
- SYS_ACL_FREE = 0x7FF
- SYS_ACL_INIT = 0x7FE
- SYS_FWIDE = 0x7DF
- SYS_FWPRINTF = 0x7D1
- SYS_FWRITE = 0x07E
- SYS_FWSCANF = 0x7D5
- SYS_GETCHAR = 0x07B
- SYS_GETS = 0x07C
- SYS_M_CREATE_LAYOUT = 0x7C9
- SYS_M_DESTROY_LAYOUT = 0x7CA
- SYS_M_GETVALUES_LAYOUT = 0x7CB
- SYS_M_SETVALUES_LAYOUT = 0x7CC
- SYS_M_TRANSFORM_LAYOUT = 0x7CD
- SYS_M_WTRANSFORM_LAYOUT = 0x7CE
- SYS_PREAD = 0x7C7
- SYS_PUTC = 0x07D
- SYS_PUTCHAR = 0x07A
- SYS_PUTS = 0x07F
- SYS_PWRITE = 0x7C8
- SYS_TOWCTRAN = 0x7D8
- SYS_TOWCTRANS = 0x7D8
- SYS_UNATEXIT = 0x7B5
- SYS_VFWPRINT = 0x7D3
- SYS_VFWPRINTF = 0x7D3
- SYS_VWPRINTF = 0x7D4
- SYS_WCTRANS = 0x7D7
- SYS_WPRINTF = 0x7D2
- SYS_WSCANF = 0x7D6
- SYS___ASCTIME_R_A = 0x7A1
- SYS___BASENAME_A = 0x7DC
- SYS___BTOWC_A = 0x7E4
- SYS___CDUMP_A = 0x7B7
- SYS___CEE3DMP_A = 0x7B6
- SYS___CEILF_H = 0x7F4
- SYS___CEILL_H = 0x7F5
- SYS___CEIL_H = 0x7EA
- SYS___CRYPT_A = 0x7BE
- SYS___CSNAP_A = 0x7B8
- SYS___CTEST_A = 0x7B9
- SYS___CTIME_R_A = 0x7A2
- SYS___CTRACE_A = 0x7BA
- SYS___DBM_OPEN_A = 0x7E6
- SYS___DIRNAME_A = 0x7DD
- SYS___FABSF_H = 0x7FA
- SYS___FABSL_H = 0x7FB
- SYS___FABS_H = 0x7ED
- SYS___FGETWC_A = 0x7AA
- SYS___FGETWS_A = 0x7AD
- SYS___FLOORF_H = 0x7F6
- SYS___FLOORL_H = 0x7F7
- SYS___FLOOR_H = 0x7EB
- SYS___FPUTWC_A = 0x7A5
- SYS___FPUTWS_A = 0x7A8
- SYS___GETTIMEOFDAY_A = 0x7AE
- SYS___GETWCHAR_A = 0x7AC
- SYS___GETWC_A = 0x7AB
- SYS___GLOB_A = 0x7DE
- SYS___GMTIME_A = 0x7AF
- SYS___GMTIME_R_A = 0x7B0
- SYS___INET_PTON_A = 0x7BC
- SYS___J0_H = 0x7EE
- SYS___J1_H = 0x7EF
- SYS___JN_H = 0x7F0
- SYS___LOCALTIME_A = 0x7B1
- SYS___LOCALTIME_R_A = 0x7B2
- SYS___MALLOC24 = 0x7FC
- SYS___MALLOC31 = 0x7FD
- SYS___MKTIME_A = 0x7B3
- SYS___MODFF_H = 0x7F8
- SYS___MODFL_H = 0x7F9
- SYS___MODF_H = 0x7EC
- SYS___OPENDIR_A = 0x7C2
- SYS___OSNAME = 0x7E0
- SYS___PUTWCHAR_A = 0x7A7
- SYS___PUTWC_A = 0x7A6
- SYS___READDIR_A = 0x7C3
- SYS___STRTOLL_A = 0x7A3
- SYS___STRTOULL_A = 0x7A4
- SYS___SYSLOG_A = 0x7BD
- SYS___TZZNA = 0x7B4
- SYS___UNGETWC_A = 0x7A9
- SYS___UTIME_A = 0x7A0
- SYS___VFPRINTF2_A = 0x7E7
- SYS___VPRINTF2_A = 0x7E8
- SYS___VSPRINTF2_A = 0x7E9
- SYS___VSWPRNTF2_A = 0x7BB
- SYS___WCSTOD_A = 0x7D9
- SYS___WCSTOL_A = 0x7DA
- SYS___WCSTOUL_A = 0x7DB
- SYS___WCTOB_A = 0x7E5
- SYS___Y0_H = 0x7F1
- SYS___Y1_H = 0x7F2
- SYS___YN_H = 0x7F3
- SYS_____OPENDIR2_A = 0x7BF
- SYS_____OSNAME_A = 0x7E1
- SYS_____READDIR2_A = 0x7C0
- SYS_DLCLOSE = 0x8DF
- SYS_DLERROR = 0x8E0
- SYS_DLOPEN = 0x8DD
- SYS_DLSYM = 0x8DE
- SYS_FLOCKFILE = 0x8D3
- SYS_FTRYLOCKFILE = 0x8D4
- SYS_FUNLOCKFILE = 0x8D5
- SYS_GETCHAR_UNLOCKED = 0x8D7
- SYS_GETC_UNLOCKED = 0x8D6
- SYS_PUTCHAR_UNLOCKED = 0x8D9
- SYS_PUTC_UNLOCKED = 0x8D8
- SYS_SNPRINTF = 0x8DA
- SYS_VSNPRINTF = 0x8DB
- SYS_WCSCSPN = 0x08B
- SYS_WCSLEN = 0x08C
- SYS_WCSNCAT = 0x08D
- SYS_WCSNCMP = 0x08A
- SYS_WCSNCPY = 0x08F
- SYS_WCSSPN = 0x08E
- SYS___ABSF_H = 0x8E7
- SYS___ABSL_H = 0x8E8
- SYS___ABS_H = 0x8E6
- SYS___ACOSF_H = 0x8EA
- SYS___ACOSH_H = 0x8EC
- SYS___ACOSL_H = 0x8EB
- SYS___ACOS_H = 0x8E9
- SYS___ASINF_H = 0x8EE
- SYS___ASINH_H = 0x8F0
- SYS___ASINL_H = 0x8EF
- SYS___ASIN_H = 0x8ED
- SYS___ATAN2F_H = 0x8F8
- SYS___ATAN2L_H = 0x8F9
- SYS___ATAN2_H = 0x8F7
- SYS___ATANF_H = 0x8F2
- SYS___ATANHF_H = 0x8F5
- SYS___ATANHL_H = 0x8F6
- SYS___ATANH_H = 0x8F4
- SYS___ATANL_H = 0x8F3
- SYS___ATAN_H = 0x8F1
- SYS___CBRT_H = 0x8FA
- SYS___COPYSIGNF_H = 0x8FB
- SYS___COPYSIGNL_H = 0x8FC
- SYS___COSF_H = 0x8FE
- SYS___COSL_H = 0x8FF
- SYS___COS_H = 0x8FD
- SYS___DLERROR_A = 0x8D2
- SYS___DLOPEN_A = 0x8D0
- SYS___DLSYM_A = 0x8D1
- SYS___GETUTXENT_A = 0x8C6
- SYS___GETUTXID_A = 0x8C7
- SYS___GETUTXLINE_A = 0x8C8
- SYS___ITOA = 0x8AA
- SYS___ITOA_A = 0x8B0
- SYS___LE_CONDITION_TOKEN_BUILD = 0x8A5
- SYS___LE_MSG_ADD_INSERT = 0x8A6
- SYS___LE_MSG_GET = 0x8A7
- SYS___LE_MSG_GET_AND_WRITE = 0x8A8
- SYS___LE_MSG_WRITE = 0x8A9
- SYS___LLTOA = 0x8AE
- SYS___LLTOA_A = 0x8B4
- SYS___LTOA = 0x8AC
- SYS___LTOA_A = 0x8B2
- SYS___PUTCHAR_UNLOCKED_A = 0x8CC
- SYS___PUTC_UNLOCKED_A = 0x8CB
- SYS___PUTUTXLINE_A = 0x8C9
- SYS___RESET_EXCEPTION_HANDLER = 0x8E3
- SYS___REXEC_A = 0x8C4
- SYS___REXEC_AF_A = 0x8C5
- SYS___SET_EXCEPTION_HANDLER = 0x8E2
- SYS___SNPRINTF_A = 0x8CD
- SYS___SUPERKILL = 0x8A4
- SYS___TCGETATTR_A = 0x8A1
- SYS___TCSETATTR_A = 0x8A2
- SYS___ULLTOA = 0x8AF
- SYS___ULLTOA_A = 0x8B5
- SYS___ULTOA = 0x8AD
- SYS___ULTOA_A = 0x8B3
- SYS___UTOA = 0x8AB
- SYS___UTOA_A = 0x8B1
- SYS___VHM_EVENT = 0x8E4
- SYS___VSNPRINTF_A = 0x8CE
- SYS_____GETENV_A = 0x8C3
- SYS_____UTMPXNAME_A = 0x8CA
- SYS_CACOSH = 0x9A0
- SYS_CACOSHF = 0x9A3
- SYS_CACOSHL = 0x9A6
- SYS_CARG = 0x9A9
- SYS_CARGF = 0x9AC
- SYS_CARGL = 0x9AF
- SYS_CASIN = 0x9B2
- SYS_CASINF = 0x9B5
- SYS_CASINH = 0x9BB
- SYS_CASINHF = 0x9BE
- SYS_CASINHL = 0x9C1
- SYS_CASINL = 0x9B8
- SYS_CATAN = 0x9C4
- SYS_CATANF = 0x9C7
- SYS_CATANH = 0x9CD
- SYS_CATANHF = 0x9D0
- SYS_CATANHL = 0x9D3
- SYS_CATANL = 0x9CA
- SYS_CCOS = 0x9D6
- SYS_CCOSF = 0x9D9
- SYS_CCOSH = 0x9DF
- SYS_CCOSHF = 0x9E2
- SYS_CCOSHL = 0x9E5
- SYS_CCOSL = 0x9DC
- SYS_CEXP = 0x9E8
- SYS_CEXPF = 0x9EB
- SYS_CEXPL = 0x9EE
- SYS_CIMAG = 0x9F1
- SYS_CIMAGF = 0x9F4
- SYS_CIMAGL = 0x9F7
- SYS_CLOGF = 0x9FD
- SYS_MEMCHR = 0x09B
- SYS_MEMCMP = 0x09A
- SYS_STRCOLL = 0x09C
- SYS_STRNCMP = 0x09D
- SYS_STRRCHR = 0x09F
- SYS_STRXFRM = 0x09E
- SYS___CACOSHF_B = 0x9A4
- SYS___CACOSHF_H = 0x9A5
- SYS___CACOSHL_B = 0x9A7
- SYS___CACOSHL_H = 0x9A8
- SYS___CACOSH_B = 0x9A1
- SYS___CACOSH_H = 0x9A2
- SYS___CARGF_B = 0x9AD
- SYS___CARGF_H = 0x9AE
- SYS___CARGL_B = 0x9B0
- SYS___CARGL_H = 0x9B1
- SYS___CARG_B = 0x9AA
- SYS___CARG_H = 0x9AB
- SYS___CASINF_B = 0x9B6
- SYS___CASINF_H = 0x9B7
- SYS___CASINHF_B = 0x9BF
- SYS___CASINHF_H = 0x9C0
- SYS___CASINHL_B = 0x9C2
- SYS___CASINHL_H = 0x9C3
- SYS___CASINH_B = 0x9BC
- SYS___CASINH_H = 0x9BD
- SYS___CASINL_B = 0x9B9
- SYS___CASINL_H = 0x9BA
- SYS___CASIN_B = 0x9B3
- SYS___CASIN_H = 0x9B4
- SYS___CATANF_B = 0x9C8
- SYS___CATANF_H = 0x9C9
- SYS___CATANHF_B = 0x9D1
- SYS___CATANHF_H = 0x9D2
- SYS___CATANHL_B = 0x9D4
- SYS___CATANHL_H = 0x9D5
- SYS___CATANH_B = 0x9CE
- SYS___CATANH_H = 0x9CF
- SYS___CATANL_B = 0x9CB
- SYS___CATANL_H = 0x9CC
- SYS___CATAN_B = 0x9C5
- SYS___CATAN_H = 0x9C6
- SYS___CCOSF_B = 0x9DA
- SYS___CCOSF_H = 0x9DB
- SYS___CCOSHF_B = 0x9E3
- SYS___CCOSHF_H = 0x9E4
- SYS___CCOSHL_B = 0x9E6
- SYS___CCOSHL_H = 0x9E7
- SYS___CCOSH_B = 0x9E0
- SYS___CCOSH_H = 0x9E1
- SYS___CCOSL_B = 0x9DD
- SYS___CCOSL_H = 0x9DE
- SYS___CCOS_B = 0x9D7
- SYS___CCOS_H = 0x9D8
- SYS___CEXPF_B = 0x9EC
- SYS___CEXPF_H = 0x9ED
- SYS___CEXPL_B = 0x9EF
- SYS___CEXPL_H = 0x9F0
- SYS___CEXP_B = 0x9E9
- SYS___CEXP_H = 0x9EA
- SYS___CIMAGF_B = 0x9F5
- SYS___CIMAGF_H = 0x9F6
- SYS___CIMAGL_B = 0x9F8
- SYS___CIMAGL_H = 0x9F9
- SYS___CIMAG_B = 0x9F2
- SYS___CIMAG_H = 0x9F3
- SYS___CLOG = 0x9FA
- SYS___CLOGF_B = 0x9FE
- SYS___CLOGF_H = 0x9FF
- SYS___CLOG_B = 0x9FB
- SYS___CLOG_H = 0x9FC
- SYS_ISWCTYPE = 0x10C
- SYS_ISWXDIGI = 0x10A
- SYS_ISWXDIGIT = 0x10A
- SYS_MBSINIT = 0x10F
- SYS_TOWLOWER = 0x10D
- SYS_TOWUPPER = 0x10E
- SYS_WCTYPE = 0x10B
- SYS_WCSSTR = 0x11B
- SYS___RPMTCH = 0x11A
- SYS_WCSTOD = 0x12E
- SYS_WCSTOK = 0x12C
- SYS_WCSTOL = 0x12D
- SYS_WCSTOUL = 0x12F
- SYS_FGETWC = 0x13C
- SYS_FGETWS = 0x13D
- SYS_FPUTWC = 0x13E
- SYS_FPUTWS = 0x13F
- SYS_REGERROR = 0x13B
- SYS_REGFREE = 0x13A
- SYS_COLLEQUIV = 0x14F
- SYS_COLLTOSTR = 0x14E
- SYS_ISMCCOLLEL = 0x14C
- SYS_STRTOCOLL = 0x14D
- SYS_DLLFREE = 0x16F
- SYS_DLLQUERYFN = 0x16D
- SYS_DLLQUERYVAR = 0x16E
- SYS_GETMCCOLL = 0x16A
- SYS_GETWMCCOLL = 0x16B
- SYS___ERR2AD = 0x16C
- SYS_CFSETOSPEED = 0x17A
- SYS_CHDIR = 0x17B
- SYS_CHMOD = 0x17C
- SYS_CHOWN = 0x17D
- SYS_CLOSE = 0x17E
- SYS_CLOSEDIR = 0x17F
- SYS_LOG = 0x017
- SYS_COSH = 0x018
- SYS_FCHMOD = 0x18A
- SYS_FCHOWN = 0x18B
- SYS_FCNTL = 0x18C
- SYS_FILENO = 0x18D
- SYS_FORK = 0x18E
- SYS_FPATHCONF = 0x18F
- SYS_GETLOGIN = 0x19A
- SYS_GETPGRP = 0x19C
- SYS_GETPID = 0x19D
- SYS_GETPPID = 0x19E
- SYS_GETPWNAM = 0x19F
- SYS_TANH = 0x019
- SYS_W_GETMNTENT = 0x19B
- SYS_POW = 0x020
- SYS_PTHREAD_SELF = 0x20A
- SYS_PTHREAD_SETINTR = 0x20B
- SYS_PTHREAD_SETINTRTYPE = 0x20C
- SYS_PTHREAD_SETSPECIFIC = 0x20D
- SYS_PTHREAD_TESTINTR = 0x20E
- SYS_PTHREAD_YIELD = 0x20F
- SYS_SQRT = 0x021
- SYS_FLOOR = 0x022
- SYS_J1 = 0x023
- SYS_WCSPBRK = 0x23F
- SYS_BSEARCH = 0x24C
- SYS_FABS = 0x024
- SYS_GETENV = 0x24A
- SYS_LDIV = 0x24D
- SYS_SYSTEM = 0x24B
- SYS_FMOD = 0x025
- SYS___RETHROW = 0x25F
- SYS___THROW = 0x25E
- SYS_J0 = 0x026
- SYS_PUTENV = 0x26A
- SYS___GETENV = 0x26F
- SYS_SEMCTL = 0x27A
- SYS_SEMGET = 0x27B
- SYS_SEMOP = 0x27C
- SYS_SHMAT = 0x27D
- SYS_SHMCTL = 0x27E
- SYS_SHMDT = 0x27F
- SYS_YN = 0x027
- SYS_JN = 0x028
- SYS_SIGALTSTACK = 0x28A
- SYS_SIGHOLD = 0x28B
- SYS_SIGIGNORE = 0x28C
- SYS_SIGINTERRUPT = 0x28D
- SYS_SIGPAUSE = 0x28E
- SYS_SIGRELSE = 0x28F
- SYS_GETOPT = 0x29A
- SYS_GETSUBOPT = 0x29D
- SYS_LCHOWN = 0x29B
- SYS_SETPGRP = 0x29E
- SYS_TRUNCATE = 0x29C
- SYS_Y0 = 0x029
- SYS___GDERR = 0x29F
- SYS_ISALPHA = 0x030
- SYS_VFORK = 0x30F
- SYS__LONGJMP = 0x30D
- SYS__SETJMP = 0x30E
- SYS_GLOB = 0x31A
- SYS_GLOBFREE = 0x31B
- SYS_ISALNUM = 0x031
- SYS_PUTW = 0x31C
- SYS_SEEKDIR = 0x31D
- SYS_TELLDIR = 0x31E
- SYS_TEMPNAM = 0x31F
- SYS_GETTIMEOFDAY_R = 0x32E
- SYS_ISLOWER = 0x032
- SYS_LGAMMA = 0x32C
- SYS_REMAINDER = 0x32A
- SYS_SCALB = 0x32B
- SYS_SYNC = 0x32F
- SYS_TTYSLOT = 0x32D
- SYS_ENDPROTOENT = 0x33A
- SYS_ENDSERVENT = 0x33B
- SYS_GETHOSTBYADDR = 0x33D
- SYS_GETHOSTBYADDR_R = 0x33C
- SYS_GETHOSTBYNAME = 0x33F
- SYS_GETHOSTBYNAME_R = 0x33E
- SYS_ISCNTRL = 0x033
- SYS_GETSERVBYNAME = 0x34A
- SYS_GETSERVBYPORT = 0x34B
- SYS_GETSERVENT = 0x34C
- SYS_GETSOCKNAME = 0x34D
- SYS_GETSOCKOPT = 0x34E
- SYS_INET_ADDR = 0x34F
- SYS_ISDIGIT = 0x034
- SYS_ISGRAPH = 0x035
- SYS_SELECT = 0x35B
- SYS_SELECTEX = 0x35C
- SYS_SEND = 0x35D
- SYS_SENDTO = 0x35F
- SYS_CHROOT = 0x36A
- SYS_ISNAN = 0x36D
- SYS_ISUPPER = 0x036
- SYS_ULIMIT = 0x36C
- SYS_UTIMES = 0x36E
- SYS_W_STATVFS = 0x36B
- SYS___H_ERRNO = 0x36F
- SYS_GRANTPT = 0x37A
- SYS_ISPRINT = 0x037
- SYS_TCGETSID = 0x37C
- SYS_UNLOCKPT = 0x37B
- SYS___TCGETCP = 0x37D
- SYS___TCSETCP = 0x37E
- SYS___TCSETTABLES = 0x37F
- SYS_ISPUNCT = 0x038
- SYS_NLIST = 0x38C
- SYS___IPDBCS = 0x38D
- SYS___IPDSPX = 0x38E
- SYS___IPMSGC = 0x38F
- SYS___STHOSTENT = 0x38B
- SYS___STSERVENT = 0x38A
- SYS_ISSPACE = 0x039
- SYS_COS = 0x040
- SYS_T_ALLOC = 0x40A
- SYS_T_BIND = 0x40B
- SYS_T_CLOSE = 0x40C
- SYS_T_CONNECT = 0x40D
- SYS_T_ERROR = 0x40E
- SYS_T_FREE = 0x40F
- SYS_TAN = 0x041
- SYS_T_RCVREL = 0x41A
- SYS_T_RCVUDATA = 0x41B
- SYS_T_RCVUDERR = 0x41C
- SYS_T_SND = 0x41D
- SYS_T_SNDDIS = 0x41E
- SYS_T_SNDREL = 0x41F
- SYS_GETPMSG = 0x42A
- SYS_ISASTREAM = 0x42B
- SYS_PUTMSG = 0x42C
- SYS_PUTPMSG = 0x42D
- SYS_SINH = 0x042
- SYS___ISPOSIXON = 0x42E
- SYS___OPENMVSREL = 0x42F
- SYS_ACOS = 0x043
- SYS_ATAN = 0x044
- SYS_ATAN2 = 0x045
- SYS_FTELL = 0x046
- SYS_FGETPOS = 0x047
- SYS_SOCK_DEBUG = 0x47A
- SYS_SOCK_DO_TESTSTOR = 0x47D
- SYS_TAKESOCKET = 0x47E
- SYS___SERVER_INIT = 0x47F
- SYS_FSEEK = 0x048
- SYS___IPHOST = 0x48B
- SYS___IPNODE = 0x48C
- SYS___SERVER_CLASSIFY_CREATE = 0x48D
- SYS___SERVER_CLASSIFY_DESTROY = 0x48E
- SYS___SERVER_CLASSIFY_RESET = 0x48F
- SYS___SMF_RECORD = 0x48A
- SYS_FSETPOS = 0x049
- SYS___FNWSA = 0x49B
- SYS___SPAWN2 = 0x49D
- SYS___SPAWNP2 = 0x49E
- SYS_ATOF = 0x050
- SYS_PTHREAD_MUTEXATTR_GETPSHARED = 0x50A
- SYS_PTHREAD_MUTEXATTR_SETPSHARED = 0x50B
- SYS_PTHREAD_RWLOCK_DESTROY = 0x50C
- SYS_PTHREAD_RWLOCK_INIT = 0x50D
- SYS_PTHREAD_RWLOCK_RDLOCK = 0x50E
- SYS_PTHREAD_RWLOCK_TRYRDLOCK = 0x50F
- SYS_ATOI = 0x051
- SYS___FP_CLASS = 0x51D
- SYS___FP_CLR_FLAG = 0x51A
- SYS___FP_FINITE = 0x51E
- SYS___FP_ISNAN = 0x51F
- SYS___FP_RAISE_XCP = 0x51C
- SYS___FP_READ_FLAG = 0x51B
- SYS_RAND = 0x052
- SYS_SIGTIMEDWAIT = 0x52D
- SYS_SIGWAITINFO = 0x52E
- SYS___CHKBFP = 0x52F
- SYS___FPC_RS = 0x52C
- SYS___FPC_RW = 0x52A
- SYS___FPC_SM = 0x52B
- SYS_STRTOD = 0x053
- SYS_STRTOL = 0x054
- SYS_STRTOUL = 0x055
- SYS_MALLOC = 0x056
- SYS_SRAND = 0x057
- SYS_CALLOC = 0x058
- SYS_FREE = 0x059
- SYS___OSENV = 0x59F
- SYS___W_PIOCTL = 0x59E
- SYS_LONGJMP = 0x060
- SYS___FLOORF_B = 0x60A
- SYS___FLOORL_B = 0x60B
- SYS___FREXPF_B = 0x60C
- SYS___FREXPL_B = 0x60D
- SYS___LDEXPF_B = 0x60E
- SYS___LDEXPL_B = 0x60F
- SYS_SIGNAL = 0x061
- SYS___ATAN2F_B = 0x61A
- SYS___ATAN2L_B = 0x61B
- SYS___COSHF_B = 0x61C
- SYS___COSHL_B = 0x61D
- SYS___EXPF_B = 0x61E
- SYS___EXPL_B = 0x61F
- SYS_TMPNAM = 0x062
- SYS___ABSF_B = 0x62A
- SYS___ABSL_B = 0x62C
- SYS___ABS_B = 0x62B
- SYS___FMODF_B = 0x62D
- SYS___FMODL_B = 0x62E
- SYS___MODFF_B = 0x62F
- SYS_ATANL = 0x63A
- SYS_CEILF = 0x63B
- SYS_CEILL = 0x63C
- SYS_COSF = 0x63D
- SYS_COSHF = 0x63F
- SYS_COSL = 0x63E
- SYS_REMOVE = 0x063
- SYS_POWL = 0x64A
- SYS_RENAME = 0x064
- SYS_SINF = 0x64B
- SYS_SINHF = 0x64F
- SYS_SINL = 0x64C
- SYS_SQRTF = 0x64D
- SYS_SQRTL = 0x64E
- SYS_BTOWC = 0x65F
- SYS_FREXPL = 0x65A
- SYS_LDEXPF = 0x65B
- SYS_LDEXPL = 0x65C
- SYS_MODFF = 0x65D
- SYS_MODFL = 0x65E
- SYS_TMPFILE = 0x065
- SYS_FREOPEN = 0x066
- SYS___CHARMAP_INIT_A = 0x66E
- SYS___GETHOSTBYADDR_R_A = 0x66C
- SYS___GETHOSTBYNAME_A = 0x66A
- SYS___GETHOSTBYNAME_R_A = 0x66D
- SYS___MBLEN_A = 0x66F
- SYS___RES_INIT_A = 0x66B
- SYS_FCLOSE = 0x067
- SYS___GETGRGID_R_A = 0x67D
- SYS___WCSTOMBS_A = 0x67A
- SYS___WCSTOMBS_STD_A = 0x67B
- SYS___WCSWIDTH_A = 0x67C
- SYS___WCSWIDTH_ASIA = 0x67F
- SYS___WCSWIDTH_STD_A = 0x67E
- SYS_FFLUSH = 0x068
- SYS___GETLOGIN_R_A = 0x68E
- SYS___GETPWNAM_R_A = 0x68C
- SYS___GETPWUID_R_A = 0x68D
- SYS___TTYNAME_R_A = 0x68F
- SYS___WCWIDTH_ASIA = 0x68B
- SYS___WCWIDTH_STD_A = 0x68A
- SYS_FOPEN = 0x069
- SYS___REGEXEC_A = 0x69A
- SYS___REGEXEC_STD_A = 0x69B
- SYS___REGFREE_A = 0x69C
- SYS___REGFREE_STD_A = 0x69D
- SYS___STRCOLL_A = 0x69E
- SYS___STRCOLL_C_A = 0x69F
- SYS_SCANF = 0x070
- SYS___A64L_A = 0x70C
- SYS___ECVT_A = 0x70D
- SYS___FCVT_A = 0x70E
- SYS___GCVT_A = 0x70F
- SYS___STRTOUL_A = 0x70A
- SYS_____AE_CORRESTBL_QUERY_A = 0x70B
- SYS_SPRINTF = 0x071
- SYS___ACCESS_A = 0x71F
- SYS___CATOPEN_A = 0x71E
- SYS___GETOPT_A = 0x71D
- SYS___REALPATH_A = 0x71A
- SYS___SETENV_A = 0x71B
- SYS___SYSTEM_A = 0x71C
- SYS_FGETC = 0x072
- SYS___GAI_STRERROR_A = 0x72F
- SYS___RMDIR_A = 0x72A
- SYS___STATVFS_A = 0x72B
- SYS___SYMLINK_A = 0x72C
- SYS___TRUNCATE_A = 0x72D
- SYS___UNLINK_A = 0x72E
- SYS_VFPRINTF = 0x073
- SYS___ISSPACE_A = 0x73A
- SYS___ISUPPER_A = 0x73B
- SYS___ISWALNUM_A = 0x73F
- SYS___ISXDIGIT_A = 0x73C
- SYS___TOLOWER_A = 0x73D
- SYS___TOUPPER_A = 0x73E
- SYS_VPRINTF = 0x074
- SYS___CONFSTR_A = 0x74B
- SYS___FDOPEN_A = 0x74E
- SYS___FLDATA_A = 0x74F
- SYS___FTOK_A = 0x74C
- SYS___ISWXDIGIT_A = 0x74A
- SYS___MKTEMP_A = 0x74D
- SYS_VSPRINTF = 0x075
- SYS___GETGRGID_A = 0x75A
- SYS___GETGRNAM_A = 0x75B
- SYS___GETGROUPSBYNAME_A = 0x75C
- SYS___GETHOSTENT_A = 0x75D
- SYS___GETHOSTNAME_A = 0x75E
- SYS___GETLOGIN_A = 0x75F
- SYS_GETC = 0x076
- SYS___CREATEWORKUNIT_A = 0x76A
- SYS___CTERMID_A = 0x76B
- SYS___FMTMSG_A = 0x76C
- SYS___INITGROUPS_A = 0x76D
- SYS___MSGRCV_A = 0x76F
- SYS_____LOGIN_A = 0x76E
- SYS_FGETS = 0x077
- SYS___STRCASECMP_A = 0x77B
- SYS___STRNCASECMP_A = 0x77C
- SYS___TTYNAME_A = 0x77D
- SYS___UNAME_A = 0x77E
- SYS___UTIMES_A = 0x77F
- SYS_____SERVER_PWU_A = 0x77A
- SYS_FPUTC = 0x078
- SYS___CREAT_O_A = 0x78E
- SYS___ENVNA = 0x78F
- SYS___FREAD_A = 0x78A
- SYS___FWRITE_A = 0x78B
- SYS___ISASCII = 0x78D
- SYS___OPEN_O_A = 0x78C
- SYS_FPUTS = 0x079
- SYS___ASCTIME_A = 0x79C
- SYS___CTIME_A = 0x79D
- SYS___GETDATE_A = 0x79E
- SYS___GETSERVBYPORT_A = 0x79A
- SYS___GETSERVENT_A = 0x79B
- SYS___TZSET_A = 0x79F
- SYS_ACL_FROM_TEXT = 0x80C
- SYS_ACL_SET_FD = 0x80A
- SYS_ACL_SET_FILE = 0x80B
- SYS_ACL_SORT = 0x80E
- SYS_ACL_TO_TEXT = 0x80D
- SYS_UNGETC = 0x080
- SYS___SHUTDOWN_REGISTRATION = 0x80F
- SYS_FREAD = 0x081
- SYS_FREEADDRINFO = 0x81A
- SYS_GAI_STRERROR = 0x81B
- SYS_REXEC_AF = 0x81C
- SYS___DYNALLOC_A = 0x81F
- SYS___POE = 0x81D
- SYS_WCSTOMBS = 0x082
- SYS___INET_ADDR_A = 0x82F
- SYS___NLIST_A = 0x82A
- SYS_____TCGETCP_A = 0x82B
- SYS_____TCSETCP_A = 0x82C
- SYS_____W_PIOCTL_A = 0x82E
- SYS_MBTOWC = 0x083
- SYS___CABEND = 0x83D
- SYS___LE_CIB_GET = 0x83E
- SYS___RECVMSG_A = 0x83B
- SYS___SENDMSG_A = 0x83A
- SYS___SET_LAA_FOR_JIT = 0x83F
- SYS_____LCHATTR_A = 0x83C
- SYS_WCTOMB = 0x084
- SYS___CBRTL_B = 0x84A
- SYS___COPYSIGNF_B = 0x84B
- SYS___COPYSIGNL_B = 0x84C
- SYS___COTANF_B = 0x84D
- SYS___COTANL_B = 0x84F
- SYS___COTAN_B = 0x84E
- SYS_MBSTOWCS = 0x085
- SYS___LOG1PL_B = 0x85A
- SYS___LOG2F_B = 0x85B
- SYS___LOG2L_B = 0x85D
- SYS___LOG2_B = 0x85C
- SYS___REMAINDERF_B = 0x85E
- SYS___REMAINDERL_B = 0x85F
- SYS_ACOSHF = 0x86E
- SYS_ACOSHL = 0x86F
- SYS_WCSCPY = 0x086
- SYS___ERFCF_B = 0x86D
- SYS___ERFF_B = 0x86C
- SYS___LROUNDF_B = 0x86A
- SYS___LROUND_B = 0x86B
- SYS_COTANL = 0x87A
- SYS_EXP2F = 0x87B
- SYS_EXP2L = 0x87C
- SYS_EXPM1F = 0x87D
- SYS_EXPM1L = 0x87E
- SYS_FDIMF = 0x87F
- SYS_WCSCAT = 0x087
- SYS___COTANL = 0x87A
- SYS_REMAINDERF = 0x88A
- SYS_REMAINDERL = 0x88B
- SYS_REMAINDF = 0x88A
- SYS_REMAINDL = 0x88B
- SYS_REMQUO = 0x88D
- SYS_REMQUOF = 0x88C
- SYS_REMQUOL = 0x88E
- SYS_TGAMMAF = 0x88F
- SYS_WCSCHR = 0x088
- SYS_ERFCF = 0x89B
- SYS_ERFCL = 0x89C
- SYS_ERFL = 0x89A
- SYS_EXP2 = 0x89E
- SYS_WCSCMP = 0x089
- SYS___EXP2_B = 0x89D
- SYS___FAR_JUMP = 0x89F
- SYS_ABS = 0x090
- SYS___ERFCL_H = 0x90A
- SYS___EXPF_H = 0x90C
- SYS___EXPL_H = 0x90D
- SYS___EXPM1_H = 0x90E
- SYS___EXP_H = 0x90B
- SYS___FDIM_H = 0x90F
- SYS_DIV = 0x091
- SYS___LOG2F_H = 0x91F
- SYS___LOG2_H = 0x91E
- SYS___LOGB_H = 0x91D
- SYS___LOGF_H = 0x91B
- SYS___LOGL_H = 0x91C
- SYS___LOG_H = 0x91A
- SYS_LABS = 0x092
- SYS___POWL_H = 0x92A
- SYS___REMAINDER_H = 0x92B
- SYS___RINT_H = 0x92C
- SYS___SCALB_H = 0x92D
- SYS___SINF_H = 0x92F
- SYS___SIN_H = 0x92E
- SYS_STRNCPY = 0x093
- SYS___TANHF_H = 0x93B
- SYS___TANHL_H = 0x93C
- SYS___TANH_H = 0x93A
- SYS___TGAMMAF_H = 0x93E
- SYS___TGAMMA_H = 0x93D
- SYS___TRUNC_H = 0x93F
- SYS_MEMCPY = 0x094
- SYS_VFWSCANF = 0x94A
- SYS_VSWSCANF = 0x94E
- SYS_VWSCANF = 0x94C
- SYS_INET6_RTH_ADD = 0x95D
- SYS_INET6_RTH_INIT = 0x95C
- SYS_INET6_RTH_REVERSE = 0x95E
- SYS_INET6_RTH_SEGMENTS = 0x95F
- SYS_INET6_RTH_SPACE = 0x95B
- SYS_MEMMOVE = 0x095
- SYS_WCSTOLD = 0x95A
- SYS_STRCPY = 0x096
- SYS_STRCMP = 0x097
- SYS_CABS = 0x98E
- SYS_STRCAT = 0x098
- SYS___CABS_B = 0x98F
- SYS___POW_II = 0x98A
- SYS___POW_II_B = 0x98B
- SYS___POW_II_H = 0x98C
- SYS_CACOSF = 0x99A
- SYS_CACOSL = 0x99D
- SYS_STRNCAT = 0x099
- SYS___CACOSF_B = 0x99B
- SYS___CACOSF_H = 0x99C
- SYS___CACOSL_B = 0x99E
- SYS___CACOSL_H = 0x99F
- SYS_ISWALPHA = 0x100
- SYS_ISWBLANK = 0x101
- SYS___ISWBLK = 0x101
- SYS_ISWCNTRL = 0x102
- SYS_ISWDIGIT = 0x103
- SYS_ISWGRAPH = 0x104
- SYS_ISWLOWER = 0x105
- SYS_ISWPRINT = 0x106
- SYS_ISWPUNCT = 0x107
- SYS_ISWSPACE = 0x108
- SYS_ISWUPPER = 0x109
- SYS_WCTOB = 0x110
- SYS_MBRLEN = 0x111
- SYS_MBRTOWC = 0x112
- SYS_MBSRTOWC = 0x113
- SYS_MBSRTOWCS = 0x113
- SYS_WCRTOMB = 0x114
- SYS_WCSRTOMB = 0x115
- SYS_WCSRTOMBS = 0x115
- SYS___CSID = 0x116
- SYS___WCSID = 0x117
- SYS_STRPTIME = 0x118
- SYS___STRPTM = 0x118
- SYS_STRFMON = 0x119
- SYS_WCSCOLL = 0x130
- SYS_WCSXFRM = 0x131
- SYS_WCSWIDTH = 0x132
- SYS_WCWIDTH = 0x133
- SYS_WCSFTIME = 0x134
- SYS_SWPRINTF = 0x135
- SYS_VSWPRINT = 0x136
- SYS_VSWPRINTF = 0x136
- SYS_SWSCANF = 0x137
- SYS_REGCOMP = 0x138
- SYS_REGEXEC = 0x139
- SYS_GETWC = 0x140
- SYS_GETWCHAR = 0x141
- SYS_PUTWC = 0x142
- SYS_PUTWCHAR = 0x143
- SYS_UNGETWC = 0x144
- SYS_ICONV_OPEN = 0x145
- SYS_ICONV = 0x146
- SYS_ICONV_CLOSE = 0x147
- SYS_COLLRANGE = 0x150
- SYS_CCLASS = 0x151
- SYS_COLLORDER = 0x152
- SYS___DEMANGLE = 0x154
- SYS_FDOPEN = 0x155
- SYS___ERRNO = 0x156
- SYS___ERRNO2 = 0x157
- SYS___TERROR = 0x158
- SYS_MAXCOLL = 0x169
- SYS_DLLLOAD = 0x170
- SYS__EXIT = 0x174
- SYS_ACCESS = 0x175
- SYS_ALARM = 0x176
- SYS_CFGETISPEED = 0x177
- SYS_CFGETOSPEED = 0x178
- SYS_CFSETISPEED = 0x179
- SYS_CREAT = 0x180
- SYS_CTERMID = 0x181
- SYS_DUP = 0x182
- SYS_DUP2 = 0x183
- SYS_EXECL = 0x184
- SYS_EXECLE = 0x185
- SYS_EXECLP = 0x186
- SYS_EXECV = 0x187
- SYS_EXECVE = 0x188
- SYS_EXECVP = 0x189
- SYS_FSTAT = 0x190
- SYS_FSYNC = 0x191
- SYS_FTRUNCATE = 0x192
- SYS_GETCWD = 0x193
- SYS_GETEGID = 0x194
- SYS_GETEUID = 0x195
- SYS_GETGID = 0x196
- SYS_GETGRGID = 0x197
- SYS_GETGRNAM = 0x198
- SYS_GETGROUPS = 0x199
- SYS_PTHREAD_MUTEXATTR_DESTROY = 0x200
- SYS_PTHREAD_MUTEXATTR_SETKIND_NP = 0x201
- SYS_PTHREAD_MUTEXATTR_GETKIND_NP = 0x202
- SYS_PTHREAD_MUTEX_INIT = 0x203
- SYS_PTHREAD_MUTEX_DESTROY = 0x204
- SYS_PTHREAD_MUTEX_LOCK = 0x205
- SYS_PTHREAD_MUTEX_TRYLOCK = 0x206
- SYS_PTHREAD_MUTEX_UNLOCK = 0x207
- SYS_PTHREAD_ONCE = 0x209
- SYS_TW_OPEN = 0x210
- SYS_TW_FCNTL = 0x211
- SYS_PTHREAD_JOIN_D4_NP = 0x212
- SYS_PTHREAD_CONDATTR_SETKIND_NP = 0x213
- SYS_PTHREAD_CONDATTR_GETKIND_NP = 0x214
- SYS_EXTLINK_NP = 0x215
- SYS___PASSWD = 0x216
- SYS_SETGROUPS = 0x217
- SYS_INITGROUPS = 0x218
- SYS_WCSRCHR = 0x240
- SYS_SVC99 = 0x241
- SYS___SVC99 = 0x241
- SYS_WCSWCS = 0x242
- SYS_LOCALECO = 0x243
- SYS_LOCALECONV = 0x243
- SYS___LIBREL = 0x244
- SYS_RELEASE = 0x245
- SYS___RLSE = 0x245
- SYS_FLOCATE = 0x246
- SYS___FLOCT = 0x246
- SYS_FDELREC = 0x247
- SYS___FDLREC = 0x247
- SYS_FETCH = 0x248
- SYS___FETCH = 0x248
- SYS_QSORT = 0x249
- SYS___CLEANUPCATCH = 0x260
- SYS___CATCHMATCH = 0x261
- SYS___CLEAN2UPCATCH = 0x262
- SYS_GETPRIORITY = 0x270
- SYS_NICE = 0x271
- SYS_SETPRIORITY = 0x272
- SYS_GETITIMER = 0x273
- SYS_SETITIMER = 0x274
- SYS_MSGCTL = 0x275
- SYS_MSGGET = 0x276
- SYS_MSGRCV = 0x277
- SYS_MSGSND = 0x278
- SYS_MSGXRCV = 0x279
- SYS___MSGXR = 0x279
- SYS_SHMGET = 0x280
- SYS___GETIPC = 0x281
- SYS_SETGRENT = 0x282
- SYS_GETGRENT = 0x283
- SYS_ENDGRENT = 0x284
- SYS_SETPWENT = 0x285
- SYS_GETPWENT = 0x286
- SYS_ENDPWENT = 0x287
- SYS_BSD_SIGNAL = 0x288
- SYS_KILLPG = 0x289
- SYS_SIGSET = 0x290
- SYS_SIGSTACK = 0x291
- SYS_GETRLIMIT = 0x292
- SYS_SETRLIMIT = 0x293
- SYS_GETRUSAGE = 0x294
- SYS_MMAP = 0x295
- SYS_MPROTECT = 0x296
- SYS_MSYNC = 0x297
- SYS_MUNMAP = 0x298
- SYS_CONFSTR = 0x299
- SYS___NDMTRM = 0x300
- SYS_FTOK = 0x301
- SYS_BASENAME = 0x302
- SYS_DIRNAME = 0x303
- SYS_GETDTABLESIZE = 0x304
- SYS_MKSTEMP = 0x305
- SYS_MKTEMP = 0x306
- SYS_NFTW = 0x307
- SYS_GETWD = 0x308
- SYS_LOCKF = 0x309
- SYS_WORDEXP = 0x310
- SYS_WORDFREE = 0x311
- SYS_GETPGID = 0x312
- SYS_GETSID = 0x313
- SYS___UTMPXNAME = 0x314
- SYS_CUSERID = 0x315
- SYS_GETPASS = 0x316
- SYS_FNMATCH = 0x317
- SYS_FTW = 0x318
- SYS_GETW = 0x319
- SYS_ACOSH = 0x320
- SYS_ASINH = 0x321
- SYS_ATANH = 0x322
- SYS_CBRT = 0x323
- SYS_EXPM1 = 0x324
- SYS_ILOGB = 0x325
- SYS_LOGB = 0x326
- SYS_LOG1P = 0x327
- SYS_NEXTAFTER = 0x328
- SYS_RINT = 0x329
- SYS_SPAWN = 0x330
- SYS_SPAWNP = 0x331
- SYS_GETLOGIN_UU = 0x332
- SYS_ECVT = 0x333
- SYS_FCVT = 0x334
- SYS_GCVT = 0x335
- SYS_ACCEPT = 0x336
- SYS_BIND = 0x337
- SYS_CONNECT = 0x338
- SYS_ENDHOSTENT = 0x339
- SYS_GETHOSTENT = 0x340
- SYS_GETHOSTID = 0x341
- SYS_GETHOSTNAME = 0x342
- SYS_GETNETBYADDR = 0x343
- SYS_GETNETBYNAME = 0x344
- SYS_GETNETENT = 0x345
- SYS_GETPEERNAME = 0x346
- SYS_GETPROTOBYNAME = 0x347
- SYS_GETPROTOBYNUMBER = 0x348
- SYS_GETPROTOENT = 0x349
- SYS_INET_LNAOF = 0x350
- SYS_INET_MAKEADDR = 0x351
- SYS_INET_NETOF = 0x352
- SYS_INET_NETWORK = 0x353
- SYS_INET_NTOA = 0x354
- SYS_IOCTL = 0x355
- SYS_LISTEN = 0x356
- SYS_READV = 0x357
- SYS_RECV = 0x358
- SYS_RECVFROM = 0x359
- SYS_SETHOSTENT = 0x360
- SYS_SETNETENT = 0x361
- SYS_SETPEER = 0x362
- SYS_SETPROTOENT = 0x363
- SYS_SETSERVENT = 0x364
- SYS_SETSOCKOPT = 0x365
- SYS_SHUTDOWN = 0x366
- SYS_SOCKET = 0x367
- SYS_SOCKETPAIR = 0x368
- SYS_WRITEV = 0x369
- SYS_ENDNETENT = 0x370
- SYS_CLOSELOG = 0x371
- SYS_OPENLOG = 0x372
- SYS_SETLOGMASK = 0x373
- SYS_SYSLOG = 0x374
- SYS_PTSNAME = 0x375
- SYS_SETREUID = 0x376
- SYS_SETREGID = 0x377
- SYS_REALPATH = 0x378
- SYS___SIGNGAM = 0x379
- SYS_POLL = 0x380
- SYS_REXEC = 0x381
- SYS___ISASCII2 = 0x382
- SYS___TOASCII2 = 0x383
- SYS_CHPRIORITY = 0x384
- SYS_PTHREAD_ATTR_SETSYNCTYPE_NP = 0x385
- SYS_PTHREAD_ATTR_GETSYNCTYPE_NP = 0x386
- SYS_PTHREAD_SET_LIMIT_NP = 0x387
- SYS___STNETENT = 0x388
- SYS___STPROTOENT = 0x389
- SYS___SELECT1 = 0x390
- SYS_PTHREAD_SECURITY_NP = 0x391
- SYS___CHECK_RESOURCE_AUTH_NP = 0x392
- SYS___CONVERT_ID_NP = 0x393
- SYS___OPENVMREL = 0x394
- SYS_WMEMCHR = 0x395
- SYS_WMEMCMP = 0x396
- SYS_WMEMCPY = 0x397
- SYS_WMEMMOVE = 0x398
- SYS_WMEMSET = 0x399
- SYS___FPUTWC = 0x400
- SYS___PUTWC = 0x401
- SYS___PWCHAR = 0x402
- SYS___WCSFTM = 0x403
- SYS___WCSTOK = 0x404
- SYS___WCWDTH = 0x405
- SYS_T_ACCEPT = 0x409
- SYS_T_GETINFO = 0x410
- SYS_T_GETPROTADDR = 0x411
- SYS_T_GETSTATE = 0x412
- SYS_T_LISTEN = 0x413
- SYS_T_LOOK = 0x414
- SYS_T_OPEN = 0x415
- SYS_T_OPTMGMT = 0x416
- SYS_T_RCV = 0x417
- SYS_T_RCVCONNECT = 0x418
- SYS_T_RCVDIS = 0x419
- SYS_T_SNDUDATA = 0x420
- SYS_T_STRERROR = 0x421
- SYS_T_SYNC = 0x422
- SYS_T_UNBIND = 0x423
- SYS___T_ERRNO = 0x424
- SYS___RECVMSG2 = 0x425
- SYS___SENDMSG2 = 0x426
- SYS_FATTACH = 0x427
- SYS_FDETACH = 0x428
- SYS_GETMSG = 0x429
- SYS_GETCONTEXT = 0x430
- SYS_SETCONTEXT = 0x431
- SYS_MAKECONTEXT = 0x432
- SYS_SWAPCONTEXT = 0x433
- SYS_PTHREAD_GETSPECIFIC_D8_NP = 0x434
- SYS_GETCLIENTID = 0x470
- SYS___GETCLIENTID = 0x471
- SYS_GETSTABLESIZE = 0x472
- SYS_GETIBMOPT = 0x473
- SYS_GETIBMSOCKOPT = 0x474
- SYS_GIVESOCKET = 0x475
- SYS_IBMSFLUSH = 0x476
- SYS_MAXDESC = 0x477
- SYS_SETIBMOPT = 0x478
- SYS_SETIBMSOCKOPT = 0x479
- SYS___SERVER_PWU = 0x480
- SYS_PTHREAD_TAG_NP = 0x481
- SYS___CONSOLE = 0x482
- SYS___WSINIT = 0x483
- SYS___IPTCPN = 0x489
- SYS___SERVER_CLASSIFY = 0x490
- SYS___HEAPRPT = 0x496
- SYS___ISBFP = 0x500
- SYS___FP_CAST = 0x501
- SYS___CERTIFICATE = 0x502
- SYS_SEND_FILE = 0x503
- SYS_AIO_CANCEL = 0x504
- SYS_AIO_ERROR = 0x505
- SYS_AIO_READ = 0x506
- SYS_AIO_RETURN = 0x507
- SYS_AIO_SUSPEND = 0x508
- SYS_AIO_WRITE = 0x509
- SYS_PTHREAD_RWLOCK_TRYWRLOCK = 0x510
- SYS_PTHREAD_RWLOCK_UNLOCK = 0x511
- SYS_PTHREAD_RWLOCK_WRLOCK = 0x512
- SYS_PTHREAD_RWLOCKATTR_GETPSHARED = 0x513
- SYS_PTHREAD_RWLOCKATTR_SETPSHARED = 0x514
- SYS_PTHREAD_RWLOCKATTR_INIT = 0x515
- SYS_PTHREAD_RWLOCKATTR_DESTROY = 0x516
- SYS___CTTBL = 0x517
- SYS_PTHREAD_MUTEXATTR_SETTYPE = 0x518
- SYS_PTHREAD_MUTEXATTR_GETTYPE = 0x519
- SYS___FP_UNORDERED = 0x520
- SYS___FP_READ_RND = 0x521
- SYS___FP_READ_RND_B = 0x522
- SYS___FP_SWAP_RND = 0x523
- SYS___FP_SWAP_RND_B = 0x524
- SYS___FP_LEVEL = 0x525
- SYS___FP_BTOH = 0x526
- SYS___FP_HTOB = 0x527
- SYS___FPC_RD = 0x528
- SYS___FPC_WR = 0x529
- SYS_PTHREAD_SETCANCELTYPE = 0x600
- SYS_PTHREAD_TESTCANCEL = 0x601
- SYS___ATANF_B = 0x602
- SYS___ATANL_B = 0x603
- SYS___CEILF_B = 0x604
- SYS___CEILL_B = 0x605
- SYS___COSF_B = 0x606
- SYS___COSL_B = 0x607
- SYS___FABSF_B = 0x608
- SYS___FABSL_B = 0x609
- SYS___SINF_B = 0x610
- SYS___SINL_B = 0x611
- SYS___TANF_B = 0x612
- SYS___TANL_B = 0x613
- SYS___TANHF_B = 0x614
- SYS___TANHL_B = 0x615
- SYS___ACOSF_B = 0x616
- SYS___ACOSL_B = 0x617
- SYS___ASINF_B = 0x618
- SYS___ASINL_B = 0x619
- SYS___LOGF_B = 0x620
- SYS___LOGL_B = 0x621
- SYS___LOG10F_B = 0x622
- SYS___LOG10L_B = 0x623
- SYS___POWF_B = 0x624
- SYS___POWL_B = 0x625
- SYS___SINHF_B = 0x626
- SYS___SINHL_B = 0x627
- SYS___SQRTF_B = 0x628
- SYS___SQRTL_B = 0x629
- SYS___MODFL_B = 0x630
- SYS_ABSF = 0x631
- SYS_ABSL = 0x632
- SYS_ACOSF = 0x633
- SYS_ACOSL = 0x634
- SYS_ASINF = 0x635
- SYS_ASINL = 0x636
- SYS_ATAN2F = 0x637
- SYS_ATAN2L = 0x638
- SYS_ATANF = 0x639
- SYS_COSHL = 0x640
- SYS_EXPF = 0x641
- SYS_EXPL = 0x642
- SYS_TANHF = 0x643
- SYS_TANHL = 0x644
- SYS_LOG10F = 0x645
- SYS_LOG10L = 0x646
- SYS_LOGF = 0x647
- SYS_LOGL = 0x648
- SYS_POWF = 0x649
- SYS_SINHL = 0x650
- SYS_TANF = 0x651
- SYS_TANL = 0x652
- SYS_FABSF = 0x653
- SYS_FABSL = 0x654
- SYS_FLOORF = 0x655
- SYS_FLOORL = 0x656
- SYS_FMODF = 0x657
- SYS_FMODL = 0x658
- SYS_FREXPF = 0x659
- SYS___CHATTR = 0x660
- SYS___FCHATTR = 0x661
- SYS___TOCCSID = 0x662
- SYS___CSNAMETYPE = 0x663
- SYS___TOCSNAME = 0x664
- SYS___CCSIDTYPE = 0x665
- SYS___AE_CORRESTBL_QUERY = 0x666
- SYS___AE_AUTOCONVERT_STATE = 0x667
- SYS_DN_FIND = 0x668
- SYS___GETHOSTBYADDR_A = 0x669
- SYS___MBLEN_SB_A = 0x670
- SYS___MBLEN_STD_A = 0x671
- SYS___MBLEN_UTF = 0x672
- SYS___MBSTOWCS_A = 0x673
- SYS___MBSTOWCS_STD_A = 0x674
- SYS___MBTOWC_A = 0x675
- SYS___MBTOWC_ISO1 = 0x676
- SYS___MBTOWC_SBCS = 0x677
- SYS___MBTOWC_MBCS = 0x678
- SYS___MBTOWC_UTF = 0x679
- SYS___CSID_A = 0x680
- SYS___CSID_STD_A = 0x681
- SYS___WCSID_A = 0x682
- SYS___WCSID_STD_A = 0x683
- SYS___WCTOMB_A = 0x684
- SYS___WCTOMB_ISO1 = 0x685
- SYS___WCTOMB_STD_A = 0x686
- SYS___WCTOMB_UTF = 0x687
- SYS___WCWIDTH_A = 0x688
- SYS___GETGRNAM_R_A = 0x689
- SYS___READDIR_R_A = 0x690
- SYS___E2A_S = 0x691
- SYS___FNMATCH_A = 0x692
- SYS___FNMATCH_C_A = 0x693
- SYS___EXECL_A = 0x694
- SYS___FNMATCH_STD_A = 0x695
- SYS___REGCOMP_A = 0x696
- SYS___REGCOMP_STD_A = 0x697
- SYS___REGERROR_A = 0x698
- SYS___REGERROR_STD_A = 0x699
- SYS___SWPRINTF_A = 0x700
- SYS___FSCANF_A = 0x701
- SYS___SCANF_A = 0x702
- SYS___SSCANF_A = 0x703
- SYS___SWSCANF_A = 0x704
- SYS___ATOF_A = 0x705
- SYS___ATOI_A = 0x706
- SYS___ATOL_A = 0x707
- SYS___STRTOD_A = 0x708
- SYS___STRTOL_A = 0x709
- SYS___L64A_A = 0x710
- SYS___STRERROR_A = 0x711
- SYS___PERROR_A = 0x712
- SYS___FETCH_A = 0x713
- SYS___GETENV_A = 0x714
- SYS___MKSTEMP_A = 0x717
- SYS___PTSNAME_A = 0x718
- SYS___PUTENV_A = 0x719
- SYS___CHDIR_A = 0x720
- SYS___CHOWN_A = 0x721
- SYS___CHROOT_A = 0x722
- SYS___GETCWD_A = 0x723
- SYS___GETWD_A = 0x724
- SYS___LCHOWN_A = 0x725
- SYS___LINK_A = 0x726
- SYS___PATHCONF_A = 0x727
- SYS___IF_NAMEINDEX_A = 0x728
- SYS___READLINK_A = 0x729
- SYS___EXTLINK_NP_A = 0x730
- SYS___ISALNUM_A = 0x731
- SYS___ISALPHA_A = 0x732
- SYS___A2E_S = 0x733
- SYS___ISCNTRL_A = 0x734
- SYS___ISDIGIT_A = 0x735
- SYS___ISGRAPH_A = 0x736
- SYS___ISLOWER_A = 0x737
- SYS___ISPRINT_A = 0x738
- SYS___ISPUNCT_A = 0x739
- SYS___ISWALPHA_A = 0x740
- SYS___A2E_L = 0x741
- SYS___ISWCNTRL_A = 0x742
- SYS___ISWDIGIT_A = 0x743
- SYS___ISWGRAPH_A = 0x744
- SYS___ISWLOWER_A = 0x745
- SYS___ISWPRINT_A = 0x746
- SYS___ISWPUNCT_A = 0x747
- SYS___ISWSPACE_A = 0x748
- SYS___ISWUPPER_A = 0x749
- SYS___REMOVE_A = 0x750
- SYS___RENAME_A = 0x751
- SYS___TMPNAM_A = 0x752
- SYS___FOPEN_A = 0x753
- SYS___FREOPEN_A = 0x754
- SYS___CUSERID_A = 0x755
- SYS___POPEN_A = 0x756
- SYS___TEMPNAM_A = 0x757
- SYS___FTW_A = 0x758
- SYS___GETGRENT_A = 0x759
- SYS___INET_NTOP_A = 0x760
- SYS___GETPASS_A = 0x761
- SYS___GETPWENT_A = 0x762
- SYS___GETPWNAM_A = 0x763
- SYS___GETPWUID_A = 0x764
- SYS_____CHECK_RESOURCE_AUTH_NP_A = 0x765
- SYS___CHECKSCHENV_A = 0x766
- SYS___CONNECTSERVER_A = 0x767
- SYS___CONNECTWORKMGR_A = 0x768
- SYS_____CONSOLE_A = 0x769
- SYS___MSGSND_A = 0x770
- SYS___MSGXRCV_A = 0x771
- SYS___NFTW_A = 0x772
- SYS_____PASSWD_A = 0x773
- SYS___PTHREAD_SECURITY_NP_A = 0x774
- SYS___QUERYMETRICS_A = 0x775
- SYS___QUERYSCHENV = 0x776
- SYS___READV_A = 0x777
- SYS_____SERVER_CLASSIFY_A = 0x778
- SYS_____SERVER_INIT_A = 0x779
- SYS___W_GETPSENT_A = 0x780
- SYS___WRITEV_A = 0x781
- SYS___W_STATFS_A = 0x782
- SYS___W_STATVFS_A = 0x783
- SYS___FPUTC_A = 0x784
- SYS___PUTCHAR_A = 0x785
- SYS___PUTS_A = 0x786
- SYS___FGETS_A = 0x787
- SYS___GETS_A = 0x788
- SYS___FPUTS_A = 0x789
- SYS___PUTC_A = 0x790
- SYS___AE_THREAD_SETMODE = 0x791
- SYS___AE_THREAD_SWAPMODE = 0x792
- SYS___GETNETBYADDR_A = 0x793
- SYS___GETNETBYNAME_A = 0x794
- SYS___GETNETENT_A = 0x795
- SYS___GETPROTOBYNAME_A = 0x796
- SYS___GETPROTOBYNUMBER_A = 0x797
- SYS___GETPROTOENT_A = 0x798
- SYS___GETSERVBYNAME_A = 0x799
- SYS_ACL_FIRST_ENTRY = 0x800
- SYS_ACL_GET_ENTRY = 0x801
- SYS_ACL_VALID = 0x802
- SYS_ACL_CREATE_ENTRY = 0x803
- SYS_ACL_DELETE_ENTRY = 0x804
- SYS_ACL_UPDATE_ENTRY = 0x805
- SYS_ACL_DELETE_FD = 0x806
- SYS_ACL_DELETE_FILE = 0x807
- SYS_ACL_GET_FD = 0x808
- SYS_ACL_GET_FILE = 0x809
- SYS___ERFL_B = 0x810
- SYS___ERFCL_B = 0x811
- SYS___LGAMMAL_B = 0x812
- SYS___SETHOOKEVENTS = 0x813
- SYS_IF_NAMETOINDEX = 0x814
- SYS_IF_INDEXTONAME = 0x815
- SYS_IF_NAMEINDEX = 0x816
- SYS_IF_FREENAMEINDEX = 0x817
- SYS_GETADDRINFO = 0x818
- SYS_GETNAMEINFO = 0x819
- SYS___DYNFREE_A = 0x820
- SYS___RES_QUERY_A = 0x821
- SYS___RES_SEARCH_A = 0x822
- SYS___RES_QUERYDOMAIN_A = 0x823
- SYS___RES_MKQUERY_A = 0x824
- SYS___RES_SEND_A = 0x825
- SYS___DN_EXPAND_A = 0x826
- SYS___DN_SKIPNAME_A = 0x827
- SYS___DN_COMP_A = 0x828
- SYS___DN_FIND_A = 0x829
- SYS___INET_NTOA_A = 0x830
- SYS___INET_NETWORK_A = 0x831
- SYS___ACCEPT_A = 0x832
- SYS___ACCEPT_AND_RECV_A = 0x833
- SYS___BIND_A = 0x834
- SYS___CONNECT_A = 0x835
- SYS___GETPEERNAME_A = 0x836
- SYS___GETSOCKNAME_A = 0x837
- SYS___RECVFROM_A = 0x838
- SYS___SENDTO_A = 0x839
- SYS___LCHATTR = 0x840
- SYS___WRITEDOWN = 0x841
- SYS_PTHREAD_MUTEX_INIT2 = 0x842
- SYS___ACOSHF_B = 0x843
- SYS___ACOSHL_B = 0x844
- SYS___ASINHF_B = 0x845
- SYS___ASINHL_B = 0x846
- SYS___ATANHF_B = 0x847
- SYS___ATANHL_B = 0x848
- SYS___CBRTF_B = 0x849
- SYS___EXP2F_B = 0x850
- SYS___EXP2L_B = 0x851
- SYS___EXPM1F_B = 0x852
- SYS___EXPM1L_B = 0x853
- SYS___FDIMF_B = 0x854
- SYS___FDIM_B = 0x855
- SYS___FDIML_B = 0x856
- SYS___HYPOTF_B = 0x857
- SYS___HYPOTL_B = 0x858
- SYS___LOG1PF_B = 0x859
- SYS___REMQUOF_B = 0x860
- SYS___REMQUO_B = 0x861
- SYS___REMQUOL_B = 0x862
- SYS___TGAMMAF_B = 0x863
- SYS___TGAMMA_B = 0x864
- SYS___TGAMMAL_B = 0x865
- SYS___TRUNCF_B = 0x866
- SYS___TRUNC_B = 0x867
- SYS___TRUNCL_B = 0x868
- SYS___LGAMMAF_B = 0x869
- SYS_ASINHF = 0x870
- SYS_ASINHL = 0x871
- SYS_ATANHF = 0x872
- SYS_ATANHL = 0x873
- SYS_CBRTF = 0x874
- SYS_CBRTL = 0x875
- SYS_COPYSIGNF = 0x876
- SYS_CPYSIGNF = 0x876
- SYS_COPYSIGNL = 0x877
- SYS_CPYSIGNL = 0x877
- SYS_COTANF = 0x878
- SYS___COTANF = 0x878
- SYS_COTAN = 0x879
- SYS___COTAN = 0x879
- SYS_FDIM = 0x881
- SYS_FDIML = 0x882
- SYS_HYPOTF = 0x883
- SYS_HYPOTL = 0x884
- SYS_LOG1PF = 0x885
- SYS_LOG1PL = 0x886
- SYS_LOG2F = 0x887
- SYS_LOG2 = 0x888
- SYS_LOG2L = 0x889
- SYS_TGAMMA = 0x890
- SYS_TGAMMAL = 0x891
- SYS_TRUNCF = 0x892
- SYS_TRUNC = 0x893
- SYS_TRUNCL = 0x894
- SYS_LGAMMAF = 0x895
- SYS_LGAMMAL = 0x896
- SYS_LROUNDF = 0x897
- SYS_LROUND = 0x898
- SYS_ERFF = 0x899
- SYS___COSHF_H = 0x900
- SYS___COSHL_H = 0x901
- SYS___COTAN_H = 0x902
- SYS___COTANF_H = 0x903
- SYS___COTANL_H = 0x904
- SYS___ERF_H = 0x905
- SYS___ERFF_H = 0x906
- SYS___ERFL_H = 0x907
- SYS___ERFC_H = 0x908
- SYS___ERFCF_H = 0x909
- SYS___FDIMF_H = 0x910
- SYS___FDIML_H = 0x911
- SYS___FMOD_H = 0x912
- SYS___FMODF_H = 0x913
- SYS___FMODL_H = 0x914
- SYS___GAMMA_H = 0x915
- SYS___HYPOT_H = 0x916
- SYS___ILOGB_H = 0x917
- SYS___LGAMMA_H = 0x918
- SYS___LGAMMAF_H = 0x919
- SYS___LOG2L_H = 0x920
- SYS___LOG1P_H = 0x921
- SYS___LOG10_H = 0x922
- SYS___LOG10F_H = 0x923
- SYS___LOG10L_H = 0x924
- SYS___LROUND_H = 0x925
- SYS___LROUNDF_H = 0x926
- SYS___NEXTAFTER_H = 0x927
- SYS___POW_H = 0x928
- SYS___POWF_H = 0x929
- SYS___SINL_H = 0x930
- SYS___SINH_H = 0x931
- SYS___SINHF_H = 0x932
- SYS___SINHL_H = 0x933
- SYS___SQRT_H = 0x934
- SYS___SQRTF_H = 0x935
- SYS___SQRTL_H = 0x936
- SYS___TAN_H = 0x937
- SYS___TANF_H = 0x938
- SYS___TANL_H = 0x939
- SYS___TRUNCF_H = 0x940
- SYS___TRUNCL_H = 0x941
- SYS___COSH_H = 0x942
- SYS___LE_DEBUG_SET_RESUME_MCH = 0x943
- SYS_VFSCANF = 0x944
- SYS_VSCANF = 0x946
- SYS_VSSCANF = 0x948
- SYS_IMAXABS = 0x950
- SYS_IMAXDIV = 0x951
- SYS_STRTOIMAX = 0x952
- SYS_STRTOUMAX = 0x953
- SYS_WCSTOIMAX = 0x954
- SYS_WCSTOUMAX = 0x955
- SYS_ATOLL = 0x956
- SYS_STRTOF = 0x957
- SYS_STRTOLD = 0x958
- SYS_WCSTOF = 0x959
- SYS_INET6_RTH_GETADDR = 0x960
- SYS_INET6_OPT_INIT = 0x961
- SYS_INET6_OPT_APPEND = 0x962
- SYS_INET6_OPT_FINISH = 0x963
- SYS_INET6_OPT_SET_VAL = 0x964
- SYS_INET6_OPT_NEXT = 0x965
- SYS_INET6_OPT_FIND = 0x966
- SYS_INET6_OPT_GET_VAL = 0x967
- SYS___POW_I = 0x987
- SYS___POW_I_B = 0x988
- SYS___POW_I_H = 0x989
- SYS___CABS_H = 0x990
- SYS_CABSF = 0x991
- SYS___CABSF_B = 0x992
- SYS___CABSF_H = 0x993
- SYS_CABSL = 0x994
- SYS___CABSL_B = 0x995
- SYS___CABSL_H = 0x996
- SYS_CACOS = 0x997
- SYS___CACOS_B = 0x998
- SYS___CACOS_H = 0x999
+ SYS_LOG = 0x17 // 23
+ SYS_COSH = 0x18 // 24
+ SYS_TANH = 0x19 // 25
+ SYS_EXP = 0x1A // 26
+ SYS_MODF = 0x1B // 27
+ SYS_LOG10 = 0x1C // 28
+ SYS_FREXP = 0x1D // 29
+ SYS_LDEXP = 0x1E // 30
+ SYS_CEIL = 0x1F // 31
+ SYS_POW = 0x20 // 32
+ SYS_SQRT = 0x21 // 33
+ SYS_FLOOR = 0x22 // 34
+ SYS_J1 = 0x23 // 35
+ SYS_FABS = 0x24 // 36
+ SYS_FMOD = 0x25 // 37
+ SYS_J0 = 0x26 // 38
+ SYS_YN = 0x27 // 39
+ SYS_JN = 0x28 // 40
+ SYS_Y0 = 0x29 // 41
+ SYS_Y1 = 0x2A // 42
+ SYS_HYPOT = 0x2B // 43
+ SYS_ERF = 0x2C // 44
+ SYS_ERFC = 0x2D // 45
+ SYS_GAMMA = 0x2E // 46
+ SYS_ISALPHA = 0x30 // 48
+ SYS_ISALNUM = 0x31 // 49
+ SYS_ISLOWER = 0x32 // 50
+ SYS_ISCNTRL = 0x33 // 51
+ SYS_ISDIGIT = 0x34 // 52
+ SYS_ISGRAPH = 0x35 // 53
+ SYS_ISUPPER = 0x36 // 54
+ SYS_ISPRINT = 0x37 // 55
+ SYS_ISPUNCT = 0x38 // 56
+ SYS_ISSPACE = 0x39 // 57
+ SYS_SETLOCAL = 0x3A // 58
+ SYS_SETLOCALE = 0x3A // 58
+ SYS_ISXDIGIT = 0x3B // 59
+ SYS_TOLOWER = 0x3C // 60
+ SYS_TOUPPER = 0x3D // 61
+ SYS_ASIN = 0x3E // 62
+ SYS_SIN = 0x3F // 63
+ SYS_COS = 0x40 // 64
+ SYS_TAN = 0x41 // 65
+ SYS_SINH = 0x42 // 66
+ SYS_ACOS = 0x43 // 67
+ SYS_ATAN = 0x44 // 68
+ SYS_ATAN2 = 0x45 // 69
+ SYS_FTELL = 0x46 // 70
+ SYS_FGETPOS = 0x47 // 71
+ SYS_FSEEK = 0x48 // 72
+ SYS_FSETPOS = 0x49 // 73
+ SYS_FERROR = 0x4A // 74
+ SYS_REWIND = 0x4B // 75
+ SYS_CLEARERR = 0x4C // 76
+ SYS_FEOF = 0x4D // 77
+ SYS_ATOL = 0x4E // 78
+ SYS_PERROR = 0x4F // 79
+ SYS_ATOF = 0x50 // 80
+ SYS_ATOI = 0x51 // 81
+ SYS_RAND = 0x52 // 82
+ SYS_STRTOD = 0x53 // 83
+ SYS_STRTOL = 0x54 // 84
+ SYS_STRTOUL = 0x55 // 85
+ SYS_MALLOC = 0x56 // 86
+ SYS_SRAND = 0x57 // 87
+ SYS_CALLOC = 0x58 // 88
+ SYS_FREE = 0x59 // 89
+ SYS_EXIT = 0x5A // 90
+ SYS_REALLOC = 0x5B // 91
+ SYS_ABORT = 0x5C // 92
+ SYS___ABORT = 0x5C // 92
+ SYS_ATEXIT = 0x5D // 93
+ SYS_RAISE = 0x5E // 94
+ SYS_SETJMP = 0x5F // 95
+ SYS_LONGJMP = 0x60 // 96
+ SYS_SIGNAL = 0x61 // 97
+ SYS_TMPNAM = 0x62 // 98
+ SYS_REMOVE = 0x63 // 99
+ SYS_RENAME = 0x64 // 100
+ SYS_TMPFILE = 0x65 // 101
+ SYS_FREOPEN = 0x66 // 102
+ SYS_FCLOSE = 0x67 // 103
+ SYS_FFLUSH = 0x68 // 104
+ SYS_FOPEN = 0x69 // 105
+ SYS_FSCANF = 0x6A // 106
+ SYS_SETBUF = 0x6B // 107
+ SYS_SETVBUF = 0x6C // 108
+ SYS_FPRINTF = 0x6D // 109
+ SYS_SSCANF = 0x6E // 110
+ SYS_PRINTF = 0x6F // 111
+ SYS_SCANF = 0x70 // 112
+ SYS_SPRINTF = 0x71 // 113
+ SYS_FGETC = 0x72 // 114
+ SYS_VFPRINTF = 0x73 // 115
+ SYS_VPRINTF = 0x74 // 116
+ SYS_VSPRINTF = 0x75 // 117
+ SYS_GETC = 0x76 // 118
+ SYS_FGETS = 0x77 // 119
+ SYS_FPUTC = 0x78 // 120
+ SYS_FPUTS = 0x79 // 121
+ SYS_PUTCHAR = 0x7A // 122
+ SYS_GETCHAR = 0x7B // 123
+ SYS_GETS = 0x7C // 124
+ SYS_PUTC = 0x7D // 125
+ SYS_FWRITE = 0x7E // 126
+ SYS_PUTS = 0x7F // 127
+ SYS_UNGETC = 0x80 // 128
+ SYS_FREAD = 0x81 // 129
+ SYS_WCSTOMBS = 0x82 // 130
+ SYS_MBTOWC = 0x83 // 131
+ SYS_WCTOMB = 0x84 // 132
+ SYS_MBSTOWCS = 0x85 // 133
+ SYS_WCSCPY = 0x86 // 134
+ SYS_WCSCAT = 0x87 // 135
+ SYS_WCSCHR = 0x88 // 136
+ SYS_WCSCMP = 0x89 // 137
+ SYS_WCSNCMP = 0x8A // 138
+ SYS_WCSCSPN = 0x8B // 139
+ SYS_WCSLEN = 0x8C // 140
+ SYS_WCSNCAT = 0x8D // 141
+ SYS_WCSSPN = 0x8E // 142
+ SYS_WCSNCPY = 0x8F // 143
+ SYS_ABS = 0x90 // 144
+ SYS_DIV = 0x91 // 145
+ SYS_LABS = 0x92 // 146
+ SYS_STRNCPY = 0x93 // 147
+ SYS_MEMCPY = 0x94 // 148
+ SYS_MEMMOVE = 0x95 // 149
+ SYS_STRCPY = 0x96 // 150
+ SYS_STRCMP = 0x97 // 151
+ SYS_STRCAT = 0x98 // 152
+ SYS_STRNCAT = 0x99 // 153
+ SYS_MEMCMP = 0x9A // 154
+ SYS_MEMCHR = 0x9B // 155
+ SYS_STRCOLL = 0x9C // 156
+ SYS_STRNCMP = 0x9D // 157
+ SYS_STRXFRM = 0x9E // 158
+ SYS_STRRCHR = 0x9F // 159
+ SYS_STRCHR = 0xA0 // 160
+ SYS_STRCSPN = 0xA1 // 161
+ SYS_STRPBRK = 0xA2 // 162
+ SYS_MEMSET = 0xA3 // 163
+ SYS_STRSPN = 0xA4 // 164
+ SYS_STRSTR = 0xA5 // 165
+ SYS_STRTOK = 0xA6 // 166
+ SYS_DIFFTIME = 0xA7 // 167
+ SYS_STRERROR = 0xA8 // 168
+ SYS_STRLEN = 0xA9 // 169
+ SYS_CLOCK = 0xAA // 170
+ SYS_CTIME = 0xAB // 171
+ SYS_MKTIME = 0xAC // 172
+ SYS_TIME = 0xAD // 173
+ SYS_ASCTIME = 0xAE // 174
+ SYS_MBLEN = 0xAF // 175
+ SYS_GMTIME = 0xB0 // 176
+ SYS_LOCALTIM = 0xB1 // 177
+ SYS_LOCALTIME = 0xB1 // 177
+ SYS_STRFTIME = 0xB2 // 178
+ SYS___GETCB = 0xB4 // 180
+ SYS_FUPDATE = 0xB5 // 181
+ SYS___FUPDT = 0xB5 // 181
+ SYS_CLRMEMF = 0xBD // 189
+ SYS___CLRMF = 0xBD // 189
+ SYS_FETCHEP = 0xBF // 191
+ SYS___FTCHEP = 0xBF // 191
+ SYS_FLDATA = 0xC1 // 193
+ SYS___FLDATA = 0xC1 // 193
+ SYS_DYNFREE = 0xC2 // 194
+ SYS___DYNFRE = 0xC2 // 194
+ SYS_DYNALLOC = 0xC3 // 195
+ SYS___DYNALL = 0xC3 // 195
+ SYS___CDUMP = 0xC4 // 196
+ SYS_CSNAP = 0xC5 // 197
+ SYS___CSNAP = 0xC5 // 197
+ SYS_CTRACE = 0xC6 // 198
+ SYS___CTRACE = 0xC6 // 198
+ SYS___CTEST = 0xC7 // 199
+ SYS_SETENV = 0xC8 // 200
+ SYS___SETENV = 0xC8 // 200
+ SYS_CLEARENV = 0xC9 // 201
+ SYS___CLRENV = 0xC9 // 201
+ SYS___REGCOMP_STD = 0xEA // 234
+ SYS_NL_LANGINFO = 0xFC // 252
+ SYS_GETSYNTX = 0xFD // 253
+ SYS_ISBLANK = 0xFE // 254
+ SYS___ISBLNK = 0xFE // 254
+ SYS_ISWALNUM = 0xFF // 255
+ SYS_ISWALPHA = 0x100 // 256
+ SYS_ISWBLANK = 0x101 // 257
+ SYS___ISWBLK = 0x101 // 257
+ SYS_ISWCNTRL = 0x102 // 258
+ SYS_ISWDIGIT = 0x103 // 259
+ SYS_ISWGRAPH = 0x104 // 260
+ SYS_ISWLOWER = 0x105 // 261
+ SYS_ISWPRINT = 0x106 // 262
+ SYS_ISWPUNCT = 0x107 // 263
+ SYS_ISWSPACE = 0x108 // 264
+ SYS_ISWUPPER = 0x109 // 265
+ SYS_ISWXDIGI = 0x10A // 266
+ SYS_ISWXDIGIT = 0x10A // 266
+ SYS_WCTYPE = 0x10B // 267
+ SYS_ISWCTYPE = 0x10C // 268
+ SYS_TOWLOWER = 0x10D // 269
+ SYS_TOWUPPER = 0x10E // 270
+ SYS_MBSINIT = 0x10F // 271
+ SYS_WCTOB = 0x110 // 272
+ SYS_MBRLEN = 0x111 // 273
+ SYS_MBRTOWC = 0x112 // 274
+ SYS_MBSRTOWC = 0x113 // 275
+ SYS_MBSRTOWCS = 0x113 // 275
+ SYS_WCRTOMB = 0x114 // 276
+ SYS_WCSRTOMB = 0x115 // 277
+ SYS_WCSRTOMBS = 0x115 // 277
+ SYS___CSID = 0x116 // 278
+ SYS___WCSID = 0x117 // 279
+ SYS_STRPTIME = 0x118 // 280
+ SYS___STRPTM = 0x118 // 280
+ SYS_STRFMON = 0x119 // 281
+ SYS___RPMTCH = 0x11A // 282
+ SYS_WCSSTR = 0x11B // 283
+ SYS_WCSTOK = 0x12C // 300
+ SYS_WCSTOL = 0x12D // 301
+ SYS_WCSTOD = 0x12E // 302
+ SYS_WCSTOUL = 0x12F // 303
+ SYS_WCSCOLL = 0x130 // 304
+ SYS_WCSXFRM = 0x131 // 305
+ SYS_WCSWIDTH = 0x132 // 306
+ SYS_WCWIDTH = 0x133 // 307
+ SYS_WCSFTIME = 0x134 // 308
+ SYS_SWPRINTF = 0x135 // 309
+ SYS_VSWPRINT = 0x136 // 310
+ SYS_VSWPRINTF = 0x136 // 310
+ SYS_SWSCANF = 0x137 // 311
+ SYS_REGCOMP = 0x138 // 312
+ SYS_REGEXEC = 0x139 // 313
+ SYS_REGFREE = 0x13A // 314
+ SYS_REGERROR = 0x13B // 315
+ SYS_FGETWC = 0x13C // 316
+ SYS_FGETWS = 0x13D // 317
+ SYS_FPUTWC = 0x13E // 318
+ SYS_FPUTWS = 0x13F // 319
+ SYS_GETWC = 0x140 // 320
+ SYS_GETWCHAR = 0x141 // 321
+ SYS_PUTWC = 0x142 // 322
+ SYS_PUTWCHAR = 0x143 // 323
+ SYS_UNGETWC = 0x144 // 324
+ SYS_ICONV_OPEN = 0x145 // 325
+ SYS_ICONV = 0x146 // 326
+ SYS_ICONV_CLOSE = 0x147 // 327
+ SYS_ISMCCOLLEL = 0x14C // 332
+ SYS_STRTOCOLL = 0x14D // 333
+ SYS_COLLTOSTR = 0x14E // 334
+ SYS_COLLEQUIV = 0x14F // 335
+ SYS_COLLRANGE = 0x150 // 336
+ SYS_CCLASS = 0x151 // 337
+ SYS_COLLORDER = 0x152 // 338
+ SYS___DEMANGLE = 0x154 // 340
+ SYS_FDOPEN = 0x155 // 341
+ SYS___ERRNO = 0x156 // 342
+ SYS___ERRNO2 = 0x157 // 343
+ SYS___TERROR = 0x158 // 344
+ SYS_MAXCOLL = 0x169 // 361
+ SYS_GETMCCOLL = 0x16A // 362
+ SYS_GETWMCCOLL = 0x16B // 363
+ SYS___ERR2AD = 0x16C // 364
+ SYS_DLLQUERYFN = 0x16D // 365
+ SYS_DLLQUERYVAR = 0x16E // 366
+ SYS_DLLFREE = 0x16F // 367
+ SYS_DLLLOAD = 0x170 // 368
+ SYS__EXIT = 0x174 // 372
+ SYS_ACCESS = 0x175 // 373
+ SYS_ALARM = 0x176 // 374
+ SYS_CFGETISPEED = 0x177 // 375
+ SYS_CFGETOSPEED = 0x178 // 376
+ SYS_CFSETISPEED = 0x179 // 377
+ SYS_CFSETOSPEED = 0x17A // 378
+ SYS_CHDIR = 0x17B // 379
+ SYS_CHMOD = 0x17C // 380
+ SYS_CHOWN = 0x17D // 381
+ SYS_CLOSE = 0x17E // 382
+ SYS_CLOSEDIR = 0x17F // 383
+ SYS_CREAT = 0x180 // 384
+ SYS_CTERMID = 0x181 // 385
+ SYS_DUP = 0x182 // 386
+ SYS_DUP2 = 0x183 // 387
+ SYS_EXECL = 0x184 // 388
+ SYS_EXECLE = 0x185 // 389
+ SYS_EXECLP = 0x186 // 390
+ SYS_EXECV = 0x187 // 391
+ SYS_EXECVE = 0x188 // 392
+ SYS_EXECVP = 0x189 // 393
+ SYS_FCHMOD = 0x18A // 394
+ SYS_FCHOWN = 0x18B // 395
+ SYS_FCNTL = 0x18C // 396
+ SYS_FILENO = 0x18D // 397
+ SYS_FORK = 0x18E // 398
+ SYS_FPATHCONF = 0x18F // 399
+ SYS_FSTAT = 0x190 // 400
+ SYS_FSYNC = 0x191 // 401
+ SYS_FTRUNCATE = 0x192 // 402
+ SYS_GETCWD = 0x193 // 403
+ SYS_GETEGID = 0x194 // 404
+ SYS_GETEUID = 0x195 // 405
+ SYS_GETGID = 0x196 // 406
+ SYS_GETGRGID = 0x197 // 407
+ SYS_GETGRNAM = 0x198 // 408
+ SYS_GETGROUPS = 0x199 // 409
+ SYS_GETLOGIN = 0x19A // 410
+ SYS_W_GETMNTENT = 0x19B // 411
+ SYS_GETPGRP = 0x19C // 412
+ SYS_GETPID = 0x19D // 413
+ SYS_GETPPID = 0x19E // 414
+ SYS_GETPWNAM = 0x19F // 415
+ SYS_GETPWUID = 0x1A0 // 416
+ SYS_GETUID = 0x1A1 // 417
+ SYS_W_IOCTL = 0x1A2 // 418
+ SYS_ISATTY = 0x1A3 // 419
+ SYS_KILL = 0x1A4 // 420
+ SYS_LINK = 0x1A5 // 421
+ SYS_LSEEK = 0x1A6 // 422
+ SYS_LSTAT = 0x1A7 // 423
+ SYS_MKDIR = 0x1A8 // 424
+ SYS_MKFIFO = 0x1A9 // 425
+ SYS_MKNOD = 0x1AA // 426
+ SYS_MOUNT = 0x1AB // 427
+ SYS_OPEN = 0x1AC // 428
+ SYS_OPENDIR = 0x1AD // 429
+ SYS_PATHCONF = 0x1AE // 430
+ SYS_PAUSE = 0x1AF // 431
+ SYS_PIPE = 0x1B0 // 432
+ SYS_W_GETPSENT = 0x1B1 // 433
+ SYS_READ = 0x1B2 // 434
+ SYS_READDIR = 0x1B3 // 435
+ SYS_READLINK = 0x1B4 // 436
+ SYS_REWINDDIR = 0x1B5 // 437
+ SYS_RMDIR = 0x1B6 // 438
+ SYS_SETEGID = 0x1B7 // 439
+ SYS_SETEUID = 0x1B8 // 440
+ SYS_SETGID = 0x1B9 // 441
+ SYS_SETPGID = 0x1BA // 442
+ SYS_SETSID = 0x1BB // 443
+ SYS_SETUID = 0x1BC // 444
+ SYS_SIGACTION = 0x1BD // 445
+ SYS_SIGADDSET = 0x1BE // 446
+ SYS_SIGDELSET = 0x1BF // 447
+ SYS_SIGEMPTYSET = 0x1C0 // 448
+ SYS_SIGFILLSET = 0x1C1 // 449
+ SYS_SIGISMEMBER = 0x1C2 // 450
+ SYS_SIGLONGJMP = 0x1C3 // 451
+ SYS_SIGPENDING = 0x1C4 // 452
+ SYS_SIGPROCMASK = 0x1C5 // 453
+ SYS_SIGSETJMP = 0x1C6 // 454
+ SYS_SIGSUSPEND = 0x1C7 // 455
+ SYS_SLEEP = 0x1C8 // 456
+ SYS_STAT = 0x1C9 // 457
+ SYS_W_STATFS = 0x1CA // 458
+ SYS_SYMLINK = 0x1CB // 459
+ SYS_SYSCONF = 0x1CC // 460
+ SYS_TCDRAIN = 0x1CD // 461
+ SYS_TCFLOW = 0x1CE // 462
+ SYS_TCFLUSH = 0x1CF // 463
+ SYS_TCGETATTR = 0x1D0 // 464
+ SYS_TCGETPGRP = 0x1D1 // 465
+ SYS_TCSENDBREAK = 0x1D2 // 466
+ SYS_TCSETATTR = 0x1D3 // 467
+ SYS_TCSETPGRP = 0x1D4 // 468
+ SYS_TIMES = 0x1D5 // 469
+ SYS_TTYNAME = 0x1D6 // 470
+ SYS_TZSET = 0x1D7 // 471
+ SYS_UMASK = 0x1D8 // 472
+ SYS_UMOUNT = 0x1D9 // 473
+ SYS_UNAME = 0x1DA // 474
+ SYS_UNLINK = 0x1DB // 475
+ SYS_UTIME = 0x1DC // 476
+ SYS_WAIT = 0x1DD // 477
+ SYS_WAITPID = 0x1DE // 478
+ SYS_WRITE = 0x1DF // 479
+ SYS_CHAUDIT = 0x1E0 // 480
+ SYS_FCHAUDIT = 0x1E1 // 481
+ SYS_GETGROUPSBYNAME = 0x1E2 // 482
+ SYS_SIGWAIT = 0x1E3 // 483
+ SYS_PTHREAD_EXIT = 0x1E4 // 484
+ SYS_PTHREAD_KILL = 0x1E5 // 485
+ SYS_PTHREAD_ATTR_INIT = 0x1E6 // 486
+ SYS_PTHREAD_ATTR_DESTROY = 0x1E7 // 487
+ SYS_PTHREAD_ATTR_SETSTACKSIZE = 0x1E8 // 488
+ SYS_PTHREAD_ATTR_GETSTACKSIZE = 0x1E9 // 489
+ SYS_PTHREAD_ATTR_SETDETACHSTATE = 0x1EA // 490
+ SYS_PTHREAD_ATTR_GETDETACHSTATE = 0x1EB // 491
+ SYS_PTHREAD_ATTR_SETWEIGHT_NP = 0x1EC // 492
+ SYS_PTHREAD_ATTR_GETWEIGHT_NP = 0x1ED // 493
+ SYS_PTHREAD_CANCEL = 0x1EE // 494
+ SYS_PTHREAD_CLEANUP_PUSH = 0x1EF // 495
+ SYS_PTHREAD_CLEANUP_POP = 0x1F0 // 496
+ SYS_PTHREAD_CONDATTR_INIT = 0x1F1 // 497
+ SYS_PTHREAD_CONDATTR_DESTROY = 0x1F2 // 498
+ SYS_PTHREAD_COND_INIT = 0x1F3 // 499
+ SYS_PTHREAD_COND_DESTROY = 0x1F4 // 500
+ SYS_PTHREAD_COND_SIGNAL = 0x1F5 // 501
+ SYS_PTHREAD_COND_BROADCAST = 0x1F6 // 502
+ SYS_PTHREAD_COND_WAIT = 0x1F7 // 503
+ SYS_PTHREAD_COND_TIMEDWAIT = 0x1F8 // 504
+ SYS_PTHREAD_CREATE = 0x1F9 // 505
+ SYS_PTHREAD_DETACH = 0x1FA // 506
+ SYS_PTHREAD_EQUAL = 0x1FB // 507
+ SYS_PTHREAD_GETSPECIFIC = 0x1FC // 508
+ SYS_PTHREAD_JOIN = 0x1FD // 509
+ SYS_PTHREAD_KEY_CREATE = 0x1FE // 510
+ SYS_PTHREAD_MUTEXATTR_INIT = 0x1FF // 511
+ SYS_PTHREAD_MUTEXATTR_DESTROY = 0x200 // 512
+ SYS_PTHREAD_MUTEXATTR_SETKIND_NP = 0x201 // 513
+ SYS_PTHREAD_MUTEXATTR_GETKIND_NP = 0x202 // 514
+ SYS_PTHREAD_MUTEX_INIT = 0x203 // 515
+ SYS_PTHREAD_MUTEX_DESTROY = 0x204 // 516
+ SYS_PTHREAD_MUTEX_LOCK = 0x205 // 517
+ SYS_PTHREAD_MUTEX_TRYLOCK = 0x206 // 518
+ SYS_PTHREAD_MUTEX_UNLOCK = 0x207 // 519
+ SYS_PTHREAD_ONCE = 0x209 // 521
+ SYS_PTHREAD_SELF = 0x20A // 522
+ SYS_PTHREAD_SETINTR = 0x20B // 523
+ SYS_PTHREAD_SETINTRTYPE = 0x20C // 524
+ SYS_PTHREAD_SETSPECIFIC = 0x20D // 525
+ SYS_PTHREAD_TESTINTR = 0x20E // 526
+ SYS_PTHREAD_YIELD = 0x20F // 527
+ SYS_TW_OPEN = 0x210 // 528
+ SYS_TW_FCNTL = 0x211 // 529
+ SYS_PTHREAD_JOIN_D4_NP = 0x212 // 530
+ SYS_PTHREAD_CONDATTR_SETKIND_NP = 0x213 // 531
+ SYS_PTHREAD_CONDATTR_GETKIND_NP = 0x214 // 532
+ SYS_EXTLINK_NP = 0x215 // 533
+ SYS___PASSWD = 0x216 // 534
+ SYS_SETGROUPS = 0x217 // 535
+ SYS_INITGROUPS = 0x218 // 536
+ SYS_WCSPBRK = 0x23F // 575
+ SYS_WCSRCHR = 0x240 // 576
+ SYS_SVC99 = 0x241 // 577
+ SYS___SVC99 = 0x241 // 577
+ SYS_WCSWCS = 0x242 // 578
+ SYS_LOCALECO = 0x243 // 579
+ SYS_LOCALECONV = 0x243 // 579
+ SYS___LIBREL = 0x244 // 580
+ SYS_RELEASE = 0x245 // 581
+ SYS___RLSE = 0x245 // 581
+ SYS_FLOCATE = 0x246 // 582
+ SYS___FLOCT = 0x246 // 582
+ SYS_FDELREC = 0x247 // 583
+ SYS___FDLREC = 0x247 // 583
+ SYS_FETCH = 0x248 // 584
+ SYS___FETCH = 0x248 // 584
+ SYS_QSORT = 0x249 // 585
+ SYS_GETENV = 0x24A // 586
+ SYS_SYSTEM = 0x24B // 587
+ SYS_BSEARCH = 0x24C // 588
+ SYS_LDIV = 0x24D // 589
+ SYS___THROW = 0x25E // 606
+ SYS___RETHROW = 0x25F // 607
+ SYS___CLEANUPCATCH = 0x260 // 608
+ SYS___CATCHMATCH = 0x261 // 609
+ SYS___CLEAN2UPCATCH = 0x262 // 610
+ SYS_PUTENV = 0x26A // 618
+ SYS___GETENV = 0x26F // 623
+ SYS_GETPRIORITY = 0x270 // 624
+ SYS_NICE = 0x271 // 625
+ SYS_SETPRIORITY = 0x272 // 626
+ SYS_GETITIMER = 0x273 // 627
+ SYS_SETITIMER = 0x274 // 628
+ SYS_MSGCTL = 0x275 // 629
+ SYS_MSGGET = 0x276 // 630
+ SYS_MSGRCV = 0x277 // 631
+ SYS_MSGSND = 0x278 // 632
+ SYS_MSGXRCV = 0x279 // 633
+ SYS___MSGXR = 0x279 // 633
+ SYS_SEMCTL = 0x27A // 634
+ SYS_SEMGET = 0x27B // 635
+ SYS_SEMOP = 0x27C // 636
+ SYS_SHMAT = 0x27D // 637
+ SYS_SHMCTL = 0x27E // 638
+ SYS_SHMDT = 0x27F // 639
+ SYS_SHMGET = 0x280 // 640
+ SYS___GETIPC = 0x281 // 641
+ SYS_SETGRENT = 0x282 // 642
+ SYS_GETGRENT = 0x283 // 643
+ SYS_ENDGRENT = 0x284 // 644
+ SYS_SETPWENT = 0x285 // 645
+ SYS_GETPWENT = 0x286 // 646
+ SYS_ENDPWENT = 0x287 // 647
+ SYS_BSD_SIGNAL = 0x288 // 648
+ SYS_KILLPG = 0x289 // 649
+ SYS_SIGALTSTACK = 0x28A // 650
+ SYS_SIGHOLD = 0x28B // 651
+ SYS_SIGIGNORE = 0x28C // 652
+ SYS_SIGINTERRUPT = 0x28D // 653
+ SYS_SIGPAUSE = 0x28E // 654
+ SYS_SIGRELSE = 0x28F // 655
+ SYS_SIGSET = 0x290 // 656
+ SYS_SIGSTACK = 0x291 // 657
+ SYS_GETRLIMIT = 0x292 // 658
+ SYS_SETRLIMIT = 0x293 // 659
+ SYS_GETRUSAGE = 0x294 // 660
+ SYS_MMAP = 0x295 // 661
+ SYS_MPROTECT = 0x296 // 662
+ SYS_MSYNC = 0x297 // 663
+ SYS_MUNMAP = 0x298 // 664
+ SYS_CONFSTR = 0x299 // 665
+ SYS_GETOPT = 0x29A // 666
+ SYS_LCHOWN = 0x29B // 667
+ SYS_TRUNCATE = 0x29C // 668
+ SYS_GETSUBOPT = 0x29D // 669
+ SYS_SETPGRP = 0x29E // 670
+ SYS___GDERR = 0x29F // 671
+ SYS___TZONE = 0x2A0 // 672
+ SYS___DLGHT = 0x2A1 // 673
+ SYS___OPARGF = 0x2A2 // 674
+ SYS___OPOPTF = 0x2A3 // 675
+ SYS___OPINDF = 0x2A4 // 676
+ SYS___OPERRF = 0x2A5 // 677
+ SYS_GETDATE = 0x2A6 // 678
+ SYS_WAIT3 = 0x2A7 // 679
+ SYS_WAITID = 0x2A8 // 680
+ SYS___CATTRM = 0x2A9 // 681
+ SYS___GDTRM = 0x2AA // 682
+ SYS___RNDTRM = 0x2AB // 683
+ SYS_CRYPT = 0x2AC // 684
+ SYS_ENCRYPT = 0x2AD // 685
+ SYS_SETKEY = 0x2AE // 686
+ SYS___CNVBLK = 0x2AF // 687
+ SYS___CRYTRM = 0x2B0 // 688
+ SYS___ECRTRM = 0x2B1 // 689
+ SYS_DRAND48 = 0x2B2 // 690
+ SYS_ERAND48 = 0x2B3 // 691
+ SYS_FSTATVFS = 0x2B4 // 692
+ SYS_STATVFS = 0x2B5 // 693
+ SYS_CATCLOSE = 0x2B6 // 694
+ SYS_CATGETS = 0x2B7 // 695
+ SYS_CATOPEN = 0x2B8 // 696
+ SYS_BCMP = 0x2B9 // 697
+ SYS_BCOPY = 0x2BA // 698
+ SYS_BZERO = 0x2BB // 699
+ SYS_FFS = 0x2BC // 700
+ SYS_INDEX = 0x2BD // 701
+ SYS_RINDEX = 0x2BE // 702
+ SYS_STRCASECMP = 0x2BF // 703
+ SYS_STRDUP = 0x2C0 // 704
+ SYS_STRNCASECMP = 0x2C1 // 705
+ SYS_INITSTATE = 0x2C2 // 706
+ SYS_SETSTATE = 0x2C3 // 707
+ SYS_RANDOM = 0x2C4 // 708
+ SYS_SRANDOM = 0x2C5 // 709
+ SYS_HCREATE = 0x2C6 // 710
+ SYS_HDESTROY = 0x2C7 // 711
+ SYS_HSEARCH = 0x2C8 // 712
+ SYS_LFIND = 0x2C9 // 713
+ SYS_LSEARCH = 0x2CA // 714
+ SYS_TDELETE = 0x2CB // 715
+ SYS_TFIND = 0x2CC // 716
+ SYS_TSEARCH = 0x2CD // 717
+ SYS_TWALK = 0x2CE // 718
+ SYS_INSQUE = 0x2CF // 719
+ SYS_REMQUE = 0x2D0 // 720
+ SYS_POPEN = 0x2D1 // 721
+ SYS_PCLOSE = 0x2D2 // 722
+ SYS_SWAB = 0x2D3 // 723
+ SYS_MEMCCPY = 0x2D4 // 724
+ SYS_GETPAGESIZE = 0x2D8 // 728
+ SYS_FCHDIR = 0x2D9 // 729
+ SYS___OCLCK = 0x2DA // 730
+ SYS___ATOE = 0x2DB // 731
+ SYS___ATOE_L = 0x2DC // 732
+ SYS___ETOA = 0x2DD // 733
+ SYS___ETOA_L = 0x2DE // 734
+ SYS_SETUTXENT = 0x2DF // 735
+ SYS_GETUTXENT = 0x2E0 // 736
+ SYS_ENDUTXENT = 0x2E1 // 737
+ SYS_GETUTXID = 0x2E2 // 738
+ SYS_GETUTXLINE = 0x2E3 // 739
+ SYS_PUTUTXLINE = 0x2E4 // 740
+ SYS_FMTMSG = 0x2E5 // 741
+ SYS_JRAND48 = 0x2E6 // 742
+ SYS_LRAND48 = 0x2E7 // 743
+ SYS_MRAND48 = 0x2E8 // 744
+ SYS_NRAND48 = 0x2E9 // 745
+ SYS_LCONG48 = 0x2EA // 746
+ SYS_SRAND48 = 0x2EB // 747
+ SYS_SEED48 = 0x2EC // 748
+ SYS_ISASCII = 0x2ED // 749
+ SYS_TOASCII = 0x2EE // 750
+ SYS_A64L = 0x2EF // 751
+ SYS_L64A = 0x2F0 // 752
+ SYS_UALARM = 0x2F1 // 753
+ SYS_USLEEP = 0x2F2 // 754
+ SYS___UTXTRM = 0x2F3 // 755
+ SYS___SRCTRM = 0x2F4 // 756
+ SYS_FTIME = 0x2F5 // 757
+ SYS_GETTIMEOFDAY = 0x2F6 // 758
+ SYS_DBM_CLEARERR = 0x2F7 // 759
+ SYS_DBM_CLOSE = 0x2F8 // 760
+ SYS_DBM_DELETE = 0x2F9 // 761
+ SYS_DBM_ERROR = 0x2FA // 762
+ SYS_DBM_FETCH = 0x2FB // 763
+ SYS_DBM_FIRSTKEY = 0x2FC // 764
+ SYS_DBM_NEXTKEY = 0x2FD // 765
+ SYS_DBM_OPEN = 0x2FE // 766
+ SYS_DBM_STORE = 0x2FF // 767
+ SYS___NDMTRM = 0x300 // 768
+ SYS_FTOK = 0x301 // 769
+ SYS_BASENAME = 0x302 // 770
+ SYS_DIRNAME = 0x303 // 771
+ SYS_GETDTABLESIZE = 0x304 // 772
+ SYS_MKSTEMP = 0x305 // 773
+ SYS_MKTEMP = 0x306 // 774
+ SYS_NFTW = 0x307 // 775
+ SYS_GETWD = 0x308 // 776
+ SYS_LOCKF = 0x309 // 777
+ SYS__LONGJMP = 0x30D // 781
+ SYS__SETJMP = 0x30E // 782
+ SYS_VFORK = 0x30F // 783
+ SYS_WORDEXP = 0x310 // 784
+ SYS_WORDFREE = 0x311 // 785
+ SYS_GETPGID = 0x312 // 786
+ SYS_GETSID = 0x313 // 787
+ SYS___UTMPXNAME = 0x314 // 788
+ SYS_CUSERID = 0x315 // 789
+ SYS_GETPASS = 0x316 // 790
+ SYS_FNMATCH = 0x317 // 791
+ SYS_FTW = 0x318 // 792
+ SYS_GETW = 0x319 // 793
+ SYS_GLOB = 0x31A // 794
+ SYS_GLOBFREE = 0x31B // 795
+ SYS_PUTW = 0x31C // 796
+ SYS_SEEKDIR = 0x31D // 797
+ SYS_TELLDIR = 0x31E // 798
+ SYS_TEMPNAM = 0x31F // 799
+ SYS_ACOSH = 0x320 // 800
+ SYS_ASINH = 0x321 // 801
+ SYS_ATANH = 0x322 // 802
+ SYS_CBRT = 0x323 // 803
+ SYS_EXPM1 = 0x324 // 804
+ SYS_ILOGB = 0x325 // 805
+ SYS_LOGB = 0x326 // 806
+ SYS_LOG1P = 0x327 // 807
+ SYS_NEXTAFTER = 0x328 // 808
+ SYS_RINT = 0x329 // 809
+ SYS_REMAINDER = 0x32A // 810
+ SYS_SCALB = 0x32B // 811
+ SYS_LGAMMA = 0x32C // 812
+ SYS_TTYSLOT = 0x32D // 813
+ SYS_GETTIMEOFDAY_R = 0x32E // 814
+ SYS_SYNC = 0x32F // 815
+ SYS_SPAWN = 0x330 // 816
+ SYS_SPAWNP = 0x331 // 817
+ SYS_GETLOGIN_UU = 0x332 // 818
+ SYS_ECVT = 0x333 // 819
+ SYS_FCVT = 0x334 // 820
+ SYS_GCVT = 0x335 // 821
+ SYS_ACCEPT = 0x336 // 822
+ SYS_BIND = 0x337 // 823
+ SYS_CONNECT = 0x338 // 824
+ SYS_ENDHOSTENT = 0x339 // 825
+ SYS_ENDPROTOENT = 0x33A // 826
+ SYS_ENDSERVENT = 0x33B // 827
+ SYS_GETHOSTBYADDR_R = 0x33C // 828
+ SYS_GETHOSTBYADDR = 0x33D // 829
+ SYS_GETHOSTBYNAME_R = 0x33E // 830
+ SYS_GETHOSTBYNAME = 0x33F // 831
+ SYS_GETHOSTENT = 0x340 // 832
+ SYS_GETHOSTID = 0x341 // 833
+ SYS_GETHOSTNAME = 0x342 // 834
+ SYS_GETNETBYADDR = 0x343 // 835
+ SYS_GETNETBYNAME = 0x344 // 836
+ SYS_GETNETENT = 0x345 // 837
+ SYS_GETPEERNAME = 0x346 // 838
+ SYS_GETPROTOBYNAME = 0x347 // 839
+ SYS_GETPROTOBYNUMBER = 0x348 // 840
+ SYS_GETPROTOENT = 0x349 // 841
+ SYS_GETSERVBYNAME = 0x34A // 842
+ SYS_GETSERVBYPORT = 0x34B // 843
+ SYS_GETSERVENT = 0x34C // 844
+ SYS_GETSOCKNAME = 0x34D // 845
+ SYS_GETSOCKOPT = 0x34E // 846
+ SYS_INET_ADDR = 0x34F // 847
+ SYS_INET_LNAOF = 0x350 // 848
+ SYS_INET_MAKEADDR = 0x351 // 849
+ SYS_INET_NETOF = 0x352 // 850
+ SYS_INET_NETWORK = 0x353 // 851
+ SYS_INET_NTOA = 0x354 // 852
+ SYS_IOCTL = 0x355 // 853
+ SYS_LISTEN = 0x356 // 854
+ SYS_READV = 0x357 // 855
+ SYS_RECV = 0x358 // 856
+ SYS_RECVFROM = 0x359 // 857
+ SYS_SELECT = 0x35B // 859
+ SYS_SELECTEX = 0x35C // 860
+ SYS_SEND = 0x35D // 861
+ SYS_SENDTO = 0x35F // 863
+ SYS_SETHOSTENT = 0x360 // 864
+ SYS_SETNETENT = 0x361 // 865
+ SYS_SETPEER = 0x362 // 866
+ SYS_SETPROTOENT = 0x363 // 867
+ SYS_SETSERVENT = 0x364 // 868
+ SYS_SETSOCKOPT = 0x365 // 869
+ SYS_SHUTDOWN = 0x366 // 870
+ SYS_SOCKET = 0x367 // 871
+ SYS_SOCKETPAIR = 0x368 // 872
+ SYS_WRITEV = 0x369 // 873
+ SYS_CHROOT = 0x36A // 874
+ SYS_W_STATVFS = 0x36B // 875
+ SYS_ULIMIT = 0x36C // 876
+ SYS_ISNAN = 0x36D // 877
+ SYS_UTIMES = 0x36E // 878
+ SYS___H_ERRNO = 0x36F // 879
+ SYS_ENDNETENT = 0x370 // 880
+ SYS_CLOSELOG = 0x371 // 881
+ SYS_OPENLOG = 0x372 // 882
+ SYS_SETLOGMASK = 0x373 // 883
+ SYS_SYSLOG = 0x374 // 884
+ SYS_PTSNAME = 0x375 // 885
+ SYS_SETREUID = 0x376 // 886
+ SYS_SETREGID = 0x377 // 887
+ SYS_REALPATH = 0x378 // 888
+ SYS___SIGNGAM = 0x379 // 889
+ SYS_GRANTPT = 0x37A // 890
+ SYS_UNLOCKPT = 0x37B // 891
+ SYS_TCGETSID = 0x37C // 892
+ SYS___TCGETCP = 0x37D // 893
+ SYS___TCSETCP = 0x37E // 894
+ SYS___TCSETTABLES = 0x37F // 895
+ SYS_POLL = 0x380 // 896
+ SYS_REXEC = 0x381 // 897
+ SYS___ISASCII2 = 0x382 // 898
+ SYS___TOASCII2 = 0x383 // 899
+ SYS_CHPRIORITY = 0x384 // 900
+ SYS_PTHREAD_ATTR_SETSYNCTYPE_NP = 0x385 // 901
+ SYS_PTHREAD_ATTR_GETSYNCTYPE_NP = 0x386 // 902
+ SYS_PTHREAD_SET_LIMIT_NP = 0x387 // 903
+ SYS___STNETENT = 0x388 // 904
+ SYS___STPROTOENT = 0x389 // 905
+ SYS___STSERVENT = 0x38A // 906
+ SYS___STHOSTENT = 0x38B // 907
+ SYS_NLIST = 0x38C // 908
+ SYS___IPDBCS = 0x38D // 909
+ SYS___IPDSPX = 0x38E // 910
+ SYS___IPMSGC = 0x38F // 911
+ SYS___SELECT1 = 0x390 // 912
+ SYS_PTHREAD_SECURITY_NP = 0x391 // 913
+ SYS___CHECK_RESOURCE_AUTH_NP = 0x392 // 914
+ SYS___CONVERT_ID_NP = 0x393 // 915
+ SYS___OPENVMREL = 0x394 // 916
+ SYS_WMEMCHR = 0x395 // 917
+ SYS_WMEMCMP = 0x396 // 918
+ SYS_WMEMCPY = 0x397 // 919
+ SYS_WMEMMOVE = 0x398 // 920
+ SYS_WMEMSET = 0x399 // 921
+ SYS___FPUTWC = 0x400 // 1024
+ SYS___PUTWC = 0x401 // 1025
+ SYS___PWCHAR = 0x402 // 1026
+ SYS___WCSFTM = 0x403 // 1027
+ SYS___WCSTOK = 0x404 // 1028
+ SYS___WCWDTH = 0x405 // 1029
+ SYS_T_ACCEPT = 0x409 // 1033
+ SYS_T_ALLOC = 0x40A // 1034
+ SYS_T_BIND = 0x40B // 1035
+ SYS_T_CLOSE = 0x40C // 1036
+ SYS_T_CONNECT = 0x40D // 1037
+ SYS_T_ERROR = 0x40E // 1038
+ SYS_T_FREE = 0x40F // 1039
+ SYS_T_GETINFO = 0x410 // 1040
+ SYS_T_GETPROTADDR = 0x411 // 1041
+ SYS_T_GETSTATE = 0x412 // 1042
+ SYS_T_LISTEN = 0x413 // 1043
+ SYS_T_LOOK = 0x414 // 1044
+ SYS_T_OPEN = 0x415 // 1045
+ SYS_T_OPTMGMT = 0x416 // 1046
+ SYS_T_RCV = 0x417 // 1047
+ SYS_T_RCVCONNECT = 0x418 // 1048
+ SYS_T_RCVDIS = 0x419 // 1049
+ SYS_T_RCVREL = 0x41A // 1050
+ SYS_T_RCVUDATA = 0x41B // 1051
+ SYS_T_RCVUDERR = 0x41C // 1052
+ SYS_T_SND = 0x41D // 1053
+ SYS_T_SNDDIS = 0x41E // 1054
+ SYS_T_SNDREL = 0x41F // 1055
+ SYS_T_SNDUDATA = 0x420 // 1056
+ SYS_T_STRERROR = 0x421 // 1057
+ SYS_T_SYNC = 0x422 // 1058
+ SYS_T_UNBIND = 0x423 // 1059
+ SYS___T_ERRNO = 0x424 // 1060
+ SYS___RECVMSG2 = 0x425 // 1061
+ SYS___SENDMSG2 = 0x426 // 1062
+ SYS_FATTACH = 0x427 // 1063
+ SYS_FDETACH = 0x428 // 1064
+ SYS_GETMSG = 0x429 // 1065
+ SYS_GETPMSG = 0x42A // 1066
+ SYS_ISASTREAM = 0x42B // 1067
+ SYS_PUTMSG = 0x42C // 1068
+ SYS_PUTPMSG = 0x42D // 1069
+ SYS___ISPOSIXON = 0x42E // 1070
+ SYS___OPENMVSREL = 0x42F // 1071
+ SYS_GETCONTEXT = 0x430 // 1072
+ SYS_SETCONTEXT = 0x431 // 1073
+ SYS_MAKECONTEXT = 0x432 // 1074
+ SYS_SWAPCONTEXT = 0x433 // 1075
+ SYS_PTHREAD_GETSPECIFIC_D8_NP = 0x434 // 1076
+ SYS_GETCLIENTID = 0x470 // 1136
+ SYS___GETCLIENTID = 0x471 // 1137
+ SYS_GETSTABLESIZE = 0x472 // 1138
+ SYS_GETIBMOPT = 0x473 // 1139
+ SYS_GETIBMSOCKOPT = 0x474 // 1140
+ SYS_GIVESOCKET = 0x475 // 1141
+ SYS_IBMSFLUSH = 0x476 // 1142
+ SYS_MAXDESC = 0x477 // 1143
+ SYS_SETIBMOPT = 0x478 // 1144
+ SYS_SETIBMSOCKOPT = 0x479 // 1145
+ SYS_SOCK_DEBUG = 0x47A // 1146
+ SYS_SOCK_DO_TESTSTOR = 0x47D // 1149
+ SYS_TAKESOCKET = 0x47E // 1150
+ SYS___SERVER_INIT = 0x47F // 1151
+ SYS___SERVER_PWU = 0x480 // 1152
+ SYS_PTHREAD_TAG_NP = 0x481 // 1153
+ SYS___CONSOLE = 0x482 // 1154
+ SYS___WSINIT = 0x483 // 1155
+ SYS___IPTCPN = 0x489 // 1161
+ SYS___SMF_RECORD = 0x48A // 1162
+ SYS___IPHOST = 0x48B // 1163
+ SYS___IPNODE = 0x48C // 1164
+ SYS___SERVER_CLASSIFY_CREATE = 0x48D // 1165
+ SYS___SERVER_CLASSIFY_DESTROY = 0x48E // 1166
+ SYS___SERVER_CLASSIFY_RESET = 0x48F // 1167
+ SYS___SERVER_CLASSIFY = 0x490 // 1168
+ SYS___HEAPRPT = 0x496 // 1174
+ SYS___FNWSA = 0x49B // 1179
+ SYS___SPAWN2 = 0x49D // 1181
+ SYS___SPAWNP2 = 0x49E // 1182
+ SYS___GDRR = 0x4A1 // 1185
+ SYS___HRRNO = 0x4A2 // 1186
+ SYS___OPRG = 0x4A3 // 1187
+ SYS___OPRR = 0x4A4 // 1188
+ SYS___OPND = 0x4A5 // 1189
+ SYS___OPPT = 0x4A6 // 1190
+ SYS___SIGGM = 0x4A7 // 1191
+ SYS___DGHT = 0x4A8 // 1192
+ SYS___TZNE = 0x4A9 // 1193
+ SYS___TZZN = 0x4AA // 1194
+ SYS___TRRNO = 0x4AF // 1199
+ SYS___ENVN = 0x4B0 // 1200
+ SYS___MLOCKALL = 0x4B1 // 1201
+ SYS_CREATEWO = 0x4B2 // 1202
+ SYS_CREATEWORKUNIT = 0x4B2 // 1202
+ SYS_CONTINUE = 0x4B3 // 1203
+ SYS_CONTINUEWORKUNIT = 0x4B3 // 1203
+ SYS_CONNECTW = 0x4B4 // 1204
+ SYS_CONNECTWORKMGR = 0x4B4 // 1204
+ SYS_CONNECTS = 0x4B5 // 1205
+ SYS_CONNECTSERVER = 0x4B5 // 1205
+ SYS_DISCONNE = 0x4B6 // 1206
+ SYS_DISCONNECTSERVER = 0x4B6 // 1206
+ SYS_JOINWORK = 0x4B7 // 1207
+ SYS_JOINWORKUNIT = 0x4B7 // 1207
+ SYS_LEAVEWOR = 0x4B8 // 1208
+ SYS_LEAVEWORKUNIT = 0x4B8 // 1208
+ SYS_DELETEWO = 0x4B9 // 1209
+ SYS_DELETEWORKUNIT = 0x4B9 // 1209
+ SYS_QUERYMET = 0x4BA // 1210
+ SYS_QUERYMETRICS = 0x4BA // 1210
+ SYS_QUERYSCH = 0x4BB // 1211
+ SYS_QUERYSCHENV = 0x4BB // 1211
+ SYS_CHECKSCH = 0x4BC // 1212
+ SYS_CHECKSCHENV = 0x4BC // 1212
+ SYS___PID_AFFINITY = 0x4BD // 1213
+ SYS___ASINH_B = 0x4BE // 1214
+ SYS___ATAN_B = 0x4BF // 1215
+ SYS___CBRT_B = 0x4C0 // 1216
+ SYS___CEIL_B = 0x4C1 // 1217
+ SYS_COPYSIGN = 0x4C2 // 1218
+ SYS___COS_B = 0x4C3 // 1219
+ SYS___ERF_B = 0x4C4 // 1220
+ SYS___ERFC_B = 0x4C5 // 1221
+ SYS___EXPM1_B = 0x4C6 // 1222
+ SYS___FABS_B = 0x4C7 // 1223
+ SYS_FINITE = 0x4C8 // 1224
+ SYS___FLOOR_B = 0x4C9 // 1225
+ SYS___FREXP_B = 0x4CA // 1226
+ SYS___ILOGB_B = 0x4CB // 1227
+ SYS___ISNAN_B = 0x4CC // 1228
+ SYS___LDEXP_B = 0x4CD // 1229
+ SYS___LOG1P_B = 0x4CE // 1230
+ SYS___LOGB_B = 0x4CF // 1231
+ SYS_MATHERR = 0x4D0 // 1232
+ SYS___MODF_B = 0x4D1 // 1233
+ SYS___NEXTAFTER_B = 0x4D2 // 1234
+ SYS___RINT_B = 0x4D3 // 1235
+ SYS_SCALBN = 0x4D4 // 1236
+ SYS_SIGNIFIC = 0x4D5 // 1237
+ SYS_SIGNIFICAND = 0x4D5 // 1237
+ SYS___SIN_B = 0x4D6 // 1238
+ SYS___TAN_B = 0x4D7 // 1239
+ SYS___TANH_B = 0x4D8 // 1240
+ SYS___ACOS_B = 0x4D9 // 1241
+ SYS___ACOSH_B = 0x4DA // 1242
+ SYS___ASIN_B = 0x4DB // 1243
+ SYS___ATAN2_B = 0x4DC // 1244
+ SYS___ATANH_B = 0x4DD // 1245
+ SYS___COSH_B = 0x4DE // 1246
+ SYS___EXP_B = 0x4DF // 1247
+ SYS___FMOD_B = 0x4E0 // 1248
+ SYS___GAMMA_B = 0x4E1 // 1249
+ SYS_GAMMA_R = 0x4E2 // 1250
+ SYS___HYPOT_B = 0x4E3 // 1251
+ SYS___J0_B = 0x4E4 // 1252
+ SYS___Y0_B = 0x4E5 // 1253
+ SYS___J1_B = 0x4E6 // 1254
+ SYS___Y1_B = 0x4E7 // 1255
+ SYS___JN_B = 0x4E8 // 1256
+ SYS___YN_B = 0x4E9 // 1257
+ SYS___LGAMMA_B = 0x4EA // 1258
+ SYS_LGAMMA_R = 0x4EB // 1259
+ SYS___LOG_B = 0x4EC // 1260
+ SYS___LOG10_B = 0x4ED // 1261
+ SYS___POW_B = 0x4EE // 1262
+ SYS___REMAINDER_B = 0x4EF // 1263
+ SYS___SCALB_B = 0x4F0 // 1264
+ SYS___SINH_B = 0x4F1 // 1265
+ SYS___SQRT_B = 0x4F2 // 1266
+ SYS___OPENDIR2 = 0x4F3 // 1267
+ SYS___READDIR2 = 0x4F4 // 1268
+ SYS___LOGIN = 0x4F5 // 1269
+ SYS___OPEN_STAT = 0x4F6 // 1270
+ SYS_ACCEPT_AND_RECV = 0x4F7 // 1271
+ SYS___FP_SETMODE = 0x4F8 // 1272
+ SYS___SIGACTIONSET = 0x4FB // 1275
+ SYS___UCREATE = 0x4FC // 1276
+ SYS___UMALLOC = 0x4FD // 1277
+ SYS___UFREE = 0x4FE // 1278
+ SYS___UHEAPREPORT = 0x4FF // 1279
+ SYS___ISBFP = 0x500 // 1280
+ SYS___FP_CAST = 0x501 // 1281
+ SYS___CERTIFICATE = 0x502 // 1282
+ SYS_SEND_FILE = 0x503 // 1283
+ SYS_AIO_CANCEL = 0x504 // 1284
+ SYS_AIO_ERROR = 0x505 // 1285
+ SYS_AIO_READ = 0x506 // 1286
+ SYS_AIO_RETURN = 0x507 // 1287
+ SYS_AIO_SUSPEND = 0x508 // 1288
+ SYS_AIO_WRITE = 0x509 // 1289
+ SYS_PTHREAD_MUTEXATTR_GETPSHARED = 0x50A // 1290
+ SYS_PTHREAD_MUTEXATTR_SETPSHARED = 0x50B // 1291
+ SYS_PTHREAD_RWLOCK_DESTROY = 0x50C // 1292
+ SYS_PTHREAD_RWLOCK_INIT = 0x50D // 1293
+ SYS_PTHREAD_RWLOCK_RDLOCK = 0x50E // 1294
+ SYS_PTHREAD_RWLOCK_TRYRDLOCK = 0x50F // 1295
+ SYS_PTHREAD_RWLOCK_TRYWRLOCK = 0x510 // 1296
+ SYS_PTHREAD_RWLOCK_UNLOCK = 0x511 // 1297
+ SYS_PTHREAD_RWLOCK_WRLOCK = 0x512 // 1298
+ SYS_PTHREAD_RWLOCKATTR_GETPSHARED = 0x513 // 1299
+ SYS_PTHREAD_RWLOCKATTR_SETPSHARED = 0x514 // 1300
+ SYS_PTHREAD_RWLOCKATTR_INIT = 0x515 // 1301
+ SYS_PTHREAD_RWLOCKATTR_DESTROY = 0x516 // 1302
+ SYS___CTTBL = 0x517 // 1303
+ SYS_PTHREAD_MUTEXATTR_SETTYPE = 0x518 // 1304
+ SYS_PTHREAD_MUTEXATTR_GETTYPE = 0x519 // 1305
+ SYS___FP_CLR_FLAG = 0x51A // 1306
+ SYS___FP_READ_FLAG = 0x51B // 1307
+ SYS___FP_RAISE_XCP = 0x51C // 1308
+ SYS___FP_CLASS = 0x51D // 1309
+ SYS___FP_FINITE = 0x51E // 1310
+ SYS___FP_ISNAN = 0x51F // 1311
+ SYS___FP_UNORDERED = 0x520 // 1312
+ SYS___FP_READ_RND = 0x521 // 1313
+ SYS___FP_READ_RND_B = 0x522 // 1314
+ SYS___FP_SWAP_RND = 0x523 // 1315
+ SYS___FP_SWAP_RND_B = 0x524 // 1316
+ SYS___FP_LEVEL = 0x525 // 1317
+ SYS___FP_BTOH = 0x526 // 1318
+ SYS___FP_HTOB = 0x527 // 1319
+ SYS___FPC_RD = 0x528 // 1320
+ SYS___FPC_WR = 0x529 // 1321
+ SYS___FPC_RW = 0x52A // 1322
+ SYS___FPC_SM = 0x52B // 1323
+ SYS___FPC_RS = 0x52C // 1324
+ SYS_SIGTIMEDWAIT = 0x52D // 1325
+ SYS_SIGWAITINFO = 0x52E // 1326
+ SYS___CHKBFP = 0x52F // 1327
+ SYS___W_PIOCTL = 0x59E // 1438
+ SYS___OSENV = 0x59F // 1439
+ SYS_EXPORTWO = 0x5A1 // 1441
+ SYS_EXPORTWORKUNIT = 0x5A1 // 1441
+ SYS_UNDOEXPO = 0x5A2 // 1442
+ SYS_UNDOEXPORTWORKUNIT = 0x5A2 // 1442
+ SYS_IMPORTWO = 0x5A3 // 1443
+ SYS_IMPORTWORKUNIT = 0x5A3 // 1443
+ SYS_UNDOIMPO = 0x5A4 // 1444
+ SYS_UNDOIMPORTWORKUNIT = 0x5A4 // 1444
+ SYS_EXTRACTW = 0x5A5 // 1445
+ SYS_EXTRACTWORKUNIT = 0x5A5 // 1445
+ SYS___CPL = 0x5A6 // 1446
+ SYS___MAP_INIT = 0x5A7 // 1447
+ SYS___MAP_SERVICE = 0x5A8 // 1448
+ SYS_SIGQUEUE = 0x5A9 // 1449
+ SYS___MOUNT = 0x5AA // 1450
+ SYS___GETUSERID = 0x5AB // 1451
+ SYS___IPDOMAINNAME = 0x5AC // 1452
+ SYS_QUERYENC = 0x5AD // 1453
+ SYS_QUERYWORKUNITCLASSIFICATION = 0x5AD // 1453
+ SYS_CONNECTE = 0x5AE // 1454
+ SYS_CONNECTEXPORTIMPORT = 0x5AE // 1454
+ SYS___FP_SWAPMODE = 0x5AF // 1455
+ SYS_STRTOLL = 0x5B0 // 1456
+ SYS_STRTOULL = 0x5B1 // 1457
+ SYS___DSA_PREV = 0x5B2 // 1458
+ SYS___EP_FIND = 0x5B3 // 1459
+ SYS___SERVER_THREADS_QUERY = 0x5B4 // 1460
+ SYS___MSGRCV_TIMED = 0x5B7 // 1463
+ SYS___SEMOP_TIMED = 0x5B8 // 1464
+ SYS___GET_CPUID = 0x5B9 // 1465
+ SYS___GET_SYSTEM_SETTINGS = 0x5BA // 1466
+ SYS_FTELLO = 0x5C8 // 1480
+ SYS_FSEEKO = 0x5C9 // 1481
+ SYS_LLDIV = 0x5CB // 1483
+ SYS_WCSTOLL = 0x5CC // 1484
+ SYS_WCSTOULL = 0x5CD // 1485
+ SYS_LLABS = 0x5CE // 1486
+ SYS___CONSOLE2 = 0x5D2 // 1490
+ SYS_INET_NTOP = 0x5D3 // 1491
+ SYS_INET_PTON = 0x5D4 // 1492
+ SYS___RES = 0x5D6 // 1494
+ SYS_RES_MKQUERY = 0x5D7 // 1495
+ SYS_RES_INIT = 0x5D8 // 1496
+ SYS_RES_QUERY = 0x5D9 // 1497
+ SYS_RES_SEARCH = 0x5DA // 1498
+ SYS_RES_SEND = 0x5DB // 1499
+ SYS_RES_QUERYDOMAIN = 0x5DC // 1500
+ SYS_DN_EXPAND = 0x5DD // 1501
+ SYS_DN_SKIPNAME = 0x5DE // 1502
+ SYS_DN_COMP = 0x5DF // 1503
+ SYS_ASCTIME_R = 0x5E0 // 1504
+ SYS_CTIME_R = 0x5E1 // 1505
+ SYS_GMTIME_R = 0x5E2 // 1506
+ SYS_LOCALTIME_R = 0x5E3 // 1507
+ SYS_RAND_R = 0x5E4 // 1508
+ SYS_STRTOK_R = 0x5E5 // 1509
+ SYS_READDIR_R = 0x5E6 // 1510
+ SYS_GETGRGID_R = 0x5E7 // 1511
+ SYS_GETGRNAM_R = 0x5E8 // 1512
+ SYS_GETLOGIN_R = 0x5E9 // 1513
+ SYS_GETPWNAM_R = 0x5EA // 1514
+ SYS_GETPWUID_R = 0x5EB // 1515
+ SYS_TTYNAME_R = 0x5EC // 1516
+ SYS_PTHREAD_ATFORK = 0x5ED // 1517
+ SYS_PTHREAD_ATTR_GETGUARDSIZE = 0x5EE // 1518
+ SYS_PTHREAD_ATTR_GETSTACKADDR = 0x5EF // 1519
+ SYS_PTHREAD_ATTR_SETGUARDSIZE = 0x5F0 // 1520
+ SYS_PTHREAD_ATTR_SETSTACKADDR = 0x5F1 // 1521
+ SYS_PTHREAD_CONDATTR_GETPSHARED = 0x5F2 // 1522
+ SYS_PTHREAD_CONDATTR_SETPSHARED = 0x5F3 // 1523
+ SYS_PTHREAD_GETCONCURRENCY = 0x5F4 // 1524
+ SYS_PTHREAD_KEY_DELETE = 0x5F5 // 1525
+ SYS_PTHREAD_SETCONCURRENCY = 0x5F6 // 1526
+ SYS_PTHREAD_SIGMASK = 0x5F7 // 1527
+ SYS___DISCARDDATA = 0x5F8 // 1528
+ SYS_PTHREAD_ATTR_GETSCHEDPARAM = 0x5F9 // 1529
+ SYS_PTHREAD_ATTR_SETSCHEDPARAM = 0x5FA // 1530
+ SYS_PTHREAD_ATTR_GETDETACHSTATE_U98 = 0x5FB // 1531
+ SYS_PTHREAD_ATTR_SETDETACHSTATE_U98 = 0x5FC // 1532
+ SYS_PTHREAD_DETACH_U98 = 0x5FD // 1533
+ SYS_PTHREAD_GETSPECIFIC_U98 = 0x5FE // 1534
+ SYS_PTHREAD_SETCANCELSTATE = 0x5FF // 1535
+ SYS_PTHREAD_SETCANCELTYPE = 0x600 // 1536
+ SYS_PTHREAD_TESTCANCEL = 0x601 // 1537
+ SYS___ATANF_B = 0x602 // 1538
+ SYS___ATANL_B = 0x603 // 1539
+ SYS___CEILF_B = 0x604 // 1540
+ SYS___CEILL_B = 0x605 // 1541
+ SYS___COSF_B = 0x606 // 1542
+ SYS___COSL_B = 0x607 // 1543
+ SYS___FABSF_B = 0x608 // 1544
+ SYS___FABSL_B = 0x609 // 1545
+ SYS___FLOORF_B = 0x60A // 1546
+ SYS___FLOORL_B = 0x60B // 1547
+ SYS___FREXPF_B = 0x60C // 1548
+ SYS___FREXPL_B = 0x60D // 1549
+ SYS___LDEXPF_B = 0x60E // 1550
+ SYS___LDEXPL_B = 0x60F // 1551
+ SYS___SINF_B = 0x610 // 1552
+ SYS___SINL_B = 0x611 // 1553
+ SYS___TANF_B = 0x612 // 1554
+ SYS___TANL_B = 0x613 // 1555
+ SYS___TANHF_B = 0x614 // 1556
+ SYS___TANHL_B = 0x615 // 1557
+ SYS___ACOSF_B = 0x616 // 1558
+ SYS___ACOSL_B = 0x617 // 1559
+ SYS___ASINF_B = 0x618 // 1560
+ SYS___ASINL_B = 0x619 // 1561
+ SYS___ATAN2F_B = 0x61A // 1562
+ SYS___ATAN2L_B = 0x61B // 1563
+ SYS___COSHF_B = 0x61C // 1564
+ SYS___COSHL_B = 0x61D // 1565
+ SYS___EXPF_B = 0x61E // 1566
+ SYS___EXPL_B = 0x61F // 1567
+ SYS___LOGF_B = 0x620 // 1568
+ SYS___LOGL_B = 0x621 // 1569
+ SYS___LOG10F_B = 0x622 // 1570
+ SYS___LOG10L_B = 0x623 // 1571
+ SYS___POWF_B = 0x624 // 1572
+ SYS___POWL_B = 0x625 // 1573
+ SYS___SINHF_B = 0x626 // 1574
+ SYS___SINHL_B = 0x627 // 1575
+ SYS___SQRTF_B = 0x628 // 1576
+ SYS___SQRTL_B = 0x629 // 1577
+ SYS___ABSF_B = 0x62A // 1578
+ SYS___ABS_B = 0x62B // 1579
+ SYS___ABSL_B = 0x62C // 1580
+ SYS___FMODF_B = 0x62D // 1581
+ SYS___FMODL_B = 0x62E // 1582
+ SYS___MODFF_B = 0x62F // 1583
+ SYS___MODFL_B = 0x630 // 1584
+ SYS_ABSF = 0x631 // 1585
+ SYS_ABSL = 0x632 // 1586
+ SYS_ACOSF = 0x633 // 1587
+ SYS_ACOSL = 0x634 // 1588
+ SYS_ASINF = 0x635 // 1589
+ SYS_ASINL = 0x636 // 1590
+ SYS_ATAN2F = 0x637 // 1591
+ SYS_ATAN2L = 0x638 // 1592
+ SYS_ATANF = 0x639 // 1593
+ SYS_ATANL = 0x63A // 1594
+ SYS_CEILF = 0x63B // 1595
+ SYS_CEILL = 0x63C // 1596
+ SYS_COSF = 0x63D // 1597
+ SYS_COSL = 0x63E // 1598
+ SYS_COSHF = 0x63F // 1599
+ SYS_COSHL = 0x640 // 1600
+ SYS_EXPF = 0x641 // 1601
+ SYS_EXPL = 0x642 // 1602
+ SYS_TANHF = 0x643 // 1603
+ SYS_TANHL = 0x644 // 1604
+ SYS_LOG10F = 0x645 // 1605
+ SYS_LOG10L = 0x646 // 1606
+ SYS_LOGF = 0x647 // 1607
+ SYS_LOGL = 0x648 // 1608
+ SYS_POWF = 0x649 // 1609
+ SYS_POWL = 0x64A // 1610
+ SYS_SINF = 0x64B // 1611
+ SYS_SINL = 0x64C // 1612
+ SYS_SQRTF = 0x64D // 1613
+ SYS_SQRTL = 0x64E // 1614
+ SYS_SINHF = 0x64F // 1615
+ SYS_SINHL = 0x650 // 1616
+ SYS_TANF = 0x651 // 1617
+ SYS_TANL = 0x652 // 1618
+ SYS_FABSF = 0x653 // 1619
+ SYS_FABSL = 0x654 // 1620
+ SYS_FLOORF = 0x655 // 1621
+ SYS_FLOORL = 0x656 // 1622
+ SYS_FMODF = 0x657 // 1623
+ SYS_FMODL = 0x658 // 1624
+ SYS_FREXPF = 0x659 // 1625
+ SYS_FREXPL = 0x65A // 1626
+ SYS_LDEXPF = 0x65B // 1627
+ SYS_LDEXPL = 0x65C // 1628
+ SYS_MODFF = 0x65D // 1629
+ SYS_MODFL = 0x65E // 1630
+ SYS_BTOWC = 0x65F // 1631
+ SYS___CHATTR = 0x660 // 1632
+ SYS___FCHATTR = 0x661 // 1633
+ SYS___TOCCSID = 0x662 // 1634
+ SYS___CSNAMETYPE = 0x663 // 1635
+ SYS___TOCSNAME = 0x664 // 1636
+ SYS___CCSIDTYPE = 0x665 // 1637
+ SYS___AE_CORRESTBL_QUERY = 0x666 // 1638
+ SYS___AE_AUTOCONVERT_STATE = 0x667 // 1639
+ SYS_DN_FIND = 0x668 // 1640
+ SYS___GETHOSTBYADDR_A = 0x669 // 1641
+ SYS___GETHOSTBYNAME_A = 0x66A // 1642
+ SYS___RES_INIT_A = 0x66B // 1643
+ SYS___GETHOSTBYADDR_R_A = 0x66C // 1644
+ SYS___GETHOSTBYNAME_R_A = 0x66D // 1645
+ SYS___CHARMAP_INIT_A = 0x66E // 1646
+ SYS___MBLEN_A = 0x66F // 1647
+ SYS___MBLEN_SB_A = 0x670 // 1648
+ SYS___MBLEN_STD_A = 0x671 // 1649
+ SYS___MBLEN_UTF = 0x672 // 1650
+ SYS___MBSTOWCS_A = 0x673 // 1651
+ SYS___MBSTOWCS_STD_A = 0x674 // 1652
+ SYS___MBTOWC_A = 0x675 // 1653
+ SYS___MBTOWC_ISO1 = 0x676 // 1654
+ SYS___MBTOWC_SBCS = 0x677 // 1655
+ SYS___MBTOWC_MBCS = 0x678 // 1656
+ SYS___MBTOWC_UTF = 0x679 // 1657
+ SYS___WCSTOMBS_A = 0x67A // 1658
+ SYS___WCSTOMBS_STD_A = 0x67B // 1659
+ SYS___WCSWIDTH_A = 0x67C // 1660
+ SYS___GETGRGID_R_A = 0x67D // 1661
+ SYS___WCSWIDTH_STD_A = 0x67E // 1662
+ SYS___WCSWIDTH_ASIA = 0x67F // 1663
+ SYS___CSID_A = 0x680 // 1664
+ SYS___CSID_STD_A = 0x681 // 1665
+ SYS___WCSID_A = 0x682 // 1666
+ SYS___WCSID_STD_A = 0x683 // 1667
+ SYS___WCTOMB_A = 0x684 // 1668
+ SYS___WCTOMB_ISO1 = 0x685 // 1669
+ SYS___WCTOMB_STD_A = 0x686 // 1670
+ SYS___WCTOMB_UTF = 0x687 // 1671
+ SYS___WCWIDTH_A = 0x688 // 1672
+ SYS___GETGRNAM_R_A = 0x689 // 1673
+ SYS___WCWIDTH_STD_A = 0x68A // 1674
+ SYS___WCWIDTH_ASIA = 0x68B // 1675
+ SYS___GETPWNAM_R_A = 0x68C // 1676
+ SYS___GETPWUID_R_A = 0x68D // 1677
+ SYS___GETLOGIN_R_A = 0x68E // 1678
+ SYS___TTYNAME_R_A = 0x68F // 1679
+ SYS___READDIR_R_A = 0x690 // 1680
+ SYS___E2A_S = 0x691 // 1681
+ SYS___FNMATCH_A = 0x692 // 1682
+ SYS___FNMATCH_C_A = 0x693 // 1683
+ SYS___EXECL_A = 0x694 // 1684
+ SYS___FNMATCH_STD_A = 0x695 // 1685
+ SYS___REGCOMP_A = 0x696 // 1686
+ SYS___REGCOMP_STD_A = 0x697 // 1687
+ SYS___REGERROR_A = 0x698 // 1688
+ SYS___REGERROR_STD_A = 0x699 // 1689
+ SYS___REGEXEC_A = 0x69A // 1690
+ SYS___REGEXEC_STD_A = 0x69B // 1691
+ SYS___REGFREE_A = 0x69C // 1692
+ SYS___REGFREE_STD_A = 0x69D // 1693
+ SYS___STRCOLL_A = 0x69E // 1694
+ SYS___STRCOLL_C_A = 0x69F // 1695
+ SYS___EXECLE_A = 0x6A0 // 1696
+ SYS___STRCOLL_STD_A = 0x6A1 // 1697
+ SYS___STRXFRM_A = 0x6A2 // 1698
+ SYS___STRXFRM_C_A = 0x6A3 // 1699
+ SYS___EXECLP_A = 0x6A4 // 1700
+ SYS___STRXFRM_STD_A = 0x6A5 // 1701
+ SYS___WCSCOLL_A = 0x6A6 // 1702
+ SYS___WCSCOLL_C_A = 0x6A7 // 1703
+ SYS___WCSCOLL_STD_A = 0x6A8 // 1704
+ SYS___WCSXFRM_A = 0x6A9 // 1705
+ SYS___WCSXFRM_C_A = 0x6AA // 1706
+ SYS___WCSXFRM_STD_A = 0x6AB // 1707
+ SYS___COLLATE_INIT_A = 0x6AC // 1708
+ SYS___WCTYPE_A = 0x6AD // 1709
+ SYS___GET_WCTYPE_STD_A = 0x6AE // 1710
+ SYS___CTYPE_INIT_A = 0x6AF // 1711
+ SYS___ISWCTYPE_A = 0x6B0 // 1712
+ SYS___EXECV_A = 0x6B1 // 1713
+ SYS___IS_WCTYPE_STD_A = 0x6B2 // 1714
+ SYS___TOWLOWER_A = 0x6B3 // 1715
+ SYS___TOWLOWER_STD_A = 0x6B4 // 1716
+ SYS___TOWUPPER_A = 0x6B5 // 1717
+ SYS___TOWUPPER_STD_A = 0x6B6 // 1718
+ SYS___LOCALE_INIT_A = 0x6B7 // 1719
+ SYS___LOCALECONV_A = 0x6B8 // 1720
+ SYS___LOCALECONV_STD_A = 0x6B9 // 1721
+ SYS___NL_LANGINFO_A = 0x6BA // 1722
+ SYS___NL_LNAGINFO_STD_A = 0x6BB // 1723
+ SYS___MONETARY_INIT_A = 0x6BC // 1724
+ SYS___STRFMON_A = 0x6BD // 1725
+ SYS___STRFMON_STD_A = 0x6BE // 1726
+ SYS___GETADDRINFO_A = 0x6BF // 1727
+ SYS___CATGETS_A = 0x6C0 // 1728
+ SYS___EXECVE_A = 0x6C1 // 1729
+ SYS___EXECVP_A = 0x6C2 // 1730
+ SYS___SPAWN_A = 0x6C3 // 1731
+ SYS___GETNAMEINFO_A = 0x6C4 // 1732
+ SYS___SPAWNP_A = 0x6C5 // 1733
+ SYS___NUMERIC_INIT_A = 0x6C6 // 1734
+ SYS___RESP_INIT_A = 0x6C7 // 1735
+ SYS___RPMATCH_A = 0x6C8 // 1736
+ SYS___RPMATCH_C_A = 0x6C9 // 1737
+ SYS___RPMATCH_STD_A = 0x6CA // 1738
+ SYS___TIME_INIT_A = 0x6CB // 1739
+ SYS___STRFTIME_A = 0x6CC // 1740
+ SYS___STRFTIME_STD_A = 0x6CD // 1741
+ SYS___STRPTIME_A = 0x6CE // 1742
+ SYS___STRPTIME_STD_A = 0x6CF // 1743
+ SYS___WCSFTIME_A = 0x6D0 // 1744
+ SYS___WCSFTIME_STD_A = 0x6D1 // 1745
+ SYS_____SPAWN2_A = 0x6D2 // 1746
+ SYS_____SPAWNP2_A = 0x6D3 // 1747
+ SYS___SYNTAX_INIT_A = 0x6D4 // 1748
+ SYS___TOD_INIT_A = 0x6D5 // 1749
+ SYS___NL_CSINFO_A = 0x6D6 // 1750
+ SYS___NL_MONINFO_A = 0x6D7 // 1751
+ SYS___NL_NUMINFO_A = 0x6D8 // 1752
+ SYS___NL_RESPINFO_A = 0x6D9 // 1753
+ SYS___NL_TIMINFO_A = 0x6DA // 1754
+ SYS___IF_NAMETOINDEX_A = 0x6DB // 1755
+ SYS___IF_INDEXTONAME_A = 0x6DC // 1756
+ SYS___PRINTF_A = 0x6DD // 1757
+ SYS___ICONV_OPEN_A = 0x6DE // 1758
+ SYS___DLLLOAD_A = 0x6DF // 1759
+ SYS___DLLQUERYFN_A = 0x6E0 // 1760
+ SYS___DLLQUERYVAR_A = 0x6E1 // 1761
+ SYS_____CHATTR_A = 0x6E2 // 1762
+ SYS___E2A_L = 0x6E3 // 1763
+ SYS_____TOCCSID_A = 0x6E4 // 1764
+ SYS_____TOCSNAME_A = 0x6E5 // 1765
+ SYS_____CCSIDTYPE_A = 0x6E6 // 1766
+ SYS_____CSNAMETYPE_A = 0x6E7 // 1767
+ SYS___CHMOD_A = 0x6E8 // 1768
+ SYS___MKDIR_A = 0x6E9 // 1769
+ SYS___STAT_A = 0x6EA // 1770
+ SYS___STAT_O_A = 0x6EB // 1771
+ SYS___MKFIFO_A = 0x6EC // 1772
+ SYS_____OPEN_STAT_A = 0x6ED // 1773
+ SYS___LSTAT_A = 0x6EE // 1774
+ SYS___LSTAT_O_A = 0x6EF // 1775
+ SYS___MKNOD_A = 0x6F0 // 1776
+ SYS___MOUNT_A = 0x6F1 // 1777
+ SYS___UMOUNT_A = 0x6F2 // 1778
+ SYS___CHAUDIT_A = 0x6F4 // 1780
+ SYS___W_GETMNTENT_A = 0x6F5 // 1781
+ SYS___CREAT_A = 0x6F6 // 1782
+ SYS___OPEN_A = 0x6F7 // 1783
+ SYS___SETLOCALE_A = 0x6F9 // 1785
+ SYS___FPRINTF_A = 0x6FA // 1786
+ SYS___SPRINTF_A = 0x6FB // 1787
+ SYS___VFPRINTF_A = 0x6FC // 1788
+ SYS___VPRINTF_A = 0x6FD // 1789
+ SYS___VSPRINTF_A = 0x6FE // 1790
+ SYS___VSWPRINTF_A = 0x6FF // 1791
+ SYS___SWPRINTF_A = 0x700 // 1792
+ SYS___FSCANF_A = 0x701 // 1793
+ SYS___SCANF_A = 0x702 // 1794
+ SYS___SSCANF_A = 0x703 // 1795
+ SYS___SWSCANF_A = 0x704 // 1796
+ SYS___ATOF_A = 0x705 // 1797
+ SYS___ATOI_A = 0x706 // 1798
+ SYS___ATOL_A = 0x707 // 1799
+ SYS___STRTOD_A = 0x708 // 1800
+ SYS___STRTOL_A = 0x709 // 1801
+ SYS___STRTOUL_A = 0x70A // 1802
+ SYS_____AE_CORRESTBL_QUERY_A = 0x70B // 1803
+ SYS___A64L_A = 0x70C // 1804
+ SYS___ECVT_A = 0x70D // 1805
+ SYS___FCVT_A = 0x70E // 1806
+ SYS___GCVT_A = 0x70F // 1807
+ SYS___L64A_A = 0x710 // 1808
+ SYS___STRERROR_A = 0x711 // 1809
+ SYS___PERROR_A = 0x712 // 1810
+ SYS___FETCH_A = 0x713 // 1811
+ SYS___GETENV_A = 0x714 // 1812
+ SYS___MKSTEMP_A = 0x717 // 1815
+ SYS___PTSNAME_A = 0x718 // 1816
+ SYS___PUTENV_A = 0x719 // 1817
+ SYS___REALPATH_A = 0x71A // 1818
+ SYS___SETENV_A = 0x71B // 1819
+ SYS___SYSTEM_A = 0x71C // 1820
+ SYS___GETOPT_A = 0x71D // 1821
+ SYS___CATOPEN_A = 0x71E // 1822
+ SYS___ACCESS_A = 0x71F // 1823
+ SYS___CHDIR_A = 0x720 // 1824
+ SYS___CHOWN_A = 0x721 // 1825
+ SYS___CHROOT_A = 0x722 // 1826
+ SYS___GETCWD_A = 0x723 // 1827
+ SYS___GETWD_A = 0x724 // 1828
+ SYS___LCHOWN_A = 0x725 // 1829
+ SYS___LINK_A = 0x726 // 1830
+ SYS___PATHCONF_A = 0x727 // 1831
+ SYS___IF_NAMEINDEX_A = 0x728 // 1832
+ SYS___READLINK_A = 0x729 // 1833
+ SYS___RMDIR_A = 0x72A // 1834
+ SYS___STATVFS_A = 0x72B // 1835
+ SYS___SYMLINK_A = 0x72C // 1836
+ SYS___TRUNCATE_A = 0x72D // 1837
+ SYS___UNLINK_A = 0x72E // 1838
+ SYS___GAI_STRERROR_A = 0x72F // 1839
+ SYS___EXTLINK_NP_A = 0x730 // 1840
+ SYS___ISALNUM_A = 0x731 // 1841
+ SYS___ISALPHA_A = 0x732 // 1842
+ SYS___A2E_S = 0x733 // 1843
+ SYS___ISCNTRL_A = 0x734 // 1844
+ SYS___ISDIGIT_A = 0x735 // 1845
+ SYS___ISGRAPH_A = 0x736 // 1846
+ SYS___ISLOWER_A = 0x737 // 1847
+ SYS___ISPRINT_A = 0x738 // 1848
+ SYS___ISPUNCT_A = 0x739 // 1849
+ SYS___ISSPACE_A = 0x73A // 1850
+ SYS___ISUPPER_A = 0x73B // 1851
+ SYS___ISXDIGIT_A = 0x73C // 1852
+ SYS___TOLOWER_A = 0x73D // 1853
+ SYS___TOUPPER_A = 0x73E // 1854
+ SYS___ISWALNUM_A = 0x73F // 1855
+ SYS___ISWALPHA_A = 0x740 // 1856
+ SYS___A2E_L = 0x741 // 1857
+ SYS___ISWCNTRL_A = 0x742 // 1858
+ SYS___ISWDIGIT_A = 0x743 // 1859
+ SYS___ISWGRAPH_A = 0x744 // 1860
+ SYS___ISWLOWER_A = 0x745 // 1861
+ SYS___ISWPRINT_A = 0x746 // 1862
+ SYS___ISWPUNCT_A = 0x747 // 1863
+ SYS___ISWSPACE_A = 0x748 // 1864
+ SYS___ISWUPPER_A = 0x749 // 1865
+ SYS___ISWXDIGIT_A = 0x74A // 1866
+ SYS___CONFSTR_A = 0x74B // 1867
+ SYS___FTOK_A = 0x74C // 1868
+ SYS___MKTEMP_A = 0x74D // 1869
+ SYS___FDOPEN_A = 0x74E // 1870
+ SYS___FLDATA_A = 0x74F // 1871
+ SYS___REMOVE_A = 0x750 // 1872
+ SYS___RENAME_A = 0x751 // 1873
+ SYS___TMPNAM_A = 0x752 // 1874
+ SYS___FOPEN_A = 0x753 // 1875
+ SYS___FREOPEN_A = 0x754 // 1876
+ SYS___CUSERID_A = 0x755 // 1877
+ SYS___POPEN_A = 0x756 // 1878
+ SYS___TEMPNAM_A = 0x757 // 1879
+ SYS___FTW_A = 0x758 // 1880
+ SYS___GETGRENT_A = 0x759 // 1881
+ SYS___GETGRGID_A = 0x75A // 1882
+ SYS___GETGRNAM_A = 0x75B // 1883
+ SYS___GETGROUPSBYNAME_A = 0x75C // 1884
+ SYS___GETHOSTENT_A = 0x75D // 1885
+ SYS___GETHOSTNAME_A = 0x75E // 1886
+ SYS___GETLOGIN_A = 0x75F // 1887
+ SYS___INET_NTOP_A = 0x760 // 1888
+ SYS___GETPASS_A = 0x761 // 1889
+ SYS___GETPWENT_A = 0x762 // 1890
+ SYS___GETPWNAM_A = 0x763 // 1891
+ SYS___GETPWUID_A = 0x764 // 1892
+ SYS_____CHECK_RESOURCE_AUTH_NP_A = 0x765 // 1893
+ SYS___CHECKSCHENV_A = 0x766 // 1894
+ SYS___CONNECTSERVER_A = 0x767 // 1895
+ SYS___CONNECTWORKMGR_A = 0x768 // 1896
+ SYS_____CONSOLE_A = 0x769 // 1897
+ SYS___CREATEWORKUNIT_A = 0x76A // 1898
+ SYS___CTERMID_A = 0x76B // 1899
+ SYS___FMTMSG_A = 0x76C // 1900
+ SYS___INITGROUPS_A = 0x76D // 1901
+ SYS_____LOGIN_A = 0x76E // 1902
+ SYS___MSGRCV_A = 0x76F // 1903
+ SYS___MSGSND_A = 0x770 // 1904
+ SYS___MSGXRCV_A = 0x771 // 1905
+ SYS___NFTW_A = 0x772 // 1906
+ SYS_____PASSWD_A = 0x773 // 1907
+ SYS___PTHREAD_SECURITY_NP_A = 0x774 // 1908
+ SYS___QUERYMETRICS_A = 0x775 // 1909
+ SYS___QUERYSCHENV = 0x776 // 1910
+ SYS___READV_A = 0x777 // 1911
+ SYS_____SERVER_CLASSIFY_A = 0x778 // 1912
+ SYS_____SERVER_INIT_A = 0x779 // 1913
+ SYS_____SERVER_PWU_A = 0x77A // 1914
+ SYS___STRCASECMP_A = 0x77B // 1915
+ SYS___STRNCASECMP_A = 0x77C // 1916
+ SYS___TTYNAME_A = 0x77D // 1917
+ SYS___UNAME_A = 0x77E // 1918
+ SYS___UTIMES_A = 0x77F // 1919
+ SYS___W_GETPSENT_A = 0x780 // 1920
+ SYS___WRITEV_A = 0x781 // 1921
+ SYS___W_STATFS_A = 0x782 // 1922
+ SYS___W_STATVFS_A = 0x783 // 1923
+ SYS___FPUTC_A = 0x784 // 1924
+ SYS___PUTCHAR_A = 0x785 // 1925
+ SYS___PUTS_A = 0x786 // 1926
+ SYS___FGETS_A = 0x787 // 1927
+ SYS___GETS_A = 0x788 // 1928
+ SYS___FPUTS_A = 0x789 // 1929
+ SYS___FREAD_A = 0x78A // 1930
+ SYS___FWRITE_A = 0x78B // 1931
+ SYS___OPEN_O_A = 0x78C // 1932
+ SYS___ISASCII = 0x78D // 1933
+ SYS___CREAT_O_A = 0x78E // 1934
+ SYS___ENVNA = 0x78F // 1935
+ SYS___PUTC_A = 0x790 // 1936
+ SYS___AE_THREAD_SETMODE = 0x791 // 1937
+ SYS___AE_THREAD_SWAPMODE = 0x792 // 1938
+ SYS___GETNETBYADDR_A = 0x793 // 1939
+ SYS___GETNETBYNAME_A = 0x794 // 1940
+ SYS___GETNETENT_A = 0x795 // 1941
+ SYS___GETPROTOBYNAME_A = 0x796 // 1942
+ SYS___GETPROTOBYNUMBER_A = 0x797 // 1943
+ SYS___GETPROTOENT_A = 0x798 // 1944
+ SYS___GETSERVBYNAME_A = 0x799 // 1945
+ SYS___GETSERVBYPORT_A = 0x79A // 1946
+ SYS___GETSERVENT_A = 0x79B // 1947
+ SYS___ASCTIME_A = 0x79C // 1948
+ SYS___CTIME_A = 0x79D // 1949
+ SYS___GETDATE_A = 0x79E // 1950
+ SYS___TZSET_A = 0x79F // 1951
+ SYS___UTIME_A = 0x7A0 // 1952
+ SYS___ASCTIME_R_A = 0x7A1 // 1953
+ SYS___CTIME_R_A = 0x7A2 // 1954
+ SYS___STRTOLL_A = 0x7A3 // 1955
+ SYS___STRTOULL_A = 0x7A4 // 1956
+ SYS___FPUTWC_A = 0x7A5 // 1957
+ SYS___PUTWC_A = 0x7A6 // 1958
+ SYS___PUTWCHAR_A = 0x7A7 // 1959
+ SYS___FPUTWS_A = 0x7A8 // 1960
+ SYS___UNGETWC_A = 0x7A9 // 1961
+ SYS___FGETWC_A = 0x7AA // 1962
+ SYS___GETWC_A = 0x7AB // 1963
+ SYS___GETWCHAR_A = 0x7AC // 1964
+ SYS___FGETWS_A = 0x7AD // 1965
+ SYS___GETTIMEOFDAY_A = 0x7AE // 1966
+ SYS___GMTIME_A = 0x7AF // 1967
+ SYS___GMTIME_R_A = 0x7B0 // 1968
+ SYS___LOCALTIME_A = 0x7B1 // 1969
+ SYS___LOCALTIME_R_A = 0x7B2 // 1970
+ SYS___MKTIME_A = 0x7B3 // 1971
+ SYS___TZZNA = 0x7B4 // 1972
+ SYS_UNATEXIT = 0x7B5 // 1973
+ SYS___CEE3DMP_A = 0x7B6 // 1974
+ SYS___CDUMP_A = 0x7B7 // 1975
+ SYS___CSNAP_A = 0x7B8 // 1976
+ SYS___CTEST_A = 0x7B9 // 1977
+ SYS___CTRACE_A = 0x7BA // 1978
+ SYS___VSWPRNTF2_A = 0x7BB // 1979
+ SYS___INET_PTON_A = 0x7BC // 1980
+ SYS___SYSLOG_A = 0x7BD // 1981
+ SYS___CRYPT_A = 0x7BE // 1982
+ SYS_____OPENDIR2_A = 0x7BF // 1983
+ SYS_____READDIR2_A = 0x7C0 // 1984
+ SYS___OPENDIR_A = 0x7C2 // 1986
+ SYS___READDIR_A = 0x7C3 // 1987
+ SYS_PREAD = 0x7C7 // 1991
+ SYS_PWRITE = 0x7C8 // 1992
+ SYS_M_CREATE_LAYOUT = 0x7C9 // 1993
+ SYS_M_DESTROY_LAYOUT = 0x7CA // 1994
+ SYS_M_GETVALUES_LAYOUT = 0x7CB // 1995
+ SYS_M_SETVALUES_LAYOUT = 0x7CC // 1996
+ SYS_M_TRANSFORM_LAYOUT = 0x7CD // 1997
+ SYS_M_WTRANSFORM_LAYOUT = 0x7CE // 1998
+ SYS_FWPRINTF = 0x7D1 // 2001
+ SYS_WPRINTF = 0x7D2 // 2002
+ SYS_VFWPRINT = 0x7D3 // 2003
+ SYS_VFWPRINTF = 0x7D3 // 2003
+ SYS_VWPRINTF = 0x7D4 // 2004
+ SYS_FWSCANF = 0x7D5 // 2005
+ SYS_WSCANF = 0x7D6 // 2006
+ SYS_WCTRANS = 0x7D7 // 2007
+ SYS_TOWCTRAN = 0x7D8 // 2008
+ SYS_TOWCTRANS = 0x7D8 // 2008
+ SYS___WCSTOD_A = 0x7D9 // 2009
+ SYS___WCSTOL_A = 0x7DA // 2010
+ SYS___WCSTOUL_A = 0x7DB // 2011
+ SYS___BASENAME_A = 0x7DC // 2012
+ SYS___DIRNAME_A = 0x7DD // 2013
+ SYS___GLOB_A = 0x7DE // 2014
+ SYS_FWIDE = 0x7DF // 2015
+ SYS___OSNAME = 0x7E0 // 2016
+ SYS_____OSNAME_A = 0x7E1 // 2017
+ SYS___BTOWC_A = 0x7E4 // 2020
+ SYS___WCTOB_A = 0x7E5 // 2021
+ SYS___DBM_OPEN_A = 0x7E6 // 2022
+ SYS___VFPRINTF2_A = 0x7E7 // 2023
+ SYS___VPRINTF2_A = 0x7E8 // 2024
+ SYS___VSPRINTF2_A = 0x7E9 // 2025
+ SYS___CEIL_H = 0x7EA // 2026
+ SYS___FLOOR_H = 0x7EB // 2027
+ SYS___MODF_H = 0x7EC // 2028
+ SYS___FABS_H = 0x7ED // 2029
+ SYS___J0_H = 0x7EE // 2030
+ SYS___J1_H = 0x7EF // 2031
+ SYS___JN_H = 0x7F0 // 2032
+ SYS___Y0_H = 0x7F1 // 2033
+ SYS___Y1_H = 0x7F2 // 2034
+ SYS___YN_H = 0x7F3 // 2035
+ SYS___CEILF_H = 0x7F4 // 2036
+ SYS___CEILL_H = 0x7F5 // 2037
+ SYS___FLOORF_H = 0x7F6 // 2038
+ SYS___FLOORL_H = 0x7F7 // 2039
+ SYS___MODFF_H = 0x7F8 // 2040
+ SYS___MODFL_H = 0x7F9 // 2041
+ SYS___FABSF_H = 0x7FA // 2042
+ SYS___FABSL_H = 0x7FB // 2043
+ SYS___MALLOC24 = 0x7FC // 2044
+ SYS___MALLOC31 = 0x7FD // 2045
+ SYS_ACL_INIT = 0x7FE // 2046
+ SYS_ACL_FREE = 0x7FF // 2047
+ SYS_ACL_FIRST_ENTRY = 0x800 // 2048
+ SYS_ACL_GET_ENTRY = 0x801 // 2049
+ SYS_ACL_VALID = 0x802 // 2050
+ SYS_ACL_CREATE_ENTRY = 0x803 // 2051
+ SYS_ACL_DELETE_ENTRY = 0x804 // 2052
+ SYS_ACL_UPDATE_ENTRY = 0x805 // 2053
+ SYS_ACL_DELETE_FD = 0x806 // 2054
+ SYS_ACL_DELETE_FILE = 0x807 // 2055
+ SYS_ACL_GET_FD = 0x808 // 2056
+ SYS_ACL_GET_FILE = 0x809 // 2057
+ SYS_ACL_SET_FD = 0x80A // 2058
+ SYS_ACL_SET_FILE = 0x80B // 2059
+ SYS_ACL_FROM_TEXT = 0x80C // 2060
+ SYS_ACL_TO_TEXT = 0x80D // 2061
+ SYS_ACL_SORT = 0x80E // 2062
+ SYS___SHUTDOWN_REGISTRATION = 0x80F // 2063
+ SYS___ERFL_B = 0x810 // 2064
+ SYS___ERFCL_B = 0x811 // 2065
+ SYS___LGAMMAL_B = 0x812 // 2066
+ SYS___SETHOOKEVENTS = 0x813 // 2067
+ SYS_IF_NAMETOINDEX = 0x814 // 2068
+ SYS_IF_INDEXTONAME = 0x815 // 2069
+ SYS_IF_NAMEINDEX = 0x816 // 2070
+ SYS_IF_FREENAMEINDEX = 0x817 // 2071
+ SYS_GETADDRINFO = 0x818 // 2072
+ SYS_GETNAMEINFO = 0x819 // 2073
+ SYS_FREEADDRINFO = 0x81A // 2074
+ SYS_GAI_STRERROR = 0x81B // 2075
+ SYS_REXEC_AF = 0x81C // 2076
+ SYS___POE = 0x81D // 2077
+ SYS___DYNALLOC_A = 0x81F // 2079
+ SYS___DYNFREE_A = 0x820 // 2080
+ SYS___RES_QUERY_A = 0x821 // 2081
+ SYS___RES_SEARCH_A = 0x822 // 2082
+ SYS___RES_QUERYDOMAIN_A = 0x823 // 2083
+ SYS___RES_MKQUERY_A = 0x824 // 2084
+ SYS___RES_SEND_A = 0x825 // 2085
+ SYS___DN_EXPAND_A = 0x826 // 2086
+ SYS___DN_SKIPNAME_A = 0x827 // 2087
+ SYS___DN_COMP_A = 0x828 // 2088
+ SYS___DN_FIND_A = 0x829 // 2089
+ SYS___NLIST_A = 0x82A // 2090
+ SYS_____TCGETCP_A = 0x82B // 2091
+ SYS_____TCSETCP_A = 0x82C // 2092
+ SYS_____W_PIOCTL_A = 0x82E // 2094
+ SYS___INET_ADDR_A = 0x82F // 2095
+ SYS___INET_NTOA_A = 0x830 // 2096
+ SYS___INET_NETWORK_A = 0x831 // 2097
+ SYS___ACCEPT_A = 0x832 // 2098
+ SYS___ACCEPT_AND_RECV_A = 0x833 // 2099
+ SYS___BIND_A = 0x834 // 2100
+ SYS___CONNECT_A = 0x835 // 2101
+ SYS___GETPEERNAME_A = 0x836 // 2102
+ SYS___GETSOCKNAME_A = 0x837 // 2103
+ SYS___RECVFROM_A = 0x838 // 2104
+ SYS___SENDTO_A = 0x839 // 2105
+ SYS___SENDMSG_A = 0x83A // 2106
+ SYS___RECVMSG_A = 0x83B // 2107
+ SYS_____LCHATTR_A = 0x83C // 2108
+ SYS___CABEND = 0x83D // 2109
+ SYS___LE_CIB_GET = 0x83E // 2110
+ SYS___SET_LAA_FOR_JIT = 0x83F // 2111
+ SYS___LCHATTR = 0x840 // 2112
+ SYS___WRITEDOWN = 0x841 // 2113
+ SYS_PTHREAD_MUTEX_INIT2 = 0x842 // 2114
+ SYS___ACOSHF_B = 0x843 // 2115
+ SYS___ACOSHL_B = 0x844 // 2116
+ SYS___ASINHF_B = 0x845 // 2117
+ SYS___ASINHL_B = 0x846 // 2118
+ SYS___ATANHF_B = 0x847 // 2119
+ SYS___ATANHL_B = 0x848 // 2120
+ SYS___CBRTF_B = 0x849 // 2121
+ SYS___CBRTL_B = 0x84A // 2122
+ SYS___COPYSIGNF_B = 0x84B // 2123
+ SYS___COPYSIGNL_B = 0x84C // 2124
+ SYS___COTANF_B = 0x84D // 2125
+ SYS___COTAN_B = 0x84E // 2126
+ SYS___COTANL_B = 0x84F // 2127
+ SYS___EXP2F_B = 0x850 // 2128
+ SYS___EXP2L_B = 0x851 // 2129
+ SYS___EXPM1F_B = 0x852 // 2130
+ SYS___EXPM1L_B = 0x853 // 2131
+ SYS___FDIMF_B = 0x854 // 2132
+ SYS___FDIM_B = 0x855 // 2133
+ SYS___FDIML_B = 0x856 // 2134
+ SYS___HYPOTF_B = 0x857 // 2135
+ SYS___HYPOTL_B = 0x858 // 2136
+ SYS___LOG1PF_B = 0x859 // 2137
+ SYS___LOG1PL_B = 0x85A // 2138
+ SYS___LOG2F_B = 0x85B // 2139
+ SYS___LOG2_B = 0x85C // 2140
+ SYS___LOG2L_B = 0x85D // 2141
+ SYS___REMAINDERF_B = 0x85E // 2142
+ SYS___REMAINDERL_B = 0x85F // 2143
+ SYS___REMQUOF_B = 0x860 // 2144
+ SYS___REMQUO_B = 0x861 // 2145
+ SYS___REMQUOL_B = 0x862 // 2146
+ SYS___TGAMMAF_B = 0x863 // 2147
+ SYS___TGAMMA_B = 0x864 // 2148
+ SYS___TGAMMAL_B = 0x865 // 2149
+ SYS___TRUNCF_B = 0x866 // 2150
+ SYS___TRUNC_B = 0x867 // 2151
+ SYS___TRUNCL_B = 0x868 // 2152
+ SYS___LGAMMAF_B = 0x869 // 2153
+ SYS___LROUNDF_B = 0x86A // 2154
+ SYS___LROUND_B = 0x86B // 2155
+ SYS___ERFF_B = 0x86C // 2156
+ SYS___ERFCF_B = 0x86D // 2157
+ SYS_ACOSHF = 0x86E // 2158
+ SYS_ACOSHL = 0x86F // 2159
+ SYS_ASINHF = 0x870 // 2160
+ SYS_ASINHL = 0x871 // 2161
+ SYS_ATANHF = 0x872 // 2162
+ SYS_ATANHL = 0x873 // 2163
+ SYS_CBRTF = 0x874 // 2164
+ SYS_CBRTL = 0x875 // 2165
+ SYS_COPYSIGNF = 0x876 // 2166
+ SYS_CPYSIGNF = 0x876 // 2166
+ SYS_COPYSIGNL = 0x877 // 2167
+ SYS_CPYSIGNL = 0x877 // 2167
+ SYS_COTANF = 0x878 // 2168
+ SYS___COTANF = 0x878 // 2168
+ SYS_COTAN = 0x879 // 2169
+ SYS___COTAN = 0x879 // 2169
+ SYS_COTANL = 0x87A // 2170
+ SYS___COTANL = 0x87A // 2170
+ SYS_EXP2F = 0x87B // 2171
+ SYS_EXP2L = 0x87C // 2172
+ SYS_EXPM1F = 0x87D // 2173
+ SYS_EXPM1L = 0x87E // 2174
+ SYS_FDIMF = 0x87F // 2175
+ SYS_FDIM = 0x881 // 2177
+ SYS_FDIML = 0x882 // 2178
+ SYS_HYPOTF = 0x883 // 2179
+ SYS_HYPOTL = 0x884 // 2180
+ SYS_LOG1PF = 0x885 // 2181
+ SYS_LOG1PL = 0x886 // 2182
+ SYS_LOG2F = 0x887 // 2183
+ SYS_LOG2 = 0x888 // 2184
+ SYS_LOG2L = 0x889 // 2185
+ SYS_REMAINDERF = 0x88A // 2186
+ SYS_REMAINDF = 0x88A // 2186
+ SYS_REMAINDERL = 0x88B // 2187
+ SYS_REMAINDL = 0x88B // 2187
+ SYS_REMQUOF = 0x88C // 2188
+ SYS_REMQUO = 0x88D // 2189
+ SYS_REMQUOL = 0x88E // 2190
+ SYS_TGAMMAF = 0x88F // 2191
+ SYS_TGAMMA = 0x890 // 2192
+ SYS_TGAMMAL = 0x891 // 2193
+ SYS_TRUNCF = 0x892 // 2194
+ SYS_TRUNC = 0x893 // 2195
+ SYS_TRUNCL = 0x894 // 2196
+ SYS_LGAMMAF = 0x895 // 2197
+ SYS_LGAMMAL = 0x896 // 2198
+ SYS_LROUNDF = 0x897 // 2199
+ SYS_LROUND = 0x898 // 2200
+ SYS_ERFF = 0x899 // 2201
+ SYS_ERFL = 0x89A // 2202
+ SYS_ERFCF = 0x89B // 2203
+ SYS_ERFCL = 0x89C // 2204
+ SYS___EXP2_B = 0x89D // 2205
+ SYS_EXP2 = 0x89E // 2206
+ SYS___FAR_JUMP = 0x89F // 2207
+ SYS___TCGETATTR_A = 0x8A1 // 2209
+ SYS___TCSETATTR_A = 0x8A2 // 2210
+ SYS___SUPERKILL = 0x8A4 // 2212
+ SYS___LE_CONDITION_TOKEN_BUILD = 0x8A5 // 2213
+ SYS___LE_MSG_ADD_INSERT = 0x8A6 // 2214
+ SYS___LE_MSG_GET = 0x8A7 // 2215
+ SYS___LE_MSG_GET_AND_WRITE = 0x8A8 // 2216
+ SYS___LE_MSG_WRITE = 0x8A9 // 2217
+ SYS___ITOA = 0x8AA // 2218
+ SYS___UTOA = 0x8AB // 2219
+ SYS___LTOA = 0x8AC // 2220
+ SYS___ULTOA = 0x8AD // 2221
+ SYS___LLTOA = 0x8AE // 2222
+ SYS___ULLTOA = 0x8AF // 2223
+ SYS___ITOA_A = 0x8B0 // 2224
+ SYS___UTOA_A = 0x8B1 // 2225
+ SYS___LTOA_A = 0x8B2 // 2226
+ SYS___ULTOA_A = 0x8B3 // 2227
+ SYS___LLTOA_A = 0x8B4 // 2228
+ SYS___ULLTOA_A = 0x8B5 // 2229
+ SYS_____GETENV_A = 0x8C3 // 2243
+ SYS___REXEC_A = 0x8C4 // 2244
+ SYS___REXEC_AF_A = 0x8C5 // 2245
+ SYS___GETUTXENT_A = 0x8C6 // 2246
+ SYS___GETUTXID_A = 0x8C7 // 2247
+ SYS___GETUTXLINE_A = 0x8C8 // 2248
+ SYS___PUTUTXLINE_A = 0x8C9 // 2249
+ SYS_____UTMPXNAME_A = 0x8CA // 2250
+ SYS___PUTC_UNLOCKED_A = 0x8CB // 2251
+ SYS___PUTCHAR_UNLOCKED_A = 0x8CC // 2252
+ SYS___SNPRINTF_A = 0x8CD // 2253
+ SYS___VSNPRINTF_A = 0x8CE // 2254
+ SYS___DLOPEN_A = 0x8D0 // 2256
+ SYS___DLSYM_A = 0x8D1 // 2257
+ SYS___DLERROR_A = 0x8D2 // 2258
+ SYS_FLOCKFILE = 0x8D3 // 2259
+ SYS_FTRYLOCKFILE = 0x8D4 // 2260
+ SYS_FUNLOCKFILE = 0x8D5 // 2261
+ SYS_GETC_UNLOCKED = 0x8D6 // 2262
+ SYS_GETCHAR_UNLOCKED = 0x8D7 // 2263
+ SYS_PUTC_UNLOCKED = 0x8D8 // 2264
+ SYS_PUTCHAR_UNLOCKED = 0x8D9 // 2265
+ SYS_SNPRINTF = 0x8DA // 2266
+ SYS_VSNPRINTF = 0x8DB // 2267
+ SYS_DLOPEN = 0x8DD // 2269
+ SYS_DLSYM = 0x8DE // 2270
+ SYS_DLCLOSE = 0x8DF // 2271
+ SYS_DLERROR = 0x8E0 // 2272
+ SYS___SET_EXCEPTION_HANDLER = 0x8E2 // 2274
+ SYS___RESET_EXCEPTION_HANDLER = 0x8E3 // 2275
+ SYS___VHM_EVENT = 0x8E4 // 2276
+ SYS___ABS_H = 0x8E6 // 2278
+ SYS___ABSF_H = 0x8E7 // 2279
+ SYS___ABSL_H = 0x8E8 // 2280
+ SYS___ACOS_H = 0x8E9 // 2281
+ SYS___ACOSF_H = 0x8EA // 2282
+ SYS___ACOSL_H = 0x8EB // 2283
+ SYS___ACOSH_H = 0x8EC // 2284
+ SYS___ASIN_H = 0x8ED // 2285
+ SYS___ASINF_H = 0x8EE // 2286
+ SYS___ASINL_H = 0x8EF // 2287
+ SYS___ASINH_H = 0x8F0 // 2288
+ SYS___ATAN_H = 0x8F1 // 2289
+ SYS___ATANF_H = 0x8F2 // 2290
+ SYS___ATANL_H = 0x8F3 // 2291
+ SYS___ATANH_H = 0x8F4 // 2292
+ SYS___ATANHF_H = 0x8F5 // 2293
+ SYS___ATANHL_H = 0x8F6 // 2294
+ SYS___ATAN2_H = 0x8F7 // 2295
+ SYS___ATAN2F_H = 0x8F8 // 2296
+ SYS___ATAN2L_H = 0x8F9 // 2297
+ SYS___CBRT_H = 0x8FA // 2298
+ SYS___COPYSIGNF_H = 0x8FB // 2299
+ SYS___COPYSIGNL_H = 0x8FC // 2300
+ SYS___COS_H = 0x8FD // 2301
+ SYS___COSF_H = 0x8FE // 2302
+ SYS___COSL_H = 0x8FF // 2303
+ SYS___COSHF_H = 0x900 // 2304
+ SYS___COSHL_H = 0x901 // 2305
+ SYS___COTAN_H = 0x902 // 2306
+ SYS___COTANF_H = 0x903 // 2307
+ SYS___COTANL_H = 0x904 // 2308
+ SYS___ERF_H = 0x905 // 2309
+ SYS___ERFF_H = 0x906 // 2310
+ SYS___ERFL_H = 0x907 // 2311
+ SYS___ERFC_H = 0x908 // 2312
+ SYS___ERFCF_H = 0x909 // 2313
+ SYS___ERFCL_H = 0x90A // 2314
+ SYS___EXP_H = 0x90B // 2315
+ SYS___EXPF_H = 0x90C // 2316
+ SYS___EXPL_H = 0x90D // 2317
+ SYS___EXPM1_H = 0x90E // 2318
+ SYS___FDIM_H = 0x90F // 2319
+ SYS___FDIMF_H = 0x910 // 2320
+ SYS___FDIML_H = 0x911 // 2321
+ SYS___FMOD_H = 0x912 // 2322
+ SYS___FMODF_H = 0x913 // 2323
+ SYS___FMODL_H = 0x914 // 2324
+ SYS___GAMMA_H = 0x915 // 2325
+ SYS___HYPOT_H = 0x916 // 2326
+ SYS___ILOGB_H = 0x917 // 2327
+ SYS___LGAMMA_H = 0x918 // 2328
+ SYS___LGAMMAF_H = 0x919 // 2329
+ SYS___LOG_H = 0x91A // 2330
+ SYS___LOGF_H = 0x91B // 2331
+ SYS___LOGL_H = 0x91C // 2332
+ SYS___LOGB_H = 0x91D // 2333
+ SYS___LOG2_H = 0x91E // 2334
+ SYS___LOG2F_H = 0x91F // 2335
+ SYS___LOG2L_H = 0x920 // 2336
+ SYS___LOG1P_H = 0x921 // 2337
+ SYS___LOG10_H = 0x922 // 2338
+ SYS___LOG10F_H = 0x923 // 2339
+ SYS___LOG10L_H = 0x924 // 2340
+ SYS___LROUND_H = 0x925 // 2341
+ SYS___LROUNDF_H = 0x926 // 2342
+ SYS___NEXTAFTER_H = 0x927 // 2343
+ SYS___POW_H = 0x928 // 2344
+ SYS___POWF_H = 0x929 // 2345
+ SYS___POWL_H = 0x92A // 2346
+ SYS___REMAINDER_H = 0x92B // 2347
+ SYS___RINT_H = 0x92C // 2348
+ SYS___SCALB_H = 0x92D // 2349
+ SYS___SIN_H = 0x92E // 2350
+ SYS___SINF_H = 0x92F // 2351
+ SYS___SINL_H = 0x930 // 2352
+ SYS___SINH_H = 0x931 // 2353
+ SYS___SINHF_H = 0x932 // 2354
+ SYS___SINHL_H = 0x933 // 2355
+ SYS___SQRT_H = 0x934 // 2356
+ SYS___SQRTF_H = 0x935 // 2357
+ SYS___SQRTL_H = 0x936 // 2358
+ SYS___TAN_H = 0x937 // 2359
+ SYS___TANF_H = 0x938 // 2360
+ SYS___TANL_H = 0x939 // 2361
+ SYS___TANH_H = 0x93A // 2362
+ SYS___TANHF_H = 0x93B // 2363
+ SYS___TANHL_H = 0x93C // 2364
+ SYS___TGAMMA_H = 0x93D // 2365
+ SYS___TGAMMAF_H = 0x93E // 2366
+ SYS___TRUNC_H = 0x93F // 2367
+ SYS___TRUNCF_H = 0x940 // 2368
+ SYS___TRUNCL_H = 0x941 // 2369
+ SYS___COSH_H = 0x942 // 2370
+ SYS___LE_DEBUG_SET_RESUME_MCH = 0x943 // 2371
+ SYS_VFSCANF = 0x944 // 2372
+ SYS_VSCANF = 0x946 // 2374
+ SYS_VSSCANF = 0x948 // 2376
+ SYS_VFWSCANF = 0x94A // 2378
+ SYS_VWSCANF = 0x94C // 2380
+ SYS_VSWSCANF = 0x94E // 2382
+ SYS_IMAXABS = 0x950 // 2384
+ SYS_IMAXDIV = 0x951 // 2385
+ SYS_STRTOIMAX = 0x952 // 2386
+ SYS_STRTOUMAX = 0x953 // 2387
+ SYS_WCSTOIMAX = 0x954 // 2388
+ SYS_WCSTOUMAX = 0x955 // 2389
+ SYS_ATOLL = 0x956 // 2390
+ SYS_STRTOF = 0x957 // 2391
+ SYS_STRTOLD = 0x958 // 2392
+ SYS_WCSTOF = 0x959 // 2393
+ SYS_WCSTOLD = 0x95A // 2394
+ SYS_INET6_RTH_SPACE = 0x95B // 2395
+ SYS_INET6_RTH_INIT = 0x95C // 2396
+ SYS_INET6_RTH_ADD = 0x95D // 2397
+ SYS_INET6_RTH_REVERSE = 0x95E // 2398
+ SYS_INET6_RTH_SEGMENTS = 0x95F // 2399
+ SYS_INET6_RTH_GETADDR = 0x960 // 2400
+ SYS_INET6_OPT_INIT = 0x961 // 2401
+ SYS_INET6_OPT_APPEND = 0x962 // 2402
+ SYS_INET6_OPT_FINISH = 0x963 // 2403
+ SYS_INET6_OPT_SET_VAL = 0x964 // 2404
+ SYS_INET6_OPT_NEXT = 0x965 // 2405
+ SYS_INET6_OPT_FIND = 0x966 // 2406
+ SYS_INET6_OPT_GET_VAL = 0x967 // 2407
+ SYS___POW_I = 0x987 // 2439
+ SYS___POW_I_B = 0x988 // 2440
+ SYS___POW_I_H = 0x989 // 2441
+ SYS___POW_II = 0x98A // 2442
+ SYS___POW_II_B = 0x98B // 2443
+ SYS___POW_II_H = 0x98C // 2444
+ SYS_CABS = 0x98E // 2446
+ SYS___CABS_B = 0x98F // 2447
+ SYS___CABS_H = 0x990 // 2448
+ SYS_CABSF = 0x991 // 2449
+ SYS___CABSF_B = 0x992 // 2450
+ SYS___CABSF_H = 0x993 // 2451
+ SYS_CABSL = 0x994 // 2452
+ SYS___CABSL_B = 0x995 // 2453
+ SYS___CABSL_H = 0x996 // 2454
+ SYS_CACOS = 0x997 // 2455
+ SYS___CACOS_B = 0x998 // 2456
+ SYS___CACOS_H = 0x999 // 2457
+ SYS_CACOSF = 0x99A // 2458
+ SYS___CACOSF_B = 0x99B // 2459
+ SYS___CACOSF_H = 0x99C // 2460
+ SYS_CACOSL = 0x99D // 2461
+ SYS___CACOSL_B = 0x99E // 2462
+ SYS___CACOSL_H = 0x99F // 2463
+ SYS_CACOSH = 0x9A0 // 2464
+ SYS___CACOSH_B = 0x9A1 // 2465
+ SYS___CACOSH_H = 0x9A2 // 2466
+ SYS_CACOSHF = 0x9A3 // 2467
+ SYS___CACOSHF_B = 0x9A4 // 2468
+ SYS___CACOSHF_H = 0x9A5 // 2469
+ SYS_CACOSHL = 0x9A6 // 2470
+ SYS___CACOSHL_B = 0x9A7 // 2471
+ SYS___CACOSHL_H = 0x9A8 // 2472
+ SYS_CARG = 0x9A9 // 2473
+ SYS___CARG_B = 0x9AA // 2474
+ SYS___CARG_H = 0x9AB // 2475
+ SYS_CARGF = 0x9AC // 2476
+ SYS___CARGF_B = 0x9AD // 2477
+ SYS___CARGF_H = 0x9AE // 2478
+ SYS_CARGL = 0x9AF // 2479
+ SYS___CARGL_B = 0x9B0 // 2480
+ SYS___CARGL_H = 0x9B1 // 2481
+ SYS_CASIN = 0x9B2 // 2482
+ SYS___CASIN_B = 0x9B3 // 2483
+ SYS___CASIN_H = 0x9B4 // 2484
+ SYS_CASINF = 0x9B5 // 2485
+ SYS___CASINF_B = 0x9B6 // 2486
+ SYS___CASINF_H = 0x9B7 // 2487
+ SYS_CASINL = 0x9B8 // 2488
+ SYS___CASINL_B = 0x9B9 // 2489
+ SYS___CASINL_H = 0x9BA // 2490
+ SYS_CASINH = 0x9BB // 2491
+ SYS___CASINH_B = 0x9BC // 2492
+ SYS___CASINH_H = 0x9BD // 2493
+ SYS_CASINHF = 0x9BE // 2494
+ SYS___CASINHF_B = 0x9BF // 2495
+ SYS___CASINHF_H = 0x9C0 // 2496
+ SYS_CASINHL = 0x9C1 // 2497
+ SYS___CASINHL_B = 0x9C2 // 2498
+ SYS___CASINHL_H = 0x9C3 // 2499
+ SYS_CATAN = 0x9C4 // 2500
+ SYS___CATAN_B = 0x9C5 // 2501
+ SYS___CATAN_H = 0x9C6 // 2502
+ SYS_CATANF = 0x9C7 // 2503
+ SYS___CATANF_B = 0x9C8 // 2504
+ SYS___CATANF_H = 0x9C9 // 2505
+ SYS_CATANL = 0x9CA // 2506
+ SYS___CATANL_B = 0x9CB // 2507
+ SYS___CATANL_H = 0x9CC // 2508
+ SYS_CATANH = 0x9CD // 2509
+ SYS___CATANH_B = 0x9CE // 2510
+ SYS___CATANH_H = 0x9CF // 2511
+ SYS_CATANHF = 0x9D0 // 2512
+ SYS___CATANHF_B = 0x9D1 // 2513
+ SYS___CATANHF_H = 0x9D2 // 2514
+ SYS_CATANHL = 0x9D3 // 2515
+ SYS___CATANHL_B = 0x9D4 // 2516
+ SYS___CATANHL_H = 0x9D5 // 2517
+ SYS_CCOS = 0x9D6 // 2518
+ SYS___CCOS_B = 0x9D7 // 2519
+ SYS___CCOS_H = 0x9D8 // 2520
+ SYS_CCOSF = 0x9D9 // 2521
+ SYS___CCOSF_B = 0x9DA // 2522
+ SYS___CCOSF_H = 0x9DB // 2523
+ SYS_CCOSL = 0x9DC // 2524
+ SYS___CCOSL_B = 0x9DD // 2525
+ SYS___CCOSL_H = 0x9DE // 2526
+ SYS_CCOSH = 0x9DF // 2527
+ SYS___CCOSH_B = 0x9E0 // 2528
+ SYS___CCOSH_H = 0x9E1 // 2529
+ SYS_CCOSHF = 0x9E2 // 2530
+ SYS___CCOSHF_B = 0x9E3 // 2531
+ SYS___CCOSHF_H = 0x9E4 // 2532
+ SYS_CCOSHL = 0x9E5 // 2533
+ SYS___CCOSHL_B = 0x9E6 // 2534
+ SYS___CCOSHL_H = 0x9E7 // 2535
+ SYS_CEXP = 0x9E8 // 2536
+ SYS___CEXP_B = 0x9E9 // 2537
+ SYS___CEXP_H = 0x9EA // 2538
+ SYS_CEXPF = 0x9EB // 2539
+ SYS___CEXPF_B = 0x9EC // 2540
+ SYS___CEXPF_H = 0x9ED // 2541
+ SYS_CEXPL = 0x9EE // 2542
+ SYS___CEXPL_B = 0x9EF // 2543
+ SYS___CEXPL_H = 0x9F0 // 2544
+ SYS_CIMAG = 0x9F1 // 2545
+ SYS___CIMAG_B = 0x9F2 // 2546
+ SYS___CIMAG_H = 0x9F3 // 2547
+ SYS_CIMAGF = 0x9F4 // 2548
+ SYS___CIMAGF_B = 0x9F5 // 2549
+ SYS___CIMAGF_H = 0x9F6 // 2550
+ SYS_CIMAGL = 0x9F7 // 2551
+ SYS___CIMAGL_B = 0x9F8 // 2552
+ SYS___CIMAGL_H = 0x9F9 // 2553
+ SYS___CLOG = 0x9FA // 2554
+ SYS___CLOG_B = 0x9FB // 2555
+ SYS___CLOG_H = 0x9FC // 2556
+ SYS_CLOGF = 0x9FD // 2557
+ SYS___CLOGF_B = 0x9FE // 2558
+ SYS___CLOGF_H = 0x9FF // 2559
+ SYS_CLOGL = 0xA00 // 2560
+ SYS___CLOGL_B = 0xA01 // 2561
+ SYS___CLOGL_H = 0xA02 // 2562
+ SYS_CONJ = 0xA03 // 2563
+ SYS___CONJ_B = 0xA04 // 2564
+ SYS___CONJ_H = 0xA05 // 2565
+ SYS_CONJF = 0xA06 // 2566
+ SYS___CONJF_B = 0xA07 // 2567
+ SYS___CONJF_H = 0xA08 // 2568
+ SYS_CONJL = 0xA09 // 2569
+ SYS___CONJL_B = 0xA0A // 2570
+ SYS___CONJL_H = 0xA0B // 2571
+ SYS_CPOW = 0xA0C // 2572
+ SYS___CPOW_B = 0xA0D // 2573
+ SYS___CPOW_H = 0xA0E // 2574
+ SYS_CPOWF = 0xA0F // 2575
+ SYS___CPOWF_B = 0xA10 // 2576
+ SYS___CPOWF_H = 0xA11 // 2577
+ SYS_CPOWL = 0xA12 // 2578
+ SYS___CPOWL_B = 0xA13 // 2579
+ SYS___CPOWL_H = 0xA14 // 2580
+ SYS_CPROJ = 0xA15 // 2581
+ SYS___CPROJ_B = 0xA16 // 2582
+ SYS___CPROJ_H = 0xA17 // 2583
+ SYS_CPROJF = 0xA18 // 2584
+ SYS___CPROJF_B = 0xA19 // 2585
+ SYS___CPROJF_H = 0xA1A // 2586
+ SYS_CPROJL = 0xA1B // 2587
+ SYS___CPROJL_B = 0xA1C // 2588
+ SYS___CPROJL_H = 0xA1D // 2589
+ SYS_CREAL = 0xA1E // 2590
+ SYS___CREAL_B = 0xA1F // 2591
+ SYS___CREAL_H = 0xA20 // 2592
+ SYS_CREALF = 0xA21 // 2593
+ SYS___CREALF_B = 0xA22 // 2594
+ SYS___CREALF_H = 0xA23 // 2595
+ SYS_CREALL = 0xA24 // 2596
+ SYS___CREALL_B = 0xA25 // 2597
+ SYS___CREALL_H = 0xA26 // 2598
+ SYS_CSIN = 0xA27 // 2599
+ SYS___CSIN_B = 0xA28 // 2600
+ SYS___CSIN_H = 0xA29 // 2601
+ SYS_CSINF = 0xA2A // 2602
+ SYS___CSINF_B = 0xA2B // 2603
+ SYS___CSINF_H = 0xA2C // 2604
+ SYS_CSINL = 0xA2D // 2605
+ SYS___CSINL_B = 0xA2E // 2606
+ SYS___CSINL_H = 0xA2F // 2607
+ SYS_CSINH = 0xA30 // 2608
+ SYS___CSINH_B = 0xA31 // 2609
+ SYS___CSINH_H = 0xA32 // 2610
+ SYS_CSINHF = 0xA33 // 2611
+ SYS___CSINHF_B = 0xA34 // 2612
+ SYS___CSINHF_H = 0xA35 // 2613
+ SYS_CSINHL = 0xA36 // 2614
+ SYS___CSINHL_B = 0xA37 // 2615
+ SYS___CSINHL_H = 0xA38 // 2616
+ SYS_CSQRT = 0xA39 // 2617
+ SYS___CSQRT_B = 0xA3A // 2618
+ SYS___CSQRT_H = 0xA3B // 2619
+ SYS_CSQRTF = 0xA3C // 2620
+ SYS___CSQRTF_B = 0xA3D // 2621
+ SYS___CSQRTF_H = 0xA3E // 2622
+ SYS_CSQRTL = 0xA3F // 2623
+ SYS___CSQRTL_B = 0xA40 // 2624
+ SYS___CSQRTL_H = 0xA41 // 2625
+ SYS_CTAN = 0xA42 // 2626
+ SYS___CTAN_B = 0xA43 // 2627
+ SYS___CTAN_H = 0xA44 // 2628
+ SYS_CTANF = 0xA45 // 2629
+ SYS___CTANF_B = 0xA46 // 2630
+ SYS___CTANF_H = 0xA47 // 2631
+ SYS_CTANL = 0xA48 // 2632
+ SYS___CTANL_B = 0xA49 // 2633
+ SYS___CTANL_H = 0xA4A // 2634
+ SYS_CTANH = 0xA4B // 2635
+ SYS___CTANH_B = 0xA4C // 2636
+ SYS___CTANH_H = 0xA4D // 2637
+ SYS_CTANHF = 0xA4E // 2638
+ SYS___CTANHF_B = 0xA4F // 2639
+ SYS___CTANHF_H = 0xA50 // 2640
+ SYS_CTANHL = 0xA51 // 2641
+ SYS___CTANHL_B = 0xA52 // 2642
+ SYS___CTANHL_H = 0xA53 // 2643
+ SYS___ACOSHF_H = 0xA54 // 2644
+ SYS___ACOSHL_H = 0xA55 // 2645
+ SYS___ASINHF_H = 0xA56 // 2646
+ SYS___ASINHL_H = 0xA57 // 2647
+ SYS___CBRTF_H = 0xA58 // 2648
+ SYS___CBRTL_H = 0xA59 // 2649
+ SYS___COPYSIGN_B = 0xA5A // 2650
+ SYS___EXPM1F_H = 0xA5B // 2651
+ SYS___EXPM1L_H = 0xA5C // 2652
+ SYS___EXP2_H = 0xA5D // 2653
+ SYS___EXP2F_H = 0xA5E // 2654
+ SYS___EXP2L_H = 0xA5F // 2655
+ SYS___LOG1PF_H = 0xA60 // 2656
+ SYS___LOG1PL_H = 0xA61 // 2657
+ SYS___LGAMMAL_H = 0xA62 // 2658
+ SYS_FMA = 0xA63 // 2659
+ SYS___FMA_B = 0xA64 // 2660
+ SYS___FMA_H = 0xA65 // 2661
+ SYS_FMAF = 0xA66 // 2662
+ SYS___FMAF_B = 0xA67 // 2663
+ SYS___FMAF_H = 0xA68 // 2664
+ SYS_FMAL = 0xA69 // 2665
+ SYS___FMAL_B = 0xA6A // 2666
+ SYS___FMAL_H = 0xA6B // 2667
+ SYS_FMAX = 0xA6C // 2668
+ SYS___FMAX_B = 0xA6D // 2669
+ SYS___FMAX_H = 0xA6E // 2670
+ SYS_FMAXF = 0xA6F // 2671
+ SYS___FMAXF_B = 0xA70 // 2672
+ SYS___FMAXF_H = 0xA71 // 2673
+ SYS_FMAXL = 0xA72 // 2674
+ SYS___FMAXL_B = 0xA73 // 2675
+ SYS___FMAXL_H = 0xA74 // 2676
+ SYS_FMIN = 0xA75 // 2677
+ SYS___FMIN_B = 0xA76 // 2678
+ SYS___FMIN_H = 0xA77 // 2679
+ SYS_FMINF = 0xA78 // 2680
+ SYS___FMINF_B = 0xA79 // 2681
+ SYS___FMINF_H = 0xA7A // 2682
+ SYS_FMINL = 0xA7B // 2683
+ SYS___FMINL_B = 0xA7C // 2684
+ SYS___FMINL_H = 0xA7D // 2685
+ SYS_ILOGBF = 0xA7E // 2686
+ SYS___ILOGBF_B = 0xA7F // 2687
+ SYS___ILOGBF_H = 0xA80 // 2688
+ SYS_ILOGBL = 0xA81 // 2689
+ SYS___ILOGBL_B = 0xA82 // 2690
+ SYS___ILOGBL_H = 0xA83 // 2691
+ SYS_LLRINT = 0xA84 // 2692
+ SYS___LLRINT_B = 0xA85 // 2693
+ SYS___LLRINT_H = 0xA86 // 2694
+ SYS_LLRINTF = 0xA87 // 2695
+ SYS___LLRINTF_B = 0xA88 // 2696
+ SYS___LLRINTF_H = 0xA89 // 2697
+ SYS_LLRINTL = 0xA8A // 2698
+ SYS___LLRINTL_B = 0xA8B // 2699
+ SYS___LLRINTL_H = 0xA8C // 2700
+ SYS_LLROUND = 0xA8D // 2701
+ SYS___LLROUND_B = 0xA8E // 2702
+ SYS___LLROUND_H = 0xA8F // 2703
+ SYS_LLROUNDF = 0xA90 // 2704
+ SYS___LLROUNDF_B = 0xA91 // 2705
+ SYS___LLROUNDF_H = 0xA92 // 2706
+ SYS_LLROUNDL = 0xA93 // 2707
+ SYS___LLROUNDL_B = 0xA94 // 2708
+ SYS___LLROUNDL_H = 0xA95 // 2709
+ SYS_LOGBF = 0xA96 // 2710
+ SYS___LOGBF_B = 0xA97 // 2711
+ SYS___LOGBF_H = 0xA98 // 2712
+ SYS_LOGBL = 0xA99 // 2713
+ SYS___LOGBL_B = 0xA9A // 2714
+ SYS___LOGBL_H = 0xA9B // 2715
+ SYS_LRINT = 0xA9C // 2716
+ SYS___LRINT_B = 0xA9D // 2717
+ SYS___LRINT_H = 0xA9E // 2718
+ SYS_LRINTF = 0xA9F // 2719
+ SYS___LRINTF_B = 0xAA0 // 2720
+ SYS___LRINTF_H = 0xAA1 // 2721
+ SYS_LRINTL = 0xAA2 // 2722
+ SYS___LRINTL_B = 0xAA3 // 2723
+ SYS___LRINTL_H = 0xAA4 // 2724
+ SYS_LROUNDL = 0xAA5 // 2725
+ SYS___LROUNDL_B = 0xAA6 // 2726
+ SYS___LROUNDL_H = 0xAA7 // 2727
+ SYS_NAN = 0xAA8 // 2728
+ SYS___NAN_B = 0xAA9 // 2729
+ SYS_NANF = 0xAAA // 2730
+ SYS___NANF_B = 0xAAB // 2731
+ SYS_NANL = 0xAAC // 2732
+ SYS___NANL_B = 0xAAD // 2733
+ SYS_NEARBYINT = 0xAAE // 2734
+ SYS___NEARBYINT_B = 0xAAF // 2735
+ SYS___NEARBYINT_H = 0xAB0 // 2736
+ SYS_NEARBYINTF = 0xAB1 // 2737
+ SYS___NEARBYINTF_B = 0xAB2 // 2738
+ SYS___NEARBYINTF_H = 0xAB3 // 2739
+ SYS_NEARBYINTL = 0xAB4 // 2740
+ SYS___NEARBYINTL_B = 0xAB5 // 2741
+ SYS___NEARBYINTL_H = 0xAB6 // 2742
+ SYS_NEXTAFTERF = 0xAB7 // 2743
+ SYS___NEXTAFTERF_B = 0xAB8 // 2744
+ SYS___NEXTAFTERF_H = 0xAB9 // 2745
+ SYS_NEXTAFTERL = 0xABA // 2746
+ SYS___NEXTAFTERL_B = 0xABB // 2747
+ SYS___NEXTAFTERL_H = 0xABC // 2748
+ SYS_NEXTTOWARD = 0xABD // 2749
+ SYS___NEXTTOWARD_B = 0xABE // 2750
+ SYS___NEXTTOWARD_H = 0xABF // 2751
+ SYS_NEXTTOWARDF = 0xAC0 // 2752
+ SYS___NEXTTOWARDF_B = 0xAC1 // 2753
+ SYS___NEXTTOWARDF_H = 0xAC2 // 2754
+ SYS_NEXTTOWARDL = 0xAC3 // 2755
+ SYS___NEXTTOWARDL_B = 0xAC4 // 2756
+ SYS___NEXTTOWARDL_H = 0xAC5 // 2757
+ SYS___REMAINDERF_H = 0xAC6 // 2758
+ SYS___REMAINDERL_H = 0xAC7 // 2759
+ SYS___REMQUO_H = 0xAC8 // 2760
+ SYS___REMQUOF_H = 0xAC9 // 2761
+ SYS___REMQUOL_H = 0xACA // 2762
+ SYS_RINTF = 0xACB // 2763
+ SYS___RINTF_B = 0xACC // 2764
+ SYS_RINTL = 0xACD // 2765
+ SYS___RINTL_B = 0xACE // 2766
+ SYS_ROUND = 0xACF // 2767
+ SYS___ROUND_B = 0xAD0 // 2768
+ SYS___ROUND_H = 0xAD1 // 2769
+ SYS_ROUNDF = 0xAD2 // 2770
+ SYS___ROUNDF_B = 0xAD3 // 2771
+ SYS___ROUNDF_H = 0xAD4 // 2772
+ SYS_ROUNDL = 0xAD5 // 2773
+ SYS___ROUNDL_B = 0xAD6 // 2774
+ SYS___ROUNDL_H = 0xAD7 // 2775
+ SYS_SCALBLN = 0xAD8 // 2776
+ SYS___SCALBLN_B = 0xAD9 // 2777
+ SYS___SCALBLN_H = 0xADA // 2778
+ SYS_SCALBLNF = 0xADB // 2779
+ SYS___SCALBLNF_B = 0xADC // 2780
+ SYS___SCALBLNF_H = 0xADD // 2781
+ SYS_SCALBLNL = 0xADE // 2782
+ SYS___SCALBLNL_B = 0xADF // 2783
+ SYS___SCALBLNL_H = 0xAE0 // 2784
+ SYS___SCALBN_B = 0xAE1 // 2785
+ SYS___SCALBN_H = 0xAE2 // 2786
+ SYS_SCALBNF = 0xAE3 // 2787
+ SYS___SCALBNF_B = 0xAE4 // 2788
+ SYS___SCALBNF_H = 0xAE5 // 2789
+ SYS_SCALBNL = 0xAE6 // 2790
+ SYS___SCALBNL_B = 0xAE7 // 2791
+ SYS___SCALBNL_H = 0xAE8 // 2792
+ SYS___TGAMMAL_H = 0xAE9 // 2793
+ SYS_FECLEAREXCEPT = 0xAEA // 2794
+ SYS_FEGETENV = 0xAEB // 2795
+ SYS_FEGETEXCEPTFLAG = 0xAEC // 2796
+ SYS_FEGETROUND = 0xAED // 2797
+ SYS_FEHOLDEXCEPT = 0xAEE // 2798
+ SYS_FERAISEEXCEPT = 0xAEF // 2799
+ SYS_FESETENV = 0xAF0 // 2800
+ SYS_FESETEXCEPTFLAG = 0xAF1 // 2801
+ SYS_FESETROUND = 0xAF2 // 2802
+ SYS_FETESTEXCEPT = 0xAF3 // 2803
+ SYS_FEUPDATEENV = 0xAF4 // 2804
+ SYS___COPYSIGN_H = 0xAF5 // 2805
+ SYS___HYPOTF_H = 0xAF6 // 2806
+ SYS___HYPOTL_H = 0xAF7 // 2807
+ SYS___CLASS = 0xAFA // 2810
+ SYS___CLASS_B = 0xAFB // 2811
+ SYS___CLASS_H = 0xAFC // 2812
+ SYS___ISBLANK_A = 0xB2E // 2862
+ SYS___ISWBLANK_A = 0xB2F // 2863
+ SYS___LROUND_FIXUP = 0xB30 // 2864
+ SYS___LROUNDF_FIXUP = 0xB31 // 2865
+ SYS_SCHED_YIELD = 0xB32 // 2866
+ SYS_STRERROR_R = 0xB33 // 2867
+ SYS_UNSETENV = 0xB34 // 2868
+ SYS___LGAMMA_H_C99 = 0xB38 // 2872
+ SYS___LGAMMA_B_C99 = 0xB39 // 2873
+ SYS___LGAMMA_R_C99 = 0xB3A // 2874
+ SYS___FTELL2 = 0xB3B // 2875
+ SYS___FSEEK2 = 0xB3C // 2876
+ SYS___STATIC_REINIT = 0xB3D // 2877
+ SYS_PTHREAD_ATTR_GETSTACK = 0xB3E // 2878
+ SYS_PTHREAD_ATTR_SETSTACK = 0xB3F // 2879
+ SYS___TGAMMA_H_C99 = 0xB78 // 2936
+ SYS___TGAMMAF_H_C99 = 0xB79 // 2937
+ SYS___LE_TRACEBACK = 0xB7A // 2938
+ SYS___MUST_STAY_CLEAN = 0xB7C // 2940
+ SYS___O_ENV = 0xB7D // 2941
+ SYS_ACOSD32 = 0xB7E // 2942
+ SYS_ACOSD64 = 0xB7F // 2943
+ SYS_ACOSD128 = 0xB80 // 2944
+ SYS_ACOSHD32 = 0xB81 // 2945
+ SYS_ACOSHD64 = 0xB82 // 2946
+ SYS_ACOSHD128 = 0xB83 // 2947
+ SYS_ASIND32 = 0xB84 // 2948
+ SYS_ASIND64 = 0xB85 // 2949
+ SYS_ASIND128 = 0xB86 // 2950
+ SYS_ASINHD32 = 0xB87 // 2951
+ SYS_ASINHD64 = 0xB88 // 2952
+ SYS_ASINHD128 = 0xB89 // 2953
+ SYS_ATAND32 = 0xB8A // 2954
+ SYS_ATAND64 = 0xB8B // 2955
+ SYS_ATAND128 = 0xB8C // 2956
+ SYS_ATAN2D32 = 0xB8D // 2957
+ SYS_ATAN2D64 = 0xB8E // 2958
+ SYS_ATAN2D128 = 0xB8F // 2959
+ SYS_ATANHD32 = 0xB90 // 2960
+ SYS_ATANHD64 = 0xB91 // 2961
+ SYS_ATANHD128 = 0xB92 // 2962
+ SYS_CBRTD32 = 0xB93 // 2963
+ SYS_CBRTD64 = 0xB94 // 2964
+ SYS_CBRTD128 = 0xB95 // 2965
+ SYS_CEILD32 = 0xB96 // 2966
+ SYS_CEILD64 = 0xB97 // 2967
+ SYS_CEILD128 = 0xB98 // 2968
+ SYS___CLASS2 = 0xB99 // 2969
+ SYS___CLASS2_B = 0xB9A // 2970
+ SYS___CLASS2_H = 0xB9B // 2971
+ SYS_COPYSIGND32 = 0xB9C // 2972
+ SYS_COPYSIGND64 = 0xB9D // 2973
+ SYS_COPYSIGND128 = 0xB9E // 2974
+ SYS_COSD32 = 0xB9F // 2975
+ SYS_COSD64 = 0xBA0 // 2976
+ SYS_COSD128 = 0xBA1 // 2977
+ SYS_COSHD32 = 0xBA2 // 2978
+ SYS_COSHD64 = 0xBA3 // 2979
+ SYS_COSHD128 = 0xBA4 // 2980
+ SYS_ERFD32 = 0xBA5 // 2981
+ SYS_ERFD64 = 0xBA6 // 2982
+ SYS_ERFD128 = 0xBA7 // 2983
+ SYS_ERFCD32 = 0xBA8 // 2984
+ SYS_ERFCD64 = 0xBA9 // 2985
+ SYS_ERFCD128 = 0xBAA // 2986
+ SYS_EXPD32 = 0xBAB // 2987
+ SYS_EXPD64 = 0xBAC // 2988
+ SYS_EXPD128 = 0xBAD // 2989
+ SYS_EXP2D32 = 0xBAE // 2990
+ SYS_EXP2D64 = 0xBAF // 2991
+ SYS_EXP2D128 = 0xBB0 // 2992
+ SYS_EXPM1D32 = 0xBB1 // 2993
+ SYS_EXPM1D64 = 0xBB2 // 2994
+ SYS_EXPM1D128 = 0xBB3 // 2995
+ SYS_FABSD32 = 0xBB4 // 2996
+ SYS_FABSD64 = 0xBB5 // 2997
+ SYS_FABSD128 = 0xBB6 // 2998
+ SYS_FDIMD32 = 0xBB7 // 2999
+ SYS_FDIMD64 = 0xBB8 // 3000
+ SYS_FDIMD128 = 0xBB9 // 3001
+ SYS_FE_DEC_GETROUND = 0xBBA // 3002
+ SYS_FE_DEC_SETROUND = 0xBBB // 3003
+ SYS_FLOORD32 = 0xBBC // 3004
+ SYS_FLOORD64 = 0xBBD // 3005
+ SYS_FLOORD128 = 0xBBE // 3006
+ SYS_FMAD32 = 0xBBF // 3007
+ SYS_FMAD64 = 0xBC0 // 3008
+ SYS_FMAD128 = 0xBC1 // 3009
+ SYS_FMAXD32 = 0xBC2 // 3010
+ SYS_FMAXD64 = 0xBC3 // 3011
+ SYS_FMAXD128 = 0xBC4 // 3012
+ SYS_FMIND32 = 0xBC5 // 3013
+ SYS_FMIND64 = 0xBC6 // 3014
+ SYS_FMIND128 = 0xBC7 // 3015
+ SYS_FMODD32 = 0xBC8 // 3016
+ SYS_FMODD64 = 0xBC9 // 3017
+ SYS_FMODD128 = 0xBCA // 3018
+ SYS___FP_CAST_D = 0xBCB // 3019
+ SYS_FREXPD32 = 0xBCC // 3020
+ SYS_FREXPD64 = 0xBCD // 3021
+ SYS_FREXPD128 = 0xBCE // 3022
+ SYS_HYPOTD32 = 0xBCF // 3023
+ SYS_HYPOTD64 = 0xBD0 // 3024
+ SYS_HYPOTD128 = 0xBD1 // 3025
+ SYS_ILOGBD32 = 0xBD2 // 3026
+ SYS_ILOGBD64 = 0xBD3 // 3027
+ SYS_ILOGBD128 = 0xBD4 // 3028
+ SYS_LDEXPD32 = 0xBD5 // 3029
+ SYS_LDEXPD64 = 0xBD6 // 3030
+ SYS_LDEXPD128 = 0xBD7 // 3031
+ SYS_LGAMMAD32 = 0xBD8 // 3032
+ SYS_LGAMMAD64 = 0xBD9 // 3033
+ SYS_LGAMMAD128 = 0xBDA // 3034
+ SYS_LLRINTD32 = 0xBDB // 3035
+ SYS_LLRINTD64 = 0xBDC // 3036
+ SYS_LLRINTD128 = 0xBDD // 3037
+ SYS_LLROUNDD32 = 0xBDE // 3038
+ SYS_LLROUNDD64 = 0xBDF // 3039
+ SYS_LLROUNDD128 = 0xBE0 // 3040
+ SYS_LOGD32 = 0xBE1 // 3041
+ SYS_LOGD64 = 0xBE2 // 3042
+ SYS_LOGD128 = 0xBE3 // 3043
+ SYS_LOG10D32 = 0xBE4 // 3044
+ SYS_LOG10D64 = 0xBE5 // 3045
+ SYS_LOG10D128 = 0xBE6 // 3046
+ SYS_LOG1PD32 = 0xBE7 // 3047
+ SYS_LOG1PD64 = 0xBE8 // 3048
+ SYS_LOG1PD128 = 0xBE9 // 3049
+ SYS_LOG2D32 = 0xBEA // 3050
+ SYS_LOG2D64 = 0xBEB // 3051
+ SYS_LOG2D128 = 0xBEC // 3052
+ SYS_LOGBD32 = 0xBED // 3053
+ SYS_LOGBD64 = 0xBEE // 3054
+ SYS_LOGBD128 = 0xBEF // 3055
+ SYS_LRINTD32 = 0xBF0 // 3056
+ SYS_LRINTD64 = 0xBF1 // 3057
+ SYS_LRINTD128 = 0xBF2 // 3058
+ SYS_LROUNDD32 = 0xBF3 // 3059
+ SYS_LROUNDD64 = 0xBF4 // 3060
+ SYS_LROUNDD128 = 0xBF5 // 3061
+ SYS_MODFD32 = 0xBF6 // 3062
+ SYS_MODFD64 = 0xBF7 // 3063
+ SYS_MODFD128 = 0xBF8 // 3064
+ SYS_NAND32 = 0xBF9 // 3065
+ SYS_NAND64 = 0xBFA // 3066
+ SYS_NAND128 = 0xBFB // 3067
+ SYS_NEARBYINTD32 = 0xBFC // 3068
+ SYS_NEARBYINTD64 = 0xBFD // 3069
+ SYS_NEARBYINTD128 = 0xBFE // 3070
+ SYS_NEXTAFTERD32 = 0xBFF // 3071
+ SYS_NEXTAFTERD64 = 0xC00 // 3072
+ SYS_NEXTAFTERD128 = 0xC01 // 3073
+ SYS_NEXTTOWARDD32 = 0xC02 // 3074
+ SYS_NEXTTOWARDD64 = 0xC03 // 3075
+ SYS_NEXTTOWARDD128 = 0xC04 // 3076
+ SYS_POWD32 = 0xC05 // 3077
+ SYS_POWD64 = 0xC06 // 3078
+ SYS_POWD128 = 0xC07 // 3079
+ SYS_QUANTIZED32 = 0xC08 // 3080
+ SYS_QUANTIZED64 = 0xC09 // 3081
+ SYS_QUANTIZED128 = 0xC0A // 3082
+ SYS_REMAINDERD32 = 0xC0B // 3083
+ SYS_REMAINDERD64 = 0xC0C // 3084
+ SYS_REMAINDERD128 = 0xC0D // 3085
+ SYS___REMQUOD32 = 0xC0E // 3086
+ SYS___REMQUOD64 = 0xC0F // 3087
+ SYS___REMQUOD128 = 0xC10 // 3088
+ SYS_RINTD32 = 0xC11 // 3089
+ SYS_RINTD64 = 0xC12 // 3090
+ SYS_RINTD128 = 0xC13 // 3091
+ SYS_ROUNDD32 = 0xC14 // 3092
+ SYS_ROUNDD64 = 0xC15 // 3093
+ SYS_ROUNDD128 = 0xC16 // 3094
+ SYS_SAMEQUANTUMD32 = 0xC17 // 3095
+ SYS_SAMEQUANTUMD64 = 0xC18 // 3096
+ SYS_SAMEQUANTUMD128 = 0xC19 // 3097
+ SYS_SCALBLND32 = 0xC1A // 3098
+ SYS_SCALBLND64 = 0xC1B // 3099
+ SYS_SCALBLND128 = 0xC1C // 3100
+ SYS_SCALBND32 = 0xC1D // 3101
+ SYS_SCALBND64 = 0xC1E // 3102
+ SYS_SCALBND128 = 0xC1F // 3103
+ SYS_SIND32 = 0xC20 // 3104
+ SYS_SIND64 = 0xC21 // 3105
+ SYS_SIND128 = 0xC22 // 3106
+ SYS_SINHD32 = 0xC23 // 3107
+ SYS_SINHD64 = 0xC24 // 3108
+ SYS_SINHD128 = 0xC25 // 3109
+ SYS_SQRTD32 = 0xC26 // 3110
+ SYS_SQRTD64 = 0xC27 // 3111
+ SYS_SQRTD128 = 0xC28 // 3112
+ SYS_STRTOD32 = 0xC29 // 3113
+ SYS_STRTOD64 = 0xC2A // 3114
+ SYS_STRTOD128 = 0xC2B // 3115
+ SYS_TAND32 = 0xC2C // 3116
+ SYS_TAND64 = 0xC2D // 3117
+ SYS_TAND128 = 0xC2E // 3118
+ SYS_TANHD32 = 0xC2F // 3119
+ SYS_TANHD64 = 0xC30 // 3120
+ SYS_TANHD128 = 0xC31 // 3121
+ SYS_TGAMMAD32 = 0xC32 // 3122
+ SYS_TGAMMAD64 = 0xC33 // 3123
+ SYS_TGAMMAD128 = 0xC34 // 3124
+ SYS_TRUNCD32 = 0xC3E // 3134
+ SYS_TRUNCD64 = 0xC3F // 3135
+ SYS_TRUNCD128 = 0xC40 // 3136
+ SYS_WCSTOD32 = 0xC41 // 3137
+ SYS_WCSTOD64 = 0xC42 // 3138
+ SYS_WCSTOD128 = 0xC43 // 3139
+ SYS___CODEPAGE_INFO = 0xC64 // 3172
+ SYS_POSIX_OPENPT = 0xC66 // 3174
+ SYS_PSELECT = 0xC67 // 3175
+ SYS_SOCKATMARK = 0xC68 // 3176
+ SYS_AIO_FSYNC = 0xC69 // 3177
+ SYS_LIO_LISTIO = 0xC6A // 3178
+ SYS___ATANPID32 = 0xC6B // 3179
+ SYS___ATANPID64 = 0xC6C // 3180
+ SYS___ATANPID128 = 0xC6D // 3181
+ SYS___COSPID32 = 0xC6E // 3182
+ SYS___COSPID64 = 0xC6F // 3183
+ SYS___COSPID128 = 0xC70 // 3184
+ SYS___SINPID32 = 0xC71 // 3185
+ SYS___SINPID64 = 0xC72 // 3186
+ SYS___SINPID128 = 0xC73 // 3187
+ SYS_SETIPV4SOURCEFILTER = 0xC76 // 3190
+ SYS_GETIPV4SOURCEFILTER = 0xC77 // 3191
+ SYS_SETSOURCEFILTER = 0xC78 // 3192
+ SYS_GETSOURCEFILTER = 0xC79 // 3193
+ SYS_FWRITE_UNLOCKED = 0xC7A // 3194
+ SYS_FREAD_UNLOCKED = 0xC7B // 3195
+ SYS_FGETS_UNLOCKED = 0xC7C // 3196
+ SYS_GETS_UNLOCKED = 0xC7D // 3197
+ SYS_FPUTS_UNLOCKED = 0xC7E // 3198
+ SYS_PUTS_UNLOCKED = 0xC7F // 3199
+ SYS_FGETC_UNLOCKED = 0xC80 // 3200
+ SYS_FPUTC_UNLOCKED = 0xC81 // 3201
+ SYS_DLADDR = 0xC82 // 3202
+ SYS_SHM_OPEN = 0xC8C // 3212
+ SYS_SHM_UNLINK = 0xC8D // 3213
+ SYS___CLASS2F = 0xC91 // 3217
+ SYS___CLASS2L = 0xC92 // 3218
+ SYS___CLASS2F_B = 0xC93 // 3219
+ SYS___CLASS2F_H = 0xC94 // 3220
+ SYS___CLASS2L_B = 0xC95 // 3221
+ SYS___CLASS2L_H = 0xC96 // 3222
+ SYS___CLASS2D32 = 0xC97 // 3223
+ SYS___CLASS2D64 = 0xC98 // 3224
+ SYS___CLASS2D128 = 0xC99 // 3225
+ SYS___TOCSNAME2 = 0xC9A // 3226
+ SYS___D1TOP = 0xC9B // 3227
+ SYS___D2TOP = 0xC9C // 3228
+ SYS___D4TOP = 0xC9D // 3229
+ SYS___PTOD1 = 0xC9E // 3230
+ SYS___PTOD2 = 0xC9F // 3231
+ SYS___PTOD4 = 0xCA0 // 3232
+ SYS_CLEARERR_UNLOCKED = 0xCA1 // 3233
+ SYS_FDELREC_UNLOCKED = 0xCA2 // 3234
+ SYS_FEOF_UNLOCKED = 0xCA3 // 3235
+ SYS_FERROR_UNLOCKED = 0xCA4 // 3236
+ SYS_FFLUSH_UNLOCKED = 0xCA5 // 3237
+ SYS_FGETPOS_UNLOCKED = 0xCA6 // 3238
+ SYS_FGETWC_UNLOCKED = 0xCA7 // 3239
+ SYS_FGETWS_UNLOCKED = 0xCA8 // 3240
+ SYS_FILENO_UNLOCKED = 0xCA9 // 3241
+ SYS_FLDATA_UNLOCKED = 0xCAA // 3242
+ SYS_FLOCATE_UNLOCKED = 0xCAB // 3243
+ SYS_FPRINTF_UNLOCKED = 0xCAC // 3244
+ SYS_FPUTWC_UNLOCKED = 0xCAD // 3245
+ SYS_FPUTWS_UNLOCKED = 0xCAE // 3246
+ SYS_FSCANF_UNLOCKED = 0xCAF // 3247
+ SYS_FSEEK_UNLOCKED = 0xCB0 // 3248
+ SYS_FSEEKO_UNLOCKED = 0xCB1 // 3249
+ SYS_FSETPOS_UNLOCKED = 0xCB3 // 3251
+ SYS_FTELL_UNLOCKED = 0xCB4 // 3252
+ SYS_FTELLO_UNLOCKED = 0xCB5 // 3253
+ SYS_FUPDATE_UNLOCKED = 0xCB7 // 3255
+ SYS_FWIDE_UNLOCKED = 0xCB8 // 3256
+ SYS_FWPRINTF_UNLOCKED = 0xCB9 // 3257
+ SYS_FWSCANF_UNLOCKED = 0xCBA // 3258
+ SYS_GETWC_UNLOCKED = 0xCBB // 3259
+ SYS_GETWCHAR_UNLOCKED = 0xCBC // 3260
+ SYS_PERROR_UNLOCKED = 0xCBD // 3261
+ SYS_PRINTF_UNLOCKED = 0xCBE // 3262
+ SYS_PUTWC_UNLOCKED = 0xCBF // 3263
+ SYS_PUTWCHAR_UNLOCKED = 0xCC0 // 3264
+ SYS_REWIND_UNLOCKED = 0xCC1 // 3265
+ SYS_SCANF_UNLOCKED = 0xCC2 // 3266
+ SYS_UNGETC_UNLOCKED = 0xCC3 // 3267
+ SYS_UNGETWC_UNLOCKED = 0xCC4 // 3268
+ SYS_VFPRINTF_UNLOCKED = 0xCC5 // 3269
+ SYS_VFSCANF_UNLOCKED = 0xCC7 // 3271
+ SYS_VFWPRINTF_UNLOCKED = 0xCC9 // 3273
+ SYS_VFWSCANF_UNLOCKED = 0xCCB // 3275
+ SYS_VPRINTF_UNLOCKED = 0xCCD // 3277
+ SYS_VSCANF_UNLOCKED = 0xCCF // 3279
+ SYS_VWPRINTF_UNLOCKED = 0xCD1 // 3281
+ SYS_VWSCANF_UNLOCKED = 0xCD3 // 3283
+ SYS_WPRINTF_UNLOCKED = 0xCD5 // 3285
+ SYS_WSCANF_UNLOCKED = 0xCD6 // 3286
+ SYS_ASCTIME64 = 0xCD7 // 3287
+ SYS_ASCTIME64_R = 0xCD8 // 3288
+ SYS_CTIME64 = 0xCD9 // 3289
+ SYS_CTIME64_R = 0xCDA // 3290
+ SYS_DIFFTIME64 = 0xCDB // 3291
+ SYS_GMTIME64 = 0xCDC // 3292
+ SYS_GMTIME64_R = 0xCDD // 3293
+ SYS_LOCALTIME64 = 0xCDE // 3294
+ SYS_LOCALTIME64_R = 0xCDF // 3295
+ SYS_MKTIME64 = 0xCE0 // 3296
+ SYS_TIME64 = 0xCE1 // 3297
+ SYS___LOGIN_APPLID = 0xCE2 // 3298
+ SYS___PASSWD_APPLID = 0xCE3 // 3299
+ SYS_PTHREAD_SECURITY_APPLID_NP = 0xCE4 // 3300
+ SYS___GETTHENT = 0xCE5 // 3301
+ SYS_FREEIFADDRS = 0xCE6 // 3302
+ SYS_GETIFADDRS = 0xCE7 // 3303
+ SYS_POSIX_FALLOCATE = 0xCE8 // 3304
+ SYS_POSIX_MEMALIGN = 0xCE9 // 3305
+ SYS_SIZEOF_ALLOC = 0xCEA // 3306
+ SYS_RESIZE_ALLOC = 0xCEB // 3307
+ SYS_FREAD_NOUPDATE = 0xCEC // 3308
+ SYS_FREAD_NOUPDATE_UNLOCKED = 0xCED // 3309
+ SYS_FGETPOS64 = 0xCEE // 3310
+ SYS_FSEEK64 = 0xCEF // 3311
+ SYS_FSEEKO64 = 0xCF0 // 3312
+ SYS_FSETPOS64 = 0xCF1 // 3313
+ SYS_FTELL64 = 0xCF2 // 3314
+ SYS_FTELLO64 = 0xCF3 // 3315
+ SYS_FGETPOS64_UNLOCKED = 0xCF4 // 3316
+ SYS_FSEEK64_UNLOCKED = 0xCF5 // 3317
+ SYS_FSEEKO64_UNLOCKED = 0xCF6 // 3318
+ SYS_FSETPOS64_UNLOCKED = 0xCF7 // 3319
+ SYS_FTELL64_UNLOCKED = 0xCF8 // 3320
+ SYS_FTELLO64_UNLOCKED = 0xCF9 // 3321
+ SYS_FOPEN_UNLOCKED = 0xCFA // 3322
+ SYS_FREOPEN_UNLOCKED = 0xCFB // 3323
+ SYS_FDOPEN_UNLOCKED = 0xCFC // 3324
+ SYS_TMPFILE_UNLOCKED = 0xCFD // 3325
+ SYS___MOSERVICES = 0xD3D // 3389
+ SYS___GETTOD = 0xD3E // 3390
+ SYS_C16RTOMB = 0xD40 // 3392
+ SYS_C32RTOMB = 0xD41 // 3393
+ SYS_MBRTOC16 = 0xD42 // 3394
+ SYS_MBRTOC32 = 0xD43 // 3395
+ SYS_QUANTEXPD32 = 0xD44 // 3396
+ SYS_QUANTEXPD64 = 0xD45 // 3397
+ SYS_QUANTEXPD128 = 0xD46 // 3398
+ SYS___LOCALE_CTL = 0xD47 // 3399
+ SYS___SMF_RECORD2 = 0xD48 // 3400
+ SYS_FOPEN64 = 0xD49 // 3401
+ SYS_FOPEN64_UNLOCKED = 0xD4A // 3402
+ SYS_FREOPEN64 = 0xD4B // 3403
+ SYS_FREOPEN64_UNLOCKED = 0xD4C // 3404
+ SYS_TMPFILE64 = 0xD4D // 3405
+ SYS_TMPFILE64_UNLOCKED = 0xD4E // 3406
+ SYS_GETDATE64 = 0xD4F // 3407
+ SYS_GETTIMEOFDAY64 = 0xD50 // 3408
+ SYS_BIND2ADDRSEL = 0xD59 // 3417
+ SYS_INET6_IS_SRCADDR = 0xD5A // 3418
+ SYS___GETGRGID1 = 0xD5B // 3419
+ SYS___GETGRNAM1 = 0xD5C // 3420
+ SYS___FBUFSIZE = 0xD60 // 3424
+ SYS___FPENDING = 0xD61 // 3425
+ SYS___FLBF = 0xD62 // 3426
+ SYS___FREADABLE = 0xD63 // 3427
+ SYS___FWRITABLE = 0xD64 // 3428
+ SYS___FREADING = 0xD65 // 3429
+ SYS___FWRITING = 0xD66 // 3430
+ SYS___FSETLOCKING = 0xD67 // 3431
+ SYS__FLUSHLBF = 0xD68 // 3432
+ SYS___FPURGE = 0xD69 // 3433
+ SYS___FREADAHEAD = 0xD6A // 3434
+ SYS___FSETERR = 0xD6B // 3435
+ SYS___FPENDING_UNLOCKED = 0xD6C // 3436
+ SYS___FREADING_UNLOCKED = 0xD6D // 3437
+ SYS___FWRITING_UNLOCKED = 0xD6E // 3438
+ SYS__FLUSHLBF_UNLOCKED = 0xD6F // 3439
+ SYS___FPURGE_UNLOCKED = 0xD70 // 3440
+ SYS___FREADAHEAD_UNLOCKED = 0xD71 // 3441
+ SYS___LE_CEEGTJS = 0xD72 // 3442
+ SYS___LE_RECORD_DUMP = 0xD73 // 3443
+ SYS_FSTAT64 = 0xD74 // 3444
+ SYS_LSTAT64 = 0xD75 // 3445
+ SYS_STAT64 = 0xD76 // 3446
+ SYS___READDIR2_64 = 0xD77 // 3447
+ SYS___OPEN_STAT64 = 0xD78 // 3448
+ SYS_FTW64 = 0xD79 // 3449
+ SYS_NFTW64 = 0xD7A // 3450
+ SYS_UTIME64 = 0xD7B // 3451
+ SYS_UTIMES64 = 0xD7C // 3452
+ SYS___GETIPC64 = 0xD7D // 3453
+ SYS_MSGCTL64 = 0xD7E // 3454
+ SYS_SEMCTL64 = 0xD7F // 3455
+ SYS_SHMCTL64 = 0xD80 // 3456
+ SYS_MSGXRCV64 = 0xD81 // 3457
+ SYS___MGXR64 = 0xD81 // 3457
+ SYS_W_GETPSENT64 = 0xD82 // 3458
+ SYS_PTHREAD_COND_TIMEDWAIT64 = 0xD83 // 3459
+ SYS_FTIME64 = 0xD85 // 3461
+ SYS_GETUTXENT64 = 0xD86 // 3462
+ SYS_GETUTXID64 = 0xD87 // 3463
+ SYS_GETUTXLINE64 = 0xD88 // 3464
+ SYS_PUTUTXLINE64 = 0xD89 // 3465
+ SYS_NEWLOCALE = 0xD8A // 3466
+ SYS_FREELOCALE = 0xD8B // 3467
+ SYS_USELOCALE = 0xD8C // 3468
+ SYS_DUPLOCALE = 0xD8D // 3469
+ SYS___CHATTR64 = 0xD9C // 3484
+ SYS___LCHATTR64 = 0xD9D // 3485
+ SYS___FCHATTR64 = 0xD9E // 3486
+ SYS_____CHATTR64_A = 0xD9F // 3487
+ SYS_____LCHATTR64_A = 0xDA0 // 3488
+ SYS___LE_CEEUSGD = 0xDA1 // 3489
+ SYS___LE_IFAM_CON = 0xDA2 // 3490
+ SYS___LE_IFAM_DSC = 0xDA3 // 3491
+ SYS___LE_IFAM_GET = 0xDA4 // 3492
+ SYS___LE_IFAM_QRY = 0xDA5 // 3493
+ SYS_ALIGNED_ALLOC = 0xDA6 // 3494
+ SYS_ACCEPT4 = 0xDA7 // 3495
+ SYS___ACCEPT4_A = 0xDA8 // 3496
+ SYS_COPYFILERANGE = 0xDA9 // 3497
+ SYS_GETLINE = 0xDAA // 3498
+ SYS___GETLINE_A = 0xDAB // 3499
+ SYS_DIRFD = 0xDAC // 3500
+ SYS_CLOCK_GETTIME = 0xDAD // 3501
+ SYS_DUP3 = 0xDAE // 3502
+ SYS_EPOLL_CREATE = 0xDAF // 3503
+ SYS_EPOLL_CREATE1 = 0xDB0 // 3504
+ SYS_EPOLL_CTL = 0xDB1 // 3505
+ SYS_EPOLL_WAIT = 0xDB2 // 3506
+ SYS_EPOLL_PWAIT = 0xDB3 // 3507
+ SYS_EVENTFD = 0xDB4 // 3508
+ SYS_STATFS = 0xDB5 // 3509
+ SYS___STATFS_A = 0xDB6 // 3510
+ SYS_FSTATFS = 0xDB7 // 3511
+ SYS_INOTIFY_INIT = 0xDB8 // 3512
+ SYS_INOTIFY_INIT1 = 0xDB9 // 3513
+ SYS_INOTIFY_ADD_WATCH = 0xDBA // 3514
+ SYS___INOTIFY_ADD_WATCH_A = 0xDBB // 3515
+ SYS_INOTIFY_RM_WATCH = 0xDBC // 3516
+ SYS_PIPE2 = 0xDBD // 3517
+ SYS_PIVOT_ROOT = 0xDBE // 3518
+ SYS___PIVOT_ROOT_A = 0xDBF // 3519
+ SYS_PRCTL = 0xDC0 // 3520
+ SYS_PRLIMIT = 0xDC1 // 3521
+ SYS_SETHOSTNAME = 0xDC2 // 3522
+ SYS___SETHOSTNAME_A = 0xDC3 // 3523
+ SYS_SETRESUID = 0xDC4 // 3524
+ SYS_SETRESGID = 0xDC5 // 3525
+ SYS_PTHREAD_CONDATTR_GETCLOCK = 0xDC6 // 3526
+ SYS_FLOCK = 0xDC7 // 3527
+ SYS_FGETXATTR = 0xDC8 // 3528
+ SYS___FGETXATTR_A = 0xDC9 // 3529
+ SYS_FLISTXATTR = 0xDCA // 3530
+ SYS___FLISTXATTR_A = 0xDCB // 3531
+ SYS_FREMOVEXATTR = 0xDCC // 3532
+ SYS___FREMOVEXATTR_A = 0xDCD // 3533
+ SYS_FSETXATTR = 0xDCE // 3534
+ SYS___FSETXATTR_A = 0xDCF // 3535
+ SYS_GETXATTR = 0xDD0 // 3536
+ SYS___GETXATTR_A = 0xDD1 // 3537
+ SYS_LGETXATTR = 0xDD2 // 3538
+ SYS___LGETXATTR_A = 0xDD3 // 3539
+ SYS_LISTXATTR = 0xDD4 // 3540
+ SYS___LISTXATTR_A = 0xDD5 // 3541
+ SYS_LLISTXATTR = 0xDD6 // 3542
+ SYS___LLISTXATTR_A = 0xDD7 // 3543
+ SYS_LREMOVEXATTR = 0xDD8 // 3544
+ SYS___LREMOVEXATTR_A = 0xDD9 // 3545
+ SYS_LSETXATTR = 0xDDA // 3546
+ SYS___LSETXATTR_A = 0xDDB // 3547
+ SYS_REMOVEXATTR = 0xDDC // 3548
+ SYS___REMOVEXATTR_A = 0xDDD // 3549
+ SYS_SETXATTR = 0xDDE // 3550
+ SYS___SETXATTR_A = 0xDDF // 3551
+ SYS_FDATASYNC = 0xDE0 // 3552
+ SYS_SYNCFS = 0xDE1 // 3553
+ SYS_FUTIMES = 0xDE2 // 3554
+ SYS_FUTIMESAT = 0xDE3 // 3555
+ SYS___FUTIMESAT_A = 0xDE4 // 3556
+ SYS_LUTIMES = 0xDE5 // 3557
+ SYS___LUTIMES_A = 0xDE6 // 3558
+ SYS_INET_ATON = 0xDE7 // 3559
+ SYS_GETRANDOM = 0xDE8 // 3560
+ SYS_GETTID = 0xDE9 // 3561
+ SYS_MEMFD_CREATE = 0xDEA // 3562
+ SYS___MEMFD_CREATE_A = 0xDEB // 3563
+ SYS_FACCESSAT = 0xDEC // 3564
+ SYS___FACCESSAT_A = 0xDED // 3565
+ SYS_FCHMODAT = 0xDEE // 3566
+ SYS___FCHMODAT_A = 0xDEF // 3567
+ SYS_FCHOWNAT = 0xDF0 // 3568
+ SYS___FCHOWNAT_A = 0xDF1 // 3569
+ SYS_FSTATAT = 0xDF2 // 3570
+ SYS___FSTATAT_A = 0xDF3 // 3571
+ SYS_LINKAT = 0xDF4 // 3572
+ SYS___LINKAT_A = 0xDF5 // 3573
+ SYS_MKDIRAT = 0xDF6 // 3574
+ SYS___MKDIRAT_A = 0xDF7 // 3575
+ SYS_MKFIFOAT = 0xDF8 // 3576
+ SYS___MKFIFOAT_A = 0xDF9 // 3577
+ SYS_MKNODAT = 0xDFA // 3578
+ SYS___MKNODAT_A = 0xDFB // 3579
+ SYS_OPENAT = 0xDFC // 3580
+ SYS___OPENAT_A = 0xDFD // 3581
+ SYS_READLINKAT = 0xDFE // 3582
+ SYS___READLINKAT_A = 0xDFF // 3583
+ SYS_RENAMEAT = 0xE00 // 3584
+ SYS___RENAMEAT_A = 0xE01 // 3585
+ SYS_RENAMEAT2 = 0xE02 // 3586
+ SYS___RENAMEAT2_A = 0xE03 // 3587
+ SYS_SYMLINKAT = 0xE04 // 3588
+ SYS___SYMLINKAT_A = 0xE05 // 3589
+ SYS_UNLINKAT = 0xE06 // 3590
+ SYS___UNLINKAT_A = 0xE07 // 3591
+ SYS_SYSINFO = 0xE08 // 3592
+ SYS_WAIT4 = 0xE0A // 3594
+ SYS_CLONE = 0xE0B // 3595
+ SYS_UNSHARE = 0xE0C // 3596
+ SYS_SETNS = 0xE0D // 3597
+ SYS_CAPGET = 0xE0E // 3598
+ SYS_CAPSET = 0xE0F // 3599
+ SYS_STRCHRNUL = 0xE10 // 3600
+ SYS_PTHREAD_CONDATTR_SETCLOCK = 0xE12 // 3602
+ SYS_OPEN_BY_HANDLE_AT = 0xE13 // 3603
+ SYS___OPEN_BY_HANDLE_AT_A = 0xE14 // 3604
+ SYS___INET_ATON_A = 0xE15 // 3605
+ SYS_MOUNT1 = 0xE16 // 3606
+ SYS___MOUNT1_A = 0xE17 // 3607
+ SYS_UMOUNT1 = 0xE18 // 3608
+ SYS___UMOUNT1_A = 0xE19 // 3609
+ SYS_UMOUNT2 = 0xE1A // 3610
+ SYS___UMOUNT2_A = 0xE1B // 3611
+ SYS___PRCTL_A = 0xE1C // 3612
+ SYS_LOCALTIME_R2 = 0xE1D // 3613
+ SYS___LOCALTIME_R2_A = 0xE1E // 3614
+ SYS_OPENAT2 = 0xE1F // 3615
+ SYS___OPENAT2_A = 0xE20 // 3616
+ SYS___LE_CEEMICT = 0xE21 // 3617
+ SYS_GETENTROPY = 0xE22 // 3618
+ SYS_NANOSLEEP = 0xE23 // 3619
+ SYS_UTIMENSAT = 0xE24 // 3620
+ SYS___UTIMENSAT_A = 0xE25 // 3621
+ SYS_ASPRINTF = 0xE26 // 3622
+ SYS___ASPRINTF_A = 0xE27 // 3623
+ SYS_VASPRINTF = 0xE28 // 3624
+ SYS___VASPRINTF_A = 0xE29 // 3625
+ SYS_DPRINTF = 0xE2A // 3626
+ SYS___DPRINTF_A = 0xE2B // 3627
+ SYS_GETOPT_LONG = 0xE2C // 3628
+ SYS___GETOPT_LONG_A = 0xE2D // 3629
+ SYS_PSIGNAL = 0xE2E // 3630
+ SYS___PSIGNAL_A = 0xE2F // 3631
+ SYS_PSIGNAL_UNLOCKED = 0xE30 // 3632
+ SYS___PSIGNAL_UNLOCKED_A = 0xE31 // 3633
+ SYS_FSTATAT_O = 0xE32 // 3634
+ SYS___FSTATAT_O_A = 0xE33 // 3635
+ SYS_FSTATAT64 = 0xE34 // 3636
+ SYS___FSTATAT64_A = 0xE35 // 3637
+ SYS___CHATTRAT = 0xE36 // 3638
+ SYS_____CHATTRAT_A = 0xE37 // 3639
+ SYS___CHATTRAT64 = 0xE38 // 3640
+ SYS_____CHATTRAT64_A = 0xE39 // 3641
+ SYS_MADVISE = 0xE3A // 3642
+ SYS___AUTHENTICATE = 0xE3B // 3643
+
)
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go
index bbf8399ff5..0036746ea1 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -174,7 +174,8 @@ type FscryptPolicyV2 struct {
Contents_encryption_mode uint8
Filenames_encryption_mode uint8
Flags uint8
- _ [4]uint8
+ Log2_data_unit_size uint8
+ _ [3]uint8
Master_key_identifier [16]uint8
}
@@ -455,60 +456,63 @@ type Ucred struct {
}
type TCPInfo struct {
- State uint8
- Ca_state uint8
- Retransmits uint8
- Probes uint8
- Backoff uint8
- Options uint8
- Rto uint32
- Ato uint32
- Snd_mss uint32
- Rcv_mss uint32
- Unacked uint32
- Sacked uint32
- Lost uint32
- Retrans uint32
- Fackets uint32
- Last_data_sent uint32
- Last_ack_sent uint32
- Last_data_recv uint32
- Last_ack_recv uint32
- Pmtu uint32
- Rcv_ssthresh uint32
- Rtt uint32
- Rttvar uint32
- Snd_ssthresh uint32
- Snd_cwnd uint32
- Advmss uint32
- Reordering uint32
- Rcv_rtt uint32
- Rcv_space uint32
- Total_retrans uint32
- Pacing_rate uint64
- Max_pacing_rate uint64
- Bytes_acked uint64
- Bytes_received uint64
- Segs_out uint32
- Segs_in uint32
- Notsent_bytes uint32
- Min_rtt uint32
- Data_segs_in uint32
- Data_segs_out uint32
- Delivery_rate uint64
- Busy_time uint64
- Rwnd_limited uint64
- Sndbuf_limited uint64
- Delivered uint32
- Delivered_ce uint32
- Bytes_sent uint64
- Bytes_retrans uint64
- Dsack_dups uint32
- Reord_seen uint32
- Rcv_ooopack uint32
- Snd_wnd uint32
- Rcv_wnd uint32
- Rehash uint32
+ State uint8
+ Ca_state uint8
+ Retransmits uint8
+ Probes uint8
+ Backoff uint8
+ Options uint8
+ Rto uint32
+ Ato uint32
+ Snd_mss uint32
+ Rcv_mss uint32
+ Unacked uint32
+ Sacked uint32
+ Lost uint32
+ Retrans uint32
+ Fackets uint32
+ Last_data_sent uint32
+ Last_ack_sent uint32
+ Last_data_recv uint32
+ Last_ack_recv uint32
+ Pmtu uint32
+ Rcv_ssthresh uint32
+ Rtt uint32
+ Rttvar uint32
+ Snd_ssthresh uint32
+ Snd_cwnd uint32
+ Advmss uint32
+ Reordering uint32
+ Rcv_rtt uint32
+ Rcv_space uint32
+ Total_retrans uint32
+ Pacing_rate uint64
+ Max_pacing_rate uint64
+ Bytes_acked uint64
+ Bytes_received uint64
+ Segs_out uint32
+ Segs_in uint32
+ Notsent_bytes uint32
+ Min_rtt uint32
+ Data_segs_in uint32
+ Data_segs_out uint32
+ Delivery_rate uint64
+ Busy_time uint64
+ Rwnd_limited uint64
+ Sndbuf_limited uint64
+ Delivered uint32
+ Delivered_ce uint32
+ Bytes_sent uint64
+ Bytes_retrans uint64
+ Dsack_dups uint32
+ Reord_seen uint32
+ Rcv_ooopack uint32
+ Snd_wnd uint32
+ Rcv_wnd uint32
+ Rehash uint32
+ Total_rto uint16
+ Total_rto_recoveries uint16
+ Total_rto_time uint32
}
type CanFilter struct {
@@ -551,7 +555,7 @@ const (
SizeofIPv6MTUInfo = 0x20
SizeofICMPv6Filter = 0x20
SizeofUcred = 0xc
- SizeofTCPInfo = 0xf0
+ SizeofTCPInfo = 0xf8
SizeofCanFilter = 0x8
SizeofTCPRepairOpt = 0x8
)
@@ -832,6 +836,15 @@ const (
FSPICK_EMPTY_PATH = 0x8
FSMOUNT_CLOEXEC = 0x1
+
+ FSCONFIG_SET_FLAG = 0x0
+ FSCONFIG_SET_STRING = 0x1
+ FSCONFIG_SET_BINARY = 0x2
+ FSCONFIG_SET_PATH = 0x3
+ FSCONFIG_SET_PATH_EMPTY = 0x4
+ FSCONFIG_SET_FD = 0x5
+ FSCONFIG_CMD_CREATE = 0x6
+ FSCONFIG_CMD_RECONFIGURE = 0x7
)
type OpenHow struct {
@@ -1165,7 +1178,8 @@ const (
PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 0x10
PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 0x11
PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 0x12
- PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x13
+ PERF_SAMPLE_BRANCH_COUNTERS = 0x80000
+ PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x14
PERF_SAMPLE_BRANCH_USER = 0x1
PERF_SAMPLE_BRANCH_KERNEL = 0x2
PERF_SAMPLE_BRANCH_HV = 0x4
@@ -1185,7 +1199,7 @@ const (
PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000
PERF_SAMPLE_BRANCH_HW_INDEX = 0x20000
PERF_SAMPLE_BRANCH_PRIV_SAVE = 0x40000
- PERF_SAMPLE_BRANCH_MAX = 0x80000
+ PERF_SAMPLE_BRANCH_MAX = 0x100000
PERF_BR_UNKNOWN = 0x0
PERF_BR_COND = 0x1
PERF_BR_UNCOND = 0x2
@@ -1546,6 +1560,7 @@ const (
IFLA_DEVLINK_PORT = 0x3e
IFLA_GSO_IPV4_MAX_SIZE = 0x3f
IFLA_GRO_IPV4_MAX_SIZE = 0x40
+ IFLA_DPLL_PIN = 0x41
IFLA_PROTO_DOWN_REASON_UNSPEC = 0x0
IFLA_PROTO_DOWN_REASON_MASK = 0x1
IFLA_PROTO_DOWN_REASON_VALUE = 0x2
@@ -1561,6 +1576,7 @@ const (
IFLA_INET6_ICMP6STATS = 0x6
IFLA_INET6_TOKEN = 0x7
IFLA_INET6_ADDR_GEN_MODE = 0x8
+ IFLA_INET6_RA_MTU = 0x9
IFLA_BR_UNSPEC = 0x0
IFLA_BR_FORWARD_DELAY = 0x1
IFLA_BR_HELLO_TIME = 0x2
@@ -1608,6 +1624,9 @@ const (
IFLA_BR_MCAST_MLD_VERSION = 0x2c
IFLA_BR_VLAN_STATS_PER_PORT = 0x2d
IFLA_BR_MULTI_BOOLOPT = 0x2e
+ IFLA_BR_MCAST_QUERIER_STATE = 0x2f
+ IFLA_BR_FDB_N_LEARNED = 0x30
+ IFLA_BR_FDB_MAX_LEARNED = 0x31
IFLA_BRPORT_UNSPEC = 0x0
IFLA_BRPORT_STATE = 0x1
IFLA_BRPORT_PRIORITY = 0x2
@@ -1645,6 +1664,14 @@ const (
IFLA_BRPORT_BACKUP_PORT = 0x22
IFLA_BRPORT_MRP_RING_OPEN = 0x23
IFLA_BRPORT_MRP_IN_OPEN = 0x24
+ IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT = 0x25
+ IFLA_BRPORT_MCAST_EHT_HOSTS_CNT = 0x26
+ IFLA_BRPORT_LOCKED = 0x27
+ IFLA_BRPORT_MAB = 0x28
+ IFLA_BRPORT_MCAST_N_GROUPS = 0x29
+ IFLA_BRPORT_MCAST_MAX_GROUPS = 0x2a
+ IFLA_BRPORT_NEIGH_VLAN_SUPPRESS = 0x2b
+ IFLA_BRPORT_BACKUP_NHID = 0x2c
IFLA_INFO_UNSPEC = 0x0
IFLA_INFO_KIND = 0x1
IFLA_INFO_DATA = 0x2
@@ -1666,6 +1693,9 @@ const (
IFLA_MACVLAN_MACADDR = 0x4
IFLA_MACVLAN_MACADDR_DATA = 0x5
IFLA_MACVLAN_MACADDR_COUNT = 0x6
+ IFLA_MACVLAN_BC_QUEUE_LEN = 0x7
+ IFLA_MACVLAN_BC_QUEUE_LEN_USED = 0x8
+ IFLA_MACVLAN_BC_CUTOFF = 0x9
IFLA_VRF_UNSPEC = 0x0
IFLA_VRF_TABLE = 0x1
IFLA_VRF_PORT_UNSPEC = 0x0
@@ -1689,9 +1719,22 @@ const (
IFLA_XFRM_UNSPEC = 0x0
IFLA_XFRM_LINK = 0x1
IFLA_XFRM_IF_ID = 0x2
+ IFLA_XFRM_COLLECT_METADATA = 0x3
IFLA_IPVLAN_UNSPEC = 0x0
IFLA_IPVLAN_MODE = 0x1
IFLA_IPVLAN_FLAGS = 0x2
+ NETKIT_NEXT = -0x1
+ NETKIT_PASS = 0x0
+ NETKIT_DROP = 0x2
+ NETKIT_REDIRECT = 0x7
+ NETKIT_L2 = 0x0
+ NETKIT_L3 = 0x1
+ IFLA_NETKIT_UNSPEC = 0x0
+ IFLA_NETKIT_PEER_INFO = 0x1
+ IFLA_NETKIT_PRIMARY = 0x2
+ IFLA_NETKIT_POLICY = 0x3
+ IFLA_NETKIT_PEER_POLICY = 0x4
+ IFLA_NETKIT_MODE = 0x5
IFLA_VXLAN_UNSPEC = 0x0
IFLA_VXLAN_ID = 0x1
IFLA_VXLAN_GROUP = 0x2
@@ -1722,6 +1765,8 @@ const (
IFLA_VXLAN_GPE = 0x1b
IFLA_VXLAN_TTL_INHERIT = 0x1c
IFLA_VXLAN_DF = 0x1d
+ IFLA_VXLAN_VNIFILTER = 0x1e
+ IFLA_VXLAN_LOCALBYPASS = 0x1f
IFLA_GENEVE_UNSPEC = 0x0
IFLA_GENEVE_ID = 0x1
IFLA_GENEVE_REMOTE = 0x2
@@ -1736,6 +1781,7 @@ const (
IFLA_GENEVE_LABEL = 0xb
IFLA_GENEVE_TTL_INHERIT = 0xc
IFLA_GENEVE_DF = 0xd
+ IFLA_GENEVE_INNER_PROTO_INHERIT = 0xe
IFLA_BAREUDP_UNSPEC = 0x0
IFLA_BAREUDP_PORT = 0x1
IFLA_BAREUDP_ETHERTYPE = 0x2
@@ -1748,6 +1794,8 @@ const (
IFLA_GTP_FD1 = 0x2
IFLA_GTP_PDP_HASHSIZE = 0x3
IFLA_GTP_ROLE = 0x4
+ IFLA_GTP_CREATE_SOCKETS = 0x5
+ IFLA_GTP_RESTART_COUNT = 0x6
IFLA_BOND_UNSPEC = 0x0
IFLA_BOND_MODE = 0x1
IFLA_BOND_ACTIVE_SLAVE = 0x2
@@ -1777,6 +1825,9 @@ const (
IFLA_BOND_AD_ACTOR_SYSTEM = 0x1a
IFLA_BOND_TLB_DYNAMIC_LB = 0x1b
IFLA_BOND_PEER_NOTIF_DELAY = 0x1c
+ IFLA_BOND_AD_LACP_ACTIVE = 0x1d
+ IFLA_BOND_MISSED_MAX = 0x1e
+ IFLA_BOND_NS_IP6_TARGET = 0x1f
IFLA_BOND_AD_INFO_UNSPEC = 0x0
IFLA_BOND_AD_INFO_AGGREGATOR = 0x1
IFLA_BOND_AD_INFO_NUM_PORTS = 0x2
@@ -1792,6 +1843,7 @@ const (
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 0x6
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 0x7
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 0x8
+ IFLA_BOND_SLAVE_PRIO = 0x9
IFLA_VF_INFO_UNSPEC = 0x0
IFLA_VF_INFO = 0x1
IFLA_VF_UNSPEC = 0x0
@@ -1850,8 +1902,16 @@ const (
IFLA_STATS_LINK_XSTATS_SLAVE = 0x3
IFLA_STATS_LINK_OFFLOAD_XSTATS = 0x4
IFLA_STATS_AF_SPEC = 0x5
+ IFLA_STATS_GETSET_UNSPEC = 0x0
+ IFLA_STATS_GET_FILTERS = 0x1
+ IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS = 0x2
IFLA_OFFLOAD_XSTATS_UNSPEC = 0x0
IFLA_OFFLOAD_XSTATS_CPU_HIT = 0x1
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO = 0x2
+ IFLA_OFFLOAD_XSTATS_L3_STATS = 0x3
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC = 0x0
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST = 0x1
+ IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED = 0x2
IFLA_XDP_UNSPEC = 0x0
IFLA_XDP_FD = 0x1
IFLA_XDP_ATTACHED = 0x2
@@ -1881,6 +1941,11 @@ const (
IFLA_RMNET_UNSPEC = 0x0
IFLA_RMNET_MUX_ID = 0x1
IFLA_RMNET_FLAGS = 0x2
+ IFLA_MCTP_UNSPEC = 0x0
+ IFLA_MCTP_NET = 0x1
+ IFLA_DSA_UNSPEC = 0x0
+ IFLA_DSA_CONDUIT = 0x1
+ IFLA_DSA_MASTER = 0x1
)
const (
@@ -2417,6 +2482,15 @@ type XDPMmapOffsets struct {
Cr XDPRingOffset
}
+type XDPUmemReg struct {
+ Addr uint64
+ Len uint64
+ Chunk_size uint32
+ Headroom uint32
+ Flags uint32
+ Tx_metadata_len uint32
+}
+
type XDPStatistics struct {
Rx_dropped uint64
Rx_invalid_descs uint64
@@ -2871,7 +2945,7 @@ const (
BPF_TCP_LISTEN = 0xa
BPF_TCP_CLOSING = 0xb
BPF_TCP_NEW_SYN_RECV = 0xc
- BPF_TCP_MAX_STATES = 0xd
+ BPF_TCP_MAX_STATES = 0xe
TCP_BPF_IW = 0x3e9
TCP_BPF_SNDCWND_CLAMP = 0x3ea
TCP_BPF_DELACK_MAX = 0x3eb
@@ -3147,7 +3221,7 @@ const (
DEVLINK_CMD_LINECARD_NEW = 0x50
DEVLINK_CMD_LINECARD_DEL = 0x51
DEVLINK_CMD_SELFTESTS_GET = 0x52
- DEVLINK_CMD_MAX = 0x53
+ DEVLINK_CMD_MAX = 0x54
DEVLINK_PORT_TYPE_NOTSET = 0x0
DEVLINK_PORT_TYPE_AUTO = 0x1
DEVLINK_PORT_TYPE_ETH = 0x2
@@ -3399,7 +3473,7 @@ const (
DEVLINK_PORT_FN_ATTR_STATE = 0x2
DEVLINK_PORT_FN_ATTR_OPSTATE = 0x3
DEVLINK_PORT_FN_ATTR_CAPS = 0x4
- DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x4
+ DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x5
)
type FsverityDigest struct {
@@ -4183,7 +4257,8 @@ const (
)
type LandlockRulesetAttr struct {
- Access_fs uint64
+ Access_fs uint64
+ Access_net uint64
}
type LandlockPathBeneathAttr struct {
@@ -4530,7 +4605,7 @@ const (
NL80211_ATTR_MAC_HINT = 0xc8
NL80211_ATTR_MAC_MASK = 0xd7
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
- NL80211_ATTR_MAX = 0x146
+ NL80211_ATTR_MAX = 0x149
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
NL80211_ATTR_MAX_MATCH_SETS = 0x85
@@ -4796,7 +4871,7 @@ const (
NL80211_BSS_FREQUENCY_OFFSET = 0x14
NL80211_BSS_INFORMATION_ELEMENTS = 0x6
NL80211_BSS_LAST_SEEN_BOOTTIME = 0xf
- NL80211_BSS_MAX = 0x16
+ NL80211_BSS_MAX = 0x18
NL80211_BSS_MLD_ADDR = 0x16
NL80211_BSS_MLO_LINK_ID = 0x15
NL80211_BSS_PAD = 0x10
@@ -4900,7 +4975,7 @@ const (
NL80211_CMD_LEAVE_IBSS = 0x2c
NL80211_CMD_LEAVE_MESH = 0x45
NL80211_CMD_LEAVE_OCB = 0x6d
- NL80211_CMD_MAX = 0x9a
+ NL80211_CMD_MAX = 0x9b
NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29
NL80211_CMD_MODIFY_LINK_STA = 0x97
NL80211_CMD_NAN_MATCH = 0x78
@@ -5134,7 +5209,7 @@ const (
NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf
NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe
NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf
- NL80211_FREQUENCY_ATTR_MAX = 0x1b
+ NL80211_FREQUENCY_ATTR_MAX = 0x1f
NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6
NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
@@ -5547,7 +5622,7 @@ const (
NL80211_REGDOM_TYPE_CUSTOM_WORLD = 0x2
NL80211_REGDOM_TYPE_INTERSECTION = 0x3
NL80211_REGDOM_TYPE_WORLD = 0x1
- NL80211_REG_RULE_ATTR_MAX = 0x7
+ NL80211_REG_RULE_ATTR_MAX = 0x8
NL80211_REKEY_DATA_AKM = 0x4
NL80211_REKEY_DATA_KCK = 0x2
NL80211_REKEY_DATA_KEK = 0x1
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go
index 438a30affa..fd402da43f 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go
@@ -477,14 +477,6 @@ const (
BLKPG = 0x1269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
index adceca3553..eb7a5e1864 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
@@ -492,15 +492,6 @@ const (
BLKPG = 0x1269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
index eeaa00a37d..d78ac108b6 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
@@ -470,15 +470,6 @@ const (
BLKPG = 0x1269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]uint8
Driver_name [64]uint8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
index 6739aa91d4..cd06d47f1f 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
@@ -471,15 +471,6 @@ const (
BLKPG = 0x1269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go
index 9920ef6317..2f28fe26c1 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go
@@ -472,15 +472,6 @@ const (
BLKPG = 0x1269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
index 2923b799a4..71d6cac2f1 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
@@ -476,15 +476,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
index ce2750ee41..8596d45356 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
@@ -474,15 +474,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
index 3038811d70..cd60ea1866 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
@@ -474,15 +474,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
index efc6fed18c..b0ae420c48 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
@@ -476,15 +476,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go
index 9a654b75a9..8359728759 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go
@@ -482,15 +482,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]uint8
Driver_name [64]uint8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
index 40d358e33e..69eb6a5c68 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
@@ -481,15 +481,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]uint8
Driver_name [64]uint8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
index 148c6ceb86..5f583cb62b 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
@@ -481,15 +481,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]uint8
Driver_name [64]uint8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
index 72ba81543e..15adc04142 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
@@ -499,15 +499,6 @@ const (
BLKPG = 0x1269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]uint8
Driver_name [64]uint8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
index 71e765508e..cf3ce90037 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
@@ -495,15 +495,6 @@ const (
BLKPG = 0x1269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
index 4abbdb9de9..590b56739c 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
@@ -476,15 +476,6 @@ const (
BLKPG = 0x20001269
)
-type XDPUmemReg struct {
- Addr uint64
- Len uint64
- Size uint32
- Headroom uint32
- Flags uint32
- _ [4]byte
-}
-
type CryptoUserAlg struct {
Name [64]int8
Driver_name [64]int8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go
index 54f31be637..d9a13af468 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go
@@ -25,10 +25,13 @@ const (
SizeofIPv6Mreq = 20
SizeofICMPv6Filter = 32
SizeofIPv6MTUInfo = 32
+ SizeofInet4Pktinfo = 8
+ SizeofInet6Pktinfo = 20
SizeofLinger = 8
SizeofSockaddrInet4 = 16
SizeofSockaddrInet6 = 28
SizeofTCPInfo = 0x68
+ SizeofUcred = 12
)
type (
@@ -69,12 +72,17 @@ type Utimbuf struct {
}
type Utsname struct {
- Sysname [65]byte
- Nodename [65]byte
- Release [65]byte
- Version [65]byte
- Machine [65]byte
- Domainname [65]byte
+ Sysname [16]byte
+ Nodename [32]byte
+ Release [8]byte
+ Version [8]byte
+ Machine [16]byte
+}
+
+type Ucred struct {
+ Pid int32
+ Uid uint32
+ Gid uint32
}
type RawSockaddrInet4 struct {
@@ -325,7 +333,7 @@ type Statvfs_t struct {
}
type Statfs_t struct {
- Type uint32
+ Type uint64
Bsize uint64
Blocks uint64
Bfree uint64
@@ -336,6 +344,7 @@ type Statfs_t struct {
Namelen uint64
Frsize uint64
Flags uint64
+ _ [4]uint64
}
type direntLE struct {
@@ -412,3 +421,126 @@ type W_Mntent struct {
Quiesceowner [8]byte
_ [38]byte
}
+
+type EpollEvent struct {
+ Events uint32
+ _ int32
+ Fd int32
+ Pad int32
+}
+
+type InotifyEvent struct {
+ Wd int32
+ Mask uint32
+ Cookie uint32
+ Len uint32
+ Name string
+}
+
+const (
+ SizeofInotifyEvent = 0x10
+)
+
+type ConsMsg2 struct {
+ Cm2Format uint16
+ Cm2R1 uint16
+ Cm2Msglength uint32
+ Cm2Msg *byte
+ Cm2R2 [4]byte
+ Cm2R3 [4]byte
+ Cm2Routcde *uint32
+ Cm2Descr *uint32
+ Cm2Msgflag uint32
+ Cm2Token uint32
+ Cm2Msgid *uint32
+ Cm2R4 [4]byte
+ Cm2DomToken uint32
+ Cm2DomMsgid *uint32
+ Cm2ModCartptr *byte
+ Cm2ModConsidptr *byte
+ Cm2MsgCart [8]byte
+ Cm2MsgConsid [4]byte
+ Cm2R5 [12]byte
+}
+
+const (
+ CC_modify = 1
+ CC_stop = 2
+ CONSOLE_FORMAT_2 = 2
+ CONSOLE_FORMAT_3 = 3
+ CONSOLE_HRDCPY = 0x80000000
+)
+
+type OpenHow struct {
+ Flags uint64
+ Mode uint64
+ Resolve uint64
+}
+
+const SizeofOpenHow = 0x18
+
+const (
+ RESOLVE_CACHED = 0x20
+ RESOLVE_BENEATH = 0x8
+ RESOLVE_IN_ROOT = 0x10
+ RESOLVE_NO_MAGICLINKS = 0x2
+ RESOLVE_NO_SYMLINKS = 0x4
+ RESOLVE_NO_XDEV = 0x1
+)
+
+type Siginfo struct {
+ Signo int32
+ Errno int32
+ Code int32
+ Pid int32
+ Uid uint32
+ _ [44]byte
+}
+
+type SysvIpcPerm struct {
+ Uid uint32
+ Gid uint32
+ Cuid uint32
+ Cgid uint32
+ Mode int32
+}
+
+type SysvShmDesc struct {
+ Perm SysvIpcPerm
+ _ [4]byte
+ Lpid int32
+ Cpid int32
+ Nattch uint32
+ _ [4]byte
+ _ [4]byte
+ _ [4]byte
+ _ int32
+ _ uint8
+ _ uint8
+ _ uint16
+ _ *byte
+ Segsz uint64
+ Atime Time_t
+ Dtime Time_t
+ Ctime Time_t
+}
+
+type SysvShmDesc64 struct {
+ Perm SysvIpcPerm
+ _ [4]byte
+ Lpid int32
+ Cpid int32
+ Nattch uint32
+ _ [4]byte
+ _ [4]byte
+ _ [4]byte
+ _ int32
+ _ byte
+ _ uint8
+ _ uint16
+ _ *byte
+ Segsz uint64
+ Atime int64
+ Dtime int64
+ Ctime int64
+}
diff --git a/vendor/golang.org/x/sys/windows/aliases.go b/vendor/golang.org/x/sys/windows/aliases.go
index ce2d713d62..16f90560a2 100644
--- a/vendor/golang.org/x/sys/windows/aliases.go
+++ b/vendor/golang.org/x/sys/windows/aliases.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build windows && go1.9
+//go:build windows
package windows
diff --git a/vendor/golang.org/x/sys/windows/empty.s b/vendor/golang.org/x/sys/windows/empty.s
deleted file mode 100644
index ba64caca5d..0000000000
--- a/vendor/golang.org/x/sys/windows/empty.s
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2019 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.
-
-//go:build !go1.12
-
-// This file is here to allow bodyless functions with go:linkname for Go 1.11
-// and earlier (see https://golang.org/issue/23311).
diff --git a/vendor/golang.org/x/sys/windows/env_windows.go b/vendor/golang.org/x/sys/windows/env_windows.go
index b8ad192506..d4577a4238 100644
--- a/vendor/golang.org/x/sys/windows/env_windows.go
+++ b/vendor/golang.org/x/sys/windows/env_windows.go
@@ -37,14 +37,17 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) {
return nil, err
}
defer DestroyEnvironmentBlock(block)
- blockp := unsafe.Pointer(block)
- for {
- entry := UTF16PtrToString((*uint16)(blockp))
- if len(entry) == 0 {
- break
+ size := unsafe.Sizeof(*block)
+ for *block != 0 {
+ // find NUL terminator
+ end := unsafe.Pointer(block)
+ for *(*uint16)(end) != 0 {
+ end = unsafe.Add(end, size)
}
- env = append(env, entry)
- blockp = unsafe.Add(blockp, 2*(len(entry)+1))
+
+ entry := unsafe.Slice(block, (uintptr(end)-uintptr(unsafe.Pointer(block)))/size)
+ env = append(env, UTF16ToString(entry))
+ block = (*uint16)(unsafe.Add(end, size))
}
return env, nil
}
diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go
index 47dc579676..6525c62f3c 100644
--- a/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -125,8 +125,7 @@ func UTF16PtrToString(p *uint16) string {
for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ {
ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(*p))
}
-
- return string(utf16.Decode(unsafe.Slice(p, n)))
+ return UTF16ToString(unsafe.Slice(p, n))
}
func Getpagesize() int { return 4096 }
@@ -166,6 +165,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
//sys CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *SecurityAttributes) (handle Handle, err error) [failretval==InvalidHandle] = CreateNamedPipeW
//sys ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error)
+//sys DisconnectNamedPipe(pipe Handle) (err error)
//sys GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error)
//sys GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
//sys SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) = SetNamedPipeHandleState
@@ -194,6 +194,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
//sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
//sys SetEndOfFile(handle Handle) (err error)
+//sys SetFileValidData(handle Handle, validDataLength int64) (err error)
//sys GetSystemTimeAsFileTime(time *Filetime)
//sys GetSystemTimePreciseAsFileTime(time *Filetime)
//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
@@ -348,8 +349,19 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost
//sys GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32)
//sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error)
+//sys ClearCommBreak(handle Handle) (err error)
+//sys ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error)
+//sys EscapeCommFunction(handle Handle, dwFunc uint32) (err error)
+//sys GetCommState(handle Handle, lpDCB *DCB) (err error)
+//sys GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error)
//sys GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
+//sys PurgeComm(handle Handle, dwFlags uint32) (err error)
+//sys SetCommBreak(handle Handle) (err error)
+//sys SetCommMask(handle Handle, dwEvtMask uint32) (err error)
+//sys SetCommState(handle Handle, lpDCB *DCB) (err error)
//sys SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
+//sys SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error)
+//sys WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error)
//sys GetActiveProcessorCount(groupNumber uint16) (ret uint32)
//sys GetMaximumProcessorCount(groupNumber uint16) (ret uint32)
//sys EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) = user32.EnumWindows
@@ -1834,3 +1846,73 @@ func ResizePseudoConsole(pconsole Handle, size Coord) error {
// accept arguments that can be casted to uintptr, and Coord can't.
return resizePseudoConsole(pconsole, *((*uint32)(unsafe.Pointer(&size))))
}
+
+// DCB constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-dcb.
+const (
+ CBR_110 = 110
+ CBR_300 = 300
+ CBR_600 = 600
+ CBR_1200 = 1200
+ CBR_2400 = 2400
+ CBR_4800 = 4800
+ CBR_9600 = 9600
+ CBR_14400 = 14400
+ CBR_19200 = 19200
+ CBR_38400 = 38400
+ CBR_57600 = 57600
+ CBR_115200 = 115200
+ CBR_128000 = 128000
+ CBR_256000 = 256000
+
+ DTR_CONTROL_DISABLE = 0x00000000
+ DTR_CONTROL_ENABLE = 0x00000010
+ DTR_CONTROL_HANDSHAKE = 0x00000020
+
+ RTS_CONTROL_DISABLE = 0x00000000
+ RTS_CONTROL_ENABLE = 0x00001000
+ RTS_CONTROL_HANDSHAKE = 0x00002000
+ RTS_CONTROL_TOGGLE = 0x00003000
+
+ NOPARITY = 0
+ ODDPARITY = 1
+ EVENPARITY = 2
+ MARKPARITY = 3
+ SPACEPARITY = 4
+
+ ONESTOPBIT = 0
+ ONE5STOPBITS = 1
+ TWOSTOPBITS = 2
+)
+
+// EscapeCommFunction constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-escapecommfunction.
+const (
+ SETXOFF = 1
+ SETXON = 2
+ SETRTS = 3
+ CLRRTS = 4
+ SETDTR = 5
+ CLRDTR = 6
+ SETBREAK = 8
+ CLRBREAK = 9
+)
+
+// PurgeComm constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-purgecomm.
+const (
+ PURGE_TXABORT = 0x0001
+ PURGE_RXABORT = 0x0002
+ PURGE_TXCLEAR = 0x0004
+ PURGE_RXCLEAR = 0x0008
+)
+
+// SetCommMask constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcommmask.
+const (
+ EV_RXCHAR = 0x0001
+ EV_RXFLAG = 0x0002
+ EV_TXEMPTY = 0x0004
+ EV_CTS = 0x0008
+ EV_DSR = 0x0010
+ EV_RLSD = 0x0020
+ EV_BREAK = 0x0040
+ EV_ERR = 0x0080
+ EV_RING = 0x0100
+)
diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go
index 359780f6ac..d8cb71db0a 100644
--- a/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/vendor/golang.org/x/sys/windows/types_windows.go
@@ -3380,3 +3380,27 @@ type BLOB struct {
Size uint32
BlobData *byte
}
+
+type ComStat struct {
+ Flags uint32
+ CBInQue uint32
+ CBOutQue uint32
+}
+
+type DCB struct {
+ DCBlength uint32
+ BaudRate uint32
+ Flags uint32
+ wReserved uint16
+ XonLim uint16
+ XoffLim uint16
+ ByteSize uint8
+ Parity uint8
+ StopBits uint8
+ XonChar byte
+ XoffChar byte
+ ErrorChar byte
+ EofChar byte
+ EvtChar byte
+ wReserved1 uint16
+}
diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index 146a1f0196..5c6035ddfa 100644
--- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -188,6 +188,8 @@ var (
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
procCancelIo = modkernel32.NewProc("CancelIo")
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
+ procClearCommBreak = modkernel32.NewProc("ClearCommBreak")
+ procClearCommError = modkernel32.NewProc("ClearCommError")
procCloseHandle = modkernel32.NewProc("CloseHandle")
procClosePseudoConsole = modkernel32.NewProc("ClosePseudoConsole")
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
@@ -212,7 +214,9 @@ var (
procDeleteProcThreadAttributeList = modkernel32.NewProc("DeleteProcThreadAttributeList")
procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW")
procDeviceIoControl = modkernel32.NewProc("DeviceIoControl")
+ procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe")
procDuplicateHandle = modkernel32.NewProc("DuplicateHandle")
+ procEscapeCommFunction = modkernel32.NewProc("EscapeCommFunction")
procExitProcess = modkernel32.NewProc("ExitProcess")
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
procFindClose = modkernel32.NewProc("FindClose")
@@ -236,6 +240,8 @@ var (
procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent")
procGetACP = modkernel32.NewProc("GetACP")
procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount")
+ procGetCommModemStatus = modkernel32.NewProc("GetCommModemStatus")
+ procGetCommState = modkernel32.NewProc("GetCommState")
procGetCommTimeouts = modkernel32.NewProc("GetCommTimeouts")
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
@@ -322,6 +328,7 @@ var (
procProcess32NextW = modkernel32.NewProc("Process32NextW")
procProcessIdToSessionId = modkernel32.NewProc("ProcessIdToSessionId")
procPulseEvent = modkernel32.NewProc("PulseEvent")
+ procPurgeComm = modkernel32.NewProc("PurgeComm")
procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW")
procQueryFullProcessImageNameW = modkernel32.NewProc("QueryFullProcessImageNameW")
procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject")
@@ -335,6 +342,9 @@ var (
procResetEvent = modkernel32.NewProc("ResetEvent")
procResizePseudoConsole = modkernel32.NewProc("ResizePseudoConsole")
procResumeThread = modkernel32.NewProc("ResumeThread")
+ procSetCommBreak = modkernel32.NewProc("SetCommBreak")
+ procSetCommMask = modkernel32.NewProc("SetCommMask")
+ procSetCommState = modkernel32.NewProc("SetCommState")
procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts")
procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition")
procSetConsoleMode = modkernel32.NewProc("SetConsoleMode")
@@ -350,6 +360,7 @@ var (
procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
procSetFilePointer = modkernel32.NewProc("SetFilePointer")
procSetFileTime = modkernel32.NewProc("SetFileTime")
+ procSetFileValidData = modkernel32.NewProc("SetFileValidData")
procSetHandleInformation = modkernel32.NewProc("SetHandleInformation")
procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject")
procSetNamedPipeHandleState = modkernel32.NewProc("SetNamedPipeHandleState")
@@ -360,6 +371,7 @@ var (
procSetStdHandle = modkernel32.NewProc("SetStdHandle")
procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW")
procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW")
+ procSetupComm = modkernel32.NewProc("SetupComm")
procSizeofResource = modkernel32.NewProc("SizeofResource")
procSleepEx = modkernel32.NewProc("SleepEx")
procTerminateJobObject = modkernel32.NewProc("TerminateJobObject")
@@ -378,6 +390,7 @@ var (
procVirtualQueryEx = modkernel32.NewProc("VirtualQueryEx")
procVirtualUnlock = modkernel32.NewProc("VirtualUnlock")
procWTSGetActiveConsoleSessionId = modkernel32.NewProc("WTSGetActiveConsoleSessionId")
+ procWaitCommEvent = modkernel32.NewProc("WaitCommEvent")
procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects")
procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject")
procWriteConsoleW = modkernel32.NewProc("WriteConsoleW")
@@ -1640,6 +1653,22 @@ func CancelIoEx(s Handle, o *Overlapped) (err error) {
return
}
+func ClearCommBreak(handle Handle) (err error) {
+ r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error) {
+ r1, _, e1 := syscall.Syscall(procClearCommError.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpErrors)), uintptr(unsafe.Pointer(lpStat)))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func CloseHandle(handle Handle) (err error) {
r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
@@ -1844,6 +1873,14 @@ func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBuff
return
}
+func DisconnectNamedPipe(pipe Handle) (err error) {
+ r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(pipe), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) {
var _p0 uint32
if bInheritHandle {
@@ -1856,6 +1893,14 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP
return
}
+func EscapeCommFunction(handle Handle, dwFunc uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procEscapeCommFunction.Addr(), 2, uintptr(handle), uintptr(dwFunc), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func ExitProcess(exitcode uint32) {
syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0)
return
@@ -2057,6 +2102,22 @@ func GetActiveProcessorCount(groupNumber uint16) (ret uint32) {
return
}
+func GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetCommModemStatus.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpModemStat)), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func GetCommState(handle Handle, lpDCB *DCB) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
if r1 == 0 {
@@ -2809,6 +2870,14 @@ func PulseEvent(event Handle) (err error) {
return
}
+func PurgeComm(handle Handle, dwFlags uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(dwFlags), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) {
r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max))
n = uint32(r0)
@@ -2923,6 +2992,30 @@ func ResumeThread(thread Handle) (ret uint32, err error) {
return
}
+func SetCommBreak(handle Handle) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetCommBreak.Addr(), 1, uintptr(handle), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func SetCommMask(handle Handle, dwEvtMask uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetCommMask.Addr(), 2, uintptr(handle), uintptr(dwEvtMask), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func SetCommState(handle Handle, lpDCB *DCB) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
if r1 == 0 {
@@ -3051,6 +3144,14 @@ func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetim
return
}
+func SetFileValidData(handle Handle, validDataLength int64) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
if r1 == 0 {
@@ -3136,6 +3237,14 @@ func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err erro
return
}
+func SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procSetupComm.Addr(), 3, uintptr(handle), uintptr(dwInQueue), uintptr(dwOutQueue))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func SizeofResource(module Handle, resInfo Handle) (size uint32, err error) {
r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
size = uint32(r0)
@@ -3282,6 +3391,14 @@ func WTSGetActiveConsoleSessionId() (sessionID uint32) {
return
}
+func WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) {
+ r1, _, e1 := syscall.Syscall(procWaitCommEvent.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpEvtMask)), uintptr(unsafe.Pointer(lpOverlapped)))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) {
var _p0 uint32
if waitAll {
diff --git a/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go b/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go
new file mode 100644
index 0000000000..d10ad66533
--- /dev/null
+++ b/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go
@@ -0,0 +1,23 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package field_mask aliases all exported identifiers in
+// package "google.golang.org/protobuf/types/known/fieldmaskpb".
+package field_mask
+
+import "google.golang.org/protobuf/types/known/fieldmaskpb"
+
+type FieldMask = fieldmaskpb.FieldMask
+
+var File_google_protobuf_field_mask_proto = fieldmaskpb.File_google_protobuf_field_mask_proto
diff --git a/vendor/google.golang.org/grpc/health/client.go b/vendor/google.golang.org/grpc/health/client.go
new file mode 100644
index 0000000000..740745c45f
--- /dev/null
+++ b/vendor/google.golang.org/grpc/health/client.go
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package health
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "time"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/connectivity"
+ healthpb "google.golang.org/grpc/health/grpc_health_v1"
+ "google.golang.org/grpc/internal"
+ "google.golang.org/grpc/internal/backoff"
+ "google.golang.org/grpc/status"
+)
+
+var (
+ backoffStrategy = backoff.DefaultExponential
+ backoffFunc = func(ctx context.Context, retries int) bool {
+ d := backoffStrategy.Backoff(retries)
+ timer := time.NewTimer(d)
+ select {
+ case <-timer.C:
+ return true
+ case <-ctx.Done():
+ timer.Stop()
+ return false
+ }
+ }
+)
+
+func init() {
+ internal.HealthCheckFunc = clientHealthCheck
+}
+
+const healthCheckMethod = "/grpc.health.v1.Health/Watch"
+
+// This function implements the protocol defined at:
+// https://github.com/grpc/grpc/blob/master/doc/health-checking.md
+func clientHealthCheck(ctx context.Context, newStream func(string) (any, error), setConnectivityState func(connectivity.State, error), service string) error {
+ tryCnt := 0
+
+retryConnection:
+ for {
+ // Backs off if the connection has failed in some way without receiving a message in the previous retry.
+ if tryCnt > 0 && !backoffFunc(ctx, tryCnt-1) {
+ return nil
+ }
+ tryCnt++
+
+ if ctx.Err() != nil {
+ return nil
+ }
+ setConnectivityState(connectivity.Connecting, nil)
+ rawS, err := newStream(healthCheckMethod)
+ if err != nil {
+ continue retryConnection
+ }
+
+ s, ok := rawS.(grpc.ClientStream)
+ // Ideally, this should never happen. But if it happens, the server is marked as healthy for LBing purposes.
+ if !ok {
+ setConnectivityState(connectivity.Ready, nil)
+ return fmt.Errorf("newStream returned %v (type %T); want grpc.ClientStream", rawS, rawS)
+ }
+
+ if err = s.SendMsg(&healthpb.HealthCheckRequest{Service: service}); err != nil && err != io.EOF {
+ // Stream should have been closed, so we can safely continue to create a new stream.
+ continue retryConnection
+ }
+ s.CloseSend()
+
+ resp := new(healthpb.HealthCheckResponse)
+ for {
+ err = s.RecvMsg(resp)
+
+ // Reports healthy for the LBing purposes if health check is not implemented in the server.
+ if status.Code(err) == codes.Unimplemented {
+ setConnectivityState(connectivity.Ready, nil)
+ return err
+ }
+
+ // Reports unhealthy if server's Watch method gives an error other than UNIMPLEMENTED.
+ if err != nil {
+ setConnectivityState(connectivity.TransientFailure, fmt.Errorf("connection active but received health check RPC error: %v", err))
+ continue retryConnection
+ }
+
+ // As a message has been received, removes the need for backoff for the next retry by resetting the try count.
+ tryCnt = 0
+ if resp.Status == healthpb.HealthCheckResponse_SERVING {
+ setConnectivityState(connectivity.Ready, nil)
+ } else {
+ setConnectivityState(connectivity.TransientFailure, fmt.Errorf("connection active but health check failed. status=%s", resp.Status))
+ }
+ }
+ }
+}
diff --git a/vendor/google.golang.org/grpc/health/logging.go b/vendor/google.golang.org/grpc/health/logging.go
new file mode 100644
index 0000000000..83c6acf55e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/health/logging.go
@@ -0,0 +1,23 @@
+/*
+ *
+ * Copyright 2020 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package health
+
+import "google.golang.org/grpc/grpclog"
+
+var logger = grpclog.Component("health_service")
diff --git a/vendor/google.golang.org/grpc/health/server.go b/vendor/google.golang.org/grpc/health/server.go
new file mode 100644
index 0000000000..cce6312d77
--- /dev/null
+++ b/vendor/google.golang.org/grpc/health/server.go
@@ -0,0 +1,163 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package health provides a service that exposes server's health and it must be
+// imported to enable support for client-side health checks.
+package health
+
+import (
+ "context"
+ "sync"
+
+ "google.golang.org/grpc/codes"
+ healthgrpc "google.golang.org/grpc/health/grpc_health_v1"
+ healthpb "google.golang.org/grpc/health/grpc_health_v1"
+ "google.golang.org/grpc/status"
+)
+
+// Server implements `service Health`.
+type Server struct {
+ healthgrpc.UnimplementedHealthServer
+ mu sync.RWMutex
+ // If shutdown is true, it's expected all serving status is NOT_SERVING, and
+ // will stay in NOT_SERVING.
+ shutdown bool
+ // statusMap stores the serving status of the services this Server monitors.
+ statusMap map[string]healthpb.HealthCheckResponse_ServingStatus
+ updates map[string]map[healthgrpc.Health_WatchServer]chan healthpb.HealthCheckResponse_ServingStatus
+}
+
+// NewServer returns a new Server.
+func NewServer() *Server {
+ return &Server{
+ statusMap: map[string]healthpb.HealthCheckResponse_ServingStatus{"": healthpb.HealthCheckResponse_SERVING},
+ updates: make(map[string]map[healthgrpc.Health_WatchServer]chan healthpb.HealthCheckResponse_ServingStatus),
+ }
+}
+
+// Check implements `service Health`.
+func (s *Server) Check(ctx context.Context, in *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) {
+ s.mu.RLock()
+ defer s.mu.RUnlock()
+ if servingStatus, ok := s.statusMap[in.Service]; ok {
+ return &healthpb.HealthCheckResponse{
+ Status: servingStatus,
+ }, nil
+ }
+ return nil, status.Error(codes.NotFound, "unknown service")
+}
+
+// Watch implements `service Health`.
+func (s *Server) Watch(in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
+ service := in.Service
+ // update channel is used for getting service status updates.
+ update := make(chan healthpb.HealthCheckResponse_ServingStatus, 1)
+ s.mu.Lock()
+ // Puts the initial status to the channel.
+ if servingStatus, ok := s.statusMap[service]; ok {
+ update <- servingStatus
+ } else {
+ update <- healthpb.HealthCheckResponse_SERVICE_UNKNOWN
+ }
+
+ // Registers the update channel to the correct place in the updates map.
+ if _, ok := s.updates[service]; !ok {
+ s.updates[service] = make(map[healthgrpc.Health_WatchServer]chan healthpb.HealthCheckResponse_ServingStatus)
+ }
+ s.updates[service][stream] = update
+ defer func() {
+ s.mu.Lock()
+ delete(s.updates[service], stream)
+ s.mu.Unlock()
+ }()
+ s.mu.Unlock()
+
+ var lastSentStatus healthpb.HealthCheckResponse_ServingStatus = -1
+ for {
+ select {
+ // Status updated. Sends the up-to-date status to the client.
+ case servingStatus := <-update:
+ if lastSentStatus == servingStatus {
+ continue
+ }
+ lastSentStatus = servingStatus
+ err := stream.Send(&healthpb.HealthCheckResponse{Status: servingStatus})
+ if err != nil {
+ return status.Error(codes.Canceled, "Stream has ended.")
+ }
+ // Context done. Removes the update channel from the updates map.
+ case <-stream.Context().Done():
+ return status.Error(codes.Canceled, "Stream has ended.")
+ }
+ }
+}
+
+// SetServingStatus is called when need to reset the serving status of a service
+// or insert a new service entry into the statusMap.
+func (s *Server) SetServingStatus(service string, servingStatus healthpb.HealthCheckResponse_ServingStatus) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.shutdown {
+ logger.Infof("health: status changing for %s to %v is ignored because health service is shutdown", service, servingStatus)
+ return
+ }
+
+ s.setServingStatusLocked(service, servingStatus)
+}
+
+func (s *Server) setServingStatusLocked(service string, servingStatus healthpb.HealthCheckResponse_ServingStatus) {
+ s.statusMap[service] = servingStatus
+ for _, update := range s.updates[service] {
+ // Clears previous updates, that are not sent to the client, from the channel.
+ // This can happen if the client is not reading and the server gets flow control limited.
+ select {
+ case <-update:
+ default:
+ }
+ // Puts the most recent update to the channel.
+ update <- servingStatus
+ }
+}
+
+// Shutdown sets all serving status to NOT_SERVING, and configures the server to
+// ignore all future status changes.
+//
+// This changes serving status for all services. To set status for a particular
+// services, call SetServingStatus().
+func (s *Server) Shutdown() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ s.shutdown = true
+ for service := range s.statusMap {
+ s.setServingStatusLocked(service, healthpb.HealthCheckResponse_NOT_SERVING)
+ }
+}
+
+// Resume sets all serving status to SERVING, and configures the server to
+// accept all future status changes.
+//
+// This changes serving status for all services. To set status for a particular
+// services, call SetServingStatus().
+func (s *Server) Resume() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ s.shutdown = false
+ for service := range s.statusMap {
+ s.setServingStatusLocked(service, healthpb.HealthCheckResponse_SERVING)
+ }
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/benchmark_service.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/benchmark_service.pb.go
new file mode 100644
index 0000000000..031e12ee2e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/benchmark_service.pb.go
@@ -0,0 +1,124 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/benchmark_service.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+var File_grpc_testing_benchmark_service_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_benchmark_service_proto_rawDesc = []byte{
+ 0x0a, 0x24, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x62,
+ 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x1b, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x32, 0xa6, 0x03, 0x0a, 0x10, 0x42, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x55, 0x6e, 0x61, 0x72, 0x79, 0x43,
+ 0x61, 0x6c, 0x6c, 0x12, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x1a, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e,
+ 0x0a, 0x0d, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x43, 0x61, 0x6c, 0x6c, 0x12,
+ 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70,
+ 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x52,
+ 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x6f, 0x6d, 0x43,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x28, 0x01, 0x12, 0x52, 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x46,
+ 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x11, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
+ 0x69, 0x6e, 0x67, 0x42, 0x6f, 0x74, 0x68, 0x57, 0x61, 0x79, 0x73, 0x12, 0x1b, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c,
+ 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x2a, 0x0a, 0x0f, 0x69, 0x6f,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x15, 0x42,
+ 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50,
+ 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var file_grpc_testing_benchmark_service_proto_goTypes = []interface{}{
+ (*SimpleRequest)(nil), // 0: grpc.testing.SimpleRequest
+ (*SimpleResponse)(nil), // 1: grpc.testing.SimpleResponse
+}
+var file_grpc_testing_benchmark_service_proto_depIdxs = []int32{
+ 0, // 0: grpc.testing.BenchmarkService.UnaryCall:input_type -> grpc.testing.SimpleRequest
+ 0, // 1: grpc.testing.BenchmarkService.StreamingCall:input_type -> grpc.testing.SimpleRequest
+ 0, // 2: grpc.testing.BenchmarkService.StreamingFromClient:input_type -> grpc.testing.SimpleRequest
+ 0, // 3: grpc.testing.BenchmarkService.StreamingFromServer:input_type -> grpc.testing.SimpleRequest
+ 0, // 4: grpc.testing.BenchmarkService.StreamingBothWays:input_type -> grpc.testing.SimpleRequest
+ 1, // 5: grpc.testing.BenchmarkService.UnaryCall:output_type -> grpc.testing.SimpleResponse
+ 1, // 6: grpc.testing.BenchmarkService.StreamingCall:output_type -> grpc.testing.SimpleResponse
+ 1, // 7: grpc.testing.BenchmarkService.StreamingFromClient:output_type -> grpc.testing.SimpleResponse
+ 1, // 8: grpc.testing.BenchmarkService.StreamingFromServer:output_type -> grpc.testing.SimpleResponse
+ 1, // 9: grpc.testing.BenchmarkService.StreamingBothWays:output_type -> grpc.testing.SimpleResponse
+ 5, // [5:10] is the sub-list for method output_type
+ 0, // [0:5] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_benchmark_service_proto_init() }
+func file_grpc_testing_benchmark_service_proto_init() {
+ if File_grpc_testing_benchmark_service_proto != nil {
+ return
+ }
+ file_grpc_testing_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_benchmark_service_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 0,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_grpc_testing_benchmark_service_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_benchmark_service_proto_depIdxs,
+ }.Build()
+ File_grpc_testing_benchmark_service_proto = out.File
+ file_grpc_testing_benchmark_service_proto_rawDesc = nil
+ file_grpc_testing_benchmark_service_proto_goTypes = nil
+ file_grpc_testing_benchmark_service_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/benchmark_service_grpc.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/benchmark_service_grpc.pb.go
new file mode 100644
index 0000000000..84cd44e4d4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/benchmark_service_grpc.pb.go
@@ -0,0 +1,422 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc v4.22.0
+// source: grpc/testing/benchmark_service.proto
+
+package grpc_testing
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+const (
+ BenchmarkService_UnaryCall_FullMethodName = "/grpc.testing.BenchmarkService/UnaryCall"
+ BenchmarkService_StreamingCall_FullMethodName = "/grpc.testing.BenchmarkService/StreamingCall"
+ BenchmarkService_StreamingFromClient_FullMethodName = "/grpc.testing.BenchmarkService/StreamingFromClient"
+ BenchmarkService_StreamingFromServer_FullMethodName = "/grpc.testing.BenchmarkService/StreamingFromServer"
+ BenchmarkService_StreamingBothWays_FullMethodName = "/grpc.testing.BenchmarkService/StreamingBothWays"
+)
+
+// BenchmarkServiceClient is the client API for BenchmarkService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type BenchmarkServiceClient interface {
+ // One request followed by one response.
+ // The server returns the client payload as-is.
+ UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
+ // Repeated sequence of one request followed by one response.
+ // Should be called streaming ping-pong
+ // The server returns the client payload as-is on each response
+ StreamingCall(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingCallClient, error)
+ // Single-sided unbounded streaming from client to server
+ // The server returns the client payload as-is once the client does WritesDone
+ StreamingFromClient(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingFromClientClient, error)
+ // Single-sided unbounded streaming from server to client
+ // The server repeatedly returns the client payload as-is
+ StreamingFromServer(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (BenchmarkService_StreamingFromServerClient, error)
+ // Two-sided unbounded streaming between server to client
+ // Both sides send the content of their own choice to the other
+ StreamingBothWays(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingBothWaysClient, error)
+}
+
+type benchmarkServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewBenchmarkServiceClient(cc grpc.ClientConnInterface) BenchmarkServiceClient {
+ return &benchmarkServiceClient{cc}
+}
+
+func (c *benchmarkServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
+ out := new(SimpleResponse)
+ err := c.cc.Invoke(ctx, BenchmarkService_UnaryCall_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *benchmarkServiceClient) StreamingCall(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingCallClient, error) {
+ stream, err := c.cc.NewStream(ctx, &BenchmarkService_ServiceDesc.Streams[0], BenchmarkService_StreamingCall_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &benchmarkServiceStreamingCallClient{stream}
+ return x, nil
+}
+
+type BenchmarkService_StreamingCallClient interface {
+ Send(*SimpleRequest) error
+ Recv() (*SimpleResponse, error)
+ grpc.ClientStream
+}
+
+type benchmarkServiceStreamingCallClient struct {
+ grpc.ClientStream
+}
+
+func (x *benchmarkServiceStreamingCallClient) Send(m *SimpleRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *benchmarkServiceStreamingCallClient) Recv() (*SimpleResponse, error) {
+ m := new(SimpleResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *benchmarkServiceClient) StreamingFromClient(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingFromClientClient, error) {
+ stream, err := c.cc.NewStream(ctx, &BenchmarkService_ServiceDesc.Streams[1], BenchmarkService_StreamingFromClient_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &benchmarkServiceStreamingFromClientClient{stream}
+ return x, nil
+}
+
+type BenchmarkService_StreamingFromClientClient interface {
+ Send(*SimpleRequest) error
+ CloseAndRecv() (*SimpleResponse, error)
+ grpc.ClientStream
+}
+
+type benchmarkServiceStreamingFromClientClient struct {
+ grpc.ClientStream
+}
+
+func (x *benchmarkServiceStreamingFromClientClient) Send(m *SimpleRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *benchmarkServiceStreamingFromClientClient) CloseAndRecv() (*SimpleResponse, error) {
+ if err := x.ClientStream.CloseSend(); err != nil {
+ return nil, err
+ }
+ m := new(SimpleResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *benchmarkServiceClient) StreamingFromServer(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (BenchmarkService_StreamingFromServerClient, error) {
+ stream, err := c.cc.NewStream(ctx, &BenchmarkService_ServiceDesc.Streams[2], BenchmarkService_StreamingFromServer_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &benchmarkServiceStreamingFromServerClient{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 BenchmarkService_StreamingFromServerClient interface {
+ Recv() (*SimpleResponse, error)
+ grpc.ClientStream
+}
+
+type benchmarkServiceStreamingFromServerClient struct {
+ grpc.ClientStream
+}
+
+func (x *benchmarkServiceStreamingFromServerClient) Recv() (*SimpleResponse, error) {
+ m := new(SimpleResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *benchmarkServiceClient) StreamingBothWays(ctx context.Context, opts ...grpc.CallOption) (BenchmarkService_StreamingBothWaysClient, error) {
+ stream, err := c.cc.NewStream(ctx, &BenchmarkService_ServiceDesc.Streams[3], BenchmarkService_StreamingBothWays_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &benchmarkServiceStreamingBothWaysClient{stream}
+ return x, nil
+}
+
+type BenchmarkService_StreamingBothWaysClient interface {
+ Send(*SimpleRequest) error
+ Recv() (*SimpleResponse, error)
+ grpc.ClientStream
+}
+
+type benchmarkServiceStreamingBothWaysClient struct {
+ grpc.ClientStream
+}
+
+func (x *benchmarkServiceStreamingBothWaysClient) Send(m *SimpleRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *benchmarkServiceStreamingBothWaysClient) Recv() (*SimpleResponse, error) {
+ m := new(SimpleResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+// BenchmarkServiceServer is the server API for BenchmarkService service.
+// All implementations must embed UnimplementedBenchmarkServiceServer
+// for forward compatibility
+type BenchmarkServiceServer interface {
+ // One request followed by one response.
+ // The server returns the client payload as-is.
+ UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
+ // Repeated sequence of one request followed by one response.
+ // Should be called streaming ping-pong
+ // The server returns the client payload as-is on each response
+ StreamingCall(BenchmarkService_StreamingCallServer) error
+ // Single-sided unbounded streaming from client to server
+ // The server returns the client payload as-is once the client does WritesDone
+ StreamingFromClient(BenchmarkService_StreamingFromClientServer) error
+ // Single-sided unbounded streaming from server to client
+ // The server repeatedly returns the client payload as-is
+ StreamingFromServer(*SimpleRequest, BenchmarkService_StreamingFromServerServer) error
+ // Two-sided unbounded streaming between server to client
+ // Both sides send the content of their own choice to the other
+ StreamingBothWays(BenchmarkService_StreamingBothWaysServer) error
+ mustEmbedUnimplementedBenchmarkServiceServer()
+}
+
+// UnimplementedBenchmarkServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedBenchmarkServiceServer struct {
+}
+
+func (UnimplementedBenchmarkServiceServer) UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UnaryCall not implemented")
+}
+func (UnimplementedBenchmarkServiceServer) StreamingCall(BenchmarkService_StreamingCallServer) error {
+ return status.Errorf(codes.Unimplemented, "method StreamingCall not implemented")
+}
+func (UnimplementedBenchmarkServiceServer) StreamingFromClient(BenchmarkService_StreamingFromClientServer) error {
+ return status.Errorf(codes.Unimplemented, "method StreamingFromClient not implemented")
+}
+func (UnimplementedBenchmarkServiceServer) StreamingFromServer(*SimpleRequest, BenchmarkService_StreamingFromServerServer) error {
+ return status.Errorf(codes.Unimplemented, "method StreamingFromServer not implemented")
+}
+func (UnimplementedBenchmarkServiceServer) StreamingBothWays(BenchmarkService_StreamingBothWaysServer) error {
+ return status.Errorf(codes.Unimplemented, "method StreamingBothWays not implemented")
+}
+func (UnimplementedBenchmarkServiceServer) mustEmbedUnimplementedBenchmarkServiceServer() {}
+
+// UnsafeBenchmarkServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to BenchmarkServiceServer will
+// result in compilation errors.
+type UnsafeBenchmarkServiceServer interface {
+ mustEmbedUnimplementedBenchmarkServiceServer()
+}
+
+func RegisterBenchmarkServiceServer(s grpc.ServiceRegistrar, srv BenchmarkServiceServer) {
+ s.RegisterService(&BenchmarkService_ServiceDesc, srv)
+}
+
+func _BenchmarkService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(SimpleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BenchmarkServiceServer).UnaryCall(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: BenchmarkService_UnaryCall_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BenchmarkServiceServer).UnaryCall(ctx, req.(*SimpleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BenchmarkService_StreamingCall_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(BenchmarkServiceServer).StreamingCall(&benchmarkServiceStreamingCallServer{stream})
+}
+
+type BenchmarkService_StreamingCallServer interface {
+ Send(*SimpleResponse) error
+ Recv() (*SimpleRequest, error)
+ grpc.ServerStream
+}
+
+type benchmarkServiceStreamingCallServer struct {
+ grpc.ServerStream
+}
+
+func (x *benchmarkServiceStreamingCallServer) Send(m *SimpleResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *benchmarkServiceStreamingCallServer) Recv() (*SimpleRequest, error) {
+ m := new(SimpleRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _BenchmarkService_StreamingFromClient_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(BenchmarkServiceServer).StreamingFromClient(&benchmarkServiceStreamingFromClientServer{stream})
+}
+
+type BenchmarkService_StreamingFromClientServer interface {
+ SendAndClose(*SimpleResponse) error
+ Recv() (*SimpleRequest, error)
+ grpc.ServerStream
+}
+
+type benchmarkServiceStreamingFromClientServer struct {
+ grpc.ServerStream
+}
+
+func (x *benchmarkServiceStreamingFromClientServer) SendAndClose(m *SimpleResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *benchmarkServiceStreamingFromClientServer) Recv() (*SimpleRequest, error) {
+ m := new(SimpleRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _BenchmarkService_StreamingFromServer_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(SimpleRequest)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(BenchmarkServiceServer).StreamingFromServer(m, &benchmarkServiceStreamingFromServerServer{stream})
+}
+
+type BenchmarkService_StreamingFromServerServer interface {
+ Send(*SimpleResponse) error
+ grpc.ServerStream
+}
+
+type benchmarkServiceStreamingFromServerServer struct {
+ grpc.ServerStream
+}
+
+func (x *benchmarkServiceStreamingFromServerServer) Send(m *SimpleResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func _BenchmarkService_StreamingBothWays_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(BenchmarkServiceServer).StreamingBothWays(&benchmarkServiceStreamingBothWaysServer{stream})
+}
+
+type BenchmarkService_StreamingBothWaysServer interface {
+ Send(*SimpleResponse) error
+ Recv() (*SimpleRequest, error)
+ grpc.ServerStream
+}
+
+type benchmarkServiceStreamingBothWaysServer struct {
+ grpc.ServerStream
+}
+
+func (x *benchmarkServiceStreamingBothWaysServer) Send(m *SimpleResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *benchmarkServiceStreamingBothWaysServer) Recv() (*SimpleRequest, error) {
+ m := new(SimpleRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+// BenchmarkService_ServiceDesc is the grpc.ServiceDesc for BenchmarkService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var BenchmarkService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.BenchmarkService",
+ HandlerType: (*BenchmarkServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "UnaryCall",
+ Handler: _BenchmarkService_UnaryCall_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "StreamingCall",
+ Handler: _BenchmarkService_StreamingCall_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ {
+ StreamName: "StreamingFromClient",
+ Handler: _BenchmarkService_StreamingFromClient_Handler,
+ ClientStreams: true,
+ },
+ {
+ StreamName: "StreamingFromServer",
+ Handler: _BenchmarkService_StreamingFromServer_Handler,
+ ServerStreams: true,
+ },
+ {
+ StreamName: "StreamingBothWays",
+ Handler: _BenchmarkService_StreamingBothWays_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ },
+ Metadata: "grpc/testing/benchmark_service.proto",
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/control.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/control.pb.go
new file mode 100644
index 0000000000..e09b9bacc0
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/control.pb.go
@@ -0,0 +1,2492 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/control.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type ClientType int32
+
+const (
+ // Many languages support a basic distinction between using
+ // sync or async client, and this allows the specification
+ ClientType_SYNC_CLIENT ClientType = 0
+ ClientType_ASYNC_CLIENT ClientType = 1
+ ClientType_OTHER_CLIENT ClientType = 2 // used for some language-specific variants
+ ClientType_CALLBACK_CLIENT ClientType = 3
+)
+
+// Enum value maps for ClientType.
+var (
+ ClientType_name = map[int32]string{
+ 0: "SYNC_CLIENT",
+ 1: "ASYNC_CLIENT",
+ 2: "OTHER_CLIENT",
+ 3: "CALLBACK_CLIENT",
+ }
+ ClientType_value = map[string]int32{
+ "SYNC_CLIENT": 0,
+ "ASYNC_CLIENT": 1,
+ "OTHER_CLIENT": 2,
+ "CALLBACK_CLIENT": 3,
+ }
+)
+
+func (x ClientType) Enum() *ClientType {
+ p := new(ClientType)
+ *p = x
+ return p
+}
+
+func (x ClientType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ClientType) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_control_proto_enumTypes[0].Descriptor()
+}
+
+func (ClientType) Type() protoreflect.EnumType {
+ return &file_grpc_testing_control_proto_enumTypes[0]
+}
+
+func (x ClientType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use ClientType.Descriptor instead.
+func (ClientType) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{0}
+}
+
+type ServerType int32
+
+const (
+ ServerType_SYNC_SERVER ServerType = 0
+ ServerType_ASYNC_SERVER ServerType = 1
+ ServerType_ASYNC_GENERIC_SERVER ServerType = 2
+ ServerType_OTHER_SERVER ServerType = 3 // used for some language-specific variants
+ ServerType_CALLBACK_SERVER ServerType = 4
+)
+
+// Enum value maps for ServerType.
+var (
+ ServerType_name = map[int32]string{
+ 0: "SYNC_SERVER",
+ 1: "ASYNC_SERVER",
+ 2: "ASYNC_GENERIC_SERVER",
+ 3: "OTHER_SERVER",
+ 4: "CALLBACK_SERVER",
+ }
+ ServerType_value = map[string]int32{
+ "SYNC_SERVER": 0,
+ "ASYNC_SERVER": 1,
+ "ASYNC_GENERIC_SERVER": 2,
+ "OTHER_SERVER": 3,
+ "CALLBACK_SERVER": 4,
+ }
+)
+
+func (x ServerType) Enum() *ServerType {
+ p := new(ServerType)
+ *p = x
+ return p
+}
+
+func (x ServerType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ServerType) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_control_proto_enumTypes[1].Descriptor()
+}
+
+func (ServerType) Type() protoreflect.EnumType {
+ return &file_grpc_testing_control_proto_enumTypes[1]
+}
+
+func (x ServerType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use ServerType.Descriptor instead.
+func (ServerType) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{1}
+}
+
+type RpcType int32
+
+const (
+ RpcType_UNARY RpcType = 0
+ RpcType_STREAMING RpcType = 1
+ RpcType_STREAMING_FROM_CLIENT RpcType = 2
+ RpcType_STREAMING_FROM_SERVER RpcType = 3
+ RpcType_STREAMING_BOTH_WAYS RpcType = 4
+)
+
+// Enum value maps for RpcType.
+var (
+ RpcType_name = map[int32]string{
+ 0: "UNARY",
+ 1: "STREAMING",
+ 2: "STREAMING_FROM_CLIENT",
+ 3: "STREAMING_FROM_SERVER",
+ 4: "STREAMING_BOTH_WAYS",
+ }
+ RpcType_value = map[string]int32{
+ "UNARY": 0,
+ "STREAMING": 1,
+ "STREAMING_FROM_CLIENT": 2,
+ "STREAMING_FROM_SERVER": 3,
+ "STREAMING_BOTH_WAYS": 4,
+ }
+)
+
+func (x RpcType) Enum() *RpcType {
+ p := new(RpcType)
+ *p = x
+ return p
+}
+
+func (x RpcType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (RpcType) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_control_proto_enumTypes[2].Descriptor()
+}
+
+func (RpcType) Type() protoreflect.EnumType {
+ return &file_grpc_testing_control_proto_enumTypes[2]
+}
+
+func (x RpcType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use RpcType.Descriptor instead.
+func (RpcType) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{2}
+}
+
+// Parameters of poisson process distribution, which is a good representation
+// of activity coming in from independent identical stationary sources.
+type PoissonParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
+ OfferedLoad float64 `protobuf:"fixed64,1,opt,name=offered_load,json=offeredLoad,proto3" json:"offered_load,omitempty"`
+}
+
+func (x *PoissonParams) Reset() {
+ *x = PoissonParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PoissonParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PoissonParams) ProtoMessage() {}
+
+func (x *PoissonParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PoissonParams.ProtoReflect.Descriptor instead.
+func (*PoissonParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *PoissonParams) GetOfferedLoad() float64 {
+ if x != nil {
+ return x.OfferedLoad
+ }
+ return 0
+}
+
+// Once an RPC finishes, immediately start a new one.
+// No configuration parameters needed.
+type ClosedLoopParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *ClosedLoopParams) Reset() {
+ *x = ClosedLoopParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClosedLoopParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClosedLoopParams) ProtoMessage() {}
+
+func (x *ClosedLoopParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClosedLoopParams.ProtoReflect.Descriptor instead.
+func (*ClosedLoopParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{1}
+}
+
+type LoadParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Types that are assignable to Load:
+ //
+ // *LoadParams_ClosedLoop
+ // *LoadParams_Poisson
+ Load isLoadParams_Load `protobuf_oneof:"load"`
+}
+
+func (x *LoadParams) Reset() {
+ *x = LoadParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadParams) ProtoMessage() {}
+
+func (x *LoadParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadParams.ProtoReflect.Descriptor instead.
+func (*LoadParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{2}
+}
+
+func (m *LoadParams) GetLoad() isLoadParams_Load {
+ if m != nil {
+ return m.Load
+ }
+ return nil
+}
+
+func (x *LoadParams) GetClosedLoop() *ClosedLoopParams {
+ if x, ok := x.GetLoad().(*LoadParams_ClosedLoop); ok {
+ return x.ClosedLoop
+ }
+ return nil
+}
+
+func (x *LoadParams) GetPoisson() *PoissonParams {
+ if x, ok := x.GetLoad().(*LoadParams_Poisson); ok {
+ return x.Poisson
+ }
+ return nil
+}
+
+type isLoadParams_Load interface {
+ isLoadParams_Load()
+}
+
+type LoadParams_ClosedLoop struct {
+ ClosedLoop *ClosedLoopParams `protobuf:"bytes,1,opt,name=closed_loop,json=closedLoop,proto3,oneof"`
+}
+
+type LoadParams_Poisson struct {
+ Poisson *PoissonParams `protobuf:"bytes,2,opt,name=poisson,proto3,oneof"`
+}
+
+func (*LoadParams_ClosedLoop) isLoadParams_Load() {}
+
+func (*LoadParams_Poisson) isLoadParams_Load() {}
+
+// presence of SecurityParams implies use of TLS
+type SecurityParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ UseTestCa bool `protobuf:"varint,1,opt,name=use_test_ca,json=useTestCa,proto3" json:"use_test_ca,omitempty"`
+ ServerHostOverride string `protobuf:"bytes,2,opt,name=server_host_override,json=serverHostOverride,proto3" json:"server_host_override,omitempty"`
+ CredType string `protobuf:"bytes,3,opt,name=cred_type,json=credType,proto3" json:"cred_type,omitempty"`
+}
+
+func (x *SecurityParams) Reset() {
+ *x = SecurityParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SecurityParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SecurityParams) ProtoMessage() {}
+
+func (x *SecurityParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SecurityParams.ProtoReflect.Descriptor instead.
+func (*SecurityParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *SecurityParams) GetUseTestCa() bool {
+ if x != nil {
+ return x.UseTestCa
+ }
+ return false
+}
+
+func (x *SecurityParams) GetServerHostOverride() string {
+ if x != nil {
+ return x.ServerHostOverride
+ }
+ return ""
+}
+
+func (x *SecurityParams) GetCredType() string {
+ if x != nil {
+ return x.CredType
+ }
+ return ""
+}
+
+type ChannelArg struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // Types that are assignable to Value:
+ //
+ // *ChannelArg_StrValue
+ // *ChannelArg_IntValue
+ Value isChannelArg_Value `protobuf_oneof:"value"`
+}
+
+func (x *ChannelArg) Reset() {
+ *x = ChannelArg{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ChannelArg) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ChannelArg) ProtoMessage() {}
+
+func (x *ChannelArg) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ChannelArg.ProtoReflect.Descriptor instead.
+func (*ChannelArg) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ChannelArg) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (m *ChannelArg) GetValue() isChannelArg_Value {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (x *ChannelArg) GetStrValue() string {
+ if x, ok := x.GetValue().(*ChannelArg_StrValue); ok {
+ return x.StrValue
+ }
+ return ""
+}
+
+func (x *ChannelArg) GetIntValue() int32 {
+ if x, ok := x.GetValue().(*ChannelArg_IntValue); ok {
+ return x.IntValue
+ }
+ return 0
+}
+
+type isChannelArg_Value interface {
+ isChannelArg_Value()
+}
+
+type ChannelArg_StrValue struct {
+ StrValue string `protobuf:"bytes,2,opt,name=str_value,json=strValue,proto3,oneof"`
+}
+
+type ChannelArg_IntValue struct {
+ IntValue int32 `protobuf:"varint,3,opt,name=int_value,json=intValue,proto3,oneof"`
+}
+
+func (*ChannelArg_StrValue) isChannelArg_Value() {}
+
+func (*ChannelArg_IntValue) isChannelArg_Value() {}
+
+type ClientConfig struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of targets to connect to. At least one target needs to be specified.
+ ServerTargets []string `protobuf:"bytes,1,rep,name=server_targets,json=serverTargets,proto3" json:"server_targets,omitempty"`
+ ClientType ClientType `protobuf:"varint,2,opt,name=client_type,json=clientType,proto3,enum=grpc.testing.ClientType" json:"client_type,omitempty"`
+ SecurityParams *SecurityParams `protobuf:"bytes,3,opt,name=security_params,json=securityParams,proto3" json:"security_params,omitempty"`
+ // How many concurrent RPCs to start for each channel.
+ // For synchronous client, use a separate thread for each outstanding RPC.
+ OutstandingRpcsPerChannel int32 `protobuf:"varint,4,opt,name=outstanding_rpcs_per_channel,json=outstandingRpcsPerChannel,proto3" json:"outstanding_rpcs_per_channel,omitempty"`
+ // Number of independent client channels to create.
+ // i-th channel will connect to server_target[i % server_targets.size()]
+ ClientChannels int32 `protobuf:"varint,5,opt,name=client_channels,json=clientChannels,proto3" json:"client_channels,omitempty"`
+ // Only for async client. Number of threads to use to start/manage RPCs.
+ AsyncClientThreads int32 `protobuf:"varint,7,opt,name=async_client_threads,json=asyncClientThreads,proto3" json:"async_client_threads,omitempty"`
+ RpcType RpcType `protobuf:"varint,8,opt,name=rpc_type,json=rpcType,proto3,enum=grpc.testing.RpcType" json:"rpc_type,omitempty"`
+ // The requested load for the entire client (aggregated over all the threads).
+ LoadParams *LoadParams `protobuf:"bytes,10,opt,name=load_params,json=loadParams,proto3" json:"load_params,omitempty"`
+ PayloadConfig *PayloadConfig `protobuf:"bytes,11,opt,name=payload_config,json=payloadConfig,proto3" json:"payload_config,omitempty"`
+ HistogramParams *HistogramParams `protobuf:"bytes,12,opt,name=histogram_params,json=histogramParams,proto3" json:"histogram_params,omitempty"`
+ // Specify the cores we should run the client on, if desired
+ CoreList []int32 `protobuf:"varint,13,rep,packed,name=core_list,json=coreList,proto3" json:"core_list,omitempty"`
+ CoreLimit int32 `protobuf:"varint,14,opt,name=core_limit,json=coreLimit,proto3" json:"core_limit,omitempty"`
+ // If we use an OTHER_CLIENT client_type, this string gives more detail
+ OtherClientApi string `protobuf:"bytes,15,opt,name=other_client_api,json=otherClientApi,proto3" json:"other_client_api,omitempty"`
+ ChannelArgs []*ChannelArg `protobuf:"bytes,16,rep,name=channel_args,json=channelArgs,proto3" json:"channel_args,omitempty"`
+ // Number of threads that share each completion queue
+ ThreadsPerCq int32 `protobuf:"varint,17,opt,name=threads_per_cq,json=threadsPerCq,proto3" json:"threads_per_cq,omitempty"`
+ // Number of messages on a stream before it gets finished/restarted
+ MessagesPerStream int32 `protobuf:"varint,18,opt,name=messages_per_stream,json=messagesPerStream,proto3" json:"messages_per_stream,omitempty"`
+ // Use coalescing API when possible.
+ UseCoalesceApi bool `protobuf:"varint,19,opt,name=use_coalesce_api,json=useCoalesceApi,proto3" json:"use_coalesce_api,omitempty"`
+ // If 0, disabled. Else, specifies the period between gathering latency
+ // medians in milliseconds.
+ MedianLatencyCollectionIntervalMillis int32 `protobuf:"varint,20,opt,name=median_latency_collection_interval_millis,json=medianLatencyCollectionIntervalMillis,proto3" json:"median_latency_collection_interval_millis,omitempty"`
+ // Number of client processes. 0 indicates no restriction.
+ ClientProcesses int32 `protobuf:"varint,21,opt,name=client_processes,json=clientProcesses,proto3" json:"client_processes,omitempty"`
+}
+
+func (x *ClientConfig) Reset() {
+ *x = ClientConfig{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClientConfig) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientConfig) ProtoMessage() {}
+
+func (x *ClientConfig) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientConfig.ProtoReflect.Descriptor instead.
+func (*ClientConfig) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ClientConfig) GetServerTargets() []string {
+ if x != nil {
+ return x.ServerTargets
+ }
+ return nil
+}
+
+func (x *ClientConfig) GetClientType() ClientType {
+ if x != nil {
+ return x.ClientType
+ }
+ return ClientType_SYNC_CLIENT
+}
+
+func (x *ClientConfig) GetSecurityParams() *SecurityParams {
+ if x != nil {
+ return x.SecurityParams
+ }
+ return nil
+}
+
+func (x *ClientConfig) GetOutstandingRpcsPerChannel() int32 {
+ if x != nil {
+ return x.OutstandingRpcsPerChannel
+ }
+ return 0
+}
+
+func (x *ClientConfig) GetClientChannels() int32 {
+ if x != nil {
+ return x.ClientChannels
+ }
+ return 0
+}
+
+func (x *ClientConfig) GetAsyncClientThreads() int32 {
+ if x != nil {
+ return x.AsyncClientThreads
+ }
+ return 0
+}
+
+func (x *ClientConfig) GetRpcType() RpcType {
+ if x != nil {
+ return x.RpcType
+ }
+ return RpcType_UNARY
+}
+
+func (x *ClientConfig) GetLoadParams() *LoadParams {
+ if x != nil {
+ return x.LoadParams
+ }
+ return nil
+}
+
+func (x *ClientConfig) GetPayloadConfig() *PayloadConfig {
+ if x != nil {
+ return x.PayloadConfig
+ }
+ return nil
+}
+
+func (x *ClientConfig) GetHistogramParams() *HistogramParams {
+ if x != nil {
+ return x.HistogramParams
+ }
+ return nil
+}
+
+func (x *ClientConfig) GetCoreList() []int32 {
+ if x != nil {
+ return x.CoreList
+ }
+ return nil
+}
+
+func (x *ClientConfig) GetCoreLimit() int32 {
+ if x != nil {
+ return x.CoreLimit
+ }
+ return 0
+}
+
+func (x *ClientConfig) GetOtherClientApi() string {
+ if x != nil {
+ return x.OtherClientApi
+ }
+ return ""
+}
+
+func (x *ClientConfig) GetChannelArgs() []*ChannelArg {
+ if x != nil {
+ return x.ChannelArgs
+ }
+ return nil
+}
+
+func (x *ClientConfig) GetThreadsPerCq() int32 {
+ if x != nil {
+ return x.ThreadsPerCq
+ }
+ return 0
+}
+
+func (x *ClientConfig) GetMessagesPerStream() int32 {
+ if x != nil {
+ return x.MessagesPerStream
+ }
+ return 0
+}
+
+func (x *ClientConfig) GetUseCoalesceApi() bool {
+ if x != nil {
+ return x.UseCoalesceApi
+ }
+ return false
+}
+
+func (x *ClientConfig) GetMedianLatencyCollectionIntervalMillis() int32 {
+ if x != nil {
+ return x.MedianLatencyCollectionIntervalMillis
+ }
+ return 0
+}
+
+func (x *ClientConfig) GetClientProcesses() int32 {
+ if x != nil {
+ return x.ClientProcesses
+ }
+ return 0
+}
+
+type ClientStatus struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Stats *ClientStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"`
+}
+
+func (x *ClientStatus) Reset() {
+ *x = ClientStatus{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClientStatus) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientStatus) ProtoMessage() {}
+
+func (x *ClientStatus) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientStatus.ProtoReflect.Descriptor instead.
+func (*ClientStatus) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ClientStatus) GetStats() *ClientStats {
+ if x != nil {
+ return x.Stats
+ }
+ return nil
+}
+
+// Request current stats
+type Mark struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // if true, the stats will be reset after taking their snapshot.
+ Reset_ bool `protobuf:"varint,1,opt,name=reset,proto3" json:"reset,omitempty"`
+}
+
+func (x *Mark) Reset() {
+ *x = Mark{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Mark) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Mark) ProtoMessage() {}
+
+func (x *Mark) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Mark.ProtoReflect.Descriptor instead.
+func (*Mark) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *Mark) GetReset_() bool {
+ if x != nil {
+ return x.Reset_
+ }
+ return false
+}
+
+type ClientArgs struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Types that are assignable to Argtype:
+ //
+ // *ClientArgs_Setup
+ // *ClientArgs_Mark
+ Argtype isClientArgs_Argtype `protobuf_oneof:"argtype"`
+}
+
+func (x *ClientArgs) Reset() {
+ *x = ClientArgs{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClientArgs) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientArgs) ProtoMessage() {}
+
+func (x *ClientArgs) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientArgs.ProtoReflect.Descriptor instead.
+func (*ClientArgs) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{8}
+}
+
+func (m *ClientArgs) GetArgtype() isClientArgs_Argtype {
+ if m != nil {
+ return m.Argtype
+ }
+ return nil
+}
+
+func (x *ClientArgs) GetSetup() *ClientConfig {
+ if x, ok := x.GetArgtype().(*ClientArgs_Setup); ok {
+ return x.Setup
+ }
+ return nil
+}
+
+func (x *ClientArgs) GetMark() *Mark {
+ if x, ok := x.GetArgtype().(*ClientArgs_Mark); ok {
+ return x.Mark
+ }
+ return nil
+}
+
+type isClientArgs_Argtype interface {
+ isClientArgs_Argtype()
+}
+
+type ClientArgs_Setup struct {
+ Setup *ClientConfig `protobuf:"bytes,1,opt,name=setup,proto3,oneof"`
+}
+
+type ClientArgs_Mark struct {
+ Mark *Mark `protobuf:"bytes,2,opt,name=mark,proto3,oneof"`
+}
+
+func (*ClientArgs_Setup) isClientArgs_Argtype() {}
+
+func (*ClientArgs_Mark) isClientArgs_Argtype() {}
+
+type ServerConfig struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ServerType ServerType `protobuf:"varint,1,opt,name=server_type,json=serverType,proto3,enum=grpc.testing.ServerType" json:"server_type,omitempty"`
+ SecurityParams *SecurityParams `protobuf:"bytes,2,opt,name=security_params,json=securityParams,proto3" json:"security_params,omitempty"`
+ // Port on which to listen. Zero means pick unused port.
+ Port int32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"`
+ // Only for async server. Number of threads used to serve the requests.
+ AsyncServerThreads int32 `protobuf:"varint,7,opt,name=async_server_threads,json=asyncServerThreads,proto3" json:"async_server_threads,omitempty"`
+ // Specify the number of cores to limit server to, if desired
+ CoreLimit int32 `protobuf:"varint,8,opt,name=core_limit,json=coreLimit,proto3" json:"core_limit,omitempty"`
+ // payload config, used in generic server.
+ // Note this must NOT be used in proto (non-generic) servers. For proto servers,
+ // 'response sizes' must be configured from the 'response_size' field of the
+ // 'SimpleRequest' objects in RPC requests.
+ PayloadConfig *PayloadConfig `protobuf:"bytes,9,opt,name=payload_config,json=payloadConfig,proto3" json:"payload_config,omitempty"`
+ // Specify the cores we should run the server on, if desired
+ CoreList []int32 `protobuf:"varint,10,rep,packed,name=core_list,json=coreList,proto3" json:"core_list,omitempty"`
+ // If we use an OTHER_SERVER client_type, this string gives more detail
+ OtherServerApi string `protobuf:"bytes,11,opt,name=other_server_api,json=otherServerApi,proto3" json:"other_server_api,omitempty"`
+ // Number of threads that share each completion queue
+ ThreadsPerCq int32 `protobuf:"varint,12,opt,name=threads_per_cq,json=threadsPerCq,proto3" json:"threads_per_cq,omitempty"`
+ // Buffer pool size (no buffer pool specified if unset)
+ ResourceQuotaSize int32 `protobuf:"varint,1001,opt,name=resource_quota_size,json=resourceQuotaSize,proto3" json:"resource_quota_size,omitempty"`
+ ChannelArgs []*ChannelArg `protobuf:"bytes,1002,rep,name=channel_args,json=channelArgs,proto3" json:"channel_args,omitempty"`
+ // Number of server processes. 0 indicates no restriction.
+ ServerProcesses int32 `protobuf:"varint,21,opt,name=server_processes,json=serverProcesses,proto3" json:"server_processes,omitempty"`
+}
+
+func (x *ServerConfig) Reset() {
+ *x = ServerConfig{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ServerConfig) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServerConfig) ProtoMessage() {}
+
+func (x *ServerConfig) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServerConfig.ProtoReflect.Descriptor instead.
+func (*ServerConfig) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *ServerConfig) GetServerType() ServerType {
+ if x != nil {
+ return x.ServerType
+ }
+ return ServerType_SYNC_SERVER
+}
+
+func (x *ServerConfig) GetSecurityParams() *SecurityParams {
+ if x != nil {
+ return x.SecurityParams
+ }
+ return nil
+}
+
+func (x *ServerConfig) GetPort() int32 {
+ if x != nil {
+ return x.Port
+ }
+ return 0
+}
+
+func (x *ServerConfig) GetAsyncServerThreads() int32 {
+ if x != nil {
+ return x.AsyncServerThreads
+ }
+ return 0
+}
+
+func (x *ServerConfig) GetCoreLimit() int32 {
+ if x != nil {
+ return x.CoreLimit
+ }
+ return 0
+}
+
+func (x *ServerConfig) GetPayloadConfig() *PayloadConfig {
+ if x != nil {
+ return x.PayloadConfig
+ }
+ return nil
+}
+
+func (x *ServerConfig) GetCoreList() []int32 {
+ if x != nil {
+ return x.CoreList
+ }
+ return nil
+}
+
+func (x *ServerConfig) GetOtherServerApi() string {
+ if x != nil {
+ return x.OtherServerApi
+ }
+ return ""
+}
+
+func (x *ServerConfig) GetThreadsPerCq() int32 {
+ if x != nil {
+ return x.ThreadsPerCq
+ }
+ return 0
+}
+
+func (x *ServerConfig) GetResourceQuotaSize() int32 {
+ if x != nil {
+ return x.ResourceQuotaSize
+ }
+ return 0
+}
+
+func (x *ServerConfig) GetChannelArgs() []*ChannelArg {
+ if x != nil {
+ return x.ChannelArgs
+ }
+ return nil
+}
+
+func (x *ServerConfig) GetServerProcesses() int32 {
+ if x != nil {
+ return x.ServerProcesses
+ }
+ return 0
+}
+
+type ServerArgs struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Types that are assignable to Argtype:
+ //
+ // *ServerArgs_Setup
+ // *ServerArgs_Mark
+ Argtype isServerArgs_Argtype `protobuf_oneof:"argtype"`
+}
+
+func (x *ServerArgs) Reset() {
+ *x = ServerArgs{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ServerArgs) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServerArgs) ProtoMessage() {}
+
+func (x *ServerArgs) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[10]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServerArgs.ProtoReflect.Descriptor instead.
+func (*ServerArgs) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{10}
+}
+
+func (m *ServerArgs) GetArgtype() isServerArgs_Argtype {
+ if m != nil {
+ return m.Argtype
+ }
+ return nil
+}
+
+func (x *ServerArgs) GetSetup() *ServerConfig {
+ if x, ok := x.GetArgtype().(*ServerArgs_Setup); ok {
+ return x.Setup
+ }
+ return nil
+}
+
+func (x *ServerArgs) GetMark() *Mark {
+ if x, ok := x.GetArgtype().(*ServerArgs_Mark); ok {
+ return x.Mark
+ }
+ return nil
+}
+
+type isServerArgs_Argtype interface {
+ isServerArgs_Argtype()
+}
+
+type ServerArgs_Setup struct {
+ Setup *ServerConfig `protobuf:"bytes,1,opt,name=setup,proto3,oneof"`
+}
+
+type ServerArgs_Mark struct {
+ Mark *Mark `protobuf:"bytes,2,opt,name=mark,proto3,oneof"`
+}
+
+func (*ServerArgs_Setup) isServerArgs_Argtype() {}
+
+func (*ServerArgs_Mark) isServerArgs_Argtype() {}
+
+type ServerStatus struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Stats *ServerStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"`
+ // the port bound by the server
+ Port int32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
+ // Number of cores available to the server
+ Cores int32 `protobuf:"varint,3,opt,name=cores,proto3" json:"cores,omitempty"`
+}
+
+func (x *ServerStatus) Reset() {
+ *x = ServerStatus{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ServerStatus) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServerStatus) ProtoMessage() {}
+
+func (x *ServerStatus) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[11]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServerStatus.ProtoReflect.Descriptor instead.
+func (*ServerStatus) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *ServerStatus) GetStats() *ServerStats {
+ if x != nil {
+ return x.Stats
+ }
+ return nil
+}
+
+func (x *ServerStatus) GetPort() int32 {
+ if x != nil {
+ return x.Port
+ }
+ return 0
+}
+
+func (x *ServerStatus) GetCores() int32 {
+ if x != nil {
+ return x.Cores
+ }
+ return 0
+}
+
+type CoreRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *CoreRequest) Reset() {
+ *x = CoreRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CoreRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CoreRequest) ProtoMessage() {}
+
+func (x *CoreRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[12]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CoreRequest.ProtoReflect.Descriptor instead.
+func (*CoreRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{12}
+}
+
+type CoreResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Number of cores available on the server
+ Cores int32 `protobuf:"varint,1,opt,name=cores,proto3" json:"cores,omitempty"`
+}
+
+func (x *CoreResponse) Reset() {
+ *x = CoreResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CoreResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CoreResponse) ProtoMessage() {}
+
+func (x *CoreResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[13]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CoreResponse.ProtoReflect.Descriptor instead.
+func (*CoreResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *CoreResponse) GetCores() int32 {
+ if x != nil {
+ return x.Cores
+ }
+ return 0
+}
+
+type Void struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *Void) Reset() {
+ *x = Void{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[14]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Void) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Void) ProtoMessage() {}
+
+func (x *Void) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[14]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Void.ProtoReflect.Descriptor instead.
+func (*Void) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{14}
+}
+
+// A single performance scenario: input to qps_json_driver
+type Scenario struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Human readable name for this scenario
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // Client configuration
+ ClientConfig *ClientConfig `protobuf:"bytes,2,opt,name=client_config,json=clientConfig,proto3" json:"client_config,omitempty"`
+ // Number of clients to start for the test
+ NumClients int32 `protobuf:"varint,3,opt,name=num_clients,json=numClients,proto3" json:"num_clients,omitempty"`
+ // Server configuration
+ ServerConfig *ServerConfig `protobuf:"bytes,4,opt,name=server_config,json=serverConfig,proto3" json:"server_config,omitempty"`
+ // Number of servers to start for the test
+ NumServers int32 `protobuf:"varint,5,opt,name=num_servers,json=numServers,proto3" json:"num_servers,omitempty"`
+ // Warmup period, in seconds
+ WarmupSeconds int32 `protobuf:"varint,6,opt,name=warmup_seconds,json=warmupSeconds,proto3" json:"warmup_seconds,omitempty"`
+ // Benchmark time, in seconds
+ BenchmarkSeconds int32 `protobuf:"varint,7,opt,name=benchmark_seconds,json=benchmarkSeconds,proto3" json:"benchmark_seconds,omitempty"`
+ // Number of workers to spawn locally (usually zero)
+ SpawnLocalWorkerCount int32 `protobuf:"varint,8,opt,name=spawn_local_worker_count,json=spawnLocalWorkerCount,proto3" json:"spawn_local_worker_count,omitempty"`
+}
+
+func (x *Scenario) Reset() {
+ *x = Scenario{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[15]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Scenario) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Scenario) ProtoMessage() {}
+
+func (x *Scenario) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[15]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Scenario.ProtoReflect.Descriptor instead.
+func (*Scenario) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{15}
+}
+
+func (x *Scenario) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *Scenario) GetClientConfig() *ClientConfig {
+ if x != nil {
+ return x.ClientConfig
+ }
+ return nil
+}
+
+func (x *Scenario) GetNumClients() int32 {
+ if x != nil {
+ return x.NumClients
+ }
+ return 0
+}
+
+func (x *Scenario) GetServerConfig() *ServerConfig {
+ if x != nil {
+ return x.ServerConfig
+ }
+ return nil
+}
+
+func (x *Scenario) GetNumServers() int32 {
+ if x != nil {
+ return x.NumServers
+ }
+ return 0
+}
+
+func (x *Scenario) GetWarmupSeconds() int32 {
+ if x != nil {
+ return x.WarmupSeconds
+ }
+ return 0
+}
+
+func (x *Scenario) GetBenchmarkSeconds() int32 {
+ if x != nil {
+ return x.BenchmarkSeconds
+ }
+ return 0
+}
+
+func (x *Scenario) GetSpawnLocalWorkerCount() int32 {
+ if x != nil {
+ return x.SpawnLocalWorkerCount
+ }
+ return 0
+}
+
+// A set of scenarios to be run with qps_json_driver
+type Scenarios struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Scenarios []*Scenario `protobuf:"bytes,1,rep,name=scenarios,proto3" json:"scenarios,omitempty"`
+}
+
+func (x *Scenarios) Reset() {
+ *x = Scenarios{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[16]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Scenarios) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Scenarios) ProtoMessage() {}
+
+func (x *Scenarios) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[16]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Scenarios.ProtoReflect.Descriptor instead.
+func (*Scenarios) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *Scenarios) GetScenarios() []*Scenario {
+ if x != nil {
+ return x.Scenarios
+ }
+ return nil
+}
+
+// Basic summary that can be computed from ClientStats and ServerStats
+// once the scenario has finished.
+type ScenarioResultSummary struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Total number of operations per second over all clients. What is counted as 1 'operation' depends on the benchmark scenarios:
+ // For unary benchmarks, an operation is processing of a single unary RPC.
+ // For streaming benchmarks, an operation is processing of a single ping pong of request and response.
+ Qps float64 `protobuf:"fixed64,1,opt,name=qps,proto3" json:"qps,omitempty"`
+ // QPS per server core.
+ QpsPerServerCore float64 `protobuf:"fixed64,2,opt,name=qps_per_server_core,json=qpsPerServerCore,proto3" json:"qps_per_server_core,omitempty"`
+ // The total server cpu load based on system time across all server processes, expressed as percentage of a single cpu core.
+ // For example, 85 implies 85% of a cpu core, 125 implies 125% of a cpu core. Since we are accumulating the cpu load across all the server
+ // processes, the value could > 100 when there are multiple servers or a single server using multiple threads and cores.
+ // Same explanation for the total client cpu load below.
+ ServerSystemTime float64 `protobuf:"fixed64,3,opt,name=server_system_time,json=serverSystemTime,proto3" json:"server_system_time,omitempty"`
+ // The total server cpu load based on user time across all server processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
+ ServerUserTime float64 `protobuf:"fixed64,4,opt,name=server_user_time,json=serverUserTime,proto3" json:"server_user_time,omitempty"`
+ // The total client cpu load based on system time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
+ ClientSystemTime float64 `protobuf:"fixed64,5,opt,name=client_system_time,json=clientSystemTime,proto3" json:"client_system_time,omitempty"`
+ // The total client cpu load based on user time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%)
+ ClientUserTime float64 `protobuf:"fixed64,6,opt,name=client_user_time,json=clientUserTime,proto3" json:"client_user_time,omitempty"`
+ // X% latency percentiles (in nanoseconds)
+ Latency_50 float64 `protobuf:"fixed64,7,opt,name=latency_50,json=latency50,proto3" json:"latency_50,omitempty"`
+ Latency_90 float64 `protobuf:"fixed64,8,opt,name=latency_90,json=latency90,proto3" json:"latency_90,omitempty"`
+ Latency_95 float64 `protobuf:"fixed64,9,opt,name=latency_95,json=latency95,proto3" json:"latency_95,omitempty"`
+ Latency_99 float64 `protobuf:"fixed64,10,opt,name=latency_99,json=latency99,proto3" json:"latency_99,omitempty"`
+ Latency_999 float64 `protobuf:"fixed64,11,opt,name=latency_999,json=latency999,proto3" json:"latency_999,omitempty"`
+ // server cpu usage percentage
+ ServerCpuUsage float64 `protobuf:"fixed64,12,opt,name=server_cpu_usage,json=serverCpuUsage,proto3" json:"server_cpu_usage,omitempty"`
+ // Number of requests that succeeded/failed
+ SuccessfulRequestsPerSecond float64 `protobuf:"fixed64,13,opt,name=successful_requests_per_second,json=successfulRequestsPerSecond,proto3" json:"successful_requests_per_second,omitempty"`
+ FailedRequestsPerSecond float64 `protobuf:"fixed64,14,opt,name=failed_requests_per_second,json=failedRequestsPerSecond,proto3" json:"failed_requests_per_second,omitempty"`
+ // Number of polls called inside completion queue per request
+ ClientPollsPerRequest float64 `protobuf:"fixed64,15,opt,name=client_polls_per_request,json=clientPollsPerRequest,proto3" json:"client_polls_per_request,omitempty"`
+ ServerPollsPerRequest float64 `protobuf:"fixed64,16,opt,name=server_polls_per_request,json=serverPollsPerRequest,proto3" json:"server_polls_per_request,omitempty"`
+ // Queries per CPU-sec over all servers or clients
+ ServerQueriesPerCpuSec float64 `protobuf:"fixed64,17,opt,name=server_queries_per_cpu_sec,json=serverQueriesPerCpuSec,proto3" json:"server_queries_per_cpu_sec,omitempty"`
+ ClientQueriesPerCpuSec float64 `protobuf:"fixed64,18,opt,name=client_queries_per_cpu_sec,json=clientQueriesPerCpuSec,proto3" json:"client_queries_per_cpu_sec,omitempty"`
+ // Start and end time for the test scenario
+ StartTime *timestamppb.Timestamp `protobuf:"bytes,19,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"`
+ EndTime *timestamppb.Timestamp `protobuf:"bytes,20,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"`
+}
+
+func (x *ScenarioResultSummary) Reset() {
+ *x = ScenarioResultSummary{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[17]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ScenarioResultSummary) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ScenarioResultSummary) ProtoMessage() {}
+
+func (x *ScenarioResultSummary) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[17]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ScenarioResultSummary.ProtoReflect.Descriptor instead.
+func (*ScenarioResultSummary) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{17}
+}
+
+func (x *ScenarioResultSummary) GetQps() float64 {
+ if x != nil {
+ return x.Qps
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetQpsPerServerCore() float64 {
+ if x != nil {
+ return x.QpsPerServerCore
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetServerSystemTime() float64 {
+ if x != nil {
+ return x.ServerSystemTime
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetServerUserTime() float64 {
+ if x != nil {
+ return x.ServerUserTime
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetClientSystemTime() float64 {
+ if x != nil {
+ return x.ClientSystemTime
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetClientUserTime() float64 {
+ if x != nil {
+ return x.ClientUserTime
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetLatency_50() float64 {
+ if x != nil {
+ return x.Latency_50
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetLatency_90() float64 {
+ if x != nil {
+ return x.Latency_90
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetLatency_95() float64 {
+ if x != nil {
+ return x.Latency_95
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetLatency_99() float64 {
+ if x != nil {
+ return x.Latency_99
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetLatency_999() float64 {
+ if x != nil {
+ return x.Latency_999
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetServerCpuUsage() float64 {
+ if x != nil {
+ return x.ServerCpuUsage
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetSuccessfulRequestsPerSecond() float64 {
+ if x != nil {
+ return x.SuccessfulRequestsPerSecond
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetFailedRequestsPerSecond() float64 {
+ if x != nil {
+ return x.FailedRequestsPerSecond
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetClientPollsPerRequest() float64 {
+ if x != nil {
+ return x.ClientPollsPerRequest
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetServerPollsPerRequest() float64 {
+ if x != nil {
+ return x.ServerPollsPerRequest
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetServerQueriesPerCpuSec() float64 {
+ if x != nil {
+ return x.ServerQueriesPerCpuSec
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetClientQueriesPerCpuSec() float64 {
+ if x != nil {
+ return x.ClientQueriesPerCpuSec
+ }
+ return 0
+}
+
+func (x *ScenarioResultSummary) GetStartTime() *timestamppb.Timestamp {
+ if x != nil {
+ return x.StartTime
+ }
+ return nil
+}
+
+func (x *ScenarioResultSummary) GetEndTime() *timestamppb.Timestamp {
+ if x != nil {
+ return x.EndTime
+ }
+ return nil
+}
+
+// Results of a single benchmark scenario.
+type ScenarioResult struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Inputs used to run the scenario.
+ Scenario *Scenario `protobuf:"bytes,1,opt,name=scenario,proto3" json:"scenario,omitempty"`
+ // Histograms from all clients merged into one histogram.
+ Latencies *HistogramData `protobuf:"bytes,2,opt,name=latencies,proto3" json:"latencies,omitempty"`
+ // Client stats for each client
+ ClientStats []*ClientStats `protobuf:"bytes,3,rep,name=client_stats,json=clientStats,proto3" json:"client_stats,omitempty"`
+ // Server stats for each server
+ ServerStats []*ServerStats `protobuf:"bytes,4,rep,name=server_stats,json=serverStats,proto3" json:"server_stats,omitempty"`
+ // Number of cores available to each server
+ ServerCores []int32 `protobuf:"varint,5,rep,packed,name=server_cores,json=serverCores,proto3" json:"server_cores,omitempty"`
+ // An after-the-fact computed summary
+ Summary *ScenarioResultSummary `protobuf:"bytes,6,opt,name=summary,proto3" json:"summary,omitempty"`
+ // Information on success or failure of each worker
+ ClientSuccess []bool `protobuf:"varint,7,rep,packed,name=client_success,json=clientSuccess,proto3" json:"client_success,omitempty"`
+ ServerSuccess []bool `protobuf:"varint,8,rep,packed,name=server_success,json=serverSuccess,proto3" json:"server_success,omitempty"`
+ // Number of failed requests (one row per status code seen)
+ RequestResults []*RequestResultCount `protobuf:"bytes,9,rep,name=request_results,json=requestResults,proto3" json:"request_results,omitempty"`
+}
+
+func (x *ScenarioResult) Reset() {
+ *x = ScenarioResult{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_control_proto_msgTypes[18]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ScenarioResult) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ScenarioResult) ProtoMessage() {}
+
+func (x *ScenarioResult) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_control_proto_msgTypes[18]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ScenarioResult.ProtoReflect.Descriptor instead.
+func (*ScenarioResult) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_control_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *ScenarioResult) GetScenario() *Scenario {
+ if x != nil {
+ return x.Scenario
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetLatencies() *HistogramData {
+ if x != nil {
+ return x.Latencies
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetClientStats() []*ClientStats {
+ if x != nil {
+ return x.ClientStats
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetServerStats() []*ServerStats {
+ if x != nil {
+ return x.ServerStats
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetServerCores() []int32 {
+ if x != nil {
+ return x.ServerCores
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetSummary() *ScenarioResultSummary {
+ if x != nil {
+ return x.Summary
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetClientSuccess() []bool {
+ if x != nil {
+ return x.ClientSuccess
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetServerSuccess() []bool {
+ if x != nil {
+ return x.ServerSuccess
+ }
+ return nil
+}
+
+func (x *ScenarioResult) GetRequestResults() []*RequestResultCount {
+ if x != nil {
+ return x.RequestResults
+ }
+ return nil
+}
+
+var File_grpc_testing_control_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_control_proto_rawDesc = []byte{
+ 0x0a, 0x1a, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x63,
+ 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x1b, 0x67, 0x72, 0x70, 0x63,
+ 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
+ 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x22, 0x32, 0x0a, 0x0d, 0x50, 0x6f, 0x69, 0x73, 0x73, 0x6f, 0x6e, 0x50, 0x61, 0x72,
+ 0x61, 0x6d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x6c,
+ 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x65, 0x64, 0x4c, 0x6f, 0x61, 0x64, 0x22, 0x12, 0x0a, 0x10, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64,
+ 0x4c, 0x6f, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x90, 0x01, 0x0a, 0x0a, 0x4c,
+ 0x6f, 0x61, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x41, 0x0a, 0x0b, 0x63, 0x6c, 0x6f,
+ 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x6f, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c,
+ 0x6f, 0x73, 0x65, 0x64, 0x4c, 0x6f, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00,
+ 0x52, 0x0a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x4c, 0x6f, 0x6f, 0x70, 0x12, 0x37, 0x0a, 0x07,
+ 0x70, 0x6f, 0x69, 0x73, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x6f, 0x69,
+ 0x73, 0x73, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52, 0x07, 0x70, 0x6f,
+ 0x69, 0x73, 0x73, 0x6f, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x7f, 0x0a,
+ 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12,
+ 0x1e, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x75, 0x73, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x12,
+ 0x30, 0x0a, 0x14, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6f,
+ 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
+ 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x72, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x22, 0x67,
+ 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x12, 0x1d, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+ 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07,
+ 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xf6, 0x07, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65,
+ 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12,
+ 0x39, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a,
+ 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0f, 0x73, 0x65,
+ 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d,
+ 0x73, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d,
+ 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x5f, 0x72, 0x70, 0x63, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
+ 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x19, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x61, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x52, 0x70, 0x63, 0x73, 0x50, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e,
+ 0x65, 0x6c, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61,
+ 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x63, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x61,
+ 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x73, 0x79, 0x6e, 0x63,
+ 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x12, 0x30, 0x0a,
+ 0x08, 0x72, 0x70, 0x63, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x15, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52,
+ 0x70, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x72, 0x70, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12,
+ 0x39, 0x0a, 0x0b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x0a,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x0a,
+ 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x70, 0x61,
+ 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0b, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+ 0x0d, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x48,
+ 0x0a, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x61,
+ 0x6d, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
+ 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x0f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72,
+ 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x72, 0x65,
+ 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x05, 0x52, 0x08, 0x63, 0x6f, 0x72,
+ 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x69,
+ 0x6d, 0x69, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x4c,
+ 0x69, 0x6d, 0x69, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x70, 0x69, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x69, 0x12, 0x3b,
+ 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x10,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x52, 0x0b,
+ 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x74,
+ 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x71, 0x18, 0x11, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x50, 0x65, 0x72, 0x43,
+ 0x71, 0x12, 0x2e, 0x0a, 0x13, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x70, 0x65,
+ 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61,
+ 0x6d, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x61, 0x6c, 0x65, 0x73, 0x63,
+ 0x65, 0x5f, 0x61, 0x70, 0x69, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65,
+ 0x43, 0x6f, 0x61, 0x6c, 0x65, 0x73, 0x63, 0x65, 0x41, 0x70, 0x69, 0x12, 0x58, 0x0a, 0x29, 0x6d,
+ 0x65, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f,
+ 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+ 0x6c, 0x5f, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x25,
+ 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x6c,
+ 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d,
+ 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73,
+ 0x22, 0x3f, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74,
+ 0x73, 0x22, 0x1c, 0x0a, 0x04, 0x4d, 0x61, 0x72, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x73,
+ 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x22,
+ 0x75, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x32, 0x0a,
+ 0x05, 0x73, 0x65, 0x74, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69, 0x65,
+ 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x05, 0x73, 0x65, 0x74, 0x75,
+ 0x70, 0x12, 0x28, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d,
+ 0x61, 0x72, 0x6b, 0x48, 0x00, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x61,
+ 0x72, 0x67, 0x74, 0x79, 0x70, 0x65, 0x22, 0xc0, 0x04, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x79,
+ 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x70,
+ 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72,
+ 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72,
+ 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72,
+ 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x30, 0x0a,
+ 0x14, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x73, 0x79,
+ 0x6e, 0x63, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x12,
+ 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x42,
+ 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
+ 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x08, 0x63, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12,
+ 0x28, 0x0a, 0x10, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
+ 0x61, 0x70, 0x69, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x70, 0x69, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x68, 0x72,
+ 0x65, 0x61, 0x64, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x71, 0x18, 0x0c, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x50, 0x65, 0x72, 0x43, 0x71, 0x12,
+ 0x2f, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x71, 0x75, 0x6f, 0x74,
+ 0x61, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x72,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x53, 0x69, 0x7a, 0x65,
+ 0x12, 0x3c, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x61, 0x72, 0x67, 0x73,
+ 0x18, 0xea, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x72,
+ 0x67, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x12, 0x29,
+ 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x75, 0x0a, 0x0a, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x41, 0x72, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x73, 0x65, 0x74, 0x75, 0x70,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x48, 0x00, 0x52, 0x05, 0x73, 0x65, 0x74, 0x75, 0x70, 0x12, 0x28, 0x0a, 0x04, 0x6d,
+ 0x61, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x48, 0x00, 0x52,
+ 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x61, 0x72, 0x67, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x69, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74,
+ 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x22, 0x0d, 0x0a, 0x0b, 0x43,
+ 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x24, 0x0a, 0x0c, 0x43, 0x6f,
+ 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f,
+ 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x72, 0x65, 0x73,
+ 0x22, 0x06, 0x0a, 0x04, 0x56, 0x6f, 0x69, 0x64, 0x22, 0xef, 0x02, 0x0a, 0x08, 0x53, 0x63, 0x65,
+ 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x0d, 0x63, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x75,
+ 0x6d, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x0a, 0x6e, 0x75, 0x6d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b,
+ 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x25, 0x0a,
+ 0x0e, 0x77, 0x61, 0x72, 0x6d, 0x75, 0x70, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x77, 0x61, 0x72, 0x6d, 0x75, 0x70, 0x53, 0x65, 0x63,
+ 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72,
+ 0x6b, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x10, 0x62, 0x65, 0x6e, 0x63, 0x68, 0x6d, 0x61, 0x72, 0x6b, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64,
+ 0x73, 0x12, 0x37, 0x0a, 0x18, 0x73, 0x70, 0x61, 0x77, 0x6e, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x15, 0x73, 0x70, 0x61, 0x77, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x57,
+ 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x41, 0x0a, 0x09, 0x53, 0x63,
+ 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x73, 0x63, 0x65, 0x6e, 0x61,
+ 0x72, 0x69, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x72, 0x70,
+ 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72,
+ 0x69, 0x6f, 0x52, 0x09, 0x73, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x73, 0x22, 0xad, 0x07,
+ 0x0a, 0x15, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
+ 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x71, 0x70, 0x73, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x71, 0x70, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x71, 0x70, 0x73,
+ 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x72, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x71, 0x70, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01,
+ 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65,
+ 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28,
+ 0x0a, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x55, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x74, 0x65,
+ 0x6e, 0x63, 0x79, 0x5f, 0x35, 0x30, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x6c, 0x61,
+ 0x74, 0x65, 0x6e, 0x63, 0x79, 0x35, 0x30, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x74, 0x65, 0x6e,
+ 0x63, 0x79, 0x5f, 0x39, 0x30, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x6c, 0x61, 0x74,
+ 0x65, 0x6e, 0x63, 0x79, 0x39, 0x30, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63,
+ 0x79, 0x5f, 0x39, 0x35, 0x18, 0x09, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x6c, 0x61, 0x74, 0x65,
+ 0x6e, 0x63, 0x79, 0x39, 0x35, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79,
+ 0x5f, 0x39, 0x39, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x6c, 0x61, 0x74, 0x65, 0x6e,
+ 0x63, 0x79, 0x39, 0x39, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f,
+ 0x39, 0x39, 0x39, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x6c, 0x61, 0x74, 0x65, 0x6e,
+ 0x63, 0x79, 0x39, 0x39, 0x39, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
+ 0x63, 0x70, 0x75, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52,
+ 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x70, 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12,
+ 0x43, 0x0a, 0x1e, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x5f, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x1b, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
+ 0x66, 0x75, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x12, 0x37, 0x0a, 0x18, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x6c,
+ 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0f, 0x20,
+ 0x01, 0x28, 0x01, 0x52, 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x6f, 0x6c, 0x6c, 0x73,
+ 0x50, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x01, 0x52, 0x15, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x6c, 0x73, 0x50, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x1a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x71, 0x75,
+ 0x65, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x73, 0x65,
+ 0x63, 0x18, 0x11, 0x20, 0x01, 0x28, 0x01, 0x52, 0x16, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x51,
+ 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x50, 0x65, 0x72, 0x43, 0x70, 0x75, 0x53, 0x65, 0x63, 0x12,
+ 0x3a, 0x0a, 0x1a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65,
+ 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x12, 0x20,
+ 0x01, 0x28, 0x01, 0x52, 0x16, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x51, 0x75, 0x65, 0x72, 0x69,
+ 0x65, 0x73, 0x50, 0x65, 0x72, 0x43, 0x70, 0x75, 0x53, 0x65, 0x63, 0x12, 0x39, 0x0a, 0x0a, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
+ 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xf6, 0x03,
+ 0x0a, 0x0e, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
+ 0x12, 0x32, 0x0a, 0x08, 0x73, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x52, 0x08, 0x73, 0x63, 0x65, 0x6e,
+ 0x61, 0x72, 0x69, 0x6f, 0x12, 0x39, 0x0a, 0x09, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x65,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+ 0x44, 0x61, 0x74, 0x61, 0x52, 0x09, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12,
+ 0x3c, 0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18,
+ 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x52, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x3c, 0x0a,
+ 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x04, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0b,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
+ 0x05, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x3d,
+ 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x23, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53,
+ 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x75, 0x6d,
+ 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x25, 0x0a,
+ 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18,
+ 0x07, 0x20, 0x03, 0x28, 0x08, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73,
+ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x49, 0x0a, 0x0f, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x09,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c,
+ 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
+ 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2a, 0x56, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x43, 0x4c, 0x49,
+ 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x43,
+ 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x54, 0x48, 0x45, 0x52,
+ 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x41, 0x4c,
+ 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x2a, 0x70,
+ 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b,
+ 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x00, 0x12, 0x10, 0x0a,
+ 0x0c, 0x41, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x01, 0x12,
+ 0x18, 0x0a, 0x14, 0x41, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x49, 0x43,
+ 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x54, 0x48,
+ 0x45, 0x52, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x43,
+ 0x41, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x04,
+ 0x2a, 0x72, 0x0a, 0x07, 0x52, 0x70, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55,
+ 0x4e, 0x41, 0x52, 0x59, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d,
+ 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x49,
+ 0x4e, 0x47, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x02,
+ 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x52,
+ 0x4f, 0x4d, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x53,
+ 0x54, 0x52, 0x45, 0x41, 0x4d, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x5f, 0x57, 0x41,
+ 0x59, 0x53, 0x10, 0x04, 0x42, 0x21, 0x0a, 0x0f, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_grpc_testing_control_proto_rawDescOnce sync.Once
+ file_grpc_testing_control_proto_rawDescData = file_grpc_testing_control_proto_rawDesc
+)
+
+func file_grpc_testing_control_proto_rawDescGZIP() []byte {
+ file_grpc_testing_control_proto_rawDescOnce.Do(func() {
+ file_grpc_testing_control_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_testing_control_proto_rawDescData)
+ })
+ return file_grpc_testing_control_proto_rawDescData
+}
+
+var file_grpc_testing_control_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
+var file_grpc_testing_control_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
+var file_grpc_testing_control_proto_goTypes = []interface{}{
+ (ClientType)(0), // 0: grpc.testing.ClientType
+ (ServerType)(0), // 1: grpc.testing.ServerType
+ (RpcType)(0), // 2: grpc.testing.RpcType
+ (*PoissonParams)(nil), // 3: grpc.testing.PoissonParams
+ (*ClosedLoopParams)(nil), // 4: grpc.testing.ClosedLoopParams
+ (*LoadParams)(nil), // 5: grpc.testing.LoadParams
+ (*SecurityParams)(nil), // 6: grpc.testing.SecurityParams
+ (*ChannelArg)(nil), // 7: grpc.testing.ChannelArg
+ (*ClientConfig)(nil), // 8: grpc.testing.ClientConfig
+ (*ClientStatus)(nil), // 9: grpc.testing.ClientStatus
+ (*Mark)(nil), // 10: grpc.testing.Mark
+ (*ClientArgs)(nil), // 11: grpc.testing.ClientArgs
+ (*ServerConfig)(nil), // 12: grpc.testing.ServerConfig
+ (*ServerArgs)(nil), // 13: grpc.testing.ServerArgs
+ (*ServerStatus)(nil), // 14: grpc.testing.ServerStatus
+ (*CoreRequest)(nil), // 15: grpc.testing.CoreRequest
+ (*CoreResponse)(nil), // 16: grpc.testing.CoreResponse
+ (*Void)(nil), // 17: grpc.testing.Void
+ (*Scenario)(nil), // 18: grpc.testing.Scenario
+ (*Scenarios)(nil), // 19: grpc.testing.Scenarios
+ (*ScenarioResultSummary)(nil), // 20: grpc.testing.ScenarioResultSummary
+ (*ScenarioResult)(nil), // 21: grpc.testing.ScenarioResult
+ (*PayloadConfig)(nil), // 22: grpc.testing.PayloadConfig
+ (*HistogramParams)(nil), // 23: grpc.testing.HistogramParams
+ (*ClientStats)(nil), // 24: grpc.testing.ClientStats
+ (*ServerStats)(nil), // 25: grpc.testing.ServerStats
+ (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp
+ (*HistogramData)(nil), // 27: grpc.testing.HistogramData
+ (*RequestResultCount)(nil), // 28: grpc.testing.RequestResultCount
+}
+var file_grpc_testing_control_proto_depIdxs = []int32{
+ 4, // 0: grpc.testing.LoadParams.closed_loop:type_name -> grpc.testing.ClosedLoopParams
+ 3, // 1: grpc.testing.LoadParams.poisson:type_name -> grpc.testing.PoissonParams
+ 0, // 2: grpc.testing.ClientConfig.client_type:type_name -> grpc.testing.ClientType
+ 6, // 3: grpc.testing.ClientConfig.security_params:type_name -> grpc.testing.SecurityParams
+ 2, // 4: grpc.testing.ClientConfig.rpc_type:type_name -> grpc.testing.RpcType
+ 5, // 5: grpc.testing.ClientConfig.load_params:type_name -> grpc.testing.LoadParams
+ 22, // 6: grpc.testing.ClientConfig.payload_config:type_name -> grpc.testing.PayloadConfig
+ 23, // 7: grpc.testing.ClientConfig.histogram_params:type_name -> grpc.testing.HistogramParams
+ 7, // 8: grpc.testing.ClientConfig.channel_args:type_name -> grpc.testing.ChannelArg
+ 24, // 9: grpc.testing.ClientStatus.stats:type_name -> grpc.testing.ClientStats
+ 8, // 10: grpc.testing.ClientArgs.setup:type_name -> grpc.testing.ClientConfig
+ 10, // 11: grpc.testing.ClientArgs.mark:type_name -> grpc.testing.Mark
+ 1, // 12: grpc.testing.ServerConfig.server_type:type_name -> grpc.testing.ServerType
+ 6, // 13: grpc.testing.ServerConfig.security_params:type_name -> grpc.testing.SecurityParams
+ 22, // 14: grpc.testing.ServerConfig.payload_config:type_name -> grpc.testing.PayloadConfig
+ 7, // 15: grpc.testing.ServerConfig.channel_args:type_name -> grpc.testing.ChannelArg
+ 12, // 16: grpc.testing.ServerArgs.setup:type_name -> grpc.testing.ServerConfig
+ 10, // 17: grpc.testing.ServerArgs.mark:type_name -> grpc.testing.Mark
+ 25, // 18: grpc.testing.ServerStatus.stats:type_name -> grpc.testing.ServerStats
+ 8, // 19: grpc.testing.Scenario.client_config:type_name -> grpc.testing.ClientConfig
+ 12, // 20: grpc.testing.Scenario.server_config:type_name -> grpc.testing.ServerConfig
+ 18, // 21: grpc.testing.Scenarios.scenarios:type_name -> grpc.testing.Scenario
+ 26, // 22: grpc.testing.ScenarioResultSummary.start_time:type_name -> google.protobuf.Timestamp
+ 26, // 23: grpc.testing.ScenarioResultSummary.end_time:type_name -> google.protobuf.Timestamp
+ 18, // 24: grpc.testing.ScenarioResult.scenario:type_name -> grpc.testing.Scenario
+ 27, // 25: grpc.testing.ScenarioResult.latencies:type_name -> grpc.testing.HistogramData
+ 24, // 26: grpc.testing.ScenarioResult.client_stats:type_name -> grpc.testing.ClientStats
+ 25, // 27: grpc.testing.ScenarioResult.server_stats:type_name -> grpc.testing.ServerStats
+ 20, // 28: grpc.testing.ScenarioResult.summary:type_name -> grpc.testing.ScenarioResultSummary
+ 28, // 29: grpc.testing.ScenarioResult.request_results:type_name -> grpc.testing.RequestResultCount
+ 30, // [30:30] is the sub-list for method output_type
+ 30, // [30:30] is the sub-list for method input_type
+ 30, // [30:30] is the sub-list for extension type_name
+ 30, // [30:30] is the sub-list for extension extendee
+ 0, // [0:30] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_control_proto_init() }
+func file_grpc_testing_control_proto_init() {
+ if File_grpc_testing_control_proto != nil {
+ return
+ }
+ file_grpc_testing_payloads_proto_init()
+ file_grpc_testing_stats_proto_init()
+ if !protoimpl.UnsafeEnabled {
+ file_grpc_testing_control_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PoissonParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClosedLoopParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SecurityParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ChannelArg); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClientConfig); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClientStatus); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Mark); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClientArgs); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ServerConfig); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ServerArgs); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ServerStatus); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CoreRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CoreResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Void); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Scenario); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Scenarios); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ScenarioResultSummary); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ScenarioResult); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ file_grpc_testing_control_proto_msgTypes[2].OneofWrappers = []interface{}{
+ (*LoadParams_ClosedLoop)(nil),
+ (*LoadParams_Poisson)(nil),
+ }
+ file_grpc_testing_control_proto_msgTypes[4].OneofWrappers = []interface{}{
+ (*ChannelArg_StrValue)(nil),
+ (*ChannelArg_IntValue)(nil),
+ }
+ file_grpc_testing_control_proto_msgTypes[8].OneofWrappers = []interface{}{
+ (*ClientArgs_Setup)(nil),
+ (*ClientArgs_Mark)(nil),
+ }
+ file_grpc_testing_control_proto_msgTypes[10].OneofWrappers = []interface{}{
+ (*ServerArgs_Setup)(nil),
+ (*ServerArgs_Mark)(nil),
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_control_proto_rawDesc,
+ NumEnums: 3,
+ NumMessages: 19,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_grpc_testing_control_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_control_proto_depIdxs,
+ EnumInfos: file_grpc_testing_control_proto_enumTypes,
+ MessageInfos: file_grpc_testing_control_proto_msgTypes,
+ }.Build()
+ File_grpc_testing_control_proto = out.File
+ file_grpc_testing_control_proto_rawDesc = nil
+ file_grpc_testing_control_proto_goTypes = nil
+ file_grpc_testing_control_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/core/stats.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/core/stats.pb.go
new file mode 100644
index 0000000000..e61bf8f5ce
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/core/stats.pb.go
@@ -0,0 +1,408 @@
+// Copyright 2017 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/core/stats.proto
+
+package core
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Bucket struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Start float64 `protobuf:"fixed64,1,opt,name=start,proto3" json:"start,omitempty"`
+ Count uint64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
+}
+
+func (x *Bucket) Reset() {
+ *x = Bucket{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_core_stats_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Bucket) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Bucket) ProtoMessage() {}
+
+func (x *Bucket) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_core_stats_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Bucket.ProtoReflect.Descriptor instead.
+func (*Bucket) Descriptor() ([]byte, []int) {
+ return file_grpc_core_stats_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Bucket) GetStart() float64 {
+ if x != nil {
+ return x.Start
+ }
+ return 0
+}
+
+func (x *Bucket) GetCount() uint64 {
+ if x != nil {
+ return x.Count
+ }
+ return 0
+}
+
+type Histogram struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Buckets []*Bucket `protobuf:"bytes,1,rep,name=buckets,proto3" json:"buckets,omitempty"`
+}
+
+func (x *Histogram) Reset() {
+ *x = Histogram{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_core_stats_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Histogram) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Histogram) ProtoMessage() {}
+
+func (x *Histogram) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_core_stats_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Histogram.ProtoReflect.Descriptor instead.
+func (*Histogram) Descriptor() ([]byte, []int) {
+ return file_grpc_core_stats_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Histogram) GetBuckets() []*Bucket {
+ if x != nil {
+ return x.Buckets
+ }
+ return nil
+}
+
+type Metric struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // Types that are assignable to Value:
+ //
+ // *Metric_Count
+ // *Metric_Histogram
+ Value isMetric_Value `protobuf_oneof:"value"`
+}
+
+func (x *Metric) Reset() {
+ *x = Metric{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_core_stats_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Metric) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Metric) ProtoMessage() {}
+
+func (x *Metric) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_core_stats_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Metric.ProtoReflect.Descriptor instead.
+func (*Metric) Descriptor() ([]byte, []int) {
+ return file_grpc_core_stats_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *Metric) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (m *Metric) GetValue() isMetric_Value {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (x *Metric) GetCount() uint64 {
+ if x, ok := x.GetValue().(*Metric_Count); ok {
+ return x.Count
+ }
+ return 0
+}
+
+func (x *Metric) GetHistogram() *Histogram {
+ if x, ok := x.GetValue().(*Metric_Histogram); ok {
+ return x.Histogram
+ }
+ return nil
+}
+
+type isMetric_Value interface {
+ isMetric_Value()
+}
+
+type Metric_Count struct {
+ Count uint64 `protobuf:"varint,10,opt,name=count,proto3,oneof"`
+}
+
+type Metric_Histogram struct {
+ Histogram *Histogram `protobuf:"bytes,11,opt,name=histogram,proto3,oneof"`
+}
+
+func (*Metric_Count) isMetric_Value() {}
+
+func (*Metric_Histogram) isMetric_Value() {}
+
+type Stats struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Metrics []*Metric `protobuf:"bytes,1,rep,name=metrics,proto3" json:"metrics,omitempty"`
+}
+
+func (x *Stats) Reset() {
+ *x = Stats{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_core_stats_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Stats) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Stats) ProtoMessage() {}
+
+func (x *Stats) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_core_stats_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Stats.ProtoReflect.Descriptor instead.
+func (*Stats) Descriptor() ([]byte, []int) {
+ return file_grpc_core_stats_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Stats) GetMetrics() []*Metric {
+ if x != nil {
+ return x.Metrics
+ }
+ return nil
+}
+
+var File_grpc_core_stats_proto protoreflect.FileDescriptor
+
+var file_grpc_core_stats_proto_rawDesc = []byte{
+ 0x0a, 0x15, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x74, 0x61, 0x74,
+ 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x63, 0x6f,
+ 0x72, 0x65, 0x22, 0x34, 0x0a, 0x06, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x09, 0x48, 0x69, 0x73, 0x74,
+ 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x2b, 0x0a, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x63, 0x6f,
+ 0x72, 0x65, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x22, 0x73, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x12, 0x16, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x48,
+ 0x00, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74,
+ 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
+ 0x6d, 0x48, 0x00, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x42, 0x07,
+ 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x34, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x12, 0x2b, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_grpc_core_stats_proto_rawDescOnce sync.Once
+ file_grpc_core_stats_proto_rawDescData = file_grpc_core_stats_proto_rawDesc
+)
+
+func file_grpc_core_stats_proto_rawDescGZIP() []byte {
+ file_grpc_core_stats_proto_rawDescOnce.Do(func() {
+ file_grpc_core_stats_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_core_stats_proto_rawDescData)
+ })
+ return file_grpc_core_stats_proto_rawDescData
+}
+
+var file_grpc_core_stats_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_grpc_core_stats_proto_goTypes = []interface{}{
+ (*Bucket)(nil), // 0: grpc.core.Bucket
+ (*Histogram)(nil), // 1: grpc.core.Histogram
+ (*Metric)(nil), // 2: grpc.core.Metric
+ (*Stats)(nil), // 3: grpc.core.Stats
+}
+var file_grpc_core_stats_proto_depIdxs = []int32{
+ 0, // 0: grpc.core.Histogram.buckets:type_name -> grpc.core.Bucket
+ 1, // 1: grpc.core.Metric.histogram:type_name -> grpc.core.Histogram
+ 2, // 2: grpc.core.Stats.metrics:type_name -> grpc.core.Metric
+ 3, // [3:3] is the sub-list for method output_type
+ 3, // [3:3] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_grpc_core_stats_proto_init() }
+func file_grpc_core_stats_proto_init() {
+ if File_grpc_core_stats_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_grpc_core_stats_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Bucket); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_core_stats_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Histogram); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_core_stats_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Metric); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_core_stats_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Stats); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ file_grpc_core_stats_proto_msgTypes[2].OneofWrappers = []interface{}{
+ (*Metric_Count)(nil),
+ (*Metric_Histogram)(nil),
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_core_stats_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 4,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_grpc_core_stats_proto_goTypes,
+ DependencyIndexes: file_grpc_core_stats_proto_depIdxs,
+ MessageInfos: file_grpc_core_stats_proto_msgTypes,
+ }.Build()
+ File_grpc_core_stats_proto = out.File
+ file_grpc_core_stats_proto_rawDesc = nil
+ file_grpc_core_stats_proto_goTypes = nil
+ file_grpc_core_stats_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/empty.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/empty.pb.go
new file mode 100644
index 0000000000..8030ccd055
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/empty.pb.go
@@ -0,0 +1,155 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/empty.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// An empty message that you can re-use to avoid defining duplicated empty
+// messages in your project. A typical example is to use it as argument or the
+// return value of a service API. For instance:
+//
+// service Foo {
+// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { };
+// };
+type Empty struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *Empty) Reset() {
+ *x = Empty{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_empty_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Empty) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Empty) ProtoMessage() {}
+
+func (x *Empty) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_empty_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
+func (*Empty) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_empty_proto_rawDescGZIP(), []int{0}
+}
+
+var File_grpc_testing_empty_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_empty_proto_rawDesc = []byte{
+ 0x0a, 0x18, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x65,
+ 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67, 0x72, 0x70, 0x63,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74,
+ 0x79, 0x42, 0x2a, 0x0a, 0x1b, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x42, 0x0b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_grpc_testing_empty_proto_rawDescOnce sync.Once
+ file_grpc_testing_empty_proto_rawDescData = file_grpc_testing_empty_proto_rawDesc
+)
+
+func file_grpc_testing_empty_proto_rawDescGZIP() []byte {
+ file_grpc_testing_empty_proto_rawDescOnce.Do(func() {
+ file_grpc_testing_empty_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_testing_empty_proto_rawDescData)
+ })
+ return file_grpc_testing_empty_proto_rawDescData
+}
+
+var file_grpc_testing_empty_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_grpc_testing_empty_proto_goTypes = []interface{}{
+ (*Empty)(nil), // 0: grpc.testing.Empty
+}
+var file_grpc_testing_empty_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_empty_proto_init() }
+func file_grpc_testing_empty_proto_init() {
+ if File_grpc_testing_empty_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_grpc_testing_empty_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Empty); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_empty_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_grpc_testing_empty_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_empty_proto_depIdxs,
+ MessageInfos: file_grpc_testing_empty_proto_msgTypes,
+ }.Build()
+ File_grpc_testing_empty_proto = out.File
+ file_grpc_testing_empty_proto_rawDesc = nil
+ file_grpc_testing_empty_proto_goTypes = nil
+ file_grpc_testing_empty_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/messages.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/messages.pb.go
new file mode 100644
index 0000000000..de3cb7affc
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/messages.pb.go
@@ -0,0 +1,2902 @@
+// Copyright 2015-2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Message definitions to be used by integration test service definitions.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/messages.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// The type of payload that should be returned.
+type PayloadType int32
+
+const (
+ // Compressable text format.
+ PayloadType_COMPRESSABLE PayloadType = 0
+)
+
+// Enum value maps for PayloadType.
+var (
+ PayloadType_name = map[int32]string{
+ 0: "COMPRESSABLE",
+ }
+ PayloadType_value = map[string]int32{
+ "COMPRESSABLE": 0,
+ }
+)
+
+func (x PayloadType) Enum() *PayloadType {
+ p := new(PayloadType)
+ *p = x
+ return p
+}
+
+func (x PayloadType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (PayloadType) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_messages_proto_enumTypes[0].Descriptor()
+}
+
+func (PayloadType) Type() protoreflect.EnumType {
+ return &file_grpc_testing_messages_proto_enumTypes[0]
+}
+
+func (x PayloadType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use PayloadType.Descriptor instead.
+func (PayloadType) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{0}
+}
+
+// The type of route that a client took to reach a server w.r.t. gRPCLB.
+// The server must fill in "fallback" if it detects that the RPC reached
+// the server via the "gRPCLB fallback" path, and "backend" if it detects
+// that the RPC reached the server via "gRPCLB backend" path (i.e. if it got
+// the address of this server from the gRPCLB server BalanceLoad RPC). Exactly
+// how this detection is done is context and server dependent.
+type GrpclbRouteType int32
+
+const (
+ // Server didn't detect the route that a client took to reach it.
+ GrpclbRouteType_GRPCLB_ROUTE_TYPE_UNKNOWN GrpclbRouteType = 0
+ // Indicates that a client reached a server via gRPCLB fallback.
+ GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK GrpclbRouteType = 1
+ // Indicates that a client reached a server as a gRPCLB-given backend.
+ GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND GrpclbRouteType = 2
+)
+
+// Enum value maps for GrpclbRouteType.
+var (
+ GrpclbRouteType_name = map[int32]string{
+ 0: "GRPCLB_ROUTE_TYPE_UNKNOWN",
+ 1: "GRPCLB_ROUTE_TYPE_FALLBACK",
+ 2: "GRPCLB_ROUTE_TYPE_BACKEND",
+ }
+ GrpclbRouteType_value = map[string]int32{
+ "GRPCLB_ROUTE_TYPE_UNKNOWN": 0,
+ "GRPCLB_ROUTE_TYPE_FALLBACK": 1,
+ "GRPCLB_ROUTE_TYPE_BACKEND": 2,
+ }
+)
+
+func (x GrpclbRouteType) Enum() *GrpclbRouteType {
+ p := new(GrpclbRouteType)
+ *p = x
+ return p
+}
+
+func (x GrpclbRouteType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (GrpclbRouteType) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_messages_proto_enumTypes[1].Descriptor()
+}
+
+func (GrpclbRouteType) Type() protoreflect.EnumType {
+ return &file_grpc_testing_messages_proto_enumTypes[1]
+}
+
+func (x GrpclbRouteType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use GrpclbRouteType.Descriptor instead.
+func (GrpclbRouteType) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{1}
+}
+
+type HookRequestCommand int32
+
+const (
+ // Start the HTTP endpoint
+ HookRequestCommand_START HookRequestCommand = 0
+ // Stop
+ HookRequestCommand_STOP HookRequestCommand = 1
+ // Return from HTTP GET/POST
+ HookRequestCommand_RETURN HookRequestCommand = 2
+)
+
+// Enum value maps for HookRequestCommand.
+var (
+ HookRequestCommand_name = map[int32]string{
+ 0: "START",
+ 1: "STOP",
+ 2: "RETURN",
+ }
+ HookRequestCommand_value = map[string]int32{
+ "START": 0,
+ "STOP": 1,
+ "RETURN": 2,
+ }
+)
+
+func (x HookRequestCommand) Enum() *HookRequestCommand {
+ p := new(HookRequestCommand)
+ *p = x
+ return p
+}
+
+func (x HookRequestCommand) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (HookRequestCommand) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_messages_proto_enumTypes[2].Descriptor()
+}
+
+func (HookRequestCommand) Type() protoreflect.EnumType {
+ return &file_grpc_testing_messages_proto_enumTypes[2]
+}
+
+func (x HookRequestCommand) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use HookRequestCommand.Descriptor instead.
+func (HookRequestCommand) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{2}
+}
+
+type LoadBalancerStatsResponse_MetadataType int32
+
+const (
+ LoadBalancerStatsResponse_Initial LoadBalancerStatsResponse_MetadataType = 0
+ LoadBalancerStatsResponse_Trailing LoadBalancerStatsResponse_MetadataType = 1
+)
+
+// Enum value maps for LoadBalancerStatsResponse_MetadataType.
+var (
+ LoadBalancerStatsResponse_MetadataType_name = map[int32]string{
+ 0: "Initial",
+ 1: "Trailing",
+ }
+ LoadBalancerStatsResponse_MetadataType_value = map[string]int32{
+ "Initial": 0,
+ "Trailing": 1,
+ }
+)
+
+func (x LoadBalancerStatsResponse_MetadataType) Enum() *LoadBalancerStatsResponse_MetadataType {
+ p := new(LoadBalancerStatsResponse_MetadataType)
+ *p = x
+ return p
+}
+
+func (x LoadBalancerStatsResponse_MetadataType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (LoadBalancerStatsResponse_MetadataType) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_messages_proto_enumTypes[3].Descriptor()
+}
+
+func (LoadBalancerStatsResponse_MetadataType) Type() protoreflect.EnumType {
+ return &file_grpc_testing_messages_proto_enumTypes[3]
+}
+
+func (x LoadBalancerStatsResponse_MetadataType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use LoadBalancerStatsResponse_MetadataType.Descriptor instead.
+func (LoadBalancerStatsResponse_MetadataType) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{13, 0}
+}
+
+// Type of RPCs to send.
+type ClientConfigureRequest_RpcType int32
+
+const (
+ ClientConfigureRequest_EMPTY_CALL ClientConfigureRequest_RpcType = 0
+ ClientConfigureRequest_UNARY_CALL ClientConfigureRequest_RpcType = 1
+)
+
+// Enum value maps for ClientConfigureRequest_RpcType.
+var (
+ ClientConfigureRequest_RpcType_name = map[int32]string{
+ 0: "EMPTY_CALL",
+ 1: "UNARY_CALL",
+ }
+ ClientConfigureRequest_RpcType_value = map[string]int32{
+ "EMPTY_CALL": 0,
+ "UNARY_CALL": 1,
+ }
+)
+
+func (x ClientConfigureRequest_RpcType) Enum() *ClientConfigureRequest_RpcType {
+ p := new(ClientConfigureRequest_RpcType)
+ *p = x
+ return p
+}
+
+func (x ClientConfigureRequest_RpcType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ClientConfigureRequest_RpcType) Descriptor() protoreflect.EnumDescriptor {
+ return file_grpc_testing_messages_proto_enumTypes[4].Descriptor()
+}
+
+func (ClientConfigureRequest_RpcType) Type() protoreflect.EnumType {
+ return &file_grpc_testing_messages_proto_enumTypes[4]
+}
+
+func (x ClientConfigureRequest_RpcType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use ClientConfigureRequest_RpcType.Descriptor instead.
+func (ClientConfigureRequest_RpcType) EnumDescriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{16, 0}
+}
+
+// TODO(dgq): Go back to using well-known types once
+// https://github.com/grpc/grpc/issues/6980 has been fixed.
+// import "google/protobuf/wrappers.proto";
+type BoolValue struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The bool value.
+ Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (x *BoolValue) Reset() {
+ *x = BoolValue{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BoolValue) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BoolValue) ProtoMessage() {}
+
+func (x *BoolValue) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BoolValue.ProtoReflect.Descriptor instead.
+func (*BoolValue) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *BoolValue) GetValue() bool {
+ if x != nil {
+ return x.Value
+ }
+ return false
+}
+
+// A block of data, to simply increase gRPC message size.
+type Payload struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The type of data in body.
+ Type PayloadType `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.testing.PayloadType" json:"type,omitempty"`
+ // Primary contents of payload.
+ Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"`
+}
+
+func (x *Payload) Reset() {
+ *x = Payload{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Payload) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Payload) ProtoMessage() {}
+
+func (x *Payload) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Payload.ProtoReflect.Descriptor instead.
+func (*Payload) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Payload) GetType() PayloadType {
+ if x != nil {
+ return x.Type
+ }
+ return PayloadType_COMPRESSABLE
+}
+
+func (x *Payload) GetBody() []byte {
+ if x != nil {
+ return x.Body
+ }
+ return nil
+}
+
+// A protobuf representation for grpc status. This is used by test
+// clients to specify a status that the server should attempt to return.
+type EchoStatus struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
+ Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
+}
+
+func (x *EchoStatus) Reset() {
+ *x = EchoStatus{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EchoStatus) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EchoStatus) ProtoMessage() {}
+
+func (x *EchoStatus) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EchoStatus.ProtoReflect.Descriptor instead.
+func (*EchoStatus) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *EchoStatus) GetCode() int32 {
+ if x != nil {
+ return x.Code
+ }
+ return 0
+}
+
+func (x *EchoStatus) GetMessage() string {
+ if x != nil {
+ return x.Message
+ }
+ return ""
+}
+
+// Unary request.
+type SimpleRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Desired payload type in the response from the server.
+ // If response_type is RANDOM, server randomly chooses one from other formats.
+ ResponseType PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,proto3,enum=grpc.testing.PayloadType" json:"response_type,omitempty"`
+ // Desired payload size in the response from the server.
+ ResponseSize int32 `protobuf:"varint,2,opt,name=response_size,json=responseSize,proto3" json:"response_size,omitempty"`
+ // Optional input payload sent along with the request.
+ Payload *Payload `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
+ // Whether SimpleResponse should include username.
+ FillUsername bool `protobuf:"varint,4,opt,name=fill_username,json=fillUsername,proto3" json:"fill_username,omitempty"`
+ // Whether SimpleResponse should include OAuth scope.
+ FillOauthScope bool `protobuf:"varint,5,opt,name=fill_oauth_scope,json=fillOauthScope,proto3" json:"fill_oauth_scope,omitempty"`
+ // Whether to request the server to compress the response. This field is
+ // "nullable" in order to interoperate seamlessly with clients not able to
+ // implement the full compression tests by introspecting the call to verify
+ // the response's compression status.
+ ResponseCompressed *BoolValue `protobuf:"bytes,6,opt,name=response_compressed,json=responseCompressed,proto3" json:"response_compressed,omitempty"`
+ // Whether server should return a given status
+ ResponseStatus *EchoStatus `protobuf:"bytes,7,opt,name=response_status,json=responseStatus,proto3" json:"response_status,omitempty"`
+ // Whether the server should expect this request to be compressed.
+ ExpectCompressed *BoolValue `protobuf:"bytes,8,opt,name=expect_compressed,json=expectCompressed,proto3" json:"expect_compressed,omitempty"`
+ // Whether SimpleResponse should include server_id.
+ FillServerId bool `protobuf:"varint,9,opt,name=fill_server_id,json=fillServerId,proto3" json:"fill_server_id,omitempty"`
+ // Whether SimpleResponse should include grpclb_route_type.
+ FillGrpclbRouteType bool `protobuf:"varint,10,opt,name=fill_grpclb_route_type,json=fillGrpclbRouteType,proto3" json:"fill_grpclb_route_type,omitempty"`
+ // If set the server should record this metrics report data for the current RPC.
+ OrcaPerQueryReport *TestOrcaReport `protobuf:"bytes,11,opt,name=orca_per_query_report,json=orcaPerQueryReport,proto3" json:"orca_per_query_report,omitempty"`
+}
+
+func (x *SimpleRequest) Reset() {
+ *x = SimpleRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SimpleRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SimpleRequest) ProtoMessage() {}
+
+func (x *SimpleRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SimpleRequest.ProtoReflect.Descriptor instead.
+func (*SimpleRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *SimpleRequest) GetResponseType() PayloadType {
+ if x != nil {
+ return x.ResponseType
+ }
+ return PayloadType_COMPRESSABLE
+}
+
+func (x *SimpleRequest) GetResponseSize() int32 {
+ if x != nil {
+ return x.ResponseSize
+ }
+ return 0
+}
+
+func (x *SimpleRequest) GetPayload() *Payload {
+ if x != nil {
+ return x.Payload
+ }
+ return nil
+}
+
+func (x *SimpleRequest) GetFillUsername() bool {
+ if x != nil {
+ return x.FillUsername
+ }
+ return false
+}
+
+func (x *SimpleRequest) GetFillOauthScope() bool {
+ if x != nil {
+ return x.FillOauthScope
+ }
+ return false
+}
+
+func (x *SimpleRequest) GetResponseCompressed() *BoolValue {
+ if x != nil {
+ return x.ResponseCompressed
+ }
+ return nil
+}
+
+func (x *SimpleRequest) GetResponseStatus() *EchoStatus {
+ if x != nil {
+ return x.ResponseStatus
+ }
+ return nil
+}
+
+func (x *SimpleRequest) GetExpectCompressed() *BoolValue {
+ if x != nil {
+ return x.ExpectCompressed
+ }
+ return nil
+}
+
+func (x *SimpleRequest) GetFillServerId() bool {
+ if x != nil {
+ return x.FillServerId
+ }
+ return false
+}
+
+func (x *SimpleRequest) GetFillGrpclbRouteType() bool {
+ if x != nil {
+ return x.FillGrpclbRouteType
+ }
+ return false
+}
+
+func (x *SimpleRequest) GetOrcaPerQueryReport() *TestOrcaReport {
+ if x != nil {
+ return x.OrcaPerQueryReport
+ }
+ return nil
+}
+
+// Unary response, as configured by the request.
+type SimpleResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Payload to increase message size.
+ Payload *Payload `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
+ // The user the request came from, for verifying authentication was
+ // successful when the client expected it.
+ Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+ // OAuth scope.
+ OauthScope string `protobuf:"bytes,3,opt,name=oauth_scope,json=oauthScope,proto3" json:"oauth_scope,omitempty"`
+ // Server ID. This must be unique among different server instances,
+ // but the same across all RPC's made to a particular server instance.
+ ServerId string `protobuf:"bytes,4,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"`
+ // gRPCLB Path.
+ GrpclbRouteType GrpclbRouteType `protobuf:"varint,5,opt,name=grpclb_route_type,json=grpclbRouteType,proto3,enum=grpc.testing.GrpclbRouteType" json:"grpclb_route_type,omitempty"`
+ // Server hostname.
+ Hostname string `protobuf:"bytes,6,opt,name=hostname,proto3" json:"hostname,omitempty"`
+}
+
+func (x *SimpleResponse) Reset() {
+ *x = SimpleResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SimpleResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SimpleResponse) ProtoMessage() {}
+
+func (x *SimpleResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SimpleResponse.ProtoReflect.Descriptor instead.
+func (*SimpleResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *SimpleResponse) GetPayload() *Payload {
+ if x != nil {
+ return x.Payload
+ }
+ return nil
+}
+
+func (x *SimpleResponse) GetUsername() string {
+ if x != nil {
+ return x.Username
+ }
+ return ""
+}
+
+func (x *SimpleResponse) GetOauthScope() string {
+ if x != nil {
+ return x.OauthScope
+ }
+ return ""
+}
+
+func (x *SimpleResponse) GetServerId() string {
+ if x != nil {
+ return x.ServerId
+ }
+ return ""
+}
+
+func (x *SimpleResponse) GetGrpclbRouteType() GrpclbRouteType {
+ if x != nil {
+ return x.GrpclbRouteType
+ }
+ return GrpclbRouteType_GRPCLB_ROUTE_TYPE_UNKNOWN
+}
+
+func (x *SimpleResponse) GetHostname() string {
+ if x != nil {
+ return x.Hostname
+ }
+ return ""
+}
+
+// Client-streaming request.
+type StreamingInputCallRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Optional input payload sent along with the request.
+ Payload *Payload `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
+ // Whether the server should expect this request to be compressed. This field
+ // is "nullable" in order to interoperate seamlessly with servers not able to
+ // implement the full compression tests by introspecting the call to verify
+ // the request's compression status.
+ ExpectCompressed *BoolValue `protobuf:"bytes,2,opt,name=expect_compressed,json=expectCompressed,proto3" json:"expect_compressed,omitempty"`
+}
+
+func (x *StreamingInputCallRequest) Reset() {
+ *x = StreamingInputCallRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *StreamingInputCallRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*StreamingInputCallRequest) ProtoMessage() {}
+
+func (x *StreamingInputCallRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use StreamingInputCallRequest.ProtoReflect.Descriptor instead.
+func (*StreamingInputCallRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *StreamingInputCallRequest) GetPayload() *Payload {
+ if x != nil {
+ return x.Payload
+ }
+ return nil
+}
+
+func (x *StreamingInputCallRequest) GetExpectCompressed() *BoolValue {
+ if x != nil {
+ return x.ExpectCompressed
+ }
+ return nil
+}
+
+// Client-streaming response.
+type StreamingInputCallResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Aggregated size of payloads received from the client.
+ AggregatedPayloadSize int32 `protobuf:"varint,1,opt,name=aggregated_payload_size,json=aggregatedPayloadSize,proto3" json:"aggregated_payload_size,omitempty"`
+}
+
+func (x *StreamingInputCallResponse) Reset() {
+ *x = StreamingInputCallResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *StreamingInputCallResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*StreamingInputCallResponse) ProtoMessage() {}
+
+func (x *StreamingInputCallResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use StreamingInputCallResponse.ProtoReflect.Descriptor instead.
+func (*StreamingInputCallResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *StreamingInputCallResponse) GetAggregatedPayloadSize() int32 {
+ if x != nil {
+ return x.AggregatedPayloadSize
+ }
+ return 0
+}
+
+// Configuration for a particular response.
+type ResponseParameters struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Desired payload sizes in responses from the server.
+ Size int32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"`
+ // Desired interval between consecutive responses in the response stream in
+ // microseconds.
+ IntervalUs int32 `protobuf:"varint,2,opt,name=interval_us,json=intervalUs,proto3" json:"interval_us,omitempty"`
+ // Whether to request the server to compress the response. This field is
+ // "nullable" in order to interoperate seamlessly with clients not able to
+ // implement the full compression tests by introspecting the call to verify
+ // the response's compression status.
+ Compressed *BoolValue `protobuf:"bytes,3,opt,name=compressed,proto3" json:"compressed,omitempty"`
+}
+
+func (x *ResponseParameters) Reset() {
+ *x = ResponseParameters{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ResponseParameters) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ResponseParameters) ProtoMessage() {}
+
+func (x *ResponseParameters) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ResponseParameters.ProtoReflect.Descriptor instead.
+func (*ResponseParameters) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ResponseParameters) GetSize() int32 {
+ if x != nil {
+ return x.Size
+ }
+ return 0
+}
+
+func (x *ResponseParameters) GetIntervalUs() int32 {
+ if x != nil {
+ return x.IntervalUs
+ }
+ return 0
+}
+
+func (x *ResponseParameters) GetCompressed() *BoolValue {
+ if x != nil {
+ return x.Compressed
+ }
+ return nil
+}
+
+// Server-streaming request.
+type StreamingOutputCallRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Desired payload type in the response from the server.
+ // If response_type is RANDOM, the payload from each response in the stream
+ // might be of different types. This is to simulate a mixed type of payload
+ // stream.
+ ResponseType PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,proto3,enum=grpc.testing.PayloadType" json:"response_type,omitempty"`
+ // Configuration for each expected response message.
+ ResponseParameters []*ResponseParameters `protobuf:"bytes,2,rep,name=response_parameters,json=responseParameters,proto3" json:"response_parameters,omitempty"`
+ // Optional input payload sent along with the request.
+ Payload *Payload `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
+ // Whether server should return a given status
+ ResponseStatus *EchoStatus `protobuf:"bytes,7,opt,name=response_status,json=responseStatus,proto3" json:"response_status,omitempty"`
+ // If set the server should update this metrics report data at the OOB server.
+ OrcaOobReport *TestOrcaReport `protobuf:"bytes,8,opt,name=orca_oob_report,json=orcaOobReport,proto3" json:"orca_oob_report,omitempty"`
+}
+
+func (x *StreamingOutputCallRequest) Reset() {
+ *x = StreamingOutputCallRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *StreamingOutputCallRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*StreamingOutputCallRequest) ProtoMessage() {}
+
+func (x *StreamingOutputCallRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use StreamingOutputCallRequest.ProtoReflect.Descriptor instead.
+func (*StreamingOutputCallRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *StreamingOutputCallRequest) GetResponseType() PayloadType {
+ if x != nil {
+ return x.ResponseType
+ }
+ return PayloadType_COMPRESSABLE
+}
+
+func (x *StreamingOutputCallRequest) GetResponseParameters() []*ResponseParameters {
+ if x != nil {
+ return x.ResponseParameters
+ }
+ return nil
+}
+
+func (x *StreamingOutputCallRequest) GetPayload() *Payload {
+ if x != nil {
+ return x.Payload
+ }
+ return nil
+}
+
+func (x *StreamingOutputCallRequest) GetResponseStatus() *EchoStatus {
+ if x != nil {
+ return x.ResponseStatus
+ }
+ return nil
+}
+
+func (x *StreamingOutputCallRequest) GetOrcaOobReport() *TestOrcaReport {
+ if x != nil {
+ return x.OrcaOobReport
+ }
+ return nil
+}
+
+// Server-streaming response, as configured by the request and parameters.
+type StreamingOutputCallResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Payload to increase response size.
+ Payload *Payload `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
+}
+
+func (x *StreamingOutputCallResponse) Reset() {
+ *x = StreamingOutputCallResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *StreamingOutputCallResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*StreamingOutputCallResponse) ProtoMessage() {}
+
+func (x *StreamingOutputCallResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use StreamingOutputCallResponse.ProtoReflect.Descriptor instead.
+func (*StreamingOutputCallResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *StreamingOutputCallResponse) GetPayload() *Payload {
+ if x != nil {
+ return x.Payload
+ }
+ return nil
+}
+
+// For reconnect interop test only.
+// Client tells server what reconnection parameters it used.
+type ReconnectParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ MaxReconnectBackoffMs int32 `protobuf:"varint,1,opt,name=max_reconnect_backoff_ms,json=maxReconnectBackoffMs,proto3" json:"max_reconnect_backoff_ms,omitempty"`
+}
+
+func (x *ReconnectParams) Reset() {
+ *x = ReconnectParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ReconnectParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReconnectParams) ProtoMessage() {}
+
+func (x *ReconnectParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[10]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReconnectParams.ProtoReflect.Descriptor instead.
+func (*ReconnectParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *ReconnectParams) GetMaxReconnectBackoffMs() int32 {
+ if x != nil {
+ return x.MaxReconnectBackoffMs
+ }
+ return 0
+}
+
+// For reconnect interop test only.
+// Server tells client whether its reconnects are following the spec and the
+// reconnect backoffs it saw.
+type ReconnectInfo struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Passed bool `protobuf:"varint,1,opt,name=passed,proto3" json:"passed,omitempty"`
+ BackoffMs []int32 `protobuf:"varint,2,rep,packed,name=backoff_ms,json=backoffMs,proto3" json:"backoff_ms,omitempty"`
+}
+
+func (x *ReconnectInfo) Reset() {
+ *x = ReconnectInfo{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ReconnectInfo) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReconnectInfo) ProtoMessage() {}
+
+func (x *ReconnectInfo) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[11]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReconnectInfo.ProtoReflect.Descriptor instead.
+func (*ReconnectInfo) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *ReconnectInfo) GetPassed() bool {
+ if x != nil {
+ return x.Passed
+ }
+ return false
+}
+
+func (x *ReconnectInfo) GetBackoffMs() []int32 {
+ if x != nil {
+ return x.BackoffMs
+ }
+ return nil
+}
+
+type LoadBalancerStatsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Request stats for the next num_rpcs sent by client.
+ NumRpcs int32 `protobuf:"varint,1,opt,name=num_rpcs,json=numRpcs,proto3" json:"num_rpcs,omitempty"`
+ // If num_rpcs have not completed within timeout_sec, return partial results.
+ TimeoutSec int32 `protobuf:"varint,2,opt,name=timeout_sec,json=timeoutSec,proto3" json:"timeout_sec,omitempty"`
+ // Response header + trailer metadata entries we want the values of.
+ // Matching of the keys is case-insensitive as per rfc7540#section-8.1.2
+ // * (asterisk) is a special value that will return all metadata entries
+ MetadataKeys []string `protobuf:"bytes,3,rep,name=metadata_keys,json=metadataKeys,proto3" json:"metadata_keys,omitempty"`
+}
+
+func (x *LoadBalancerStatsRequest) Reset() {
+ *x = LoadBalancerStatsRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerStatsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerStatsRequest) ProtoMessage() {}
+
+func (x *LoadBalancerStatsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[12]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerStatsRequest.ProtoReflect.Descriptor instead.
+func (*LoadBalancerStatsRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *LoadBalancerStatsRequest) GetNumRpcs() int32 {
+ if x != nil {
+ return x.NumRpcs
+ }
+ return 0
+}
+
+func (x *LoadBalancerStatsRequest) GetTimeoutSec() int32 {
+ if x != nil {
+ return x.TimeoutSec
+ }
+ return 0
+}
+
+func (x *LoadBalancerStatsRequest) GetMetadataKeys() []string {
+ if x != nil {
+ return x.MetadataKeys
+ }
+ return nil
+}
+
+type LoadBalancerStatsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The number of completed RPCs for each peer.
+ RpcsByPeer map[string]int32 `protobuf:"bytes,1,rep,name=rpcs_by_peer,json=rpcsByPeer,proto3" json:"rpcs_by_peer,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ // The number of RPCs that failed to record a remote peer.
+ NumFailures int32 `protobuf:"varint,2,opt,name=num_failures,json=numFailures,proto3" json:"num_failures,omitempty"`
+ RpcsByMethod map[string]*LoadBalancerStatsResponse_RpcsByPeer `protobuf:"bytes,3,rep,name=rpcs_by_method,json=rpcsByMethod,proto3" json:"rpcs_by_method,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ // All the metadata of all RPCs for each peer.
+ MetadatasByPeer map[string]*LoadBalancerStatsResponse_MetadataByPeer `protobuf:"bytes,4,rep,name=metadatas_by_peer,json=metadatasByPeer,proto3" json:"metadatas_by_peer,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+}
+
+func (x *LoadBalancerStatsResponse) Reset() {
+ *x = LoadBalancerStatsResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerStatsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerStatsResponse) ProtoMessage() {}
+
+func (x *LoadBalancerStatsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[13]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerStatsResponse.ProtoReflect.Descriptor instead.
+func (*LoadBalancerStatsResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *LoadBalancerStatsResponse) GetRpcsByPeer() map[string]int32 {
+ if x != nil {
+ return x.RpcsByPeer
+ }
+ return nil
+}
+
+func (x *LoadBalancerStatsResponse) GetNumFailures() int32 {
+ if x != nil {
+ return x.NumFailures
+ }
+ return 0
+}
+
+func (x *LoadBalancerStatsResponse) GetRpcsByMethod() map[string]*LoadBalancerStatsResponse_RpcsByPeer {
+ if x != nil {
+ return x.RpcsByMethod
+ }
+ return nil
+}
+
+func (x *LoadBalancerStatsResponse) GetMetadatasByPeer() map[string]*LoadBalancerStatsResponse_MetadataByPeer {
+ if x != nil {
+ return x.MetadatasByPeer
+ }
+ return nil
+}
+
+// Request for retrieving a test client's accumulated stats.
+type LoadBalancerAccumulatedStatsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *LoadBalancerAccumulatedStatsRequest) Reset() {
+ *x = LoadBalancerAccumulatedStatsRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[14]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerAccumulatedStatsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerAccumulatedStatsRequest) ProtoMessage() {}
+
+func (x *LoadBalancerAccumulatedStatsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[14]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerAccumulatedStatsRequest.ProtoReflect.Descriptor instead.
+func (*LoadBalancerAccumulatedStatsRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{14}
+}
+
+// Accumulated stats for RPCs sent by a test client.
+type LoadBalancerAccumulatedStatsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The total number of RPCs have ever issued for each type.
+ // Deprecated: use stats_per_method.rpcs_started instead.
+ //
+ // Deprecated: Marked as deprecated in grpc/testing/messages.proto.
+ NumRpcsStartedByMethod map[string]int32 `protobuf:"bytes,1,rep,name=num_rpcs_started_by_method,json=numRpcsStartedByMethod,proto3" json:"num_rpcs_started_by_method,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ // The total number of RPCs have ever completed successfully for each type.
+ // Deprecated: use stats_per_method.result instead.
+ //
+ // Deprecated: Marked as deprecated in grpc/testing/messages.proto.
+ NumRpcsSucceededByMethod map[string]int32 `protobuf:"bytes,2,rep,name=num_rpcs_succeeded_by_method,json=numRpcsSucceededByMethod,proto3" json:"num_rpcs_succeeded_by_method,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ // The total number of RPCs have ever failed for each type.
+ // Deprecated: use stats_per_method.result instead.
+ //
+ // Deprecated: Marked as deprecated in grpc/testing/messages.proto.
+ NumRpcsFailedByMethod map[string]int32 `protobuf:"bytes,3,rep,name=num_rpcs_failed_by_method,json=numRpcsFailedByMethod,proto3" json:"num_rpcs_failed_by_method,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ // Per-method RPC statistics. The key is the RpcType in string form; e.g.
+ // 'EMPTY_CALL' or 'UNARY_CALL'
+ StatsPerMethod map[string]*LoadBalancerAccumulatedStatsResponse_MethodStats `protobuf:"bytes,4,rep,name=stats_per_method,json=statsPerMethod,proto3" json:"stats_per_method,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+}
+
+func (x *LoadBalancerAccumulatedStatsResponse) Reset() {
+ *x = LoadBalancerAccumulatedStatsResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[15]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerAccumulatedStatsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerAccumulatedStatsResponse) ProtoMessage() {}
+
+func (x *LoadBalancerAccumulatedStatsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[15]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerAccumulatedStatsResponse.ProtoReflect.Descriptor instead.
+func (*LoadBalancerAccumulatedStatsResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{15}
+}
+
+// Deprecated: Marked as deprecated in grpc/testing/messages.proto.
+func (x *LoadBalancerAccumulatedStatsResponse) GetNumRpcsStartedByMethod() map[string]int32 {
+ if x != nil {
+ return x.NumRpcsStartedByMethod
+ }
+ return nil
+}
+
+// Deprecated: Marked as deprecated in grpc/testing/messages.proto.
+func (x *LoadBalancerAccumulatedStatsResponse) GetNumRpcsSucceededByMethod() map[string]int32 {
+ if x != nil {
+ return x.NumRpcsSucceededByMethod
+ }
+ return nil
+}
+
+// Deprecated: Marked as deprecated in grpc/testing/messages.proto.
+func (x *LoadBalancerAccumulatedStatsResponse) GetNumRpcsFailedByMethod() map[string]int32 {
+ if x != nil {
+ return x.NumRpcsFailedByMethod
+ }
+ return nil
+}
+
+func (x *LoadBalancerAccumulatedStatsResponse) GetStatsPerMethod() map[string]*LoadBalancerAccumulatedStatsResponse_MethodStats {
+ if x != nil {
+ return x.StatsPerMethod
+ }
+ return nil
+}
+
+// Configurations for a test client.
+type ClientConfigureRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The types of RPCs the client sends.
+ Types []ClientConfigureRequest_RpcType `protobuf:"varint,1,rep,packed,name=types,proto3,enum=grpc.testing.ClientConfigureRequest_RpcType" json:"types,omitempty"`
+ // The collection of custom metadata to be attached to RPCs sent by the client.
+ Metadata []*ClientConfigureRequest_Metadata `protobuf:"bytes,2,rep,name=metadata,proto3" json:"metadata,omitempty"`
+ // The deadline to use, in seconds, for all RPCs. If unset or zero, the
+ // client will use the default from the command-line.
+ TimeoutSec int32 `protobuf:"varint,3,opt,name=timeout_sec,json=timeoutSec,proto3" json:"timeout_sec,omitempty"`
+}
+
+func (x *ClientConfigureRequest) Reset() {
+ *x = ClientConfigureRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[16]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClientConfigureRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientConfigureRequest) ProtoMessage() {}
+
+func (x *ClientConfigureRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[16]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientConfigureRequest.ProtoReflect.Descriptor instead.
+func (*ClientConfigureRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *ClientConfigureRequest) GetTypes() []ClientConfigureRequest_RpcType {
+ if x != nil {
+ return x.Types
+ }
+ return nil
+}
+
+func (x *ClientConfigureRequest) GetMetadata() []*ClientConfigureRequest_Metadata {
+ if x != nil {
+ return x.Metadata
+ }
+ return nil
+}
+
+func (x *ClientConfigureRequest) GetTimeoutSec() int32 {
+ if x != nil {
+ return x.TimeoutSec
+ }
+ return 0
+}
+
+// Response for updating a test client's configuration.
+type ClientConfigureResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *ClientConfigureResponse) Reset() {
+ *x = ClientConfigureResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[17]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClientConfigureResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientConfigureResponse) ProtoMessage() {}
+
+func (x *ClientConfigureResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[17]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientConfigureResponse.ProtoReflect.Descriptor instead.
+func (*ClientConfigureResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{17}
+}
+
+type MemorySize struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Rss int64 `protobuf:"varint,1,opt,name=rss,proto3" json:"rss,omitempty"`
+}
+
+func (x *MemorySize) Reset() {
+ *x = MemorySize{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[18]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *MemorySize) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MemorySize) ProtoMessage() {}
+
+func (x *MemorySize) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[18]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use MemorySize.ProtoReflect.Descriptor instead.
+func (*MemorySize) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *MemorySize) GetRss() int64 {
+ if x != nil {
+ return x.Rss
+ }
+ return 0
+}
+
+// Metrics data the server will update and send to the client. It mirrors orca load report
+// https://github.com/cncf/xds/blob/eded343319d09f30032952beda9840bbd3dcf7ac/xds/data/orca/v3/orca_load_report.proto#L15,
+// but avoids orca dependency. Used by both per-query and out-of-band reporting tests.
+type TestOrcaReport struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ CpuUtilization float64 `protobuf:"fixed64,1,opt,name=cpu_utilization,json=cpuUtilization,proto3" json:"cpu_utilization,omitempty"`
+ MemoryUtilization float64 `protobuf:"fixed64,2,opt,name=memory_utilization,json=memoryUtilization,proto3" json:"memory_utilization,omitempty"`
+ RequestCost map[string]float64 `protobuf:"bytes,3,rep,name=request_cost,json=requestCost,proto3" json:"request_cost,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"fixed64,2,opt,name=value,proto3"`
+ Utilization map[string]float64 `protobuf:"bytes,4,rep,name=utilization,proto3" json:"utilization,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"fixed64,2,opt,name=value,proto3"`
+}
+
+func (x *TestOrcaReport) Reset() {
+ *x = TestOrcaReport{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[19]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TestOrcaReport) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TestOrcaReport) ProtoMessage() {}
+
+func (x *TestOrcaReport) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[19]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TestOrcaReport.ProtoReflect.Descriptor instead.
+func (*TestOrcaReport) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *TestOrcaReport) GetCpuUtilization() float64 {
+ if x != nil {
+ return x.CpuUtilization
+ }
+ return 0
+}
+
+func (x *TestOrcaReport) GetMemoryUtilization() float64 {
+ if x != nil {
+ return x.MemoryUtilization
+ }
+ return 0
+}
+
+func (x *TestOrcaReport) GetRequestCost() map[string]float64 {
+ if x != nil {
+ return x.RequestCost
+ }
+ return nil
+}
+
+func (x *TestOrcaReport) GetUtilization() map[string]float64 {
+ if x != nil {
+ return x.Utilization
+ }
+ return nil
+}
+
+type HookRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Command HookRequestCommand `protobuf:"varint,1,opt,name=command,proto3,enum=grpc.testing.HookRequestCommand" json:"command,omitempty"`
+ GrpcCodeToReturn int32 `protobuf:"varint,2,opt,name=grpc_code_to_return,json=grpcCodeToReturn,proto3" json:"grpc_code_to_return,omitempty"`
+ GrpcStatusDescription string `protobuf:"bytes,3,opt,name=grpc_status_description,json=grpcStatusDescription,proto3" json:"grpc_status_description,omitempty"`
+ // Server port to listen to
+ ServerPort int32 `protobuf:"varint,4,opt,name=server_port,json=serverPort,proto3" json:"server_port,omitempty"`
+}
+
+func (x *HookRequest) Reset() {
+ *x = HookRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[20]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HookRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HookRequest) ProtoMessage() {}
+
+func (x *HookRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[20]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HookRequest.ProtoReflect.Descriptor instead.
+func (*HookRequest) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *HookRequest) GetCommand() HookRequestCommand {
+ if x != nil {
+ return x.Command
+ }
+ return HookRequestCommand_START
+}
+
+func (x *HookRequest) GetGrpcCodeToReturn() int32 {
+ if x != nil {
+ return x.GrpcCodeToReturn
+ }
+ return 0
+}
+
+func (x *HookRequest) GetGrpcStatusDescription() string {
+ if x != nil {
+ return x.GrpcStatusDescription
+ }
+ return ""
+}
+
+func (x *HookRequest) GetServerPort() int32 {
+ if x != nil {
+ return x.ServerPort
+ }
+ return 0
+}
+
+type HookResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *HookResponse) Reset() {
+ *x = HookResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[21]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HookResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HookResponse) ProtoMessage() {}
+
+func (x *HookResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[21]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HookResponse.ProtoReflect.Descriptor instead.
+func (*HookResponse) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{21}
+}
+
+type LoadBalancerStatsResponse_MetadataEntry struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Key, exactly as received from the server. Case may be different from what
+ // was requested in the LoadBalancerStatsRequest)
+ Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // Value, exactly as received from the server.
+ Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+ // Metadata type is either Initial or Trailing
+ Type LoadBalancerStatsResponse_MetadataType `protobuf:"varint,3,opt,name=type,proto3,enum=grpc.testing.LoadBalancerStatsResponse_MetadataType" json:"type,omitempty"`
+}
+
+func (x *LoadBalancerStatsResponse_MetadataEntry) Reset() {
+ *x = LoadBalancerStatsResponse_MetadataEntry{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[22]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerStatsResponse_MetadataEntry) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerStatsResponse_MetadataEntry) ProtoMessage() {}
+
+func (x *LoadBalancerStatsResponse_MetadataEntry) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[22]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerStatsResponse_MetadataEntry.ProtoReflect.Descriptor instead.
+func (*LoadBalancerStatsResponse_MetadataEntry) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{13, 0}
+}
+
+func (x *LoadBalancerStatsResponse_MetadataEntry) GetKey() string {
+ if x != nil {
+ return x.Key
+ }
+ return ""
+}
+
+func (x *LoadBalancerStatsResponse_MetadataEntry) GetValue() string {
+ if x != nil {
+ return x.Value
+ }
+ return ""
+}
+
+func (x *LoadBalancerStatsResponse_MetadataEntry) GetType() LoadBalancerStatsResponse_MetadataType {
+ if x != nil {
+ return x.Type
+ }
+ return LoadBalancerStatsResponse_Initial
+}
+
+type LoadBalancerStatsResponse_RpcMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // metadata values for each rpc for the keys specified in
+ // LoadBalancerStatsRequest.metadata_keys.
+ Metadata []*LoadBalancerStatsResponse_MetadataEntry `protobuf:"bytes,1,rep,name=metadata,proto3" json:"metadata,omitempty"`
+}
+
+func (x *LoadBalancerStatsResponse_RpcMetadata) Reset() {
+ *x = LoadBalancerStatsResponse_RpcMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[23]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerStatsResponse_RpcMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerStatsResponse_RpcMetadata) ProtoMessage() {}
+
+func (x *LoadBalancerStatsResponse_RpcMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[23]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerStatsResponse_RpcMetadata.ProtoReflect.Descriptor instead.
+func (*LoadBalancerStatsResponse_RpcMetadata) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{13, 1}
+}
+
+func (x *LoadBalancerStatsResponse_RpcMetadata) GetMetadata() []*LoadBalancerStatsResponse_MetadataEntry {
+ if x != nil {
+ return x.Metadata
+ }
+ return nil
+}
+
+type LoadBalancerStatsResponse_MetadataByPeer struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of RpcMetadata in for each RPC with a given peer
+ RpcMetadata []*LoadBalancerStatsResponse_RpcMetadata `protobuf:"bytes,1,rep,name=rpc_metadata,json=rpcMetadata,proto3" json:"rpc_metadata,omitempty"`
+}
+
+func (x *LoadBalancerStatsResponse_MetadataByPeer) Reset() {
+ *x = LoadBalancerStatsResponse_MetadataByPeer{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[24]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerStatsResponse_MetadataByPeer) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerStatsResponse_MetadataByPeer) ProtoMessage() {}
+
+func (x *LoadBalancerStatsResponse_MetadataByPeer) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[24]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerStatsResponse_MetadataByPeer.ProtoReflect.Descriptor instead.
+func (*LoadBalancerStatsResponse_MetadataByPeer) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{13, 2}
+}
+
+func (x *LoadBalancerStatsResponse_MetadataByPeer) GetRpcMetadata() []*LoadBalancerStatsResponse_RpcMetadata {
+ if x != nil {
+ return x.RpcMetadata
+ }
+ return nil
+}
+
+type LoadBalancerStatsResponse_RpcsByPeer struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The number of completed RPCs for each peer.
+ RpcsByPeer map[string]int32 `protobuf:"bytes,1,rep,name=rpcs_by_peer,json=rpcsByPeer,proto3" json:"rpcs_by_peer,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+}
+
+func (x *LoadBalancerStatsResponse_RpcsByPeer) Reset() {
+ *x = LoadBalancerStatsResponse_RpcsByPeer{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[25]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerStatsResponse_RpcsByPeer) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerStatsResponse_RpcsByPeer) ProtoMessage() {}
+
+func (x *LoadBalancerStatsResponse_RpcsByPeer) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[25]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerStatsResponse_RpcsByPeer.ProtoReflect.Descriptor instead.
+func (*LoadBalancerStatsResponse_RpcsByPeer) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{13, 3}
+}
+
+func (x *LoadBalancerStatsResponse_RpcsByPeer) GetRpcsByPeer() map[string]int32 {
+ if x != nil {
+ return x.RpcsByPeer
+ }
+ return nil
+}
+
+type LoadBalancerAccumulatedStatsResponse_MethodStats struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The number of RPCs that were started for this method.
+ RpcsStarted int32 `protobuf:"varint,1,opt,name=rpcs_started,json=rpcsStarted,proto3" json:"rpcs_started,omitempty"`
+ // The number of RPCs that completed with each status for this method. The
+ // key is the integral value of a google.rpc.Code; the value is the count.
+ Result map[int32]int32 `protobuf:"bytes,2,rep,name=result,proto3" json:"result,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+}
+
+func (x *LoadBalancerAccumulatedStatsResponse_MethodStats) Reset() {
+ *x = LoadBalancerAccumulatedStatsResponse_MethodStats{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[33]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadBalancerAccumulatedStatsResponse_MethodStats) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadBalancerAccumulatedStatsResponse_MethodStats) ProtoMessage() {}
+
+func (x *LoadBalancerAccumulatedStatsResponse_MethodStats) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[33]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadBalancerAccumulatedStatsResponse_MethodStats.ProtoReflect.Descriptor instead.
+func (*LoadBalancerAccumulatedStatsResponse_MethodStats) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{15, 3}
+}
+
+func (x *LoadBalancerAccumulatedStatsResponse_MethodStats) GetRpcsStarted() int32 {
+ if x != nil {
+ return x.RpcsStarted
+ }
+ return 0
+}
+
+func (x *LoadBalancerAccumulatedStatsResponse_MethodStats) GetResult() map[int32]int32 {
+ if x != nil {
+ return x.Result
+ }
+ return nil
+}
+
+// Metadata to be attached for the given type of RPCs.
+type ClientConfigureRequest_Metadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Type ClientConfigureRequest_RpcType `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.testing.ClientConfigureRequest_RpcType" json:"type,omitempty"`
+ Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
+ Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (x *ClientConfigureRequest_Metadata) Reset() {
+ *x = ClientConfigureRequest_Metadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_messages_proto_msgTypes[36]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClientConfigureRequest_Metadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientConfigureRequest_Metadata) ProtoMessage() {}
+
+func (x *ClientConfigureRequest_Metadata) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_messages_proto_msgTypes[36]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientConfigureRequest_Metadata.ProtoReflect.Descriptor instead.
+func (*ClientConfigureRequest_Metadata) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_messages_proto_rawDescGZIP(), []int{16, 0}
+}
+
+func (x *ClientConfigureRequest_Metadata) GetType() ClientConfigureRequest_RpcType {
+ if x != nil {
+ return x.Type
+ }
+ return ClientConfigureRequest_EMPTY_CALL
+}
+
+func (x *ClientConfigureRequest_Metadata) GetKey() string {
+ if x != nil {
+ return x.Key
+ }
+ return ""
+}
+
+func (x *ClientConfigureRequest_Metadata) GetValue() string {
+ if x != nil {
+ return x.Value
+ }
+ return ""
+}
+
+var File_grpc_testing_messages_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_messages_proto_rawDesc = []byte{
+ 0x0a, 0x1b, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x21, 0x0a, 0x09, 0x42,
+ 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4c,
+ 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79,
+ 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x3a, 0x0a, 0x0a,
+ 0x45, 0x63, 0x68, 0x6f, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f,
+ 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18,
+ 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xf3, 0x04, 0x0a, 0x0d, 0x53, 0x69, 0x6d,
+ 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67,
+ 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12,
+ 0x2f, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x15, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
+ 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x69, 0x6c, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x69, 0x6c, 0x6c, 0x55, 0x73, 0x65,
+ 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x6c, 0x5f, 0x6f, 0x61,
+ 0x75, 0x74, 0x68, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0e, 0x66, 0x69, 0x6c, 0x6c, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12,
+ 0x48, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70,
+ 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x6f, 0x6f, 0x6c,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43,
+ 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0f, 0x72, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x72, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x44, 0x0a, 0x11,
+ 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65,
+ 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x52, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x69, 0x6c, 0x6c,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x66, 0x69, 0x6c, 0x6c,
+ 0x5f, 0x67, 0x72, 0x70, 0x63, 0x6c, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x79,
+ 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x66, 0x69, 0x6c, 0x6c, 0x47, 0x72,
+ 0x70, 0x63, 0x6c, 0x62, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x4f, 0x0a,
+ 0x15, 0x6f, 0x72, 0x63, 0x61, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f,
+ 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x65, 0x73, 0x74,
+ 0x4f, 0x72, 0x63, 0x61, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x12, 0x6f, 0x72, 0x63, 0x61,
+ 0x50, 0x65, 0x72, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x82,
+ 0x02, 0x0a, 0x0e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f,
+ 0x61, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12,
+ 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x49, 0x0a, 0x11,
+ 0x67, 0x72, 0x70, 0x63, 0x6c, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70,
+ 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x72, 0x70, 0x63, 0x6c, 0x62, 0x52, 0x6f, 0x75,
+ 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x67, 0x72, 0x70, 0x63, 0x6c, 0x62, 0x52, 0x6f,
+ 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e,
+ 0x61, 0x6d, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x19, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e,
+ 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f,
+ 0x61, 0x64, 0x12, 0x44, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6d,
+ 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
+ 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x6f, 0x6f,
+ 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f,
+ 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x22, 0x54, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x65,
+ 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67,
+ 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x69, 0x7a,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
+ 0x74, 0x65, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x82,
+ 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d,
+ 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x55, 0x73, 0x12, 0x37, 0x0a, 0x0a, 0x63, 0x6f,
+ 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x6f,
+ 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73,
+ 0x73, 0x65, 0x64, 0x22, 0xe9, 0x02, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e,
+ 0x67, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74,
+ 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
+ 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x12, 0x51, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x70,
+ 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
+ 0x73, 0x52, 0x12, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d,
+ 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x07, 0x70,
+ 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x41, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45,
+ 0x63, 0x68, 0x6f, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x44, 0x0a, 0x0f, 0x6f, 0x72, 0x63,
+ 0x61, 0x5f, 0x6f, 0x6f, 0x62, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x63, 0x61, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
+ 0x52, 0x0d, 0x6f, 0x72, 0x63, 0x61, 0x4f, 0x6f, 0x62, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22,
+ 0x4e, 0x0a, 0x1b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70,
+ 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f,
+ 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x15, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x50,
+ 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22,
+ 0x4a, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x61, 0x72, 0x61,
+ 0x6d, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e,
+ 0x65, 0x63, 0x74, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, 0x6d, 0x73, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
+ 0x63, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x4d, 0x73, 0x22, 0x46, 0x0a, 0x0d, 0x52,
+ 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06,
+ 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f,
+ 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x52, 0x09, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66,
+ 0x66, 0x4d, 0x73, 0x22, 0x7b, 0x0a, 0x18, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e,
+ 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x19, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x70, 0x63, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x07, 0x6e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x69,
+ 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x12, 0x23, 0x0a, 0x0d, 0x6d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x73,
+ 0x22, 0xc3, 0x09, 0x0a, 0x19, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
+ 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59,
+ 0x0a, 0x0c, 0x72, 0x70, 0x63, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x70,
+ 0x63, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72,
+ 0x70, 0x63, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x75, 0x6d,
+ 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x0b, 0x6e, 0x75, 0x6d, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x0e,
+ 0x72, 0x70, 0x63, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x70,
+ 0x63, 0x73, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
+ 0x0c, 0x72, 0x70, 0x63, 0x73, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x68, 0x0a,
+ 0x11, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x65,
+ 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61,
+ 0x6e, 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65,
+ 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x1a, 0x81, 0x01, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x12, 0x48, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c,
+ 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+ 0x61, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x1a, 0x60, 0x0a, 0x0b, 0x52,
+ 0x70, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x51, 0x0a, 0x08, 0x6d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64,
+ 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e,
+ 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x68, 0x0a,
+ 0x0e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x12,
+ 0x56, 0x0a, 0x0c, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18,
+ 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
+ 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52,
+ 0x70, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x72, 0x70, 0x63, 0x4d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0xb1, 0x01, 0x0a, 0x0a, 0x52, 0x70, 0x63, 0x73,
+ 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x12, 0x64, 0x0a, 0x0c, 0x72, 0x70, 0x63, 0x73, 0x5f, 0x62,
+ 0x79, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64,
+ 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72,
+ 0x2e, 0x52, 0x70, 0x63, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79,
+ 0x52, 0x0a, 0x72, 0x70, 0x63, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x1a, 0x3d, 0x0a, 0x0f,
+ 0x52, 0x70, 0x63, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+ 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+ 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x52,
+ 0x70, 0x63, 0x73, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
+ 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
+ 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x73, 0x0a, 0x11, 0x52, 0x70,
+ 0x63, 0x73, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+ 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+ 0x79, 0x12, 0x48, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
+ 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x73, 0x42, 0x79,
+ 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a,
+ 0x7a, 0x0a, 0x14, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x73, 0x42, 0x79, 0x50, 0x65,
+ 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4c, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61,
+ 0x6e, 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x79, 0x50, 0x65, 0x65, 0x72,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x29, 0x0a, 0x0c, 0x4d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49,
+ 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x54, 0x72, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x22, 0x25, 0x0a, 0x23, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61,
+ 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65,
+ 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x86, 0x09,
+ 0x0a, 0x24, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63,
+ 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1a, 0x6e, 0x75, 0x6d, 0x5f, 0x72,
+ 0x70, 0x63, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x6d,
+ 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4e, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42,
+ 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e,
+ 0x4e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79,
+ 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x02, 0x18, 0x01, 0x52,
+ 0x16, 0x6e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x42,
+ 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x94, 0x01, 0x0a, 0x1c, 0x6e, 0x75, 0x6d, 0x5f,
+ 0x72, 0x70, 0x63, 0x73, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x5f, 0x62,
+ 0x79, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x50,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f,
+ 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63, 0x63, 0x75, 0x6d, 0x75,
+ 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x2e, 0x4e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x53, 0x75, 0x63, 0x63, 0x65, 0x65,
+ 0x64, 0x65, 0x64, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79,
+ 0x42, 0x02, 0x18, 0x01, 0x52, 0x18, 0x6e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x53, 0x75, 0x63,
+ 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x8b,
+ 0x01, 0x0a, 0x19, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x70, 0x63, 0x73, 0x5f, 0x66, 0x61, 0x69, 0x6c,
+ 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x4d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63,
+ 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x46, 0x61,
+ 0x69, 0x6c, 0x65, 0x64, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72,
+ 0x79, 0x42, 0x02, 0x18, 0x01, 0x52, 0x15, 0x6e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x46, 0x61,
+ 0x69, 0x6c, 0x65, 0x64, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x70, 0x0a, 0x10,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
+ 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
+ 0x65, 0x72, 0x41, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61,
+ 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x50, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x50, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x1a, 0x49,
+ 0x0a, 0x1b, 0x4e, 0x75, 0x6d, 0x52, 0x70, 0x63, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64,
+ 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
+ 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
+ 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4b, 0x0a, 0x1d, 0x4e, 0x75, 0x6d,
+ 0x52, 0x70, 0x63, 0x73, 0x53, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x42, 0x79, 0x4d,
+ 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x48, 0x0a, 0x1a, 0x4e, 0x75, 0x6d, 0x52, 0x70, 0x63,
+ 0x73, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x42, 0x79, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45,
+ 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
+ 0x1a, 0xcf, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x70, 0x63, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x72, 0x70, 0x63, 0x73, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x65, 0x64, 0x12, 0x62, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x4a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41,
+ 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x74,
+ 0x61, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
+ 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x75, 0x6c,
+ 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
+ 0x38, 0x01, 0x1a, 0x81, 0x01, 0x0a, 0x13, 0x53, 0x74, 0x61, 0x74, 0x73, 0x50, 0x65, 0x72, 0x4d,
+ 0x65, 0x74, 0x68, 0x6f, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42,
+ 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74,
+ 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e,
+ 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe9, 0x02, 0x0a, 0x16, 0x43, 0x6c, 0x69, 0x65, 0x6e,
+ 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x42, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e,
+ 0x32, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x70, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05,
+ 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
+ 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65,
+ 0x63, 0x1a, 0x74, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a,
+ 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e,
+ 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x2e, 0x52, 0x70, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
+ 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+ 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x29, 0x0a, 0x07, 0x52, 0x70, 0x63, 0x54, 0x79,
+ 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x5f, 0x43, 0x41, 0x4c, 0x4c,
+ 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x43, 0x41, 0x4c, 0x4c,
+ 0x10, 0x01, 0x22, 0x19, 0x0a, 0x17, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x0a,
+ 0x0a, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72,
+ 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x72, 0x73, 0x73, 0x22, 0x8b, 0x03,
+ 0x0a, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x63, 0x61, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
+ 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x70, 0x75, 0x5f, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x63, 0x70, 0x75, 0x55, 0x74,
+ 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x6d, 0x65, 0x6d,
+ 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x11, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x74, 0x69,
+ 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x65,
+ 0x73, 0x74, 0x4f, 0x72, 0x63, 0x61, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x72,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0b, 0x75, 0x74,
+ 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x54,
+ 0x65, 0x73, 0x74, 0x4f, 0x72, 0x63, 0x61, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x55, 0x74,
+ 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b,
+ 0x75, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x3e, 0x0a, 0x10, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+ 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+ 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3e, 0x0a, 0x10, 0x55,
+ 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+ 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+ 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd1, 0x01, 0x0a, 0x0b,
+ 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x07, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x48, 0x6f, 0x6f, 0x6b,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x07,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x2d, 0x0a, 0x13, 0x67, 0x72, 0x70, 0x63, 0x5f,
+ 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x67, 0x72, 0x70, 0x63, 0x43, 0x6f, 0x64, 0x65, 0x54, 0x6f,
+ 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x73,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x67, 0x72, 0x70, 0x63, 0x53, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x22,
+ 0x0e, 0x0a, 0x0c, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a,
+ 0x1f, 0x0a, 0x0b, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10,
+ 0x0a, 0x0c, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x00,
+ 0x2a, 0x6f, 0x0a, 0x0f, 0x47, 0x72, 0x70, 0x63, 0x6c, 0x62, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x52, 0x50, 0x43, 0x4c, 0x42, 0x5f, 0x52, 0x4f,
+ 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
+ 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x47, 0x52, 0x50, 0x43, 0x4c, 0x42, 0x5f, 0x52, 0x4f, 0x55,
+ 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x41, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b,
+ 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x47, 0x52, 0x50, 0x43, 0x4c, 0x42, 0x5f, 0x52, 0x4f, 0x55,
+ 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x10,
+ 0x02, 0x2a, 0x35, 0x0a, 0x12, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x54,
+ 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06,
+ 0x52, 0x45, 0x54, 0x55, 0x52, 0x4e, 0x10, 0x02, 0x42, 0x1d, 0x0a, 0x1b, 0x69, 0x6f, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x69, 0x6e, 0x74, 0x65,
+ 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_grpc_testing_messages_proto_rawDescOnce sync.Once
+ file_grpc_testing_messages_proto_rawDescData = file_grpc_testing_messages_proto_rawDesc
+)
+
+func file_grpc_testing_messages_proto_rawDescGZIP() []byte {
+ file_grpc_testing_messages_proto_rawDescOnce.Do(func() {
+ file_grpc_testing_messages_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_testing_messages_proto_rawDescData)
+ })
+ return file_grpc_testing_messages_proto_rawDescData
+}
+
+var file_grpc_testing_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
+var file_grpc_testing_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 39)
+var file_grpc_testing_messages_proto_goTypes = []interface{}{
+ (PayloadType)(0), // 0: grpc.testing.PayloadType
+ (GrpclbRouteType)(0), // 1: grpc.testing.GrpclbRouteType
+ (HookRequestCommand)(0), // 2: grpc.testing.HookRequestCommand
+ (LoadBalancerStatsResponse_MetadataType)(0), // 3: grpc.testing.LoadBalancerStatsResponse.MetadataType
+ (ClientConfigureRequest_RpcType)(0), // 4: grpc.testing.ClientConfigureRequest.RpcType
+ (*BoolValue)(nil), // 5: grpc.testing.BoolValue
+ (*Payload)(nil), // 6: grpc.testing.Payload
+ (*EchoStatus)(nil), // 7: grpc.testing.EchoStatus
+ (*SimpleRequest)(nil), // 8: grpc.testing.SimpleRequest
+ (*SimpleResponse)(nil), // 9: grpc.testing.SimpleResponse
+ (*StreamingInputCallRequest)(nil), // 10: grpc.testing.StreamingInputCallRequest
+ (*StreamingInputCallResponse)(nil), // 11: grpc.testing.StreamingInputCallResponse
+ (*ResponseParameters)(nil), // 12: grpc.testing.ResponseParameters
+ (*StreamingOutputCallRequest)(nil), // 13: grpc.testing.StreamingOutputCallRequest
+ (*StreamingOutputCallResponse)(nil), // 14: grpc.testing.StreamingOutputCallResponse
+ (*ReconnectParams)(nil), // 15: grpc.testing.ReconnectParams
+ (*ReconnectInfo)(nil), // 16: grpc.testing.ReconnectInfo
+ (*LoadBalancerStatsRequest)(nil), // 17: grpc.testing.LoadBalancerStatsRequest
+ (*LoadBalancerStatsResponse)(nil), // 18: grpc.testing.LoadBalancerStatsResponse
+ (*LoadBalancerAccumulatedStatsRequest)(nil), // 19: grpc.testing.LoadBalancerAccumulatedStatsRequest
+ (*LoadBalancerAccumulatedStatsResponse)(nil), // 20: grpc.testing.LoadBalancerAccumulatedStatsResponse
+ (*ClientConfigureRequest)(nil), // 21: grpc.testing.ClientConfigureRequest
+ (*ClientConfigureResponse)(nil), // 22: grpc.testing.ClientConfigureResponse
+ (*MemorySize)(nil), // 23: grpc.testing.MemorySize
+ (*TestOrcaReport)(nil), // 24: grpc.testing.TestOrcaReport
+ (*HookRequest)(nil), // 25: grpc.testing.HookRequest
+ (*HookResponse)(nil), // 26: grpc.testing.HookResponse
+ (*LoadBalancerStatsResponse_MetadataEntry)(nil), // 27: grpc.testing.LoadBalancerStatsResponse.MetadataEntry
+ (*LoadBalancerStatsResponse_RpcMetadata)(nil), // 28: grpc.testing.LoadBalancerStatsResponse.RpcMetadata
+ (*LoadBalancerStatsResponse_MetadataByPeer)(nil), // 29: grpc.testing.LoadBalancerStatsResponse.MetadataByPeer
+ (*LoadBalancerStatsResponse_RpcsByPeer)(nil), // 30: grpc.testing.LoadBalancerStatsResponse.RpcsByPeer
+ nil, // 31: grpc.testing.LoadBalancerStatsResponse.RpcsByPeerEntry
+ nil, // 32: grpc.testing.LoadBalancerStatsResponse.RpcsByMethodEntry
+ nil, // 33: grpc.testing.LoadBalancerStatsResponse.MetadatasByPeerEntry
+ nil, // 34: grpc.testing.LoadBalancerStatsResponse.RpcsByPeer.RpcsByPeerEntry
+ nil, // 35: grpc.testing.LoadBalancerAccumulatedStatsResponse.NumRpcsStartedByMethodEntry
+ nil, // 36: grpc.testing.LoadBalancerAccumulatedStatsResponse.NumRpcsSucceededByMethodEntry
+ nil, // 37: grpc.testing.LoadBalancerAccumulatedStatsResponse.NumRpcsFailedByMethodEntry
+ (*LoadBalancerAccumulatedStatsResponse_MethodStats)(nil), // 38: grpc.testing.LoadBalancerAccumulatedStatsResponse.MethodStats
+ nil, // 39: grpc.testing.LoadBalancerAccumulatedStatsResponse.StatsPerMethodEntry
+ nil, // 40: grpc.testing.LoadBalancerAccumulatedStatsResponse.MethodStats.ResultEntry
+ (*ClientConfigureRequest_Metadata)(nil), // 41: grpc.testing.ClientConfigureRequest.Metadata
+ nil, // 42: grpc.testing.TestOrcaReport.RequestCostEntry
+ nil, // 43: grpc.testing.TestOrcaReport.UtilizationEntry
+}
+var file_grpc_testing_messages_proto_depIdxs = []int32{
+ 0, // 0: grpc.testing.Payload.type:type_name -> grpc.testing.PayloadType
+ 0, // 1: grpc.testing.SimpleRequest.response_type:type_name -> grpc.testing.PayloadType
+ 6, // 2: grpc.testing.SimpleRequest.payload:type_name -> grpc.testing.Payload
+ 5, // 3: grpc.testing.SimpleRequest.response_compressed:type_name -> grpc.testing.BoolValue
+ 7, // 4: grpc.testing.SimpleRequest.response_status:type_name -> grpc.testing.EchoStatus
+ 5, // 5: grpc.testing.SimpleRequest.expect_compressed:type_name -> grpc.testing.BoolValue
+ 24, // 6: grpc.testing.SimpleRequest.orca_per_query_report:type_name -> grpc.testing.TestOrcaReport
+ 6, // 7: grpc.testing.SimpleResponse.payload:type_name -> grpc.testing.Payload
+ 1, // 8: grpc.testing.SimpleResponse.grpclb_route_type:type_name -> grpc.testing.GrpclbRouteType
+ 6, // 9: grpc.testing.StreamingInputCallRequest.payload:type_name -> grpc.testing.Payload
+ 5, // 10: grpc.testing.StreamingInputCallRequest.expect_compressed:type_name -> grpc.testing.BoolValue
+ 5, // 11: grpc.testing.ResponseParameters.compressed:type_name -> grpc.testing.BoolValue
+ 0, // 12: grpc.testing.StreamingOutputCallRequest.response_type:type_name -> grpc.testing.PayloadType
+ 12, // 13: grpc.testing.StreamingOutputCallRequest.response_parameters:type_name -> grpc.testing.ResponseParameters
+ 6, // 14: grpc.testing.StreamingOutputCallRequest.payload:type_name -> grpc.testing.Payload
+ 7, // 15: grpc.testing.StreamingOutputCallRequest.response_status:type_name -> grpc.testing.EchoStatus
+ 24, // 16: grpc.testing.StreamingOutputCallRequest.orca_oob_report:type_name -> grpc.testing.TestOrcaReport
+ 6, // 17: grpc.testing.StreamingOutputCallResponse.payload:type_name -> grpc.testing.Payload
+ 31, // 18: grpc.testing.LoadBalancerStatsResponse.rpcs_by_peer:type_name -> grpc.testing.LoadBalancerStatsResponse.RpcsByPeerEntry
+ 32, // 19: grpc.testing.LoadBalancerStatsResponse.rpcs_by_method:type_name -> grpc.testing.LoadBalancerStatsResponse.RpcsByMethodEntry
+ 33, // 20: grpc.testing.LoadBalancerStatsResponse.metadatas_by_peer:type_name -> grpc.testing.LoadBalancerStatsResponse.MetadatasByPeerEntry
+ 35, // 21: grpc.testing.LoadBalancerAccumulatedStatsResponse.num_rpcs_started_by_method:type_name -> grpc.testing.LoadBalancerAccumulatedStatsResponse.NumRpcsStartedByMethodEntry
+ 36, // 22: grpc.testing.LoadBalancerAccumulatedStatsResponse.num_rpcs_succeeded_by_method:type_name -> grpc.testing.LoadBalancerAccumulatedStatsResponse.NumRpcsSucceededByMethodEntry
+ 37, // 23: grpc.testing.LoadBalancerAccumulatedStatsResponse.num_rpcs_failed_by_method:type_name -> grpc.testing.LoadBalancerAccumulatedStatsResponse.NumRpcsFailedByMethodEntry
+ 39, // 24: grpc.testing.LoadBalancerAccumulatedStatsResponse.stats_per_method:type_name -> grpc.testing.LoadBalancerAccumulatedStatsResponse.StatsPerMethodEntry
+ 4, // 25: grpc.testing.ClientConfigureRequest.types:type_name -> grpc.testing.ClientConfigureRequest.RpcType
+ 41, // 26: grpc.testing.ClientConfigureRequest.metadata:type_name -> grpc.testing.ClientConfigureRequest.Metadata
+ 42, // 27: grpc.testing.TestOrcaReport.request_cost:type_name -> grpc.testing.TestOrcaReport.RequestCostEntry
+ 43, // 28: grpc.testing.TestOrcaReport.utilization:type_name -> grpc.testing.TestOrcaReport.UtilizationEntry
+ 2, // 29: grpc.testing.HookRequest.command:type_name -> grpc.testing.HookRequestCommand
+ 3, // 30: grpc.testing.LoadBalancerStatsResponse.MetadataEntry.type:type_name -> grpc.testing.LoadBalancerStatsResponse.MetadataType
+ 27, // 31: grpc.testing.LoadBalancerStatsResponse.RpcMetadata.metadata:type_name -> grpc.testing.LoadBalancerStatsResponse.MetadataEntry
+ 28, // 32: grpc.testing.LoadBalancerStatsResponse.MetadataByPeer.rpc_metadata:type_name -> grpc.testing.LoadBalancerStatsResponse.RpcMetadata
+ 34, // 33: grpc.testing.LoadBalancerStatsResponse.RpcsByPeer.rpcs_by_peer:type_name -> grpc.testing.LoadBalancerStatsResponse.RpcsByPeer.RpcsByPeerEntry
+ 30, // 34: grpc.testing.LoadBalancerStatsResponse.RpcsByMethodEntry.value:type_name -> grpc.testing.LoadBalancerStatsResponse.RpcsByPeer
+ 29, // 35: grpc.testing.LoadBalancerStatsResponse.MetadatasByPeerEntry.value:type_name -> grpc.testing.LoadBalancerStatsResponse.MetadataByPeer
+ 40, // 36: grpc.testing.LoadBalancerAccumulatedStatsResponse.MethodStats.result:type_name -> grpc.testing.LoadBalancerAccumulatedStatsResponse.MethodStats.ResultEntry
+ 38, // 37: grpc.testing.LoadBalancerAccumulatedStatsResponse.StatsPerMethodEntry.value:type_name -> grpc.testing.LoadBalancerAccumulatedStatsResponse.MethodStats
+ 4, // 38: grpc.testing.ClientConfigureRequest.Metadata.type:type_name -> grpc.testing.ClientConfigureRequest.RpcType
+ 39, // [39:39] is the sub-list for method output_type
+ 39, // [39:39] is the sub-list for method input_type
+ 39, // [39:39] is the sub-list for extension type_name
+ 39, // [39:39] is the sub-list for extension extendee
+ 0, // [0:39] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_messages_proto_init() }
+func file_grpc_testing_messages_proto_init() {
+ if File_grpc_testing_messages_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_grpc_testing_messages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*BoolValue); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Payload); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*EchoStatus); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SimpleRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SimpleResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*StreamingInputCallRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*StreamingInputCallResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ResponseParameters); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*StreamingOutputCallRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*StreamingOutputCallResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ReconnectParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ReconnectInfo); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerStatsRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerStatsResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerAccumulatedStatsRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerAccumulatedStatsResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClientConfigureRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClientConfigureResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*MemorySize); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TestOrcaReport); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HookRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HookResponse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerStatsResponse_MetadataEntry); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerStatsResponse_RpcMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerStatsResponse_MetadataByPeer); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerStatsResponse_RpcsByPeer); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LoadBalancerAccumulatedStatsResponse_MethodStats); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_messages_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClientConfigureRequest_Metadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_messages_proto_rawDesc,
+ NumEnums: 5,
+ NumMessages: 39,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_grpc_testing_messages_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_messages_proto_depIdxs,
+ EnumInfos: file_grpc_testing_messages_proto_enumTypes,
+ MessageInfos: file_grpc_testing_messages_proto_msgTypes,
+ }.Build()
+ File_grpc_testing_messages_proto = out.File
+ file_grpc_testing_messages_proto_rawDesc = nil
+ file_grpc_testing_messages_proto_goTypes = nil
+ file_grpc_testing_messages_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/payloads.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/payloads.pb.go
new file mode 100644
index 0000000000..684fd10273
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/payloads.pb.go
@@ -0,0 +1,425 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/payloads.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type ByteBufferParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ReqSize int32 `protobuf:"varint,1,opt,name=req_size,json=reqSize,proto3" json:"req_size,omitempty"`
+ RespSize int32 `protobuf:"varint,2,opt,name=resp_size,json=respSize,proto3" json:"resp_size,omitempty"`
+}
+
+func (x *ByteBufferParams) Reset() {
+ *x = ByteBufferParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ByteBufferParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ByteBufferParams) ProtoMessage() {}
+
+func (x *ByteBufferParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ByteBufferParams.ProtoReflect.Descriptor instead.
+func (*ByteBufferParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_payloads_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ByteBufferParams) GetReqSize() int32 {
+ if x != nil {
+ return x.ReqSize
+ }
+ return 0
+}
+
+func (x *ByteBufferParams) GetRespSize() int32 {
+ if x != nil {
+ return x.RespSize
+ }
+ return 0
+}
+
+type SimpleProtoParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ReqSize int32 `protobuf:"varint,1,opt,name=req_size,json=reqSize,proto3" json:"req_size,omitempty"`
+ RespSize int32 `protobuf:"varint,2,opt,name=resp_size,json=respSize,proto3" json:"resp_size,omitempty"`
+}
+
+func (x *SimpleProtoParams) Reset() {
+ *x = SimpleProtoParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SimpleProtoParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SimpleProtoParams) ProtoMessage() {}
+
+func (x *SimpleProtoParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SimpleProtoParams.ProtoReflect.Descriptor instead.
+func (*SimpleProtoParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_payloads_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *SimpleProtoParams) GetReqSize() int32 {
+ if x != nil {
+ return x.ReqSize
+ }
+ return 0
+}
+
+func (x *SimpleProtoParams) GetRespSize() int32 {
+ if x != nil {
+ return x.RespSize
+ }
+ return 0
+}
+
+type ComplexProtoParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *ComplexProtoParams) Reset() {
+ *x = ComplexProtoParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ComplexProtoParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ComplexProtoParams) ProtoMessage() {}
+
+func (x *ComplexProtoParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ComplexProtoParams.ProtoReflect.Descriptor instead.
+func (*ComplexProtoParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_payloads_proto_rawDescGZIP(), []int{2}
+}
+
+type PayloadConfig struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Types that are assignable to Payload:
+ //
+ // *PayloadConfig_BytebufParams
+ // *PayloadConfig_SimpleParams
+ // *PayloadConfig_ComplexParams
+ Payload isPayloadConfig_Payload `protobuf_oneof:"payload"`
+}
+
+func (x *PayloadConfig) Reset() {
+ *x = PayloadConfig{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PayloadConfig) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PayloadConfig) ProtoMessage() {}
+
+func (x *PayloadConfig) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_payloads_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PayloadConfig.ProtoReflect.Descriptor instead.
+func (*PayloadConfig) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_payloads_proto_rawDescGZIP(), []int{3}
+}
+
+func (m *PayloadConfig) GetPayload() isPayloadConfig_Payload {
+ if m != nil {
+ return m.Payload
+ }
+ return nil
+}
+
+func (x *PayloadConfig) GetBytebufParams() *ByteBufferParams {
+ if x, ok := x.GetPayload().(*PayloadConfig_BytebufParams); ok {
+ return x.BytebufParams
+ }
+ return nil
+}
+
+func (x *PayloadConfig) GetSimpleParams() *SimpleProtoParams {
+ if x, ok := x.GetPayload().(*PayloadConfig_SimpleParams); ok {
+ return x.SimpleParams
+ }
+ return nil
+}
+
+func (x *PayloadConfig) GetComplexParams() *ComplexProtoParams {
+ if x, ok := x.GetPayload().(*PayloadConfig_ComplexParams); ok {
+ return x.ComplexParams
+ }
+ return nil
+}
+
+type isPayloadConfig_Payload interface {
+ isPayloadConfig_Payload()
+}
+
+type PayloadConfig_BytebufParams struct {
+ BytebufParams *ByteBufferParams `protobuf:"bytes,1,opt,name=bytebuf_params,json=bytebufParams,proto3,oneof"`
+}
+
+type PayloadConfig_SimpleParams struct {
+ SimpleParams *SimpleProtoParams `protobuf:"bytes,2,opt,name=simple_params,json=simpleParams,proto3,oneof"`
+}
+
+type PayloadConfig_ComplexParams struct {
+ ComplexParams *ComplexProtoParams `protobuf:"bytes,3,opt,name=complex_params,json=complexParams,proto3,oneof"`
+}
+
+func (*PayloadConfig_BytebufParams) isPayloadConfig_Payload() {}
+
+func (*PayloadConfig_SimpleParams) isPayloadConfig_Payload() {}
+
+func (*PayloadConfig_ComplexParams) isPayloadConfig_Payload() {}
+
+var File_grpc_testing_payloads_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_payloads_proto_rawDesc = []byte{
+ 0x0a, 0x1b, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x70,
+ 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x4a, 0x0a, 0x10, 0x42,
+ 0x79, 0x74, 0x65, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12,
+ 0x19, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x07, 0x72, 0x65, 0x71, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65,
+ 0x73, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72,
+ 0x65, 0x73, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x4b, 0x0a, 0x11, 0x53, 0x69, 0x6d, 0x70, 0x6c,
+ 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x19, 0x0a, 0x08,
+ 0x72, 0x65, 0x71, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07,
+ 0x72, 0x65, 0x71, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x5f,
+ 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70,
+ 0x53, 0x69, 0x7a, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x50,
+ 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0xf6, 0x01, 0x0a, 0x0d, 0x50,
+ 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x47, 0x0a, 0x0e,
+ 0x62, 0x79, 0x74, 0x65, 0x62, 0x75, 0x66, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x50, 0x61,
+ 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52, 0x0d, 0x62, 0x79, 0x74, 0x65, 0x62, 0x75, 0x66, 0x50,
+ 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x46, 0x0a, 0x0d, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x5f,
+ 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70,
+ 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52,
+ 0x0c, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x49, 0x0a,
+ 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x48, 0x00, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x6c,
+ 0x65, 0x78, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c,
+ 0x6f, 0x61, 0x64, 0x42, 0x22, 0x0a, 0x0f, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x0d, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_grpc_testing_payloads_proto_rawDescOnce sync.Once
+ file_grpc_testing_payloads_proto_rawDescData = file_grpc_testing_payloads_proto_rawDesc
+)
+
+func file_grpc_testing_payloads_proto_rawDescGZIP() []byte {
+ file_grpc_testing_payloads_proto_rawDescOnce.Do(func() {
+ file_grpc_testing_payloads_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_testing_payloads_proto_rawDescData)
+ })
+ return file_grpc_testing_payloads_proto_rawDescData
+}
+
+var file_grpc_testing_payloads_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_grpc_testing_payloads_proto_goTypes = []interface{}{
+ (*ByteBufferParams)(nil), // 0: grpc.testing.ByteBufferParams
+ (*SimpleProtoParams)(nil), // 1: grpc.testing.SimpleProtoParams
+ (*ComplexProtoParams)(nil), // 2: grpc.testing.ComplexProtoParams
+ (*PayloadConfig)(nil), // 3: grpc.testing.PayloadConfig
+}
+var file_grpc_testing_payloads_proto_depIdxs = []int32{
+ 0, // 0: grpc.testing.PayloadConfig.bytebuf_params:type_name -> grpc.testing.ByteBufferParams
+ 1, // 1: grpc.testing.PayloadConfig.simple_params:type_name -> grpc.testing.SimpleProtoParams
+ 2, // 2: grpc.testing.PayloadConfig.complex_params:type_name -> grpc.testing.ComplexProtoParams
+ 3, // [3:3] is the sub-list for method output_type
+ 3, // [3:3] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_payloads_proto_init() }
+func file_grpc_testing_payloads_proto_init() {
+ if File_grpc_testing_payloads_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_grpc_testing_payloads_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ByteBufferParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_payloads_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SimpleProtoParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_payloads_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ComplexProtoParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_payloads_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PayloadConfig); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ file_grpc_testing_payloads_proto_msgTypes[3].OneofWrappers = []interface{}{
+ (*PayloadConfig_BytebufParams)(nil),
+ (*PayloadConfig_SimpleParams)(nil),
+ (*PayloadConfig_ComplexParams)(nil),
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_payloads_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 4,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_grpc_testing_payloads_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_payloads_proto_depIdxs,
+ MessageInfos: file_grpc_testing_payloads_proto_msgTypes,
+ }.Build()
+ File_grpc_testing_payloads_proto = out.File
+ file_grpc_testing_payloads_proto_rawDesc = nil
+ file_grpc_testing_payloads_proto_goTypes = nil
+ file_grpc_testing_payloads_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/report_qps_scenario_service.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/report_qps_scenario_service.pb.go
new file mode 100644
index 0000000000..3660677148
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/report_qps_scenario_service.pb.go
@@ -0,0 +1,97 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/report_qps_scenario_service.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+var File_grpc_testing_report_qps_scenario_service_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_report_qps_scenario_service_proto_rawDesc = []byte{
+ 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x72,
+ 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x71, 0x70, 0x73, 0x5f, 0x73, 0x63, 0x65, 0x6e, 0x61, 0x72,
+ 0x69, 0x6f, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x12, 0x0c, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x1a,
+ 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f, 0x6e,
+ 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x5e, 0x0a, 0x18, 0x52, 0x65,
+ 0x70, 0x6f, 0x72, 0x74, 0x51, 0x70, 0x73, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74,
+ 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x12, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f,
+ 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x56, 0x6f, 0x69, 0x64, 0x42, 0x32, 0x0a, 0x0f, 0x69, 0x6f,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x1d, 0x52,
+ 0x65, 0x70, 0x6f, 0x72, 0x74, 0x51, 0x70, 0x73, 0x53, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f,
+ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var file_grpc_testing_report_qps_scenario_service_proto_goTypes = []interface{}{
+ (*ScenarioResult)(nil), // 0: grpc.testing.ScenarioResult
+ (*Void)(nil), // 1: grpc.testing.Void
+}
+var file_grpc_testing_report_qps_scenario_service_proto_depIdxs = []int32{
+ 0, // 0: grpc.testing.ReportQpsScenarioService.ReportScenario:input_type -> grpc.testing.ScenarioResult
+ 1, // 1: grpc.testing.ReportQpsScenarioService.ReportScenario:output_type -> grpc.testing.Void
+ 1, // [1:2] is the sub-list for method output_type
+ 0, // [0:1] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_report_qps_scenario_service_proto_init() }
+func file_grpc_testing_report_qps_scenario_service_proto_init() {
+ if File_grpc_testing_report_qps_scenario_service_proto != nil {
+ return
+ }
+ file_grpc_testing_control_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_report_qps_scenario_service_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 0,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_grpc_testing_report_qps_scenario_service_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_report_qps_scenario_service_proto_depIdxs,
+ }.Build()
+ File_grpc_testing_report_qps_scenario_service_proto = out.File
+ file_grpc_testing_report_qps_scenario_service_proto_rawDesc = nil
+ file_grpc_testing_report_qps_scenario_service_proto_goTypes = nil
+ file_grpc_testing_report_qps_scenario_service_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/report_qps_scenario_service_grpc.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/report_qps_scenario_service_grpc.pb.go
new file mode 100644
index 0000000000..33392bc6ae
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/report_qps_scenario_service_grpc.pb.go
@@ -0,0 +1,129 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc v4.22.0
+// source: grpc/testing/report_qps_scenario_service.proto
+
+package grpc_testing
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+const (
+ ReportQpsScenarioService_ReportScenario_FullMethodName = "/grpc.testing.ReportQpsScenarioService/ReportScenario"
+)
+
+// ReportQpsScenarioServiceClient is the client API for ReportQpsScenarioService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type ReportQpsScenarioServiceClient interface {
+ // Report results of a QPS test benchmark scenario.
+ ReportScenario(ctx context.Context, in *ScenarioResult, opts ...grpc.CallOption) (*Void, error)
+}
+
+type reportQpsScenarioServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewReportQpsScenarioServiceClient(cc grpc.ClientConnInterface) ReportQpsScenarioServiceClient {
+ return &reportQpsScenarioServiceClient{cc}
+}
+
+func (c *reportQpsScenarioServiceClient) ReportScenario(ctx context.Context, in *ScenarioResult, opts ...grpc.CallOption) (*Void, error) {
+ out := new(Void)
+ err := c.cc.Invoke(ctx, ReportQpsScenarioService_ReportScenario_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// ReportQpsScenarioServiceServer is the server API for ReportQpsScenarioService service.
+// All implementations must embed UnimplementedReportQpsScenarioServiceServer
+// for forward compatibility
+type ReportQpsScenarioServiceServer interface {
+ // Report results of a QPS test benchmark scenario.
+ ReportScenario(context.Context, *ScenarioResult) (*Void, error)
+ mustEmbedUnimplementedReportQpsScenarioServiceServer()
+}
+
+// UnimplementedReportQpsScenarioServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedReportQpsScenarioServiceServer struct {
+}
+
+func (UnimplementedReportQpsScenarioServiceServer) ReportScenario(context.Context, *ScenarioResult) (*Void, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ReportScenario not implemented")
+}
+func (UnimplementedReportQpsScenarioServiceServer) mustEmbedUnimplementedReportQpsScenarioServiceServer() {
+}
+
+// UnsafeReportQpsScenarioServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to ReportQpsScenarioServiceServer will
+// result in compilation errors.
+type UnsafeReportQpsScenarioServiceServer interface {
+ mustEmbedUnimplementedReportQpsScenarioServiceServer()
+}
+
+func RegisterReportQpsScenarioServiceServer(s grpc.ServiceRegistrar, srv ReportQpsScenarioServiceServer) {
+ s.RegisterService(&ReportQpsScenarioService_ServiceDesc, srv)
+}
+
+func _ReportQpsScenarioService_ReportScenario_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ScenarioResult)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ReportQpsScenarioServiceServer).ReportScenario(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: ReportQpsScenarioService_ReportScenario_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ReportQpsScenarioServiceServer).ReportScenario(ctx, req.(*ScenarioResult))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// ReportQpsScenarioService_ServiceDesc is the grpc.ServiceDesc for ReportQpsScenarioService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var ReportQpsScenarioService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.ReportQpsScenarioService",
+ HandlerType: (*ReportQpsScenarioServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "ReportScenario",
+ Handler: _ReportQpsScenarioService_ReportScenario_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "grpc/testing/report_qps_scenario_service.proto",
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/stats.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/stats.pb.go
new file mode 100644
index 0000000000..aa6e9b3bc4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/stats.pb.go
@@ -0,0 +1,629 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/stats.proto
+
+package grpc_testing
+
+import (
+ core "google.golang.org/grpc/interop/grpc_testing/core"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type ServerStats struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // wall clock time change in seconds since last reset
+ TimeElapsed float64 `protobuf:"fixed64,1,opt,name=time_elapsed,json=timeElapsed,proto3" json:"time_elapsed,omitempty"`
+ // change in user time (in seconds) used by the server since last reset
+ TimeUser float64 `protobuf:"fixed64,2,opt,name=time_user,json=timeUser,proto3" json:"time_user,omitempty"`
+ // change in server time (in seconds) used by the server process and all
+ // threads since last reset
+ TimeSystem float64 `protobuf:"fixed64,3,opt,name=time_system,json=timeSystem,proto3" json:"time_system,omitempty"`
+ // change in total cpu time of the server (data from proc/stat)
+ TotalCpuTime uint64 `protobuf:"varint,4,opt,name=total_cpu_time,json=totalCpuTime,proto3" json:"total_cpu_time,omitempty"`
+ // change in idle time of the server (data from proc/stat)
+ IdleCpuTime uint64 `protobuf:"varint,5,opt,name=idle_cpu_time,json=idleCpuTime,proto3" json:"idle_cpu_time,omitempty"`
+ // Number of polls called inside completion queue
+ CqPollCount uint64 `protobuf:"varint,6,opt,name=cq_poll_count,json=cqPollCount,proto3" json:"cq_poll_count,omitempty"`
+ // Core library stats
+ CoreStats *core.Stats `protobuf:"bytes,7,opt,name=core_stats,json=coreStats,proto3" json:"core_stats,omitempty"`
+}
+
+func (x *ServerStats) Reset() {
+ *x = ServerStats{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_stats_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ServerStats) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServerStats) ProtoMessage() {}
+
+func (x *ServerStats) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_stats_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ServerStats.ProtoReflect.Descriptor instead.
+func (*ServerStats) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_stats_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ServerStats) GetTimeElapsed() float64 {
+ if x != nil {
+ return x.TimeElapsed
+ }
+ return 0
+}
+
+func (x *ServerStats) GetTimeUser() float64 {
+ if x != nil {
+ return x.TimeUser
+ }
+ return 0
+}
+
+func (x *ServerStats) GetTimeSystem() float64 {
+ if x != nil {
+ return x.TimeSystem
+ }
+ return 0
+}
+
+func (x *ServerStats) GetTotalCpuTime() uint64 {
+ if x != nil {
+ return x.TotalCpuTime
+ }
+ return 0
+}
+
+func (x *ServerStats) GetIdleCpuTime() uint64 {
+ if x != nil {
+ return x.IdleCpuTime
+ }
+ return 0
+}
+
+func (x *ServerStats) GetCqPollCount() uint64 {
+ if x != nil {
+ return x.CqPollCount
+ }
+ return 0
+}
+
+func (x *ServerStats) GetCoreStats() *core.Stats {
+ if x != nil {
+ return x.CoreStats
+ }
+ return nil
+}
+
+// Histogram params based on grpc/support/histogram.c
+type HistogramParams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Resolution float64 `protobuf:"fixed64,1,opt,name=resolution,proto3" json:"resolution,omitempty"` // first bucket is [0, 1 + resolution)
+ MaxPossible float64 `protobuf:"fixed64,2,opt,name=max_possible,json=maxPossible,proto3" json:"max_possible,omitempty"` // use enough buckets to allow this value
+}
+
+func (x *HistogramParams) Reset() {
+ *x = HistogramParams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_stats_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HistogramParams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HistogramParams) ProtoMessage() {}
+
+func (x *HistogramParams) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_stats_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HistogramParams.ProtoReflect.Descriptor instead.
+func (*HistogramParams) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_stats_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *HistogramParams) GetResolution() float64 {
+ if x != nil {
+ return x.Resolution
+ }
+ return 0
+}
+
+func (x *HistogramParams) GetMaxPossible() float64 {
+ if x != nil {
+ return x.MaxPossible
+ }
+ return 0
+}
+
+// Histogram data based on grpc/support/histogram.c
+type HistogramData struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Bucket []uint32 `protobuf:"varint,1,rep,packed,name=bucket,proto3" json:"bucket,omitempty"`
+ MinSeen float64 `protobuf:"fixed64,2,opt,name=min_seen,json=minSeen,proto3" json:"min_seen,omitempty"`
+ MaxSeen float64 `protobuf:"fixed64,3,opt,name=max_seen,json=maxSeen,proto3" json:"max_seen,omitempty"`
+ Sum float64 `protobuf:"fixed64,4,opt,name=sum,proto3" json:"sum,omitempty"`
+ SumOfSquares float64 `protobuf:"fixed64,5,opt,name=sum_of_squares,json=sumOfSquares,proto3" json:"sum_of_squares,omitempty"`
+ Count float64 `protobuf:"fixed64,6,opt,name=count,proto3" json:"count,omitempty"`
+}
+
+func (x *HistogramData) Reset() {
+ *x = HistogramData{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_stats_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HistogramData) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HistogramData) ProtoMessage() {}
+
+func (x *HistogramData) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_stats_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HistogramData.ProtoReflect.Descriptor instead.
+func (*HistogramData) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_stats_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *HistogramData) GetBucket() []uint32 {
+ if x != nil {
+ return x.Bucket
+ }
+ return nil
+}
+
+func (x *HistogramData) GetMinSeen() float64 {
+ if x != nil {
+ return x.MinSeen
+ }
+ return 0
+}
+
+func (x *HistogramData) GetMaxSeen() float64 {
+ if x != nil {
+ return x.MaxSeen
+ }
+ return 0
+}
+
+func (x *HistogramData) GetSum() float64 {
+ if x != nil {
+ return x.Sum
+ }
+ return 0
+}
+
+func (x *HistogramData) GetSumOfSquares() float64 {
+ if x != nil {
+ return x.SumOfSquares
+ }
+ return 0
+}
+
+func (x *HistogramData) GetCount() float64 {
+ if x != nil {
+ return x.Count
+ }
+ return 0
+}
+
+type RequestResultCount struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ StatusCode int32 `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
+ Count int64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
+}
+
+func (x *RequestResultCount) Reset() {
+ *x = RequestResultCount{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_stats_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *RequestResultCount) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RequestResultCount) ProtoMessage() {}
+
+func (x *RequestResultCount) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_stats_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use RequestResultCount.ProtoReflect.Descriptor instead.
+func (*RequestResultCount) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_stats_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *RequestResultCount) GetStatusCode() int32 {
+ if x != nil {
+ return x.StatusCode
+ }
+ return 0
+}
+
+func (x *RequestResultCount) GetCount() int64 {
+ if x != nil {
+ return x.Count
+ }
+ return 0
+}
+
+type ClientStats struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Latency histogram. Data points are in nanoseconds.
+ Latencies *HistogramData `protobuf:"bytes,1,opt,name=latencies,proto3" json:"latencies,omitempty"`
+ // See ServerStats for details.
+ TimeElapsed float64 `protobuf:"fixed64,2,opt,name=time_elapsed,json=timeElapsed,proto3" json:"time_elapsed,omitempty"`
+ TimeUser float64 `protobuf:"fixed64,3,opt,name=time_user,json=timeUser,proto3" json:"time_user,omitempty"`
+ TimeSystem float64 `protobuf:"fixed64,4,opt,name=time_system,json=timeSystem,proto3" json:"time_system,omitempty"`
+ // Number of failed requests (one row per status code seen)
+ RequestResults []*RequestResultCount `protobuf:"bytes,5,rep,name=request_results,json=requestResults,proto3" json:"request_results,omitempty"`
+ // Number of polls called inside completion queue
+ CqPollCount uint64 `protobuf:"varint,6,opt,name=cq_poll_count,json=cqPollCount,proto3" json:"cq_poll_count,omitempty"`
+ // Core library stats
+ CoreStats *core.Stats `protobuf:"bytes,7,opt,name=core_stats,json=coreStats,proto3" json:"core_stats,omitempty"`
+}
+
+func (x *ClientStats) Reset() {
+ *x = ClientStats{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_grpc_testing_stats_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClientStats) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientStats) ProtoMessage() {}
+
+func (x *ClientStats) ProtoReflect() protoreflect.Message {
+ mi := &file_grpc_testing_stats_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientStats.ProtoReflect.Descriptor instead.
+func (*ClientStats) Descriptor() ([]byte, []int) {
+ return file_grpc_testing_stats_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ClientStats) GetLatencies() *HistogramData {
+ if x != nil {
+ return x.Latencies
+ }
+ return nil
+}
+
+func (x *ClientStats) GetTimeElapsed() float64 {
+ if x != nil {
+ return x.TimeElapsed
+ }
+ return 0
+}
+
+func (x *ClientStats) GetTimeUser() float64 {
+ if x != nil {
+ return x.TimeUser
+ }
+ return 0
+}
+
+func (x *ClientStats) GetTimeSystem() float64 {
+ if x != nil {
+ return x.TimeSystem
+ }
+ return 0
+}
+
+func (x *ClientStats) GetRequestResults() []*RequestResultCount {
+ if x != nil {
+ return x.RequestResults
+ }
+ return nil
+}
+
+func (x *ClientStats) GetCqPollCount() uint64 {
+ if x != nil {
+ return x.CqPollCount
+ }
+ return 0
+}
+
+func (x *ClientStats) GetCoreStats() *core.Stats {
+ if x != nil {
+ return x.CoreStats
+ }
+ return nil
+}
+
+var File_grpc_testing_stats_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_stats_proto_rawDesc = []byte{
+ 0x0a, 0x18, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x73,
+ 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67, 0x72, 0x70, 0x63,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x15, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63,
+ 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+ 0x8d, 0x02, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12,
+ 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6c, 0x61, 0x70, 0x73,
+ 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12,
+ 0x1f, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43,
+ 0x70, 0x75, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x63,
+ 0x70, 0x75, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69,
+ 0x64, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x71,
+ 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x0b, 0x63, 0x71, 0x50, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2f,
+ 0x0a, 0x0a, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x52, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22,
+ 0x54, 0x0a, 0x0f, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61,
+ 0x6d, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69,
+ 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62,
+ 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x50, 0x6f, 0x73,
+ 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0xab, 0x01, 0x0a, 0x0d, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67,
+ 0x72, 0x61, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65,
+ 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12,
+ 0x19, 0x0a, 0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61,
+ 0x78, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x6d, 0x61,
+ 0x78, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x01, 0x52, 0x03, 0x73, 0x75, 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x75, 0x6d, 0x5f, 0x6f,
+ 0x66, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52,
+ 0x0c, 0x73, 0x75, 0x6d, 0x4f, 0x66, 0x53, 0x71, 0x75, 0x61, 0x72, 0x65, 0x73, 0x12, 0x14, 0x0a,
+ 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x22, 0x4b, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
+ 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+ 0x22, 0xc9, 0x02, 0x0a, 0x0b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x12, 0x39, 0x0a, 0x09, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x44, 0x61, 0x74, 0x61,
+ 0x52, 0x09, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74,
+ 0x69, 0x6d, 0x65, 0x5f, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x12, 0x1b,
+ 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x74,
+ 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01,
+ 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x49, 0x0a, 0x0f,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18,
+ 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75,
+ 0x6c, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x71, 0x5f, 0x70, 0x6f,
+ 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
+ 0x63, 0x71, 0x50, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x63,
+ 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x10, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74,
+ 0x73, 0x52, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x1f, 0x0a, 0x0f,
+ 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x42,
+ 0x0a, 0x53, 0x74, 0x61, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_grpc_testing_stats_proto_rawDescOnce sync.Once
+ file_grpc_testing_stats_proto_rawDescData = file_grpc_testing_stats_proto_rawDesc
+)
+
+func file_grpc_testing_stats_proto_rawDescGZIP() []byte {
+ file_grpc_testing_stats_proto_rawDescOnce.Do(func() {
+ file_grpc_testing_stats_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_testing_stats_proto_rawDescData)
+ })
+ return file_grpc_testing_stats_proto_rawDescData
+}
+
+var file_grpc_testing_stats_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
+var file_grpc_testing_stats_proto_goTypes = []interface{}{
+ (*ServerStats)(nil), // 0: grpc.testing.ServerStats
+ (*HistogramParams)(nil), // 1: grpc.testing.HistogramParams
+ (*HistogramData)(nil), // 2: grpc.testing.HistogramData
+ (*RequestResultCount)(nil), // 3: grpc.testing.RequestResultCount
+ (*ClientStats)(nil), // 4: grpc.testing.ClientStats
+ (*core.Stats)(nil), // 5: grpc.core.Stats
+}
+var file_grpc_testing_stats_proto_depIdxs = []int32{
+ 5, // 0: grpc.testing.ServerStats.core_stats:type_name -> grpc.core.Stats
+ 2, // 1: grpc.testing.ClientStats.latencies:type_name -> grpc.testing.HistogramData
+ 3, // 2: grpc.testing.ClientStats.request_results:type_name -> grpc.testing.RequestResultCount
+ 5, // 3: grpc.testing.ClientStats.core_stats:type_name -> grpc.core.Stats
+ 4, // [4:4] is the sub-list for method output_type
+ 4, // [4:4] is the sub-list for method input_type
+ 4, // [4:4] is the sub-list for extension type_name
+ 4, // [4:4] is the sub-list for extension extendee
+ 0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_stats_proto_init() }
+func file_grpc_testing_stats_proto_init() {
+ if File_grpc_testing_stats_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_grpc_testing_stats_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ServerStats); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_stats_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HistogramParams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_stats_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HistogramData); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_stats_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RequestResultCount); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_grpc_testing_stats_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ClientStats); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_stats_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 5,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_grpc_testing_stats_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_stats_proto_depIdxs,
+ MessageInfos: file_grpc_testing_stats_proto_msgTypes,
+ }.Build()
+ File_grpc_testing_stats_proto = out.File
+ file_grpc_testing_stats_proto_rawDesc = nil
+ file_grpc_testing_stats_proto_goTypes = nil
+ file_grpc_testing_stats_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/test.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/test.pb.go
new file mode 100644
index 0000000000..58305cd3fc
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/test.pb.go
@@ -0,0 +1,241 @@
+// Copyright 2015-2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/test.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+var File_grpc_testing_test_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_test_proto_rawDesc = []byte{
+ 0x0a, 0x17, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x74,
+ 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67, 0x72, 0x70, 0x63, 0x2e,
+ 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x18, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x1a, 0x1b, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xcb,
+ 0x05, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35,
+ 0x0a, 0x09, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x13, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
+ 0x1a, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x09, 0x55, 0x6e, 0x61, 0x72, 0x79, 0x43, 0x61,
+ 0x6c, 0x6c, 0x12, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a,
+ 0x12, 0x43, 0x61, 0x63, 0x68, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x6e, 0x61, 0x72, 0x79, 0x43,
+ 0x61, 0x6c, 0x6c, 0x12, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x1a, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c,
+ 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70, 0x75,
+ 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4f, 0x75,
+ 0x74, 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x29, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53,
+ 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x61,
+ 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x69, 0x0a, 0x12,
+ 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x43, 0x61,
+ 0x6c, 0x6c, 0x12, 0x27, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74,
+ 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61,
+ 0x6d, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x12, 0x69, 0x0a, 0x0e, 0x46, 0x75, 0x6c, 0x6c, 0x44,
+ 0x75, 0x70, 0x6c, 0x65, 0x78, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69,
+ 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70,
+ 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01,
+ 0x30, 0x01, 0x12, 0x69, 0x0a, 0x0e, 0x48, 0x61, 0x6c, 0x66, 0x44, 0x75, 0x70, 0x6c, 0x65, 0x78,
+ 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74,
+ 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x74,
+ 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x61, 0x6c,
+ 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x3d, 0x0a,
+ 0x11, 0x55, 0x6e, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x43, 0x61,
+ 0x6c, 0x6c, 0x12, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x55, 0x0a, 0x14,
+ 0x55, 0x6e, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x11, 0x55, 0x6e, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d,
+ 0x70, 0x74, 0x79, 0x32, 0x89, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+ 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67,
+ 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
+ 0x1a, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x38, 0x0a, 0x04, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x13, 0x2e,
+ 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d, 0x70,
+ 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x32,
+ 0x86, 0x02, 0x0a, 0x18, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0e,
+ 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x26,
+ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f,
+ 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
+ 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
+ 0x00, 0x12, 0x84, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41,
+ 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12,
+ 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4c,
+ 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63, 0x63, 0x75, 0x6d,
+ 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x63,
+ 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0x3f, 0x0a, 0x0b, 0x48, 0x6f, 0x6f, 0x6b,
+ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x48, 0x6f, 0x6f, 0x6b, 0x12,
+ 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45,
+ 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xd5, 0x01, 0x0a, 0x16, 0x58, 0x64,
+ 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69,
+ 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x0d,
+ 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e,
+ 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x6d, 0x70,
+ 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x48,
+ 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x67, 0x72, 0x70,
+ 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x32, 0x7b, 0x0a, 0x1f, 0x58, 0x64, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x53, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,
+ 0x65, 0x12, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67,
+ 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x1d,
+ 0x0a, 0x1b, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var file_grpc_testing_test_proto_goTypes = []interface{}{
+ (*Empty)(nil), // 0: grpc.testing.Empty
+ (*SimpleRequest)(nil), // 1: grpc.testing.SimpleRequest
+ (*StreamingOutputCallRequest)(nil), // 2: grpc.testing.StreamingOutputCallRequest
+ (*StreamingInputCallRequest)(nil), // 3: grpc.testing.StreamingInputCallRequest
+ (*ReconnectParams)(nil), // 4: grpc.testing.ReconnectParams
+ (*LoadBalancerStatsRequest)(nil), // 5: grpc.testing.LoadBalancerStatsRequest
+ (*LoadBalancerAccumulatedStatsRequest)(nil), // 6: grpc.testing.LoadBalancerAccumulatedStatsRequest
+ (*HookRequest)(nil), // 7: grpc.testing.HookRequest
+ (*ClientConfigureRequest)(nil), // 8: grpc.testing.ClientConfigureRequest
+ (*SimpleResponse)(nil), // 9: grpc.testing.SimpleResponse
+ (*StreamingOutputCallResponse)(nil), // 10: grpc.testing.StreamingOutputCallResponse
+ (*StreamingInputCallResponse)(nil), // 11: grpc.testing.StreamingInputCallResponse
+ (*ReconnectInfo)(nil), // 12: grpc.testing.ReconnectInfo
+ (*LoadBalancerStatsResponse)(nil), // 13: grpc.testing.LoadBalancerStatsResponse
+ (*LoadBalancerAccumulatedStatsResponse)(nil), // 14: grpc.testing.LoadBalancerAccumulatedStatsResponse
+ (*HookResponse)(nil), // 15: grpc.testing.HookResponse
+ (*ClientConfigureResponse)(nil), // 16: grpc.testing.ClientConfigureResponse
+}
+var file_grpc_testing_test_proto_depIdxs = []int32{
+ 0, // 0: grpc.testing.TestService.EmptyCall:input_type -> grpc.testing.Empty
+ 1, // 1: grpc.testing.TestService.UnaryCall:input_type -> grpc.testing.SimpleRequest
+ 1, // 2: grpc.testing.TestService.CacheableUnaryCall:input_type -> grpc.testing.SimpleRequest
+ 2, // 3: grpc.testing.TestService.StreamingOutputCall:input_type -> grpc.testing.StreamingOutputCallRequest
+ 3, // 4: grpc.testing.TestService.StreamingInputCall:input_type -> grpc.testing.StreamingInputCallRequest
+ 2, // 5: grpc.testing.TestService.FullDuplexCall:input_type -> grpc.testing.StreamingOutputCallRequest
+ 2, // 6: grpc.testing.TestService.HalfDuplexCall:input_type -> grpc.testing.StreamingOutputCallRequest
+ 0, // 7: grpc.testing.TestService.UnimplementedCall:input_type -> grpc.testing.Empty
+ 0, // 8: grpc.testing.UnimplementedService.UnimplementedCall:input_type -> grpc.testing.Empty
+ 4, // 9: grpc.testing.ReconnectService.Start:input_type -> grpc.testing.ReconnectParams
+ 0, // 10: grpc.testing.ReconnectService.Stop:input_type -> grpc.testing.Empty
+ 5, // 11: grpc.testing.LoadBalancerStatsService.GetClientStats:input_type -> grpc.testing.LoadBalancerStatsRequest
+ 6, // 12: grpc.testing.LoadBalancerStatsService.GetClientAccumulatedStats:input_type -> grpc.testing.LoadBalancerAccumulatedStatsRequest
+ 0, // 13: grpc.testing.HookService.Hook:input_type -> grpc.testing.Empty
+ 0, // 14: grpc.testing.XdsUpdateHealthService.SetServing:input_type -> grpc.testing.Empty
+ 0, // 15: grpc.testing.XdsUpdateHealthService.SetNotServing:input_type -> grpc.testing.Empty
+ 7, // 16: grpc.testing.XdsUpdateHealthService.SendHookRequest:input_type -> grpc.testing.HookRequest
+ 8, // 17: grpc.testing.XdsUpdateClientConfigureService.Configure:input_type -> grpc.testing.ClientConfigureRequest
+ 0, // 18: grpc.testing.TestService.EmptyCall:output_type -> grpc.testing.Empty
+ 9, // 19: grpc.testing.TestService.UnaryCall:output_type -> grpc.testing.SimpleResponse
+ 9, // 20: grpc.testing.TestService.CacheableUnaryCall:output_type -> grpc.testing.SimpleResponse
+ 10, // 21: grpc.testing.TestService.StreamingOutputCall:output_type -> grpc.testing.StreamingOutputCallResponse
+ 11, // 22: grpc.testing.TestService.StreamingInputCall:output_type -> grpc.testing.StreamingInputCallResponse
+ 10, // 23: grpc.testing.TestService.FullDuplexCall:output_type -> grpc.testing.StreamingOutputCallResponse
+ 10, // 24: grpc.testing.TestService.HalfDuplexCall:output_type -> grpc.testing.StreamingOutputCallResponse
+ 0, // 25: grpc.testing.TestService.UnimplementedCall:output_type -> grpc.testing.Empty
+ 0, // 26: grpc.testing.UnimplementedService.UnimplementedCall:output_type -> grpc.testing.Empty
+ 0, // 27: grpc.testing.ReconnectService.Start:output_type -> grpc.testing.Empty
+ 12, // 28: grpc.testing.ReconnectService.Stop:output_type -> grpc.testing.ReconnectInfo
+ 13, // 29: grpc.testing.LoadBalancerStatsService.GetClientStats:output_type -> grpc.testing.LoadBalancerStatsResponse
+ 14, // 30: grpc.testing.LoadBalancerStatsService.GetClientAccumulatedStats:output_type -> grpc.testing.LoadBalancerAccumulatedStatsResponse
+ 0, // 31: grpc.testing.HookService.Hook:output_type -> grpc.testing.Empty
+ 0, // 32: grpc.testing.XdsUpdateHealthService.SetServing:output_type -> grpc.testing.Empty
+ 0, // 33: grpc.testing.XdsUpdateHealthService.SetNotServing:output_type -> grpc.testing.Empty
+ 15, // 34: grpc.testing.XdsUpdateHealthService.SendHookRequest:output_type -> grpc.testing.HookResponse
+ 16, // 35: grpc.testing.XdsUpdateClientConfigureService.Configure:output_type -> grpc.testing.ClientConfigureResponse
+ 18, // [18:36] is the sub-list for method output_type
+ 0, // [0:18] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_test_proto_init() }
+func file_grpc_testing_test_proto_init() {
+ if File_grpc_testing_test_proto != nil {
+ return
+ }
+ file_grpc_testing_empty_proto_init()
+ file_grpc_testing_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_test_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 0,
+ NumExtensions: 0,
+ NumServices: 7,
+ },
+ GoTypes: file_grpc_testing_test_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_test_proto_depIdxs,
+ }.Build()
+ File_grpc_testing_test_proto = out.File
+ file_grpc_testing_test_proto_rawDesc = nil
+ file_grpc_testing_test_proto_goTypes = nil
+ file_grpc_testing_test_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/test_grpc.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/test_grpc.pb.go
new file mode 100644
index 0000000000..2d0181a7f3
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/test_grpc.pb.go
@@ -0,0 +1,1246 @@
+// Copyright 2015-2016 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc v4.22.0
+// source: grpc/testing/test.proto
+
+package grpc_testing
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+const (
+ TestService_EmptyCall_FullMethodName = "/grpc.testing.TestService/EmptyCall"
+ TestService_UnaryCall_FullMethodName = "/grpc.testing.TestService/UnaryCall"
+ TestService_CacheableUnaryCall_FullMethodName = "/grpc.testing.TestService/CacheableUnaryCall"
+ TestService_StreamingOutputCall_FullMethodName = "/grpc.testing.TestService/StreamingOutputCall"
+ TestService_StreamingInputCall_FullMethodName = "/grpc.testing.TestService/StreamingInputCall"
+ TestService_FullDuplexCall_FullMethodName = "/grpc.testing.TestService/FullDuplexCall"
+ TestService_HalfDuplexCall_FullMethodName = "/grpc.testing.TestService/HalfDuplexCall"
+ TestService_UnimplementedCall_FullMethodName = "/grpc.testing.TestService/UnimplementedCall"
+)
+
+// TestServiceClient is the client API for TestService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type TestServiceClient interface {
+ // One empty request followed by one empty response.
+ EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
+ // One request followed by one response.
+ UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
+ // One request followed by one response. Response has cache control
+ // headers set such that a caching HTTP proxy (such as GFE) can
+ // satisfy subsequent requests.
+ CacheableUnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
+ // One request followed by a sequence of responses (streamed download).
+ // The server returns the payload with client desired type and sizes.
+ StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error)
+ // A sequence of requests followed by one response (streamed upload).
+ // The server returns the aggregated size of client payload as the result.
+ StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error)
+ // A sequence of requests with each request served by the server immediately.
+ // As one request could lead to multiple responses, this interface
+ // demonstrates the idea of full duplexing.
+ FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error)
+ // A sequence of requests followed by a sequence of responses.
+ // The server buffers all the client requests and then serves them in order. A
+ // stream of responses are returned to the client when the server starts with
+ // first request.
+ HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error)
+ // The test server will not implement this method. It will be used
+ // to test the behavior when clients call unimplemented methods.
+ UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
+}
+
+type testServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient {
+ return &testServiceClient{cc}
+}
+
+func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ out := new(Empty)
+ err := c.cc.Invoke(ctx, TestService_EmptyCall_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
+ out := new(SimpleResponse)
+ err := c.cc.Invoke(ctx, TestService_UnaryCall_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *testServiceClient) CacheableUnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
+ out := new(SimpleResponse)
+ err := c.cc.Invoke(ctx, TestService_CacheableUnaryCall_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *testServiceClient) StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) {
+ stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[0], TestService_StreamingOutputCall_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &testServiceStreamingOutputCallClient{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 TestService_StreamingOutputCallClient interface {
+ Recv() (*StreamingOutputCallResponse, error)
+ grpc.ClientStream
+}
+
+type testServiceStreamingOutputCallClient struct {
+ grpc.ClientStream
+}
+
+func (x *testServiceStreamingOutputCallClient) Recv() (*StreamingOutputCallResponse, error) {
+ m := new(StreamingOutputCallResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *testServiceClient) StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) {
+ stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[1], TestService_StreamingInputCall_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &testServiceStreamingInputCallClient{stream}
+ return x, nil
+}
+
+type TestService_StreamingInputCallClient interface {
+ Send(*StreamingInputCallRequest) error
+ CloseAndRecv() (*StreamingInputCallResponse, error)
+ grpc.ClientStream
+}
+
+type testServiceStreamingInputCallClient struct {
+ grpc.ClientStream
+}
+
+func (x *testServiceStreamingInputCallClient) Send(m *StreamingInputCallRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *testServiceStreamingInputCallClient) CloseAndRecv() (*StreamingInputCallResponse, error) {
+ if err := x.ClientStream.CloseSend(); err != nil {
+ return nil, err
+ }
+ m := new(StreamingInputCallResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) {
+ stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[2], TestService_FullDuplexCall_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &testServiceFullDuplexCallClient{stream}
+ return x, nil
+}
+
+type TestService_FullDuplexCallClient interface {
+ Send(*StreamingOutputCallRequest) error
+ Recv() (*StreamingOutputCallResponse, error)
+ grpc.ClientStream
+}
+
+type testServiceFullDuplexCallClient struct {
+ grpc.ClientStream
+}
+
+func (x *testServiceFullDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *testServiceFullDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
+ m := new(StreamingOutputCallResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *testServiceClient) HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) {
+ stream, err := c.cc.NewStream(ctx, &TestService_ServiceDesc.Streams[3], TestService_HalfDuplexCall_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &testServiceHalfDuplexCallClient{stream}
+ return x, nil
+}
+
+type TestService_HalfDuplexCallClient interface {
+ Send(*StreamingOutputCallRequest) error
+ Recv() (*StreamingOutputCallResponse, error)
+ grpc.ClientStream
+}
+
+type testServiceHalfDuplexCallClient struct {
+ grpc.ClientStream
+}
+
+func (x *testServiceHalfDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
+ m := new(StreamingOutputCallResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *testServiceClient) UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ out := new(Empty)
+ err := c.cc.Invoke(ctx, TestService_UnimplementedCall_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// TestServiceServer is the server API for TestService service.
+// All implementations must embed UnimplementedTestServiceServer
+// for forward compatibility
+type TestServiceServer interface {
+ // One empty request followed by one empty response.
+ EmptyCall(context.Context, *Empty) (*Empty, error)
+ // One request followed by one response.
+ UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
+ // One request followed by one response. Response has cache control
+ // headers set such that a caching HTTP proxy (such as GFE) can
+ // satisfy subsequent requests.
+ CacheableUnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
+ // One request followed by a sequence of responses (streamed download).
+ // The server returns the payload with client desired type and sizes.
+ StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error
+ // A sequence of requests followed by one response (streamed upload).
+ // The server returns the aggregated size of client payload as the result.
+ StreamingInputCall(TestService_StreamingInputCallServer) error
+ // A sequence of requests with each request served by the server immediately.
+ // As one request could lead to multiple responses, this interface
+ // demonstrates the idea of full duplexing.
+ FullDuplexCall(TestService_FullDuplexCallServer) error
+ // A sequence of requests followed by a sequence of responses.
+ // The server buffers all the client requests and then serves them in order. A
+ // stream of responses are returned to the client when the server starts with
+ // first request.
+ HalfDuplexCall(TestService_HalfDuplexCallServer) error
+ // The test server will not implement this method. It will be used
+ // to test the behavior when clients call unimplemented methods.
+ UnimplementedCall(context.Context, *Empty) (*Empty, error)
+ mustEmbedUnimplementedTestServiceServer()
+}
+
+// UnimplementedTestServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedTestServiceServer struct {
+}
+
+func (UnimplementedTestServiceServer) EmptyCall(context.Context, *Empty) (*Empty, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method EmptyCall not implemented")
+}
+func (UnimplementedTestServiceServer) UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UnaryCall not implemented")
+}
+func (UnimplementedTestServiceServer) CacheableUnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CacheableUnaryCall not implemented")
+}
+func (UnimplementedTestServiceServer) StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error {
+ return status.Errorf(codes.Unimplemented, "method StreamingOutputCall not implemented")
+}
+func (UnimplementedTestServiceServer) StreamingInputCall(TestService_StreamingInputCallServer) error {
+ return status.Errorf(codes.Unimplemented, "method StreamingInputCall not implemented")
+}
+func (UnimplementedTestServiceServer) FullDuplexCall(TestService_FullDuplexCallServer) error {
+ return status.Errorf(codes.Unimplemented, "method FullDuplexCall not implemented")
+}
+func (UnimplementedTestServiceServer) HalfDuplexCall(TestService_HalfDuplexCallServer) error {
+ return status.Errorf(codes.Unimplemented, "method HalfDuplexCall not implemented")
+}
+func (UnimplementedTestServiceServer) UnimplementedCall(context.Context, *Empty) (*Empty, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UnimplementedCall not implemented")
+}
+func (UnimplementedTestServiceServer) mustEmbedUnimplementedTestServiceServer() {}
+
+// UnsafeTestServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to TestServiceServer will
+// result in compilation errors.
+type UnsafeTestServiceServer interface {
+ mustEmbedUnimplementedTestServiceServer()
+}
+
+func RegisterTestServiceServer(s grpc.ServiceRegistrar, srv TestServiceServer) {
+ s.RegisterService(&TestService_ServiceDesc, srv)
+}
+
+func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Empty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(TestServiceServer).EmptyCall(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: TestService_EmptyCall_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(SimpleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(TestServiceServer).UnaryCall(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: TestService_UnaryCall_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _TestService_CacheableUnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(SimpleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(TestServiceServer).CacheableUnaryCall(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: TestService_CacheableUnaryCall_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(TestServiceServer).CacheableUnaryCall(ctx, req.(*SimpleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _TestService_StreamingOutputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(StreamingOutputCallRequest)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(TestServiceServer).StreamingOutputCall(m, &testServiceStreamingOutputCallServer{stream})
+}
+
+type TestService_StreamingOutputCallServer interface {
+ Send(*StreamingOutputCallResponse) error
+ grpc.ServerStream
+}
+
+type testServiceStreamingOutputCallServer struct {
+ grpc.ServerStream
+}
+
+func (x *testServiceStreamingOutputCallServer) Send(m *StreamingOutputCallResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func _TestService_StreamingInputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(TestServiceServer).StreamingInputCall(&testServiceStreamingInputCallServer{stream})
+}
+
+type TestService_StreamingInputCallServer interface {
+ SendAndClose(*StreamingInputCallResponse) error
+ Recv() (*StreamingInputCallRequest, error)
+ grpc.ServerStream
+}
+
+type testServiceStreamingInputCallServer struct {
+ grpc.ServerStream
+}
+
+func (x *testServiceStreamingInputCallServer) SendAndClose(m *StreamingInputCallResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *testServiceStreamingInputCallServer) Recv() (*StreamingInputCallRequest, error) {
+ m := new(StreamingInputCallRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream})
+}
+
+type TestService_FullDuplexCallServer interface {
+ Send(*StreamingOutputCallResponse) error
+ Recv() (*StreamingOutputCallRequest, error)
+ grpc.ServerStream
+}
+
+type testServiceFullDuplexCallServer struct {
+ grpc.ServerStream
+}
+
+func (x *testServiceFullDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *testServiceFullDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
+ m := new(StreamingOutputCallRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _TestService_HalfDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(TestServiceServer).HalfDuplexCall(&testServiceHalfDuplexCallServer{stream})
+}
+
+type TestService_HalfDuplexCallServer interface {
+ Send(*StreamingOutputCallResponse) error
+ Recv() (*StreamingOutputCallRequest, error)
+ grpc.ServerStream
+}
+
+type testServiceHalfDuplexCallServer struct {
+ grpc.ServerStream
+}
+
+func (x *testServiceHalfDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *testServiceHalfDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
+ m := new(StreamingOutputCallRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _TestService_UnimplementedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Empty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(TestServiceServer).UnimplementedCall(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: TestService_UnimplementedCall_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(TestServiceServer).UnimplementedCall(ctx, req.(*Empty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// TestService_ServiceDesc is the grpc.ServiceDesc for TestService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var TestService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.TestService",
+ HandlerType: (*TestServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "EmptyCall",
+ Handler: _TestService_EmptyCall_Handler,
+ },
+ {
+ MethodName: "UnaryCall",
+ Handler: _TestService_UnaryCall_Handler,
+ },
+ {
+ MethodName: "CacheableUnaryCall",
+ Handler: _TestService_CacheableUnaryCall_Handler,
+ },
+ {
+ MethodName: "UnimplementedCall",
+ Handler: _TestService_UnimplementedCall_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "StreamingOutputCall",
+ Handler: _TestService_StreamingOutputCall_Handler,
+ ServerStreams: true,
+ },
+ {
+ StreamName: "StreamingInputCall",
+ Handler: _TestService_StreamingInputCall_Handler,
+ ClientStreams: true,
+ },
+ {
+ StreamName: "FullDuplexCall",
+ Handler: _TestService_FullDuplexCall_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ {
+ StreamName: "HalfDuplexCall",
+ Handler: _TestService_HalfDuplexCall_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ },
+ Metadata: "grpc/testing/test.proto",
+}
+
+const (
+ UnimplementedService_UnimplementedCall_FullMethodName = "/grpc.testing.UnimplementedService/UnimplementedCall"
+)
+
+// UnimplementedServiceClient is the client API for UnimplementedService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type UnimplementedServiceClient interface {
+ // A call that no server should implement
+ UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
+}
+
+type unimplementedServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewUnimplementedServiceClient(cc grpc.ClientConnInterface) UnimplementedServiceClient {
+ return &unimplementedServiceClient{cc}
+}
+
+func (c *unimplementedServiceClient) UnimplementedCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ out := new(Empty)
+ err := c.cc.Invoke(ctx, UnimplementedService_UnimplementedCall_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// UnimplementedServiceServer is the server API for UnimplementedService service.
+// All implementations must embed UnimplementedUnimplementedServiceServer
+// for forward compatibility
+type UnimplementedServiceServer interface {
+ // A call that no server should implement
+ UnimplementedCall(context.Context, *Empty) (*Empty, error)
+ mustEmbedUnimplementedUnimplementedServiceServer()
+}
+
+// UnimplementedUnimplementedServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedUnimplementedServiceServer struct {
+}
+
+func (UnimplementedUnimplementedServiceServer) UnimplementedCall(context.Context, *Empty) (*Empty, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UnimplementedCall not implemented")
+}
+func (UnimplementedUnimplementedServiceServer) mustEmbedUnimplementedUnimplementedServiceServer() {}
+
+// UnsafeUnimplementedServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to UnimplementedServiceServer will
+// result in compilation errors.
+type UnsafeUnimplementedServiceServer interface {
+ mustEmbedUnimplementedUnimplementedServiceServer()
+}
+
+func RegisterUnimplementedServiceServer(s grpc.ServiceRegistrar, srv UnimplementedServiceServer) {
+ s.RegisterService(&UnimplementedService_ServiceDesc, srv)
+}
+
+func _UnimplementedService_UnimplementedCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Empty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: UnimplementedService_UnimplementedCall_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(UnimplementedServiceServer).UnimplementedCall(ctx, req.(*Empty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// UnimplementedService_ServiceDesc is the grpc.ServiceDesc for UnimplementedService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var UnimplementedService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.UnimplementedService",
+ HandlerType: (*UnimplementedServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "UnimplementedCall",
+ Handler: _UnimplementedService_UnimplementedCall_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "grpc/testing/test.proto",
+}
+
+const (
+ ReconnectService_Start_FullMethodName = "/grpc.testing.ReconnectService/Start"
+ ReconnectService_Stop_FullMethodName = "/grpc.testing.ReconnectService/Stop"
+)
+
+// ReconnectServiceClient is the client API for ReconnectService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type ReconnectServiceClient interface {
+ Start(ctx context.Context, in *ReconnectParams, opts ...grpc.CallOption) (*Empty, error)
+ Stop(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ReconnectInfo, error)
+}
+
+type reconnectServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewReconnectServiceClient(cc grpc.ClientConnInterface) ReconnectServiceClient {
+ return &reconnectServiceClient{cc}
+}
+
+func (c *reconnectServiceClient) Start(ctx context.Context, in *ReconnectParams, opts ...grpc.CallOption) (*Empty, error) {
+ out := new(Empty)
+ err := c.cc.Invoke(ctx, ReconnectService_Start_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *reconnectServiceClient) Stop(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ReconnectInfo, error) {
+ out := new(ReconnectInfo)
+ err := c.cc.Invoke(ctx, ReconnectService_Stop_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// ReconnectServiceServer is the server API for ReconnectService service.
+// All implementations must embed UnimplementedReconnectServiceServer
+// for forward compatibility
+type ReconnectServiceServer interface {
+ Start(context.Context, *ReconnectParams) (*Empty, error)
+ Stop(context.Context, *Empty) (*ReconnectInfo, error)
+ mustEmbedUnimplementedReconnectServiceServer()
+}
+
+// UnimplementedReconnectServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedReconnectServiceServer struct {
+}
+
+func (UnimplementedReconnectServiceServer) Start(context.Context, *ReconnectParams) (*Empty, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Start not implemented")
+}
+func (UnimplementedReconnectServiceServer) Stop(context.Context, *Empty) (*ReconnectInfo, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented")
+}
+func (UnimplementedReconnectServiceServer) mustEmbedUnimplementedReconnectServiceServer() {}
+
+// UnsafeReconnectServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to ReconnectServiceServer will
+// result in compilation errors.
+type UnsafeReconnectServiceServer interface {
+ mustEmbedUnimplementedReconnectServiceServer()
+}
+
+func RegisterReconnectServiceServer(s grpc.ServiceRegistrar, srv ReconnectServiceServer) {
+ s.RegisterService(&ReconnectService_ServiceDesc, srv)
+}
+
+func _ReconnectService_Start_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ReconnectParams)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ReconnectServiceServer).Start(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: ReconnectService_Start_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ReconnectServiceServer).Start(ctx, req.(*ReconnectParams))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _ReconnectService_Stop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Empty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ReconnectServiceServer).Stop(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: ReconnectService_Stop_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ReconnectServiceServer).Stop(ctx, req.(*Empty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// ReconnectService_ServiceDesc is the grpc.ServiceDesc for ReconnectService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var ReconnectService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.ReconnectService",
+ HandlerType: (*ReconnectServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Start",
+ Handler: _ReconnectService_Start_Handler,
+ },
+ {
+ MethodName: "Stop",
+ Handler: _ReconnectService_Stop_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "grpc/testing/test.proto",
+}
+
+const (
+ LoadBalancerStatsService_GetClientStats_FullMethodName = "/grpc.testing.LoadBalancerStatsService/GetClientStats"
+ LoadBalancerStatsService_GetClientAccumulatedStats_FullMethodName = "/grpc.testing.LoadBalancerStatsService/GetClientAccumulatedStats"
+)
+
+// LoadBalancerStatsServiceClient is the client API for LoadBalancerStatsService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type LoadBalancerStatsServiceClient interface {
+ // Gets the backend distribution for RPCs sent by a test client.
+ GetClientStats(ctx context.Context, in *LoadBalancerStatsRequest, opts ...grpc.CallOption) (*LoadBalancerStatsResponse, error)
+ // Gets the accumulated stats for RPCs sent by a test client.
+ GetClientAccumulatedStats(ctx context.Context, in *LoadBalancerAccumulatedStatsRequest, opts ...grpc.CallOption) (*LoadBalancerAccumulatedStatsResponse, error)
+}
+
+type loadBalancerStatsServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewLoadBalancerStatsServiceClient(cc grpc.ClientConnInterface) LoadBalancerStatsServiceClient {
+ return &loadBalancerStatsServiceClient{cc}
+}
+
+func (c *loadBalancerStatsServiceClient) GetClientStats(ctx context.Context, in *LoadBalancerStatsRequest, opts ...grpc.CallOption) (*LoadBalancerStatsResponse, error) {
+ out := new(LoadBalancerStatsResponse)
+ err := c.cc.Invoke(ctx, LoadBalancerStatsService_GetClientStats_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *loadBalancerStatsServiceClient) GetClientAccumulatedStats(ctx context.Context, in *LoadBalancerAccumulatedStatsRequest, opts ...grpc.CallOption) (*LoadBalancerAccumulatedStatsResponse, error) {
+ out := new(LoadBalancerAccumulatedStatsResponse)
+ err := c.cc.Invoke(ctx, LoadBalancerStatsService_GetClientAccumulatedStats_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// LoadBalancerStatsServiceServer is the server API for LoadBalancerStatsService service.
+// All implementations must embed UnimplementedLoadBalancerStatsServiceServer
+// for forward compatibility
+type LoadBalancerStatsServiceServer interface {
+ // Gets the backend distribution for RPCs sent by a test client.
+ GetClientStats(context.Context, *LoadBalancerStatsRequest) (*LoadBalancerStatsResponse, error)
+ // Gets the accumulated stats for RPCs sent by a test client.
+ GetClientAccumulatedStats(context.Context, *LoadBalancerAccumulatedStatsRequest) (*LoadBalancerAccumulatedStatsResponse, error)
+ mustEmbedUnimplementedLoadBalancerStatsServiceServer()
+}
+
+// UnimplementedLoadBalancerStatsServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedLoadBalancerStatsServiceServer struct {
+}
+
+func (UnimplementedLoadBalancerStatsServiceServer) GetClientStats(context.Context, *LoadBalancerStatsRequest) (*LoadBalancerStatsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GetClientStats not implemented")
+}
+func (UnimplementedLoadBalancerStatsServiceServer) GetClientAccumulatedStats(context.Context, *LoadBalancerAccumulatedStatsRequest) (*LoadBalancerAccumulatedStatsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GetClientAccumulatedStats not implemented")
+}
+func (UnimplementedLoadBalancerStatsServiceServer) mustEmbedUnimplementedLoadBalancerStatsServiceServer() {
+}
+
+// UnsafeLoadBalancerStatsServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to LoadBalancerStatsServiceServer will
+// result in compilation errors.
+type UnsafeLoadBalancerStatsServiceServer interface {
+ mustEmbedUnimplementedLoadBalancerStatsServiceServer()
+}
+
+func RegisterLoadBalancerStatsServiceServer(s grpc.ServiceRegistrar, srv LoadBalancerStatsServiceServer) {
+ s.RegisterService(&LoadBalancerStatsService_ServiceDesc, srv)
+}
+
+func _LoadBalancerStatsService_GetClientStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LoadBalancerStatsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LoadBalancerStatsServiceServer).GetClientStats(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: LoadBalancerStatsService_GetClientStats_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LoadBalancerStatsServiceServer).GetClientStats(ctx, req.(*LoadBalancerStatsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _LoadBalancerStatsService_GetClientAccumulatedStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LoadBalancerAccumulatedStatsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LoadBalancerStatsServiceServer).GetClientAccumulatedStats(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: LoadBalancerStatsService_GetClientAccumulatedStats_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LoadBalancerStatsServiceServer).GetClientAccumulatedStats(ctx, req.(*LoadBalancerAccumulatedStatsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// LoadBalancerStatsService_ServiceDesc is the grpc.ServiceDesc for LoadBalancerStatsService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var LoadBalancerStatsService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.LoadBalancerStatsService",
+ HandlerType: (*LoadBalancerStatsServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "GetClientStats",
+ Handler: _LoadBalancerStatsService_GetClientStats_Handler,
+ },
+ {
+ MethodName: "GetClientAccumulatedStats",
+ Handler: _LoadBalancerStatsService_GetClientAccumulatedStats_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "grpc/testing/test.proto",
+}
+
+const (
+ HookService_Hook_FullMethodName = "/grpc.testing.HookService/Hook"
+)
+
+// HookServiceClient is the client API for HookService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HookServiceClient interface {
+ Hook(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
+}
+
+type hookServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHookServiceClient(cc grpc.ClientConnInterface) HookServiceClient {
+ return &hookServiceClient{cc}
+}
+
+func (c *hookServiceClient) Hook(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ out := new(Empty)
+ err := c.cc.Invoke(ctx, HookService_Hook_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HookServiceServer is the server API for HookService service.
+// All implementations must embed UnimplementedHookServiceServer
+// for forward compatibility
+type HookServiceServer interface {
+ Hook(context.Context, *Empty) (*Empty, error)
+ mustEmbedUnimplementedHookServiceServer()
+}
+
+// UnimplementedHookServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedHookServiceServer struct {
+}
+
+func (UnimplementedHookServiceServer) Hook(context.Context, *Empty) (*Empty, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Hook not implemented")
+}
+func (UnimplementedHookServiceServer) mustEmbedUnimplementedHookServiceServer() {}
+
+// UnsafeHookServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HookServiceServer will
+// result in compilation errors.
+type UnsafeHookServiceServer interface {
+ mustEmbedUnimplementedHookServiceServer()
+}
+
+func RegisterHookServiceServer(s grpc.ServiceRegistrar, srv HookServiceServer) {
+ s.RegisterService(&HookService_ServiceDesc, srv)
+}
+
+func _HookService_Hook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Empty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HookServiceServer).Hook(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HookService_Hook_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HookServiceServer).Hook(ctx, req.(*Empty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HookService_ServiceDesc is the grpc.ServiceDesc for HookService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HookService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.HookService",
+ HandlerType: (*HookServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Hook",
+ Handler: _HookService_Hook_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "grpc/testing/test.proto",
+}
+
+const (
+ XdsUpdateHealthService_SetServing_FullMethodName = "/grpc.testing.XdsUpdateHealthService/SetServing"
+ XdsUpdateHealthService_SetNotServing_FullMethodName = "/grpc.testing.XdsUpdateHealthService/SetNotServing"
+ XdsUpdateHealthService_SendHookRequest_FullMethodName = "/grpc.testing.XdsUpdateHealthService/SendHookRequest"
+)
+
+// XdsUpdateHealthServiceClient is the client API for XdsUpdateHealthService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type XdsUpdateHealthServiceClient interface {
+ SetServing(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
+ SetNotServing(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
+ SendHookRequest(ctx context.Context, in *HookRequest, opts ...grpc.CallOption) (*HookResponse, error)
+}
+
+type xdsUpdateHealthServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewXdsUpdateHealthServiceClient(cc grpc.ClientConnInterface) XdsUpdateHealthServiceClient {
+ return &xdsUpdateHealthServiceClient{cc}
+}
+
+func (c *xdsUpdateHealthServiceClient) SetServing(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ out := new(Empty)
+ err := c.cc.Invoke(ctx, XdsUpdateHealthService_SetServing_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *xdsUpdateHealthServiceClient) SetNotServing(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
+ out := new(Empty)
+ err := c.cc.Invoke(ctx, XdsUpdateHealthService_SetNotServing_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *xdsUpdateHealthServiceClient) SendHookRequest(ctx context.Context, in *HookRequest, opts ...grpc.CallOption) (*HookResponse, error) {
+ out := new(HookResponse)
+ err := c.cc.Invoke(ctx, XdsUpdateHealthService_SendHookRequest_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// XdsUpdateHealthServiceServer is the server API for XdsUpdateHealthService service.
+// All implementations must embed UnimplementedXdsUpdateHealthServiceServer
+// for forward compatibility
+type XdsUpdateHealthServiceServer interface {
+ SetServing(context.Context, *Empty) (*Empty, error)
+ SetNotServing(context.Context, *Empty) (*Empty, error)
+ SendHookRequest(context.Context, *HookRequest) (*HookResponse, error)
+ mustEmbedUnimplementedXdsUpdateHealthServiceServer()
+}
+
+// UnimplementedXdsUpdateHealthServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedXdsUpdateHealthServiceServer struct {
+}
+
+func (UnimplementedXdsUpdateHealthServiceServer) SetServing(context.Context, *Empty) (*Empty, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SetServing not implemented")
+}
+func (UnimplementedXdsUpdateHealthServiceServer) SetNotServing(context.Context, *Empty) (*Empty, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SetNotServing not implemented")
+}
+func (UnimplementedXdsUpdateHealthServiceServer) SendHookRequest(context.Context, *HookRequest) (*HookResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SendHookRequest not implemented")
+}
+func (UnimplementedXdsUpdateHealthServiceServer) mustEmbedUnimplementedXdsUpdateHealthServiceServer() {
+}
+
+// UnsafeXdsUpdateHealthServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to XdsUpdateHealthServiceServer will
+// result in compilation errors.
+type UnsafeXdsUpdateHealthServiceServer interface {
+ mustEmbedUnimplementedXdsUpdateHealthServiceServer()
+}
+
+func RegisterXdsUpdateHealthServiceServer(s grpc.ServiceRegistrar, srv XdsUpdateHealthServiceServer) {
+ s.RegisterService(&XdsUpdateHealthService_ServiceDesc, srv)
+}
+
+func _XdsUpdateHealthService_SetServing_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Empty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(XdsUpdateHealthServiceServer).SetServing(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: XdsUpdateHealthService_SetServing_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(XdsUpdateHealthServiceServer).SetServing(ctx, req.(*Empty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _XdsUpdateHealthService_SetNotServing_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Empty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(XdsUpdateHealthServiceServer).SetNotServing(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: XdsUpdateHealthService_SetNotServing_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(XdsUpdateHealthServiceServer).SetNotServing(ctx, req.(*Empty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _XdsUpdateHealthService_SendHookRequest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HookRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(XdsUpdateHealthServiceServer).SendHookRequest(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: XdsUpdateHealthService_SendHookRequest_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(XdsUpdateHealthServiceServer).SendHookRequest(ctx, req.(*HookRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// XdsUpdateHealthService_ServiceDesc is the grpc.ServiceDesc for XdsUpdateHealthService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var XdsUpdateHealthService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.XdsUpdateHealthService",
+ HandlerType: (*XdsUpdateHealthServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "SetServing",
+ Handler: _XdsUpdateHealthService_SetServing_Handler,
+ },
+ {
+ MethodName: "SetNotServing",
+ Handler: _XdsUpdateHealthService_SetNotServing_Handler,
+ },
+ {
+ MethodName: "SendHookRequest",
+ Handler: _XdsUpdateHealthService_SendHookRequest_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "grpc/testing/test.proto",
+}
+
+const (
+ XdsUpdateClientConfigureService_Configure_FullMethodName = "/grpc.testing.XdsUpdateClientConfigureService/Configure"
+)
+
+// XdsUpdateClientConfigureServiceClient is the client API for XdsUpdateClientConfigureService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type XdsUpdateClientConfigureServiceClient interface {
+ // Update the tes client's configuration.
+ Configure(ctx context.Context, in *ClientConfigureRequest, opts ...grpc.CallOption) (*ClientConfigureResponse, error)
+}
+
+type xdsUpdateClientConfigureServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewXdsUpdateClientConfigureServiceClient(cc grpc.ClientConnInterface) XdsUpdateClientConfigureServiceClient {
+ return &xdsUpdateClientConfigureServiceClient{cc}
+}
+
+func (c *xdsUpdateClientConfigureServiceClient) Configure(ctx context.Context, in *ClientConfigureRequest, opts ...grpc.CallOption) (*ClientConfigureResponse, error) {
+ out := new(ClientConfigureResponse)
+ err := c.cc.Invoke(ctx, XdsUpdateClientConfigureService_Configure_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// XdsUpdateClientConfigureServiceServer is the server API for XdsUpdateClientConfigureService service.
+// All implementations must embed UnimplementedXdsUpdateClientConfigureServiceServer
+// for forward compatibility
+type XdsUpdateClientConfigureServiceServer interface {
+ // Update the tes client's configuration.
+ Configure(context.Context, *ClientConfigureRequest) (*ClientConfigureResponse, error)
+ mustEmbedUnimplementedXdsUpdateClientConfigureServiceServer()
+}
+
+// UnimplementedXdsUpdateClientConfigureServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedXdsUpdateClientConfigureServiceServer struct {
+}
+
+func (UnimplementedXdsUpdateClientConfigureServiceServer) Configure(context.Context, *ClientConfigureRequest) (*ClientConfigureResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method Configure not implemented")
+}
+func (UnimplementedXdsUpdateClientConfigureServiceServer) mustEmbedUnimplementedXdsUpdateClientConfigureServiceServer() {
+}
+
+// UnsafeXdsUpdateClientConfigureServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to XdsUpdateClientConfigureServiceServer will
+// result in compilation errors.
+type UnsafeXdsUpdateClientConfigureServiceServer interface {
+ mustEmbedUnimplementedXdsUpdateClientConfigureServiceServer()
+}
+
+func RegisterXdsUpdateClientConfigureServiceServer(s grpc.ServiceRegistrar, srv XdsUpdateClientConfigureServiceServer) {
+ s.RegisterService(&XdsUpdateClientConfigureService_ServiceDesc, srv)
+}
+
+func _XdsUpdateClientConfigureService_Configure_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ClientConfigureRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(XdsUpdateClientConfigureServiceServer).Configure(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: XdsUpdateClientConfigureService_Configure_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(XdsUpdateClientConfigureServiceServer).Configure(ctx, req.(*ClientConfigureRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// XdsUpdateClientConfigureService_ServiceDesc is the grpc.ServiceDesc for XdsUpdateClientConfigureService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var XdsUpdateClientConfigureService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.XdsUpdateClientConfigureService",
+ HandlerType: (*XdsUpdateClientConfigureServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Configure",
+ Handler: _XdsUpdateClientConfigureService_Configure_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "grpc/testing/test.proto",
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/worker_service.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/worker_service.pb.go
new file mode 100644
index 0000000000..1feccc9f76
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/worker_service.pb.go
@@ -0,0 +1,118 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.31.0
+// protoc v4.22.0
+// source: grpc/testing/worker_service.proto
+
+package grpc_testing
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+var File_grpc_testing_worker_service_proto protoreflect.FileDescriptor
+
+var file_grpc_testing_worker_service_proto_rawDesc = []byte{
+ 0x0a, 0x21, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x77,
+ 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x1a, 0x1a, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x97, 0x02,
+ 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
+ 0x45, 0x0a, 0x09, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x67,
+ 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
+ 0x75, 0x73, 0x28, 0x01, 0x30, 0x01, 0x12, 0x45, 0x0a, 0x09, 0x52, 0x75, 0x6e, 0x43, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1a, 0x2e,
+ 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x28, 0x01, 0x30, 0x01, 0x12, 0x42, 0x0a,
+ 0x09, 0x43, 0x6f, 0x72, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x67, 0x72, 0x70,
+ 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x51, 0x75, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12,
+ 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x56,
+ 0x6f, 0x69, 0x64, 0x1a, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x56, 0x6f, 0x69, 0x64, 0x42, 0x27, 0x0a, 0x0f, 0x69, 0x6f, 0x2e, 0x67, 0x72,
+ 0x70, 0x63, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x12, 0x57, 0x6f, 0x72, 0x6b,
+ 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
+ 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var file_grpc_testing_worker_service_proto_goTypes = []interface{}{
+ (*ServerArgs)(nil), // 0: grpc.testing.ServerArgs
+ (*ClientArgs)(nil), // 1: grpc.testing.ClientArgs
+ (*CoreRequest)(nil), // 2: grpc.testing.CoreRequest
+ (*Void)(nil), // 3: grpc.testing.Void
+ (*ServerStatus)(nil), // 4: grpc.testing.ServerStatus
+ (*ClientStatus)(nil), // 5: grpc.testing.ClientStatus
+ (*CoreResponse)(nil), // 6: grpc.testing.CoreResponse
+}
+var file_grpc_testing_worker_service_proto_depIdxs = []int32{
+ 0, // 0: grpc.testing.WorkerService.RunServer:input_type -> grpc.testing.ServerArgs
+ 1, // 1: grpc.testing.WorkerService.RunClient:input_type -> grpc.testing.ClientArgs
+ 2, // 2: grpc.testing.WorkerService.CoreCount:input_type -> grpc.testing.CoreRequest
+ 3, // 3: grpc.testing.WorkerService.QuitWorker:input_type -> grpc.testing.Void
+ 4, // 4: grpc.testing.WorkerService.RunServer:output_type -> grpc.testing.ServerStatus
+ 5, // 5: grpc.testing.WorkerService.RunClient:output_type -> grpc.testing.ClientStatus
+ 6, // 6: grpc.testing.WorkerService.CoreCount:output_type -> grpc.testing.CoreResponse
+ 3, // 7: grpc.testing.WorkerService.QuitWorker:output_type -> grpc.testing.Void
+ 4, // [4:8] is the sub-list for method output_type
+ 0, // [0:4] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_grpc_testing_worker_service_proto_init() }
+func file_grpc_testing_worker_service_proto_init() {
+ if File_grpc_testing_worker_service_proto != nil {
+ return
+ }
+ file_grpc_testing_control_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_grpc_testing_worker_service_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 0,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_grpc_testing_worker_service_proto_goTypes,
+ DependencyIndexes: file_grpc_testing_worker_service_proto_depIdxs,
+ }.Build()
+ File_grpc_testing_worker_service_proto = out.File
+ file_grpc_testing_worker_service_proto_rawDesc = nil
+ file_grpc_testing_worker_service_proto_goTypes = nil
+ file_grpc_testing_worker_service_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/grpc/interop/grpc_testing/worker_service_grpc.pb.go b/vendor/google.golang.org/grpc/interop/grpc_testing/worker_service_grpc.pb.go
new file mode 100644
index 0000000000..1de7f09f84
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interop/grpc_testing/worker_service_grpc.pb.go
@@ -0,0 +1,330 @@
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc v4.22.0
+// source: grpc/testing/worker_service.proto
+
+package grpc_testing
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+const (
+ WorkerService_RunServer_FullMethodName = "/grpc.testing.WorkerService/RunServer"
+ WorkerService_RunClient_FullMethodName = "/grpc.testing.WorkerService/RunClient"
+ WorkerService_CoreCount_FullMethodName = "/grpc.testing.WorkerService/CoreCount"
+ WorkerService_QuitWorker_FullMethodName = "/grpc.testing.WorkerService/QuitWorker"
+)
+
+// WorkerServiceClient is the client API for WorkerService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type WorkerServiceClient interface {
+ // Start server with specified workload.
+ // First request sent specifies the ServerConfig followed by ServerStatus
+ // response. After that, a "Mark" can be sent anytime to request the latest
+ // stats. Closing the stream will initiate shutdown of the test server
+ // and once the shutdown has finished, the OK status is sent to terminate
+ // this RPC.
+ RunServer(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunServerClient, error)
+ // Start client with specified workload.
+ // First request sent specifies the ClientConfig followed by ClientStatus
+ // response. After that, a "Mark" can be sent anytime to request the latest
+ // stats. Closing the stream will initiate shutdown of the test client
+ // and once the shutdown has finished, the OK status is sent to terminate
+ // this RPC.
+ RunClient(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunClientClient, error)
+ // Just return the core count - unary call
+ CoreCount(ctx context.Context, in *CoreRequest, opts ...grpc.CallOption) (*CoreResponse, error)
+ // Quit this worker
+ QuitWorker(ctx context.Context, in *Void, opts ...grpc.CallOption) (*Void, error)
+}
+
+type workerServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewWorkerServiceClient(cc grpc.ClientConnInterface) WorkerServiceClient {
+ return &workerServiceClient{cc}
+}
+
+func (c *workerServiceClient) RunServer(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunServerClient, error) {
+ stream, err := c.cc.NewStream(ctx, &WorkerService_ServiceDesc.Streams[0], WorkerService_RunServer_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &workerServiceRunServerClient{stream}
+ return x, nil
+}
+
+type WorkerService_RunServerClient interface {
+ Send(*ServerArgs) error
+ Recv() (*ServerStatus, error)
+ grpc.ClientStream
+}
+
+type workerServiceRunServerClient struct {
+ grpc.ClientStream
+}
+
+func (x *workerServiceRunServerClient) Send(m *ServerArgs) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *workerServiceRunServerClient) Recv() (*ServerStatus, error) {
+ m := new(ServerStatus)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *workerServiceClient) RunClient(ctx context.Context, opts ...grpc.CallOption) (WorkerService_RunClientClient, error) {
+ stream, err := c.cc.NewStream(ctx, &WorkerService_ServiceDesc.Streams[1], WorkerService_RunClient_FullMethodName, opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &workerServiceRunClientClient{stream}
+ return x, nil
+}
+
+type WorkerService_RunClientClient interface {
+ Send(*ClientArgs) error
+ Recv() (*ClientStatus, error)
+ grpc.ClientStream
+}
+
+type workerServiceRunClientClient struct {
+ grpc.ClientStream
+}
+
+func (x *workerServiceRunClientClient) Send(m *ClientArgs) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *workerServiceRunClientClient) Recv() (*ClientStatus, error) {
+ m := new(ClientStatus)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *workerServiceClient) CoreCount(ctx context.Context, in *CoreRequest, opts ...grpc.CallOption) (*CoreResponse, error) {
+ out := new(CoreResponse)
+ err := c.cc.Invoke(ctx, WorkerService_CoreCount_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *workerServiceClient) QuitWorker(ctx context.Context, in *Void, opts ...grpc.CallOption) (*Void, error) {
+ out := new(Void)
+ err := c.cc.Invoke(ctx, WorkerService_QuitWorker_FullMethodName, in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// WorkerServiceServer is the server API for WorkerService service.
+// All implementations must embed UnimplementedWorkerServiceServer
+// for forward compatibility
+type WorkerServiceServer interface {
+ // Start server with specified workload.
+ // First request sent specifies the ServerConfig followed by ServerStatus
+ // response. After that, a "Mark" can be sent anytime to request the latest
+ // stats. Closing the stream will initiate shutdown of the test server
+ // and once the shutdown has finished, the OK status is sent to terminate
+ // this RPC.
+ RunServer(WorkerService_RunServerServer) error
+ // Start client with specified workload.
+ // First request sent specifies the ClientConfig followed by ClientStatus
+ // response. After that, a "Mark" can be sent anytime to request the latest
+ // stats. Closing the stream will initiate shutdown of the test client
+ // and once the shutdown has finished, the OK status is sent to terminate
+ // this RPC.
+ RunClient(WorkerService_RunClientServer) error
+ // Just return the core count - unary call
+ CoreCount(context.Context, *CoreRequest) (*CoreResponse, error)
+ // Quit this worker
+ QuitWorker(context.Context, *Void) (*Void, error)
+ mustEmbedUnimplementedWorkerServiceServer()
+}
+
+// UnimplementedWorkerServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedWorkerServiceServer struct {
+}
+
+func (UnimplementedWorkerServiceServer) RunServer(WorkerService_RunServerServer) error {
+ return status.Errorf(codes.Unimplemented, "method RunServer not implemented")
+}
+func (UnimplementedWorkerServiceServer) RunClient(WorkerService_RunClientServer) error {
+ return status.Errorf(codes.Unimplemented, "method RunClient not implemented")
+}
+func (UnimplementedWorkerServiceServer) CoreCount(context.Context, *CoreRequest) (*CoreResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CoreCount not implemented")
+}
+func (UnimplementedWorkerServiceServer) QuitWorker(context.Context, *Void) (*Void, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method QuitWorker not implemented")
+}
+func (UnimplementedWorkerServiceServer) mustEmbedUnimplementedWorkerServiceServer() {}
+
+// UnsafeWorkerServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to WorkerServiceServer will
+// result in compilation errors.
+type UnsafeWorkerServiceServer interface {
+ mustEmbedUnimplementedWorkerServiceServer()
+}
+
+func RegisterWorkerServiceServer(s grpc.ServiceRegistrar, srv WorkerServiceServer) {
+ s.RegisterService(&WorkerService_ServiceDesc, srv)
+}
+
+func _WorkerService_RunServer_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(WorkerServiceServer).RunServer(&workerServiceRunServerServer{stream})
+}
+
+type WorkerService_RunServerServer interface {
+ Send(*ServerStatus) error
+ Recv() (*ServerArgs, error)
+ grpc.ServerStream
+}
+
+type workerServiceRunServerServer struct {
+ grpc.ServerStream
+}
+
+func (x *workerServiceRunServerServer) Send(m *ServerStatus) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *workerServiceRunServerServer) Recv() (*ServerArgs, error) {
+ m := new(ServerArgs)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _WorkerService_RunClient_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(WorkerServiceServer).RunClient(&workerServiceRunClientServer{stream})
+}
+
+type WorkerService_RunClientServer interface {
+ Send(*ClientStatus) error
+ Recv() (*ClientArgs, error)
+ grpc.ServerStream
+}
+
+type workerServiceRunClientServer struct {
+ grpc.ServerStream
+}
+
+func (x *workerServiceRunClientServer) Send(m *ClientStatus) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *workerServiceRunClientServer) Recv() (*ClientArgs, error) {
+ m := new(ClientArgs)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _WorkerService_CoreCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CoreRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(WorkerServiceServer).CoreCount(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: WorkerService_CoreCount_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(WorkerServiceServer).CoreCount(ctx, req.(*CoreRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _WorkerService_QuitWorker_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Void)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(WorkerServiceServer).QuitWorker(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: WorkerService_QuitWorker_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(WorkerServiceServer).QuitWorker(ctx, req.(*Void))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// WorkerService_ServiceDesc is the grpc.ServiceDesc for WorkerService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var WorkerService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "grpc.testing.WorkerService",
+ HandlerType: (*WorkerServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "CoreCount",
+ Handler: _WorkerService_CoreCount_Handler,
+ },
+ {
+ MethodName: "QuitWorker",
+ Handler: _WorkerService_QuitWorker_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "RunServer",
+ Handler: _WorkerService_RunServer_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ {
+ StreamName: "RunClient",
+ Handler: _WorkerService_RunClient_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ },
+ Metadata: "grpc/testing/worker_service.proto",
+}
diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go
index 5f28148d80..bb2966e3b4 100644
--- a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go
+++ b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go
@@ -11,6 +11,7 @@ import (
"strconv"
"strings"
+ "google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/json"
"google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/errors"
@@ -23,7 +24,7 @@ import (
"google.golang.org/protobuf/reflect/protoregistry"
)
-// Unmarshal reads the given []byte into the given proto.Message.
+// Unmarshal reads the given []byte into the given [proto.Message].
// The provided message must be mutable (e.g., a non-nil pointer to a message).
func Unmarshal(b []byte, m proto.Message) error {
return UnmarshalOptions{}.Unmarshal(b, m)
@@ -37,7 +38,7 @@ type UnmarshalOptions struct {
// required fields will not return an error.
AllowPartial bool
- // If DiscardUnknown is set, unknown fields are ignored.
+ // If DiscardUnknown is set, unknown fields and enum name values are ignored.
DiscardUnknown bool
// Resolver is used for looking up types when unmarshaling
@@ -47,9 +48,13 @@ type UnmarshalOptions struct {
protoregistry.MessageTypeResolver
protoregistry.ExtensionTypeResolver
}
+
+ // RecursionLimit limits how deeply messages may be nested.
+ // If zero, a default limit is applied.
+ RecursionLimit int
}
-// Unmarshal reads the given []byte and populates the given proto.Message
+// Unmarshal reads the given []byte and populates the given [proto.Message]
// using options in the UnmarshalOptions object.
// It will clear the message first before setting the fields.
// If it returns an error, the given message may be partially set.
@@ -67,6 +72,9 @@ func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error {
if o.Resolver == nil {
o.Resolver = protoregistry.GlobalTypes
}
+ if o.RecursionLimit == 0 {
+ o.RecursionLimit = protowire.DefaultRecursionLimit
+ }
dec := decoder{json.NewDecoder(b), o}
if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil {
@@ -94,7 +102,7 @@ type decoder struct {
}
// newError returns an error object with position info.
-func (d decoder) newError(pos int, f string, x ...interface{}) error {
+func (d decoder) newError(pos int, f string, x ...any) error {
line, column := d.Position(pos)
head := fmt.Sprintf("(line %d:%d): ", line, column)
return errors.New(head+f, x...)
@@ -106,7 +114,7 @@ func (d decoder) unexpectedTokenError(tok json.Token) error {
}
// syntaxError returns a syntax error for given position.
-func (d decoder) syntaxError(pos int, f string, x ...interface{}) error {
+func (d decoder) syntaxError(pos int, f string, x ...any) error {
line, column := d.Position(pos)
head := fmt.Sprintf("syntax error (line %d:%d): ", line, column)
return errors.New(head+f, x...)
@@ -114,6 +122,10 @@ func (d decoder) syntaxError(pos int, f string, x ...interface{}) error {
// unmarshalMessage unmarshals a message into the given protoreflect.Message.
func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) error {
+ d.opts.RecursionLimit--
+ if d.opts.RecursionLimit < 0 {
+ return errors.New("exceeded max recursion depth")
+ }
if unmarshal := wellKnownTypeUnmarshaler(m.Descriptor().FullName()); unmarshal != nil {
return unmarshal(d, m)
}
@@ -266,7 +278,9 @@ func (d decoder) unmarshalSingular(m protoreflect.Message, fd protoreflect.Field
if err != nil {
return err
}
- m.Set(fd, val)
+ if val.IsValid() {
+ m.Set(fd, val)
+ }
return nil
}
@@ -329,7 +343,7 @@ func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.
}
case protoreflect.EnumKind:
- if v, ok := unmarshalEnum(tok, fd); ok {
+ if v, ok := unmarshalEnum(tok, fd, d.opts.DiscardUnknown); ok {
return v, nil
}
@@ -474,7 +488,7 @@ func unmarshalBytes(tok json.Token) (protoreflect.Value, bool) {
return protoreflect.ValueOfBytes(b), true
}
-func unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflect.Value, bool) {
+func unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor, discardUnknown bool) (protoreflect.Value, bool) {
switch tok.Kind() {
case json.String:
// Lookup EnumNumber based on name.
@@ -482,6 +496,9 @@ func unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflec
if enumVal := fd.Enum().Values().ByName(protoreflect.Name(s)); enumVal != nil {
return protoreflect.ValueOfEnum(enumVal.Number()), true
}
+ if discardUnknown {
+ return protoreflect.Value{}, true
+ }
case json.Number:
if n, ok := tok.Int(32); ok {
@@ -542,7 +559,9 @@ func (d decoder) unmarshalList(list protoreflect.List, fd protoreflect.FieldDesc
if err != nil {
return err
}
- list.Append(val)
+ if val.IsValid() {
+ list.Append(val)
+ }
}
}
@@ -609,8 +628,9 @@ Loop:
if err != nil {
return err
}
-
- mmap.Set(pkey, pval)
+ if pval.IsValid() {
+ mmap.Set(pkey, pval)
+ }
}
return nil
diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/doc.go b/vendor/google.golang.org/protobuf/encoding/protojson/doc.go
index 21d5d2cb18..ae71007c18 100644
--- a/vendor/google.golang.org/protobuf/encoding/protojson/doc.go
+++ b/vendor/google.golang.org/protobuf/encoding/protojson/doc.go
@@ -6,6 +6,6 @@
// format. It follows the guide at
// https://protobuf.dev/programming-guides/proto3#json.
//
-// This package produces a different output than the standard "encoding/json"
+// This package produces a different output than the standard [encoding/json]
// package, which does not operate correctly on protocol buffer messages.
package protojson
diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/encode.go b/vendor/google.golang.org/protobuf/encoding/protojson/encode.go
index 66b95870e9..29846df222 100644
--- a/vendor/google.golang.org/protobuf/encoding/protojson/encode.go
+++ b/vendor/google.golang.org/protobuf/encoding/protojson/encode.go
@@ -25,15 +25,17 @@ const defaultIndent = " "
// Format formats the message as a multiline string.
// This function is only intended for human consumption and ignores errors.
-// Do not depend on the output being stable. It may change over time across
-// different versions of the program.
+// Do not depend on the output being stable. Its output will change across
+// different builds of your program, even when using the same version of the
+// protobuf module.
func Format(m proto.Message) string {
return MarshalOptions{Multiline: true}.Format(m)
}
-// Marshal writes the given proto.Message in JSON format using default options.
-// Do not depend on the output being stable. It may change over time across
-// different versions of the program.
+// Marshal writes the given [proto.Message] in JSON format using default options.
+// Do not depend on the output being stable. Its output will change across
+// different builds of your program, even when using the same version of the
+// protobuf module.
func Marshal(m proto.Message) ([]byte, error) {
return MarshalOptions{}.Marshal(m)
}
@@ -81,6 +83,25 @@ type MarshalOptions struct {
// ╚═══════╧════════════════════════════╝
EmitUnpopulated bool
+ // EmitDefaultValues specifies whether to emit default-valued primitive fields,
+ // empty lists, and empty maps. The fields affected are as follows:
+ // ╔═══════╤════════════════════════════════════════╗
+ // ║ JSON │ Protobuf field ║
+ // ╠═══════╪════════════════════════════════════════╣
+ // ║ false │ non-optional scalar boolean fields ║
+ // ║ 0 │ non-optional scalar numeric fields ║
+ // ║ "" │ non-optional scalar string/byte fields ║
+ // ║ [] │ empty repeated fields ║
+ // ║ {} │ empty map fields ║
+ // ╚═══════╧════════════════════════════════════════╝
+ //
+ // Behaves similarly to EmitUnpopulated, but does not emit "null"-value fields,
+ // i.e. presence-sensing fields that are omitted will remain omitted to preserve
+ // presence-sensing.
+ // EmitUnpopulated takes precedence over EmitDefaultValues since the former generates
+ // a strict superset of the latter.
+ EmitDefaultValues bool
+
// Resolver is used for looking up types when expanding google.protobuf.Any
// messages. If nil, this defaults to using protoregistry.GlobalTypes.
Resolver interface {
@@ -91,8 +112,9 @@ type MarshalOptions struct {
// Format formats the message as a string.
// This method is only intended for human consumption and ignores errors.
-// Do not depend on the output being stable. It may change over time across
-// different versions of the program.
+// Do not depend on the output being stable. Its output will change across
+// different builds of your program, even when using the same version of the
+// protobuf module.
func (o MarshalOptions) Format(m proto.Message) string {
if m == nil || !m.ProtoReflect().IsValid() {
return "" // invalid syntax, but okay since this is for debugging
@@ -102,9 +124,10 @@ func (o MarshalOptions) Format(m proto.Message) string {
return string(b)
}
-// Marshal marshals the given proto.Message in the JSON format using options in
-// MarshalOptions. Do not depend on the output being stable. It may change over
-// time across different versions of the program.
+// Marshal marshals the given [proto.Message] in the JSON format using options in
+// Do not depend on the output being stable. Its output will change across
+// different builds of your program, even when using the same version of the
+// protobuf module.
func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
return o.marshal(nil, m)
}
@@ -178,7 +201,11 @@ func (m typeURLFieldRanger) Range(f func(protoreflect.FieldDescriptor, protorefl
// unpopulatedFieldRanger wraps a protoreflect.Message and modifies its Range
// method to additionally iterate over unpopulated fields.
-type unpopulatedFieldRanger struct{ protoreflect.Message }
+type unpopulatedFieldRanger struct {
+ protoreflect.Message
+
+ skipNull bool
+}
func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
fds := m.Descriptor().Fields()
@@ -192,6 +219,9 @@ func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, proto
isProto2Scalar := fd.Syntax() == protoreflect.Proto2 && fd.Default().IsValid()
isSingularMessage := fd.Cardinality() != protoreflect.Repeated && fd.Message() != nil
if isProto2Scalar || isSingularMessage {
+ if m.skipNull {
+ continue
+ }
v = protoreflect.Value{} // use invalid value to emit null
}
if !f(fd, v) {
@@ -217,8 +247,11 @@ func (e encoder) marshalMessage(m protoreflect.Message, typeURL string) error {
defer e.EndObject()
var fields order.FieldRanger = m
- if e.opts.EmitUnpopulated {
- fields = unpopulatedFieldRanger{m}
+ switch {
+ case e.opts.EmitUnpopulated:
+ fields = unpopulatedFieldRanger{Message: m, skipNull: false}
+ case e.opts.EmitDefaultValues:
+ fields = unpopulatedFieldRanger{Message: m, skipNull: true}
}
if typeURL != "" {
fields = typeURLFieldRanger{fields, typeURL}
diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go b/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go
index 6c37d41744..4b177c8206 100644
--- a/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go
+++ b/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go
@@ -176,7 +176,7 @@ func (d decoder) unmarshalAny(m protoreflect.Message) error {
// Use another decoder to parse the unread bytes for @type field. This
// avoids advancing a read from current decoder because the current JSON
// object may contain the fields of the embedded type.
- dec := decoder{d.Clone(), UnmarshalOptions{}}
+ dec := decoder{d.Clone(), UnmarshalOptions{RecursionLimit: d.opts.RecursionLimit}}
tok, err := findTypeURL(dec)
switch err {
case errEmptyObject:
@@ -308,48 +308,29 @@ Loop:
// array) in order to advance the read to the next JSON value. It relies on
// the decoder returning an error if the types are not in valid sequence.
func (d decoder) skipJSONValue() error {
- tok, err := d.Read()
- if err != nil {
- return err
- }
- // Only need to continue reading for objects and arrays.
- switch tok.Kind() {
- case json.ObjectOpen:
- for {
- tok, err := d.Read()
- if err != nil {
- return err
- }
- switch tok.Kind() {
- case json.ObjectClose:
- return nil
- case json.Name:
- // Skip object field value.
- if err := d.skipJSONValue(); err != nil {
- return err
- }
- }
+ var open int
+ for {
+ tok, err := d.Read()
+ if err != nil {
+ return err
}
-
- case json.ArrayOpen:
- for {
- tok, err := d.Peek()
- if err != nil {
- return err
- }
- switch tok.Kind() {
- case json.ArrayClose:
- d.Read()
- return nil
- default:
- // Skip array item.
- if err := d.skipJSONValue(); err != nil {
- return err
- }
+ switch tok.Kind() {
+ case json.ObjectClose, json.ArrayClose:
+ open--
+ case json.ObjectOpen, json.ArrayOpen:
+ open++
+ if open > d.opts.RecursionLimit {
+ return errors.New("exceeded max recursion depth")
}
+ case json.EOF:
+ // This can only happen if there's a bug in Decoder.Read.
+ // Avoid an infinite loop if this does happen.
+ return errors.New("unexpected EOF")
+ }
+ if open == 0 {
+ return nil
}
}
- return nil
}
// unmarshalAnyValue unmarshals the given custom-type message from the JSON
diff --git a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go
index 4921b2d4a7..24bc98ac42 100644
--- a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go
+++ b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go
@@ -21,7 +21,7 @@ import (
"google.golang.org/protobuf/reflect/protoregistry"
)
-// Unmarshal reads the given []byte into the given proto.Message.
+// Unmarshal reads the given []byte into the given [proto.Message].
// The provided message must be mutable (e.g., a non-nil pointer to a message).
func Unmarshal(b []byte, m proto.Message) error {
return UnmarshalOptions{}.Unmarshal(b, m)
@@ -51,7 +51,7 @@ type UnmarshalOptions struct {
}
}
-// Unmarshal reads the given []byte and populates the given proto.Message
+// Unmarshal reads the given []byte and populates the given [proto.Message]
// using options in the UnmarshalOptions object.
// The provided message must be mutable (e.g., a non-nil pointer to a message).
func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
@@ -84,7 +84,7 @@ type decoder struct {
}
// newError returns an error object with position info.
-func (d decoder) newError(pos int, f string, x ...interface{}) error {
+func (d decoder) newError(pos int, f string, x ...any) error {
line, column := d.Position(pos)
head := fmt.Sprintf("(line %d:%d): ", line, column)
return errors.New(head+f, x...)
@@ -96,7 +96,7 @@ func (d decoder) unexpectedTokenError(tok text.Token) error {
}
// syntaxError returns a syntax error for given position.
-func (d decoder) syntaxError(pos int, f string, x ...interface{}) error {
+func (d decoder) syntaxError(pos int, f string, x ...any) error {
line, column := d.Position(pos)
head := fmt.Sprintf("syntax error (line %d:%d): ", line, column)
return errors.New(head+f, x...)
@@ -739,7 +739,9 @@ func (d decoder) skipValue() error {
case text.ListClose:
return nil
case text.MessageOpen:
- return d.skipMessageValue()
+ if err := d.skipMessageValue(); err != nil {
+ return err
+ }
default:
// Skip items. This will not validate whether skipped values are
// of the same type or not, same behavior as C++
diff --git a/vendor/google.golang.org/protobuf/encoding/prototext/encode.go b/vendor/google.golang.org/protobuf/encoding/prototext/encode.go
index 722a7b41df..1f57e6610a 100644
--- a/vendor/google.golang.org/protobuf/encoding/prototext/encode.go
+++ b/vendor/google.golang.org/protobuf/encoding/prototext/encode.go
@@ -27,15 +27,17 @@ const defaultIndent = " "
// Format formats the message as a multiline string.
// This function is only intended for human consumption and ignores errors.
-// Do not depend on the output being stable. It may change over time across
-// different versions of the program.
+// Do not depend on the output being stable. Its output will change across
+// different builds of your program, even when using the same version of the
+// protobuf module.
func Format(m proto.Message) string {
return MarshalOptions{Multiline: true}.Format(m)
}
-// Marshal writes the given proto.Message in textproto format using default
-// options. Do not depend on the output being stable. It may change over time
-// across different versions of the program.
+// Marshal writes the given [proto.Message] in textproto format using default
+// options. Do not depend on the output being stable. Its output will change
+// across different builds of your program, even when using the same version of
+// the protobuf module.
func Marshal(m proto.Message) ([]byte, error) {
return MarshalOptions{}.Marshal(m)
}
@@ -84,8 +86,9 @@ type MarshalOptions struct {
// Format formats the message as a string.
// This method is only intended for human consumption and ignores errors.
-// Do not depend on the output being stable. It may change over time across
-// different versions of the program.
+// Do not depend on the output being stable. Its output will change across
+// different builds of your program, even when using the same version of the
+// protobuf module.
func (o MarshalOptions) Format(m proto.Message) string {
if m == nil || !m.ProtoReflect().IsValid() {
return "" // invalid syntax, but okay since this is for debugging
@@ -97,9 +100,10 @@ func (o MarshalOptions) Format(m proto.Message) string {
return string(b)
}
-// Marshal writes the given proto.Message in textproto format using options in
-// MarshalOptions object. Do not depend on the output being stable. It may
-// change over time across different versions of the program.
+// Marshal writes the given [proto.Message] in textproto format using options in
+// MarshalOptions object. Do not depend on the output being stable. Its output
+// will change across different builds of your program, even when using the
+// same version of the protobuf module.
func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
return o.marshal(nil, m)
}
diff --git a/vendor/google.golang.org/protobuf/encoding/protowire/wire.go b/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
index f4b4686cf9..e942bc983e 100644
--- a/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
+++ b/vendor/google.golang.org/protobuf/encoding/protowire/wire.go
@@ -6,7 +6,7 @@
// See https://protobuf.dev/programming-guides/encoding.
//
// For marshaling and unmarshaling entire protobuf messages,
-// use the "google.golang.org/protobuf/proto" package instead.
+// use the [google.golang.org/protobuf/proto] package instead.
package protowire
import (
@@ -87,7 +87,7 @@ func ParseError(n int) error {
// ConsumeField parses an entire field record (both tag and value) and returns
// the field number, the wire type, and the total length.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
//
// The total length includes the tag header and the end group marker (if the
// field is a group).
@@ -104,8 +104,8 @@ func ConsumeField(b []byte) (Number, Type, int) {
}
// ConsumeFieldValue parses a field value and returns its length.
-// This assumes that the field Number and wire Type have already been parsed.
-// This returns a negative length upon an error (see ParseError).
+// This assumes that the field [Number] and wire [Type] have already been parsed.
+// This returns a negative length upon an error (see [ParseError]).
//
// When parsing a group, the length includes the end group marker and
// the end group is verified to match the starting field number.
@@ -164,7 +164,7 @@ func AppendTag(b []byte, num Number, typ Type) []byte {
}
// ConsumeTag parses b as a varint-encoded tag, reporting its length.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
func ConsumeTag(b []byte) (Number, Type, int) {
v, n := ConsumeVarint(b)
if n < 0 {
@@ -263,7 +263,7 @@ func AppendVarint(b []byte, v uint64) []byte {
}
// ConsumeVarint parses b as a varint-encoded uint64, reporting its length.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
func ConsumeVarint(b []byte) (v uint64, n int) {
var y uint64
if len(b) <= 0 {
@@ -384,7 +384,7 @@ func AppendFixed32(b []byte, v uint32) []byte {
}
// ConsumeFixed32 parses b as a little-endian uint32, reporting its length.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
func ConsumeFixed32(b []byte) (v uint32, n int) {
if len(b) < 4 {
return 0, errCodeTruncated
@@ -412,7 +412,7 @@ func AppendFixed64(b []byte, v uint64) []byte {
}
// ConsumeFixed64 parses b as a little-endian uint64, reporting its length.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
func ConsumeFixed64(b []byte) (v uint64, n int) {
if len(b) < 8 {
return 0, errCodeTruncated
@@ -432,7 +432,7 @@ func AppendBytes(b []byte, v []byte) []byte {
}
// ConsumeBytes parses b as a length-prefixed bytes value, reporting its length.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
func ConsumeBytes(b []byte) (v []byte, n int) {
m, n := ConsumeVarint(b)
if n < 0 {
@@ -456,7 +456,7 @@ func AppendString(b []byte, v string) []byte {
}
// ConsumeString parses b as a length-prefixed bytes value, reporting its length.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
func ConsumeString(b []byte) (v string, n int) {
bb, n := ConsumeBytes(b)
return string(bb), n
@@ -471,7 +471,7 @@ func AppendGroup(b []byte, num Number, v []byte) []byte {
// ConsumeGroup parses b as a group value until the trailing end group marker,
// and verifies that the end marker matches the provided num. The value v
// does not contain the end marker, while the length does contain the end marker.
-// This returns a negative length upon an error (see ParseError).
+// This returns a negative length upon an error (see [ParseError]).
func ConsumeGroup(num Number, b []byte) (v []byte, n int) {
n = ConsumeFieldValue(num, StartGroupType, b)
if n < 0 {
@@ -495,8 +495,8 @@ func SizeGroup(num Number, n int) int {
return n + SizeTag(num)
}
-// DecodeTag decodes the field Number and wire Type from its unified form.
-// The Number is -1 if the decoded field number overflows int32.
+// DecodeTag decodes the field [Number] and wire [Type] from its unified form.
+// The [Number] is -1 if the decoded field number overflows int32.
// Other than overflow, this does not check for field number validity.
func DecodeTag(x uint64) (Number, Type) {
// NOTE: MessageSet allows for larger field numbers than normal.
@@ -506,7 +506,7 @@ func DecodeTag(x uint64) (Number, Type) {
return Number(x >> 3), Type(x & 7)
}
-// EncodeTag encodes the field Number and wire Type into its unified form.
+// EncodeTag encodes the field [Number] and wire [Type] into its unified form.
func EncodeTag(num Number, typ Type) uint64 {
return uint64(num)<<3 | uint64(typ&7)
}
diff --git a/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go b/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go
index db5248e1b5..87e46bd4df 100644
--- a/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go
+++ b/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go
@@ -83,7 +83,13 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
case protoreflect.FileImports:
for i := 0; i < vs.Len(); i++ {
var rs records
- rs.Append(reflect.ValueOf(vs.Get(i)), "Path", "Package", "IsPublic", "IsWeak")
+ rv := reflect.ValueOf(vs.Get(i))
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Path"), "Path"},
+ {rv.MethodByName("Package"), "Package"},
+ {rv.MethodByName("IsPublic"), "IsPublic"},
+ {rv.MethodByName("IsWeak"), "IsWeak"},
+ }...)
ss = append(ss, "{"+rs.Join()+"}")
}
return start + joinStrings(ss, allowMulti) + end
@@ -92,34 +98,26 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
for i := 0; i < vs.Len(); i++ {
m := reflect.ValueOf(vs).MethodByName("Get")
v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface()
- ss = append(ss, formatDescOpt(v.(protoreflect.Descriptor), false, allowMulti && !isEnumValue))
+ ss = append(ss, formatDescOpt(v.(protoreflect.Descriptor), false, allowMulti && !isEnumValue, nil))
}
return start + joinStrings(ss, allowMulti && isEnumValue) + end
}
}
-// descriptorAccessors is a list of accessors to print for each descriptor.
-//
-// Do not print all accessors since some contain redundant information,
-// while others are pointers that we do not want to follow since the descriptor
-// is actually a cyclic graph.
-//
-// Using a list allows us to print the accessors in a sensible order.
-var descriptorAccessors = map[reflect.Type][]string{
- reflect.TypeOf((*protoreflect.FileDescriptor)(nil)).Elem(): {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"},
- reflect.TypeOf((*protoreflect.MessageDescriptor)(nil)).Elem(): {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"},
- reflect.TypeOf((*protoreflect.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "HasPresence", "IsExtension", "IsPacked", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"},
- reflect.TypeOf((*protoreflect.OneofDescriptor)(nil)).Elem(): {"Fields"}, // not directly used; must keep in sync with formatDescOpt
- reflect.TypeOf((*protoreflect.EnumDescriptor)(nil)).Elem(): {"Values", "ReservedNames", "ReservedRanges"},
- reflect.TypeOf((*protoreflect.EnumValueDescriptor)(nil)).Elem(): {"Number"},
- reflect.TypeOf((*protoreflect.ServiceDescriptor)(nil)).Elem(): {"Methods"},
- reflect.TypeOf((*protoreflect.MethodDescriptor)(nil)).Elem(): {"Input", "Output", "IsStreamingClient", "IsStreamingServer"},
+type methodAndName struct {
+ method reflect.Value
+ name string
}
func FormatDesc(s fmt.State, r rune, t protoreflect.Descriptor) {
- io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#'))))
+ io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')), nil))
}
-func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
+
+func InternalFormatDescOptForTesting(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
+ return formatDescOpt(t, isRoot, allowMulti, record)
+}
+
+func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool, record func(string)) string {
rv := reflect.ValueOf(t)
rt := rv.MethodByName("ProtoType").Type().In(0)
@@ -129,26 +127,60 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
}
_, isFile := t.(protoreflect.FileDescriptor)
- rs := records{allowMulti: allowMulti}
+ rs := records{
+ allowMulti: allowMulti,
+ record: record,
+ }
if t.IsPlaceholder() {
if isFile {
- rs.Append(rv, "Path", "Package", "IsPlaceholder")
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Path"), "Path"},
+ {rv.MethodByName("Package"), "Package"},
+ {rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
+ }...)
} else {
- rs.Append(rv, "FullName", "IsPlaceholder")
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("FullName"), "FullName"},
+ {rv.MethodByName("IsPlaceholder"), "IsPlaceholder"},
+ }...)
}
} else {
switch {
case isFile:
- rs.Append(rv, "Syntax")
+ rs.Append(rv, methodAndName{rv.MethodByName("Syntax"), "Syntax"})
case isRoot:
- rs.Append(rv, "Syntax", "FullName")
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Syntax"), "Syntax"},
+ {rv.MethodByName("FullName"), "FullName"},
+ }...)
default:
- rs.Append(rv, "Name")
+ rs.Append(rv, methodAndName{rv.MethodByName("Name"), "Name"})
}
switch t := t.(type) {
case protoreflect.FieldDescriptor:
- for _, s := range descriptorAccessors[rt] {
- switch s {
+ accessors := []methodAndName{
+ {rv.MethodByName("Number"), "Number"},
+ {rv.MethodByName("Cardinality"), "Cardinality"},
+ {rv.MethodByName("Kind"), "Kind"},
+ {rv.MethodByName("HasJSONName"), "HasJSONName"},
+ {rv.MethodByName("JSONName"), "JSONName"},
+ {rv.MethodByName("HasPresence"), "HasPresence"},
+ {rv.MethodByName("IsExtension"), "IsExtension"},
+ {rv.MethodByName("IsPacked"), "IsPacked"},
+ {rv.MethodByName("IsWeak"), "IsWeak"},
+ {rv.MethodByName("IsList"), "IsList"},
+ {rv.MethodByName("IsMap"), "IsMap"},
+ {rv.MethodByName("MapKey"), "MapKey"},
+ {rv.MethodByName("MapValue"), "MapValue"},
+ {rv.MethodByName("HasDefault"), "HasDefault"},
+ {rv.MethodByName("Default"), "Default"},
+ {rv.MethodByName("ContainingOneof"), "ContainingOneof"},
+ {rv.MethodByName("ContainingMessage"), "ContainingMessage"},
+ {rv.MethodByName("Message"), "Message"},
+ {rv.MethodByName("Enum"), "Enum"},
+ }
+ for _, s := range accessors {
+ switch s.name {
case "MapKey":
if k := t.MapKey(); k != nil {
rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()})
@@ -157,20 +189,20 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
if v := t.MapValue(); v != nil {
switch v.Kind() {
case protoreflect.EnumKind:
- rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Enum().FullName())})
+ rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Enum().FullName())})
case protoreflect.MessageKind, protoreflect.GroupKind:
- rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Message().FullName())})
+ rs.AppendRecs("MapValue", [2]string{"MapValue", string(v.Message().FullName())})
default:
- rs.recs = append(rs.recs, [2]string{"MapValue", v.Kind().String()})
+ rs.AppendRecs("MapValue", [2]string{"MapValue", v.Kind().String()})
}
}
case "ContainingOneof":
if od := t.ContainingOneof(); od != nil {
- rs.recs = append(rs.recs, [2]string{"Oneof", string(od.Name())})
+ rs.AppendRecs("ContainingOneof", [2]string{"Oneof", string(od.Name())})
}
case "ContainingMessage":
if t.IsExtension() {
- rs.recs = append(rs.recs, [2]string{"Extendee", string(t.ContainingMessage().FullName())})
+ rs.AppendRecs("ContainingMessage", [2]string{"Extendee", string(t.ContainingMessage().FullName())})
}
case "Message":
if !t.IsMap() {
@@ -187,13 +219,62 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
ss = append(ss, string(fs.Get(i).Name()))
}
if len(ss) > 0 {
- rs.recs = append(rs.recs, [2]string{"Fields", "[" + joinStrings(ss, false) + "]"})
+ rs.AppendRecs("Fields", [2]string{"Fields", "[" + joinStrings(ss, false) + "]"})
}
- default:
- rs.Append(rv, descriptorAccessors[rt]...)
+
+ case protoreflect.FileDescriptor:
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Path"), "Path"},
+ {rv.MethodByName("Package"), "Package"},
+ {rv.MethodByName("Imports"), "Imports"},
+ {rv.MethodByName("Messages"), "Messages"},
+ {rv.MethodByName("Enums"), "Enums"},
+ {rv.MethodByName("Extensions"), "Extensions"},
+ {rv.MethodByName("Services"), "Services"},
+ }...)
+
+ case protoreflect.MessageDescriptor:
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("IsMapEntry"), "IsMapEntry"},
+ {rv.MethodByName("Fields"), "Fields"},
+ {rv.MethodByName("Oneofs"), "Oneofs"},
+ {rv.MethodByName("ReservedNames"), "ReservedNames"},
+ {rv.MethodByName("ReservedRanges"), "ReservedRanges"},
+ {rv.MethodByName("RequiredNumbers"), "RequiredNumbers"},
+ {rv.MethodByName("ExtensionRanges"), "ExtensionRanges"},
+ {rv.MethodByName("Messages"), "Messages"},
+ {rv.MethodByName("Enums"), "Enums"},
+ {rv.MethodByName("Extensions"), "Extensions"},
+ }...)
+
+ case protoreflect.EnumDescriptor:
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Values"), "Values"},
+ {rv.MethodByName("ReservedNames"), "ReservedNames"},
+ {rv.MethodByName("ReservedRanges"), "ReservedRanges"},
+ {rv.MethodByName("IsClosed"), "IsClosed"},
+ }...)
+
+ case protoreflect.EnumValueDescriptor:
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Number"), "Number"},
+ }...)
+
+ case protoreflect.ServiceDescriptor:
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Methods"), "Methods"},
+ }...)
+
+ case protoreflect.MethodDescriptor:
+ rs.Append(rv, []methodAndName{
+ {rv.MethodByName("Input"), "Input"},
+ {rv.MethodByName("Output"), "Output"},
+ {rv.MethodByName("IsStreamingClient"), "IsStreamingClient"},
+ {rv.MethodByName("IsStreamingServer"), "IsStreamingServer"},
+ }...)
}
- if rv.MethodByName("GoType").IsValid() {
- rs.Append(rv, "GoType")
+ if m := rv.MethodByName("GoType"); m.IsValid() {
+ rs.Append(rv, methodAndName{m, "GoType"})
}
}
return start + rs.Join() + end
@@ -202,19 +283,34 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool) string {
type records struct {
recs [][2]string
allowMulti bool
+
+ // record is a function that will be called for every Append() or
+ // AppendRecs() call, to be used for testing with the
+ // InternalFormatDescOptForTesting function.
+ record func(string)
}
-func (rs *records) Append(v reflect.Value, accessors ...string) {
+func (rs *records) AppendRecs(fieldName string, newRecs [2]string) {
+ if rs.record != nil {
+ rs.record(fieldName)
+ }
+ rs.recs = append(rs.recs, newRecs)
+}
+
+func (rs *records) Append(v reflect.Value, accessors ...methodAndName) {
for _, a := range accessors {
+ if rs.record != nil {
+ rs.record(a.name)
+ }
var rv reflect.Value
- if m := v.MethodByName(a); m.IsValid() {
- rv = m.Call(nil)[0]
+ if a.method.IsValid() {
+ rv = a.method.Call(nil)[0]
}
if v.Kind() == reflect.Struct && !rv.IsValid() {
- rv = v.FieldByName(a)
+ rv = v.FieldByName(a.name)
}
if !rv.IsValid() {
- panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a))
+ panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a.name))
}
if _, ok := rv.Interface().(protoreflect.Value); ok {
rv = rv.MethodByName("Interface").Call(nil)[0]
@@ -261,7 +357,7 @@ func (rs *records) Append(v reflect.Value, accessors ...string) {
default:
s = fmt.Sprint(v)
}
- rs.recs = append(rs.recs, [2]string{a, s})
+ rs.recs = append(rs.recs, [2]string{a.name, s})
}
}
diff --git a/vendor/google.golang.org/protobuf/internal/editiondefaults/defaults.go b/vendor/google.golang.org/protobuf/internal/editiondefaults/defaults.go
new file mode 100644
index 0000000000..14656b65ab
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/internal/editiondefaults/defaults.go
@@ -0,0 +1,12 @@
+// Copyright 2024 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 editiondefaults contains the binary representation of the editions
+// defaults.
+package editiondefaults
+
+import _ "embed"
+
+//go:embed editions_defaults.binpb
+var Defaults []byte
diff --git a/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb b/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb
new file mode 100644
index 0000000000..ff6a38360a
Binary files /dev/null and b/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb differ
diff --git a/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go b/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
new file mode 100644
index 0000000000..029a6a12d7
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go
@@ -0,0 +1,13 @@
+// Copyright 2024 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 editionssupport defines constants for editions that are supported.
+package editionssupport
+
+import descriptorpb "google.golang.org/protobuf/types/descriptorpb"
+
+const (
+ Minimum = descriptorpb.Edition_EDITION_PROTO2
+ Maximum = descriptorpb.Edition_EDITION_2023
+)
diff --git a/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go b/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go
index d043a6ebe0..ea1d3e65a5 100644
--- a/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go
+++ b/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go
@@ -121,7 +121,7 @@ func (d *Decoder) Read() (Token, error) {
case ObjectClose:
if len(d.openStack) == 0 ||
- d.lastToken.kind == comma ||
+ d.lastToken.kind&(Name|comma) != 0 ||
d.openStack[len(d.openStack)-1] != ObjectOpen {
return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString())
}
@@ -214,7 +214,7 @@ func (d *Decoder) parseNext() (Token, error) {
// newSyntaxError returns an error with line and column information useful for
// syntax errors.
-func (d *Decoder) newSyntaxError(pos int, f string, x ...interface{}) error {
+func (d *Decoder) newSyntaxError(pos int, f string, x ...any) error {
e := errors.New(f, x...)
line, column := d.Position(pos)
return errors.New("syntax error (line %d:%d): %v", line, column, e)
diff --git a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go
index 373d208374..7e87c76044 100644
--- a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go
+++ b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go
@@ -32,6 +32,7 @@ var byteType = reflect.TypeOf(byte(0))
func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor {
f := new(filedesc.Field)
f.L0.ParentFile = filedesc.SurrogateProto2
+ f.L1.EditionFeatures = f.L0.ParentFile.L1.EditionFeatures
for len(tag) > 0 {
i := strings.IndexByte(tag, ',')
if i < 0 {
@@ -107,8 +108,7 @@ func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescri
f.L1.StringName.InitJSON(jsonName)
}
case s == "packed":
- f.L1.HasPacked = true
- f.L1.IsPacked = true
+ f.L1.EditionFeatures.IsPacked = true
case strings.HasPrefix(s, "weak="):
f.L1.IsWeak = true
f.L1.Message = filedesc.PlaceholderMessage(protoreflect.FullName(s[len("weak="):]))
diff --git a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go
index 87853e786d..099b2bf451 100644
--- a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go
+++ b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go
@@ -601,7 +601,7 @@ func (d *Decoder) consumeToken(kind Kind, size int, attrs uint8) Token {
// newSyntaxError returns a syntax error with line and column information for
// current position.
-func (d *Decoder) newSyntaxError(f string, x ...interface{}) error {
+func (d *Decoder) newSyntaxError(f string, x ...any) error {
e := errors.New(f, x...)
line, column := d.Position(len(d.orig) - len(d.in))
return errors.New("syntax error (line %d:%d): %v", line, column, e)
diff --git a/vendor/google.golang.org/protobuf/internal/errors/errors.go b/vendor/google.golang.org/protobuf/internal/errors/errors.go
index 20c17b35e3..c2d6bd5265 100644
--- a/vendor/google.golang.org/protobuf/internal/errors/errors.go
+++ b/vendor/google.golang.org/protobuf/internal/errors/errors.go
@@ -17,7 +17,7 @@ var Error = errors.New("protobuf error")
// New formats a string according to the format specifier and arguments and
// returns an error that has a "proto" prefix.
-func New(f string, x ...interface{}) error {
+func New(f string, x ...any) error {
return &prefixError{s: format(f, x...)}
}
@@ -43,7 +43,7 @@ func (e *prefixError) Unwrap() error {
// Wrap returns an error that has a "proto" prefix, the formatted string described
// by the format specifier and arguments, and a suffix of err. The error wraps err.
-func Wrap(err error, f string, x ...interface{}) error {
+func Wrap(err error, f string, x ...any) error {
return &wrapError{
s: format(f, x...),
err: err,
@@ -67,7 +67,7 @@ func (e *wrapError) Is(target error) bool {
return target == Error
}
-func format(f string, x ...interface{}) string {
+func format(f string, x ...any) string {
// avoid "proto: " prefix when chaining
for i := 0; i < len(x); i++ {
switch e := x[i].(type) {
@@ -87,3 +87,18 @@ func InvalidUTF8(name string) error {
func RequiredNotSet(name string) error {
return New("required field %v not set", name)
}
+
+type SizeMismatchError struct {
+ Calculated, Measured int
+}
+
+func (e *SizeMismatchError) Error() string {
+ return fmt.Sprintf("size mismatch (see https://github.com/golang/protobuf/issues/1609): calculated=%d, measured=%d", e.Calculated, e.Measured)
+}
+
+func MismatchedSizeCalculation(calculated, measured int) error {
+ return &SizeMismatchError{
+ Calculated: calculated,
+ Measured: measured,
+ }
+}
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
index 7c3689baee..df53ff40b2 100644
--- a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go
@@ -7,6 +7,7 @@ package filedesc
import (
"bytes"
"fmt"
+ "strings"
"sync"
"sync/atomic"
@@ -21,11 +22,26 @@ import (
"google.golang.org/protobuf/reflect/protoregistry"
)
+// Edition is an Enum for proto2.Edition
+type Edition int32
+
+// These values align with the value of Enum in descriptor.proto which allows
+// direct conversion between the proto enum and this enum.
+const (
+ EditionUnknown Edition = 0
+ EditionProto2 Edition = 998
+ EditionProto3 Edition = 999
+ Edition2023 Edition = 1000
+ EditionUnsupported Edition = 100000
+)
+
// The types in this file may have a suffix:
// • L0: Contains fields common to all descriptors (except File) and
// must be initialized up front.
// • L1: Contains fields specific to a descriptor and
-// must be initialized up front.
+// must be initialized up front. If the associated proto uses Editions, the
+// Editions features must always be resolved. If not explicitly set, the
+// appropriate default must be resolved and set.
// • L2: Contains fields that are lazily initialized when constructing
// from the raw file descriptor. When constructing as a literal, the L2
// fields must be initialized up front.
@@ -44,6 +60,7 @@ type (
}
FileL1 struct {
Syntax protoreflect.Syntax
+ Edition Edition // Only used if Syntax == Editions
Path string
Package protoreflect.FullName
@@ -51,21 +68,53 @@ type (
Messages Messages
Extensions Extensions
Services Services
+
+ EditionFeatures EditionFeatures
}
FileL2 struct {
Options func() protoreflect.ProtoMessage
Imports FileImports
Locations SourceLocations
}
+
+ EditionFeatures struct {
+ // IsFieldPresence is true if field_presence is EXPLICIT
+ // https://protobuf.dev/editions/features/#field_presence
+ IsFieldPresence bool
+ // IsFieldPresence is true if field_presence is LEGACY_REQUIRED
+ // https://protobuf.dev/editions/features/#field_presence
+ IsLegacyRequired bool
+ // IsOpenEnum is true if enum_type is OPEN
+ // https://protobuf.dev/editions/features/#enum_type
+ IsOpenEnum bool
+ // IsPacked is true if repeated_field_encoding is PACKED
+ // https://protobuf.dev/editions/features/#repeated_field_encoding
+ IsPacked bool
+ // IsUTF8Validated is true if utf_validation is VERIFY
+ // https://protobuf.dev/editions/features/#utf8_validation
+ IsUTF8Validated bool
+ // IsDelimitedEncoded is true if message_encoding is DELIMITED
+ // https://protobuf.dev/editions/features/#message_encoding
+ IsDelimitedEncoded bool
+ // IsJSONCompliant is true if json_format is ALLOW
+ // https://protobuf.dev/editions/features/#json_format
+ IsJSONCompliant bool
+ // GenerateLegacyUnmarshalJSON determines if the plugin generates the
+ // UnmarshalJSON([]byte) error method for enums.
+ GenerateLegacyUnmarshalJSON bool
+ }
)
func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd }
func (fd *File) Parent() protoreflect.Descriptor { return nil }
func (fd *File) Index() int { return 0 }
func (fd *File) Syntax() protoreflect.Syntax { return fd.L1.Syntax }
-func (fd *File) Name() protoreflect.Name { return fd.L1.Package.Name() }
-func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
-func (fd *File) IsPlaceholder() bool { return false }
+
+// Not exported and just used to reconstruct the original FileDescriptor proto
+func (fd *File) Edition() int32 { return int32(fd.L1.Edition) }
+func (fd *File) Name() protoreflect.Name { return fd.L1.Package.Name() }
+func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package }
+func (fd *File) IsPlaceholder() bool { return false }
func (fd *File) Options() protoreflect.ProtoMessage {
if f := fd.lazyInit().Options; f != nil {
return f()
@@ -117,6 +166,8 @@ type (
}
EnumL1 struct {
eagerValues bool // controls whether EnumL2.Values is already populated
+
+ EditionFeatures EditionFeatures
}
EnumL2 struct {
Options func() protoreflect.ProtoMessage
@@ -155,6 +206,9 @@ func (ed *Enum) lazyInit() *EnumL2 {
ed.L0.ParentFile.lazyInit() // implicitly initializes L2
return ed.L2
}
+func (ed *Enum) IsClosed() bool {
+ return !ed.L1.EditionFeatures.IsOpenEnum
+}
func (ed *EnumValue) Options() protoreflect.ProtoMessage {
if f := ed.L1.Options; f != nil {
@@ -178,6 +232,8 @@ type (
Extensions Extensions
IsMapEntry bool // promoted from google.protobuf.MessageOptions
IsMessageSet bool // promoted from google.protobuf.MessageOptions
+
+ EditionFeatures EditionFeatures
}
MessageL2 struct {
Options func() protoreflect.ProtoMessage
@@ -202,14 +258,12 @@ type (
StringName stringName
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
IsWeak bool // promoted from google.protobuf.FieldOptions
- HasPacked bool // promoted from google.protobuf.FieldOptions
- IsPacked bool // promoted from google.protobuf.FieldOptions
- HasEnforceUTF8 bool // promoted from google.protobuf.FieldOptions
- EnforceUTF8 bool // promoted from google.protobuf.FieldOptions
Default defaultValue
ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields
Enum protoreflect.EnumDescriptor
Message protoreflect.MessageDescriptor
+
+ EditionFeatures EditionFeatures
}
Oneof struct {
@@ -219,6 +273,8 @@ type (
OneofL1 struct {
Options func() protoreflect.ProtoMessage
Fields OneofFields // must be consistent with Message.Fields.ContainingOneof
+
+ EditionFeatures EditionFeatures
}
)
@@ -268,25 +324,30 @@ func (fd *Field) Options() protoreflect.ProtoMessage {
}
func (fd *Field) Number() protoreflect.FieldNumber { return fd.L1.Number }
func (fd *Field) Cardinality() protoreflect.Cardinality { return fd.L1.Cardinality }
-func (fd *Field) Kind() protoreflect.Kind { return fd.L1.Kind }
-func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON }
-func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) }
-func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) }
+func (fd *Field) Kind() protoreflect.Kind {
+ return fd.L1.Kind
+}
+func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON }
+func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) }
+func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) }
func (fd *Field) HasPresence() bool {
- return fd.L1.Cardinality != protoreflect.Repeated && (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil)
+ if fd.L1.Cardinality == protoreflect.Repeated {
+ return false
+ }
+ return fd.IsExtension() || fd.L1.EditionFeatures.IsFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil
}
func (fd *Field) HasOptionalKeyword() bool {
return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
}
func (fd *Field) IsPacked() bool {
- if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Repeated {
- switch fd.L1.Kind {
- case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
- default:
- return true
- }
+ if fd.L1.Cardinality != protoreflect.Repeated {
+ return false
}
- return fd.L1.IsPacked
+ switch fd.L1.Kind {
+ case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
+ return false
+ }
+ return fd.L1.EditionFeatures.IsPacked
}
func (fd *Field) IsExtension() bool { return false }
func (fd *Field) IsWeak() bool { return fd.L1.IsWeak }
@@ -322,6 +383,10 @@ func (fd *Field) Message() protoreflect.MessageDescriptor {
}
return fd.L1.Message
}
+func (fd *Field) IsMapEntry() bool {
+ parent, ok := fd.L0.Parent.(protoreflect.MessageDescriptor)
+ return ok && parent.IsMapEntry()
+}
func (fd *Field) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) }
func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}
@@ -333,10 +398,7 @@ func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {}
// WARNING: This method is exempt from the compatibility promise and may be
// removed in the future without warning.
func (fd *Field) EnforceUTF8() bool {
- if fd.L1.HasEnforceUTF8 {
- return fd.L1.EnforceUTF8
- }
- return fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3
+ return fd.L1.EditionFeatures.IsUTF8Validated
}
func (od *Oneof) IsSynthetic() bool {
@@ -359,16 +421,16 @@ type (
L2 *ExtensionL2 // protected by fileDesc.once
}
ExtensionL1 struct {
- Number protoreflect.FieldNumber
- Extendee protoreflect.MessageDescriptor
- Cardinality protoreflect.Cardinality
- Kind protoreflect.Kind
+ Number protoreflect.FieldNumber
+ Extendee protoreflect.MessageDescriptor
+ Cardinality protoreflect.Cardinality
+ Kind protoreflect.Kind
+ EditionFeatures EditionFeatures
}
ExtensionL2 struct {
Options func() protoreflect.ProtoMessage
StringName stringName
IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
- IsPacked bool // promoted from google.protobuf.FieldOptions
Default defaultValue
Enum protoreflect.EnumDescriptor
Message protoreflect.MessageDescriptor
@@ -391,7 +453,16 @@ func (xd *Extension) HasPresence() bool { return xd.L1.Cardi
func (xd *Extension) HasOptionalKeyword() bool {
return (xd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && xd.L1.Cardinality == protoreflect.Optional) || xd.lazyInit().IsProto3Optional
}
-func (xd *Extension) IsPacked() bool { return xd.lazyInit().IsPacked }
+func (xd *Extension) IsPacked() bool {
+ if xd.L1.Cardinality != protoreflect.Repeated {
+ return false
+ }
+ switch xd.L1.Kind {
+ case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
+ return false
+ }
+ return xd.L1.EditionFeatures.IsPacked
+}
func (xd *Extension) IsExtension() bool { return true }
func (xd *Extension) IsWeak() bool { return false }
func (xd *Extension) IsList() bool { return xd.Cardinality() == protoreflect.Repeated }
@@ -472,8 +543,9 @@ func (md *Method) ProtoInternal(pragma.DoNotImplement) {}
// Surrogate files are can be used to create standalone descriptors
// where the syntax is only information derived from the parent file.
var (
- SurrogateProto2 = &File{L1: FileL1{Syntax: protoreflect.Proto2}, L2: &FileL2{}}
- SurrogateProto3 = &File{L1: FileL1{Syntax: protoreflect.Proto3}, L2: &FileL2{}}
+ SurrogateProto2 = &File{L1: FileL1{Syntax: protoreflect.Proto2}, L2: &FileL2{}}
+ SurrogateProto3 = &File{L1: FileL1{Syntax: protoreflect.Proto3}, L2: &FileL2{}}
+ SurrogateEdition2023 = &File{L1: FileL1{Syntax: protoreflect.Editions, Edition: Edition2023}, L2: &FileL2{}}
)
type (
@@ -515,6 +587,34 @@ func (s *stringName) InitJSON(name string) {
s.nameJSON = name
}
+// Returns true if this field is structured like the synthetic field of a proto2
+// group. This allows us to expand our treatment of delimited fields without
+// breaking proto2 files that have been upgraded to editions.
+func isGroupLike(fd protoreflect.FieldDescriptor) bool {
+ // Groups are always group types.
+ if fd.Kind() != protoreflect.GroupKind {
+ return false
+ }
+
+ // Group fields are always the lowercase type name.
+ if strings.ToLower(string(fd.Message().Name())) != string(fd.Name()) {
+ return false
+ }
+
+ // Groups could only be defined in the same file they're used.
+ if fd.Message().ParentFile() != fd.ParentFile() {
+ return false
+ }
+
+ // Group messages are always defined in the same scope as the field. File
+ // level extensions will compare NULL == NULL here, which is why the file
+ // comparison above is necessary to ensure both come from the same file.
+ if fd.IsExtension() {
+ return fd.Parent() == fd.Message().Parent()
+ }
+ return fd.ContainingMessage() == fd.Message().Parent()
+}
+
func (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName {
s.once.Do(func() {
if fd.IsExtension() {
@@ -535,7 +635,7 @@ func (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName {
// Format the text name.
s.nameText = string(fd.Name())
- if fd.Kind() == protoreflect.GroupKind {
+ if isGroupLike(fd) {
s.nameText = string(fd.Message().Name())
}
}
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
index 4a1584c9d2..8a57d60b08 100644
--- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go
@@ -5,6 +5,7 @@
package filedesc
import (
+ "fmt"
"sync"
"google.golang.org/protobuf/encoding/protowire"
@@ -98,6 +99,7 @@ func (fd *File) unmarshalSeed(b []byte) {
var prevField protoreflect.FieldNumber
var numEnums, numMessages, numExtensions, numServices int
var posEnums, posMessages, posExtensions, posServices int
+ var options []byte
b0 := b
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
@@ -111,8 +113,12 @@ func (fd *File) unmarshalSeed(b []byte) {
switch string(v) {
case "proto2":
fd.L1.Syntax = protoreflect.Proto2
+ fd.L1.Edition = EditionProto2
case "proto3":
fd.L1.Syntax = protoreflect.Proto3
+ fd.L1.Edition = EditionProto3
+ case "editions":
+ fd.L1.Syntax = protoreflect.Editions
default:
panic("invalid syntax")
}
@@ -120,6 +126,8 @@ func (fd *File) unmarshalSeed(b []byte) {
fd.L1.Path = sb.MakeString(v)
case genid.FileDescriptorProto_Package_field_number:
fd.L1.Package = protoreflect.FullName(sb.MakeString(v))
+ case genid.FileDescriptorProto_Options_field_number:
+ options = v
case genid.FileDescriptorProto_EnumType_field_number:
if prevField != genid.FileDescriptorProto_EnumType_field_number {
if numEnums > 0 {
@@ -154,6 +162,13 @@ func (fd *File) unmarshalSeed(b []byte) {
numServices++
}
prevField = num
+ case protowire.VarintType:
+ v, m := protowire.ConsumeVarint(b)
+ b = b[m:]
+ switch num {
+ case genid.FileDescriptorProto_Edition_field_number:
+ fd.L1.Edition = Edition(v)
+ }
default:
m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:]
@@ -164,6 +179,14 @@ func (fd *File) unmarshalSeed(b []byte) {
// If syntax is missing, it is assumed to be proto2.
if fd.L1.Syntax == 0 {
fd.L1.Syntax = protoreflect.Proto2
+ fd.L1.Edition = EditionProto2
+ }
+
+ fd.L1.EditionFeatures = getFeaturesFor(fd.L1.Edition)
+
+ // Parse editions features from options if any
+ if options != nil {
+ fd.unmarshalSeedOptions(options)
}
// Must allocate all declarations before parsing each descriptor type
@@ -219,10 +242,33 @@ func (fd *File) unmarshalSeed(b []byte) {
}
}
+func (fd *File) unmarshalSeedOptions(b []byte) {
+ for b := b; len(b) > 0; {
+ num, typ, n := protowire.ConsumeTag(b)
+ b = b[n:]
+ switch typ {
+ case protowire.BytesType:
+ v, m := protowire.ConsumeBytes(b)
+ b = b[m:]
+ switch num {
+ case genid.FileOptions_Features_field_number:
+ if fd.Syntax() != protoreflect.Editions {
+ panic(fmt.Sprintf("invalid descriptor: using edition features in a proto with syntax %s", fd.Syntax()))
+ }
+ fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
+ }
+ default:
+ m := protowire.ConsumeFieldValue(num, typ, b)
+ b = b[m:]
+ }
+ }
+}
+
func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
ed.L0.ParentFile = pf
ed.L0.Parent = pd
ed.L0.Index = i
+ ed.L1.EditionFeatures = featuresFromParentDesc(ed.Parent())
var numValues int
for b := b; len(b) > 0; {
@@ -275,6 +321,7 @@ func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
md.L0.ParentFile = pf
md.L0.Parent = pd
md.L0.Index = i
+ md.L1.EditionFeatures = featuresFromParentDesc(md.Parent())
var prevField protoreflect.FieldNumber
var numEnums, numMessages, numExtensions int
@@ -380,6 +427,13 @@ func (md *Message) unmarshalSeedOptions(b []byte) {
case genid.MessageOptions_MessageSetWireFormat_field_number:
md.L1.IsMessageSet = protowire.DecodeBool(v)
}
+ case protowire.BytesType:
+ v, m := protowire.ConsumeBytes(b)
+ b = b[m:]
+ switch num {
+ case genid.MessageOptions_Features_field_number:
+ md.L1.EditionFeatures = unmarshalFeatureSet(v, md.L1.EditionFeatures)
+ }
default:
m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:]
@@ -391,6 +445,7 @@ func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd prot
xd.L0.ParentFile = pf
xd.L0.Parent = pd
xd.L0.Index = i
+ xd.L1.EditionFeatures = featuresFromParentDesc(pd)
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
@@ -415,6 +470,38 @@ func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd prot
xd.L0.FullName = appendFullName(sb, pd.FullName(), v)
case genid.FieldDescriptorProto_Extendee_field_number:
xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v))
+ case genid.FieldDescriptorProto_Options_field_number:
+ xd.unmarshalOptions(v)
+ }
+ default:
+ m := protowire.ConsumeFieldValue(num, typ, b)
+ b = b[m:]
+ }
+ }
+
+ if xd.L1.Kind == protoreflect.MessageKind && xd.L1.EditionFeatures.IsDelimitedEncoded {
+ xd.L1.Kind = protoreflect.GroupKind
+ }
+}
+
+func (xd *Extension) unmarshalOptions(b []byte) {
+ for len(b) > 0 {
+ num, typ, n := protowire.ConsumeTag(b)
+ b = b[n:]
+ switch typ {
+ case protowire.VarintType:
+ v, m := protowire.ConsumeVarint(b)
+ b = b[m:]
+ switch num {
+ case genid.FieldOptions_Packed_field_number:
+ xd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v)
+ }
+ case protowire.BytesType:
+ v, m := protowire.ConsumeBytes(b)
+ b = b[m:]
+ switch num {
+ case genid.FieldOptions_Features_field_number:
+ xd.L1.EditionFeatures = unmarshalFeatureSet(v, xd.L1.EditionFeatures)
}
default:
m := protowire.ConsumeFieldValue(num, typ, b)
@@ -447,7 +534,7 @@ func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor
}
var nameBuilderPool = sync.Pool{
- New: func() interface{} { return new(strs.Builder) },
+ New: func() any { return new(strs.Builder) },
}
func getBuilder() *strs.Builder {
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
index 736a19a75b..e56c91a8db 100644
--- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go
@@ -45,6 +45,11 @@ func (file *File) resolveMessages() {
case protoreflect.MessageKind, protoreflect.GroupKind:
fd.L1.Message = file.resolveMessageDependency(fd.L1.Message, listFieldDeps, depIdx)
depIdx++
+ if fd.L1.Kind == protoreflect.GroupKind && (fd.IsMap() || fd.IsMapEntry()) {
+ // A map field might inherit delimited encoding from a file-wide default feature.
+ // But maps never actually use delimited encoding. (At least for now...)
+ fd.L1.Kind = protoreflect.MessageKind
+ }
}
// Default is resolved here since it depends on Enum being resolved.
@@ -414,6 +419,7 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
fd.L0.ParentFile = pf
fd.L0.Parent = pd
fd.L0.Index = i
+ fd.L1.EditionFeatures = featuresFromParentDesc(fd.Parent())
var rawTypeName []byte
var rawOptions []byte
@@ -465,6 +471,12 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref
b = b[m:]
}
}
+ if fd.L1.Kind == protoreflect.MessageKind && fd.L1.EditionFeatures.IsDelimitedEncoded {
+ fd.L1.Kind = protoreflect.GroupKind
+ }
+ if fd.L1.EditionFeatures.IsLegacyRequired {
+ fd.L1.Cardinality = protoreflect.Required
+ }
if rawTypeName != nil {
name := makeFullName(sb, rawTypeName)
switch fd.L1.Kind {
@@ -489,13 +501,18 @@ func (fd *Field) unmarshalOptions(b []byte) {
b = b[m:]
switch num {
case genid.FieldOptions_Packed_field_number:
- fd.L1.HasPacked = true
- fd.L1.IsPacked = protowire.DecodeBool(v)
+ fd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v)
case genid.FieldOptions_Weak_field_number:
fd.L1.IsWeak = protowire.DecodeBool(v)
case FieldOptions_EnforceUTF8:
- fd.L1.HasEnforceUTF8 = true
- fd.L1.EnforceUTF8 = protowire.DecodeBool(v)
+ fd.L1.EditionFeatures.IsUTF8Validated = protowire.DecodeBool(v)
+ }
+ case protowire.BytesType:
+ v, m := protowire.ConsumeBytes(b)
+ b = b[m:]
+ switch num {
+ case genid.FieldOptions_Features_field_number:
+ fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
}
default:
m := protowire.ConsumeFieldValue(num, typ, b)
@@ -557,7 +574,6 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
case genid.FieldDescriptorProto_TypeName_field_number:
rawTypeName = v
case genid.FieldDescriptorProto_Options_field_number:
- xd.unmarshalOptions(v)
rawOptions = appendOptions(rawOptions, v)
}
default:
@@ -577,25 +593,6 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
xd.L2.Options = xd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Field, rawOptions)
}
-func (xd *Extension) unmarshalOptions(b []byte) {
- for len(b) > 0 {
- num, typ, n := protowire.ConsumeTag(b)
- b = b[n:]
- switch typ {
- case protowire.VarintType:
- v, m := protowire.ConsumeVarint(b)
- b = b[m:]
- switch num {
- case genid.FieldOptions_Packed_field_number:
- xd.L2.IsPacked = protowire.DecodeBool(v)
- }
- default:
- m := protowire.ConsumeFieldValue(num, typ, b)
- b = b[m:]
- }
- }
-}
-
func (sd *Service) unmarshalFull(b []byte, sb *strs.Builder) {
var rawMethods [][]byte
var rawOptions []byte
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go
index 30db19fdc7..f4107c05f4 100644
--- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go
@@ -8,6 +8,7 @@ package filedesc
import (
"fmt"
+ "strings"
"sync"
"google.golang.org/protobuf/internal/descfmt"
@@ -198,6 +199,16 @@ func (p *Fields) lazyInit() *Fields {
if _, ok := p.byText[d.TextName()]; !ok {
p.byText[d.TextName()] = d
}
+ if isGroupLike(d) {
+ lowerJSONName := strings.ToLower(d.JSONName())
+ if _, ok := p.byJSON[lowerJSONName]; !ok {
+ p.byJSON[lowerJSONName] = d
+ }
+ lowerTextName := strings.ToLower(d.TextName())
+ if _, ok := p.byText[lowerTextName]; !ok {
+ p.byText[lowerTextName] = d
+ }
+ }
if _, ok := p.byNum[d.Number()]; !ok {
p.byNum[d.Number()] = d
}
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/editions.go b/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
new file mode 100644
index 0000000000..11f5f356b6
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/editions.go
@@ -0,0 +1,156 @@
+// Copyright 2024 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 filedesc
+
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/encoding/protowire"
+ "google.golang.org/protobuf/internal/editiondefaults"
+ "google.golang.org/protobuf/internal/genid"
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+var defaultsCache = make(map[Edition]EditionFeatures)
+var defaultsKeys = []Edition{}
+
+func init() {
+ unmarshalEditionDefaults(editiondefaults.Defaults)
+ SurrogateProto2.L1.EditionFeatures = getFeaturesFor(EditionProto2)
+ SurrogateProto3.L1.EditionFeatures = getFeaturesFor(EditionProto3)
+ SurrogateEdition2023.L1.EditionFeatures = getFeaturesFor(Edition2023)
+}
+
+func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
+ for len(b) > 0 {
+ num, _, n := protowire.ConsumeTag(b)
+ b = b[n:]
+ switch num {
+ case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
+ v, m := protowire.ConsumeVarint(b)
+ b = b[m:]
+ parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v)
+ default:
+ panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
+ }
+ }
+ return parent
+}
+
+func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
+ for len(b) > 0 {
+ num, typ, n := protowire.ConsumeTag(b)
+ b = b[n:]
+ switch typ {
+ case protowire.VarintType:
+ v, m := protowire.ConsumeVarint(b)
+ b = b[m:]
+ switch num {
+ case genid.FeatureSet_FieldPresence_field_number:
+ parent.IsFieldPresence = v == genid.FeatureSet_EXPLICIT_enum_value || v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
+ parent.IsLegacyRequired = v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
+ case genid.FeatureSet_EnumType_field_number:
+ parent.IsOpenEnum = v == genid.FeatureSet_OPEN_enum_value
+ case genid.FeatureSet_RepeatedFieldEncoding_field_number:
+ parent.IsPacked = v == genid.FeatureSet_PACKED_enum_value
+ case genid.FeatureSet_Utf8Validation_field_number:
+ parent.IsUTF8Validated = v == genid.FeatureSet_VERIFY_enum_value
+ case genid.FeatureSet_MessageEncoding_field_number:
+ parent.IsDelimitedEncoded = v == genid.FeatureSet_DELIMITED_enum_value
+ case genid.FeatureSet_JsonFormat_field_number:
+ parent.IsJSONCompliant = v == genid.FeatureSet_ALLOW_enum_value
+ default:
+ panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
+ }
+ case protowire.BytesType:
+ v, m := protowire.ConsumeBytes(b)
+ b = b[m:]
+ switch num {
+ case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
+ parent = unmarshalGoFeature(v, parent)
+ }
+ }
+ }
+
+ return parent
+}
+
+func featuresFromParentDesc(parentDesc protoreflect.Descriptor) EditionFeatures {
+ var parentFS EditionFeatures
+ switch p := parentDesc.(type) {
+ case *File:
+ parentFS = p.L1.EditionFeatures
+ case *Message:
+ parentFS = p.L1.EditionFeatures
+ default:
+ panic(fmt.Sprintf("unknown parent type %T", parentDesc))
+ }
+ return parentFS
+}
+
+func unmarshalEditionDefault(b []byte) {
+ var ed Edition
+ var fs EditionFeatures
+ for len(b) > 0 {
+ num, typ, n := protowire.ConsumeTag(b)
+ b = b[n:]
+ switch typ {
+ case protowire.VarintType:
+ v, m := protowire.ConsumeVarint(b)
+ b = b[m:]
+ switch num {
+ case genid.FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number:
+ ed = Edition(v)
+ }
+ case protowire.BytesType:
+ v, m := protowire.ConsumeBytes(b)
+ b = b[m:]
+ switch num {
+ case genid.FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_number:
+ fs = unmarshalFeatureSet(v, fs)
+ case genid.FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_number:
+ fs = unmarshalFeatureSet(v, fs)
+ }
+ }
+ }
+ defaultsCache[ed] = fs
+ defaultsKeys = append(defaultsKeys, ed)
+}
+
+func unmarshalEditionDefaults(b []byte) {
+ for len(b) > 0 {
+ num, _, n := protowire.ConsumeTag(b)
+ b = b[n:]
+ switch num {
+ case genid.FeatureSetDefaults_Defaults_field_number:
+ def, m := protowire.ConsumeBytes(b)
+ b = b[m:]
+ unmarshalEditionDefault(def)
+ case genid.FeatureSetDefaults_MinimumEdition_field_number,
+ genid.FeatureSetDefaults_MaximumEdition_field_number:
+ // We don't care about the minimum and maximum editions. If the
+ // edition we are looking for later on is not in the cache we know
+ // it is outside of the range between minimum and maximum edition.
+ _, m := protowire.ConsumeVarint(b)
+ b = b[m:]
+ default:
+ panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
+ }
+ }
+}
+
+func getFeaturesFor(ed Edition) EditionFeatures {
+ match := EditionUnknown
+ for _, key := range defaultsKeys {
+ if key > ed {
+ break
+ }
+ match = key
+ }
+ if match == EditionUnknown {
+ panic(fmt.Sprintf("unsupported edition: %v", ed))
+ }
+ return defaultsCache[match]
+}
diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go b/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go
index 28240ebc5c..bfb3b84170 100644
--- a/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go
+++ b/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go
@@ -63,6 +63,7 @@ func (e PlaceholderEnum) Options() protoreflect.ProtoMessage { return des
func (e PlaceholderEnum) Values() protoreflect.EnumValueDescriptors { return emptyEnumValues }
func (e PlaceholderEnum) ReservedNames() protoreflect.Names { return emptyNames }
func (e PlaceholderEnum) ReservedRanges() protoreflect.EnumRanges { return emptyEnumRanges }
+func (e PlaceholderEnum) IsClosed() bool { return false }
func (e PlaceholderEnum) ProtoType(protoreflect.EnumDescriptor) { return }
func (e PlaceholderEnum) ProtoInternal(pragma.DoNotImplement) { return }
diff --git a/vendor/google.golang.org/protobuf/internal/filetype/build.go b/vendor/google.golang.org/protobuf/internal/filetype/build.go
index f0e38c4ef4..ba83fea44c 100644
--- a/vendor/google.golang.org/protobuf/internal/filetype/build.go
+++ b/vendor/google.golang.org/protobuf/internal/filetype/build.go
@@ -68,7 +68,7 @@ type Builder struct {
// and for input and output messages referenced by service methods.
// Dependencies must come after declarations, but the ordering of
// dependencies themselves is unspecified.
- GoTypes []interface{}
+ GoTypes []any
// DependencyIndexes is an ordered list of indexes into GoTypes for the
// dependencies of messages, extensions, or services.
@@ -268,7 +268,7 @@ func (x depIdxs) Get(i, j int32) int32 {
type (
resolverByIndex struct {
- goTypes []interface{}
+ goTypes []any
depIdxs depIdxs
fileRegistry
}
diff --git a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
index 136f1b2157..f30ab6b586 100644
--- a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
+++ b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go
@@ -12,6 +12,28 @@ import (
const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto"
+// Full and short names for google.protobuf.Edition.
+const (
+ Edition_enum_fullname = "google.protobuf.Edition"
+ Edition_enum_name = "Edition"
+)
+
+// Enum values for google.protobuf.Edition.
+const (
+ Edition_EDITION_UNKNOWN_enum_value = 0
+ Edition_EDITION_LEGACY_enum_value = 900
+ Edition_EDITION_PROTO2_enum_value = 998
+ Edition_EDITION_PROTO3_enum_value = 999
+ Edition_EDITION_2023_enum_value = 1000
+ Edition_EDITION_2024_enum_value = 1001
+ Edition_EDITION_1_TEST_ONLY_enum_value = 1
+ Edition_EDITION_2_TEST_ONLY_enum_value = 2
+ Edition_EDITION_99997_TEST_ONLY_enum_value = 99997
+ Edition_EDITION_99998_TEST_ONLY_enum_value = 99998
+ Edition_EDITION_99999_TEST_ONLY_enum_value = 99999
+ Edition_EDITION_MAX_enum_value = 2147483647
+)
+
// Names for google.protobuf.FileDescriptorSet.
const (
FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet"
@@ -81,7 +103,7 @@ const (
FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8
FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9
FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12
- FileDescriptorProto_Edition_field_number protoreflect.FieldNumber = 13
+ FileDescriptorProto_Edition_field_number protoreflect.FieldNumber = 14
)
// Names for google.protobuf.DescriptorProto.
@@ -184,10 +206,12 @@ const (
const (
ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
ExtensionRangeOptions_Declaration_field_name protoreflect.Name = "declaration"
+ ExtensionRangeOptions_Features_field_name protoreflect.Name = "features"
ExtensionRangeOptions_Verification_field_name protoreflect.Name = "verification"
ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option"
ExtensionRangeOptions_Declaration_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.declaration"
+ ExtensionRangeOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.features"
ExtensionRangeOptions_Verification_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.verification"
)
@@ -195,6 +219,7 @@ const (
const (
ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
ExtensionRangeOptions_Declaration_field_number protoreflect.FieldNumber = 2
+ ExtensionRangeOptions_Features_field_number protoreflect.FieldNumber = 50
ExtensionRangeOptions_Verification_field_number protoreflect.FieldNumber = 3
)
@@ -204,6 +229,12 @@ const (
ExtensionRangeOptions_VerificationState_enum_name = "VerificationState"
)
+// Enum values for google.protobuf.ExtensionRangeOptions.VerificationState.
+const (
+ ExtensionRangeOptions_DECLARATION_enum_value = 0
+ ExtensionRangeOptions_UNVERIFIED_enum_value = 1
+)
+
// Names for google.protobuf.ExtensionRangeOptions.Declaration.
const (
ExtensionRangeOptions_Declaration_message_name protoreflect.Name = "Declaration"
@@ -212,29 +243,26 @@ const (
// Field names for google.protobuf.ExtensionRangeOptions.Declaration.
const (
- ExtensionRangeOptions_Declaration_Number_field_name protoreflect.Name = "number"
- ExtensionRangeOptions_Declaration_FullName_field_name protoreflect.Name = "full_name"
- ExtensionRangeOptions_Declaration_Type_field_name protoreflect.Name = "type"
- ExtensionRangeOptions_Declaration_IsRepeated_field_name protoreflect.Name = "is_repeated"
- ExtensionRangeOptions_Declaration_Reserved_field_name protoreflect.Name = "reserved"
- ExtensionRangeOptions_Declaration_Repeated_field_name protoreflect.Name = "repeated"
+ ExtensionRangeOptions_Declaration_Number_field_name protoreflect.Name = "number"
+ ExtensionRangeOptions_Declaration_FullName_field_name protoreflect.Name = "full_name"
+ ExtensionRangeOptions_Declaration_Type_field_name protoreflect.Name = "type"
+ ExtensionRangeOptions_Declaration_Reserved_field_name protoreflect.Name = "reserved"
+ ExtensionRangeOptions_Declaration_Repeated_field_name protoreflect.Name = "repeated"
- ExtensionRangeOptions_Declaration_Number_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.number"
- ExtensionRangeOptions_Declaration_FullName_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.full_name"
- ExtensionRangeOptions_Declaration_Type_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.type"
- ExtensionRangeOptions_Declaration_IsRepeated_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.is_repeated"
- ExtensionRangeOptions_Declaration_Reserved_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.reserved"
- ExtensionRangeOptions_Declaration_Repeated_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.repeated"
+ ExtensionRangeOptions_Declaration_Number_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.number"
+ ExtensionRangeOptions_Declaration_FullName_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.full_name"
+ ExtensionRangeOptions_Declaration_Type_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.type"
+ ExtensionRangeOptions_Declaration_Reserved_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.reserved"
+ ExtensionRangeOptions_Declaration_Repeated_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.Declaration.repeated"
)
// Field numbers for google.protobuf.ExtensionRangeOptions.Declaration.
const (
- ExtensionRangeOptions_Declaration_Number_field_number protoreflect.FieldNumber = 1
- ExtensionRangeOptions_Declaration_FullName_field_number protoreflect.FieldNumber = 2
- ExtensionRangeOptions_Declaration_Type_field_number protoreflect.FieldNumber = 3
- ExtensionRangeOptions_Declaration_IsRepeated_field_number protoreflect.FieldNumber = 4
- ExtensionRangeOptions_Declaration_Reserved_field_number protoreflect.FieldNumber = 5
- ExtensionRangeOptions_Declaration_Repeated_field_number protoreflect.FieldNumber = 6
+ ExtensionRangeOptions_Declaration_Number_field_number protoreflect.FieldNumber = 1
+ ExtensionRangeOptions_Declaration_FullName_field_number protoreflect.FieldNumber = 2
+ ExtensionRangeOptions_Declaration_Type_field_number protoreflect.FieldNumber = 3
+ ExtensionRangeOptions_Declaration_Reserved_field_number protoreflect.FieldNumber = 5
+ ExtensionRangeOptions_Declaration_Repeated_field_number protoreflect.FieldNumber = 6
)
// Names for google.protobuf.FieldDescriptorProto.
@@ -291,12 +319,41 @@ const (
FieldDescriptorProto_Type_enum_name = "Type"
)
+// Enum values for google.protobuf.FieldDescriptorProto.Type.
+const (
+ FieldDescriptorProto_TYPE_DOUBLE_enum_value = 1
+ FieldDescriptorProto_TYPE_FLOAT_enum_value = 2
+ FieldDescriptorProto_TYPE_INT64_enum_value = 3
+ FieldDescriptorProto_TYPE_UINT64_enum_value = 4
+ FieldDescriptorProto_TYPE_INT32_enum_value = 5
+ FieldDescriptorProto_TYPE_FIXED64_enum_value = 6
+ FieldDescriptorProto_TYPE_FIXED32_enum_value = 7
+ FieldDescriptorProto_TYPE_BOOL_enum_value = 8
+ FieldDescriptorProto_TYPE_STRING_enum_value = 9
+ FieldDescriptorProto_TYPE_GROUP_enum_value = 10
+ FieldDescriptorProto_TYPE_MESSAGE_enum_value = 11
+ FieldDescriptorProto_TYPE_BYTES_enum_value = 12
+ FieldDescriptorProto_TYPE_UINT32_enum_value = 13
+ FieldDescriptorProto_TYPE_ENUM_enum_value = 14
+ FieldDescriptorProto_TYPE_SFIXED32_enum_value = 15
+ FieldDescriptorProto_TYPE_SFIXED64_enum_value = 16
+ FieldDescriptorProto_TYPE_SINT32_enum_value = 17
+ FieldDescriptorProto_TYPE_SINT64_enum_value = 18
+)
+
// Full and short names for google.protobuf.FieldDescriptorProto.Label.
const (
FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label"
FieldDescriptorProto_Label_enum_name = "Label"
)
+// Enum values for google.protobuf.FieldDescriptorProto.Label.
+const (
+ FieldDescriptorProto_LABEL_OPTIONAL_enum_value = 1
+ FieldDescriptorProto_LABEL_REPEATED_enum_value = 3
+ FieldDescriptorProto_LABEL_REQUIRED_enum_value = 2
+)
+
// Names for google.protobuf.OneofDescriptorProto.
const (
OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto"
@@ -468,7 +525,6 @@ const (
FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services"
FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services"
FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services"
- FileOptions_PhpGenericServices_field_name protoreflect.Name = "php_generic_services"
FileOptions_Deprecated_field_name protoreflect.Name = "deprecated"
FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix"
@@ -478,6 +534,7 @@ const (
FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace"
FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace"
FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package"
+ FileOptions_Features_field_name protoreflect.Name = "features"
FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package"
@@ -490,7 +547,6 @@ const (
FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services"
FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services"
FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services"
- FileOptions_PhpGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_generic_services"
FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated"
FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas"
FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix"
@@ -500,6 +556,7 @@ const (
FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace"
FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace"
FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package"
+ FileOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.features"
FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option"
)
@@ -515,7 +572,6 @@ const (
FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16
FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17
FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18
- FileOptions_PhpGenericServices_field_number protoreflect.FieldNumber = 42
FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23
FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31
FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36
@@ -525,6 +581,7 @@ const (
FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41
FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44
FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45
+ FileOptions_Features_field_number protoreflect.FieldNumber = 50
FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -534,6 +591,13 @@ const (
FileOptions_OptimizeMode_enum_name = "OptimizeMode"
)
+// Enum values for google.protobuf.FileOptions.OptimizeMode.
+const (
+ FileOptions_SPEED_enum_value = 1
+ FileOptions_CODE_SIZE_enum_value = 2
+ FileOptions_LITE_RUNTIME_enum_value = 3
+)
+
// Names for google.protobuf.MessageOptions.
const (
MessageOptions_message_name protoreflect.Name = "MessageOptions"
@@ -547,6 +611,7 @@ const (
MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry"
MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts"
+ MessageOptions_Features_field_name protoreflect.Name = "features"
MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format"
@@ -554,6 +619,7 @@ const (
MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated"
MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry"
MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated_legacy_json_field_conflicts"
+ MessageOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.features"
MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option"
)
@@ -564,6 +630,7 @@ const (
MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3
MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7
MessageOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 11
+ MessageOptions_Features_field_number protoreflect.FieldNumber = 12
MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -584,8 +651,10 @@ const (
FieldOptions_Weak_field_name protoreflect.Name = "weak"
FieldOptions_DebugRedact_field_name protoreflect.Name = "debug_redact"
FieldOptions_Retention_field_name protoreflect.Name = "retention"
- FieldOptions_Target_field_name protoreflect.Name = "target"
FieldOptions_Targets_field_name protoreflect.Name = "targets"
+ FieldOptions_EditionDefaults_field_name protoreflect.Name = "edition_defaults"
+ FieldOptions_Features_field_name protoreflect.Name = "features"
+ FieldOptions_FeatureSupport_field_name protoreflect.Name = "feature_support"
FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype"
@@ -597,8 +666,10 @@ const (
FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak"
FieldOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.debug_redact"
FieldOptions_Retention_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.retention"
- FieldOptions_Target_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.target"
FieldOptions_Targets_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.targets"
+ FieldOptions_EditionDefaults_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.edition_defaults"
+ FieldOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.features"
+ FieldOptions_FeatureSupport_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.feature_support"
FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option"
)
@@ -613,8 +684,10 @@ const (
FieldOptions_Weak_field_number protoreflect.FieldNumber = 10
FieldOptions_DebugRedact_field_number protoreflect.FieldNumber = 16
FieldOptions_Retention_field_number protoreflect.FieldNumber = 17
- FieldOptions_Target_field_number protoreflect.FieldNumber = 18
FieldOptions_Targets_field_number protoreflect.FieldNumber = 19
+ FieldOptions_EditionDefaults_field_number protoreflect.FieldNumber = 20
+ FieldOptions_Features_field_number protoreflect.FieldNumber = 21
+ FieldOptions_FeatureSupport_field_number protoreflect.FieldNumber = 22
FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -624,24 +697,107 @@ const (
FieldOptions_CType_enum_name = "CType"
)
+// Enum values for google.protobuf.FieldOptions.CType.
+const (
+ FieldOptions_STRING_enum_value = 0
+ FieldOptions_CORD_enum_value = 1
+ FieldOptions_STRING_PIECE_enum_value = 2
+)
+
// Full and short names for google.protobuf.FieldOptions.JSType.
const (
FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType"
FieldOptions_JSType_enum_name = "JSType"
)
+// Enum values for google.protobuf.FieldOptions.JSType.
+const (
+ FieldOptions_JS_NORMAL_enum_value = 0
+ FieldOptions_JS_STRING_enum_value = 1
+ FieldOptions_JS_NUMBER_enum_value = 2
+)
+
// Full and short names for google.protobuf.FieldOptions.OptionRetention.
const (
FieldOptions_OptionRetention_enum_fullname = "google.protobuf.FieldOptions.OptionRetention"
FieldOptions_OptionRetention_enum_name = "OptionRetention"
)
+// Enum values for google.protobuf.FieldOptions.OptionRetention.
+const (
+ FieldOptions_RETENTION_UNKNOWN_enum_value = 0
+ FieldOptions_RETENTION_RUNTIME_enum_value = 1
+ FieldOptions_RETENTION_SOURCE_enum_value = 2
+)
+
// Full and short names for google.protobuf.FieldOptions.OptionTargetType.
const (
FieldOptions_OptionTargetType_enum_fullname = "google.protobuf.FieldOptions.OptionTargetType"
FieldOptions_OptionTargetType_enum_name = "OptionTargetType"
)
+// Enum values for google.protobuf.FieldOptions.OptionTargetType.
+const (
+ FieldOptions_TARGET_TYPE_UNKNOWN_enum_value = 0
+ FieldOptions_TARGET_TYPE_FILE_enum_value = 1
+ FieldOptions_TARGET_TYPE_EXTENSION_RANGE_enum_value = 2
+ FieldOptions_TARGET_TYPE_MESSAGE_enum_value = 3
+ FieldOptions_TARGET_TYPE_FIELD_enum_value = 4
+ FieldOptions_TARGET_TYPE_ONEOF_enum_value = 5
+ FieldOptions_TARGET_TYPE_ENUM_enum_value = 6
+ FieldOptions_TARGET_TYPE_ENUM_ENTRY_enum_value = 7
+ FieldOptions_TARGET_TYPE_SERVICE_enum_value = 8
+ FieldOptions_TARGET_TYPE_METHOD_enum_value = 9
+)
+
+// Names for google.protobuf.FieldOptions.EditionDefault.
+const (
+ FieldOptions_EditionDefault_message_name protoreflect.Name = "EditionDefault"
+ FieldOptions_EditionDefault_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault"
+)
+
+// Field names for google.protobuf.FieldOptions.EditionDefault.
+const (
+ FieldOptions_EditionDefault_Edition_field_name protoreflect.Name = "edition"
+ FieldOptions_EditionDefault_Value_field_name protoreflect.Name = "value"
+
+ FieldOptions_EditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault.edition"
+ FieldOptions_EditionDefault_Value_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.EditionDefault.value"
+)
+
+// Field numbers for google.protobuf.FieldOptions.EditionDefault.
+const (
+ FieldOptions_EditionDefault_Edition_field_number protoreflect.FieldNumber = 3
+ FieldOptions_EditionDefault_Value_field_number protoreflect.FieldNumber = 2
+)
+
+// Names for google.protobuf.FieldOptions.FeatureSupport.
+const (
+ FieldOptions_FeatureSupport_message_name protoreflect.Name = "FeatureSupport"
+ FieldOptions_FeatureSupport_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport"
+)
+
+// Field names for google.protobuf.FieldOptions.FeatureSupport.
+const (
+ FieldOptions_FeatureSupport_EditionIntroduced_field_name protoreflect.Name = "edition_introduced"
+ FieldOptions_FeatureSupport_EditionDeprecated_field_name protoreflect.Name = "edition_deprecated"
+ FieldOptions_FeatureSupport_DeprecationWarning_field_name protoreflect.Name = "deprecation_warning"
+ FieldOptions_FeatureSupport_EditionRemoved_field_name protoreflect.Name = "edition_removed"
+
+ FieldOptions_FeatureSupport_EditionIntroduced_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.edition_introduced"
+ FieldOptions_FeatureSupport_EditionDeprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.edition_deprecated"
+ FieldOptions_FeatureSupport_DeprecationWarning_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.deprecation_warning"
+ FieldOptions_FeatureSupport_EditionRemoved_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.edition_removed"
+)
+
+// Field numbers for google.protobuf.FieldOptions.FeatureSupport.
+const (
+ FieldOptions_FeatureSupport_EditionIntroduced_field_number protoreflect.FieldNumber = 1
+ FieldOptions_FeatureSupport_EditionDeprecated_field_number protoreflect.FieldNumber = 2
+ FieldOptions_FeatureSupport_DeprecationWarning_field_number protoreflect.FieldNumber = 3
+ FieldOptions_FeatureSupport_EditionRemoved_field_number protoreflect.FieldNumber = 4
+)
+
// Names for google.protobuf.OneofOptions.
const (
OneofOptions_message_name protoreflect.Name = "OneofOptions"
@@ -650,13 +806,16 @@ const (
// Field names for google.protobuf.OneofOptions.
const (
+ OneofOptions_Features_field_name protoreflect.Name = "features"
OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
+ OneofOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.features"
OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.OneofOptions.
const (
+ OneofOptions_Features_field_number protoreflect.FieldNumber = 1
OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -671,11 +830,13 @@ const (
EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias"
EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated"
EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_name protoreflect.Name = "deprecated_legacy_json_field_conflicts"
+ EnumOptions_Features_field_name protoreflect.Name = "features"
EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias"
EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated"
EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated_legacy_json_field_conflicts"
+ EnumOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.features"
EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option"
)
@@ -684,6 +845,7 @@ const (
EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2
EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3
EnumOptions_DeprecatedLegacyJsonFieldConflicts_field_number protoreflect.FieldNumber = 6
+ EnumOptions_Features_field_number protoreflect.FieldNumber = 7
EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -696,15 +858,24 @@ const (
// Field names for google.protobuf.EnumValueOptions.
const (
EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated"
+ EnumValueOptions_Features_field_name protoreflect.Name = "features"
+ EnumValueOptions_DebugRedact_field_name protoreflect.Name = "debug_redact"
+ EnumValueOptions_FeatureSupport_field_name protoreflect.Name = "feature_support"
EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated"
+ EnumValueOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.features"
+ EnumValueOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.debug_redact"
+ EnumValueOptions_FeatureSupport_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.feature_support"
EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.EnumValueOptions.
const (
EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1
+ EnumValueOptions_Features_field_number protoreflect.FieldNumber = 2
+ EnumValueOptions_DebugRedact_field_number protoreflect.FieldNumber = 3
+ EnumValueOptions_FeatureSupport_field_number protoreflect.FieldNumber = 4
EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -716,15 +887,18 @@ const (
// Field names for google.protobuf.ServiceOptions.
const (
+ ServiceOptions_Features_field_name protoreflect.Name = "features"
ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated"
ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
+ ServiceOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.features"
ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated"
ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option"
)
// Field numbers for google.protobuf.ServiceOptions.
const (
+ ServiceOptions_Features_field_number protoreflect.FieldNumber = 34
ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33
ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -739,10 +913,12 @@ const (
const (
MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated"
MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level"
+ MethodOptions_Features_field_name protoreflect.Name = "features"
MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option"
MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated"
MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level"
+ MethodOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.features"
MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option"
)
@@ -750,6 +926,7 @@ const (
const (
MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33
MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34
+ MethodOptions_Features_field_number protoreflect.FieldNumber = 35
MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999
)
@@ -759,6 +936,13 @@ const (
MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel"
)
+// Enum values for google.protobuf.MethodOptions.IdempotencyLevel.
+const (
+ MethodOptions_IDEMPOTENCY_UNKNOWN_enum_value = 0
+ MethodOptions_NO_SIDE_EFFECTS_enum_value = 1
+ MethodOptions_IDEMPOTENT_enum_value = 2
+)
+
// Names for google.protobuf.UninterpretedOption.
const (
UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption"
@@ -816,6 +1000,166 @@ const (
UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2
)
+// Names for google.protobuf.FeatureSet.
+const (
+ FeatureSet_message_name protoreflect.Name = "FeatureSet"
+ FeatureSet_message_fullname protoreflect.FullName = "google.protobuf.FeatureSet"
+)
+
+// Field names for google.protobuf.FeatureSet.
+const (
+ FeatureSet_FieldPresence_field_name protoreflect.Name = "field_presence"
+ FeatureSet_EnumType_field_name protoreflect.Name = "enum_type"
+ FeatureSet_RepeatedFieldEncoding_field_name protoreflect.Name = "repeated_field_encoding"
+ FeatureSet_Utf8Validation_field_name protoreflect.Name = "utf8_validation"
+ FeatureSet_MessageEncoding_field_name protoreflect.Name = "message_encoding"
+ FeatureSet_JsonFormat_field_name protoreflect.Name = "json_format"
+
+ FeatureSet_FieldPresence_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.field_presence"
+ FeatureSet_EnumType_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.enum_type"
+ FeatureSet_RepeatedFieldEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.repeated_field_encoding"
+ FeatureSet_Utf8Validation_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.utf8_validation"
+ FeatureSet_MessageEncoding_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.message_encoding"
+ FeatureSet_JsonFormat_field_fullname protoreflect.FullName = "google.protobuf.FeatureSet.json_format"
+)
+
+// Field numbers for google.protobuf.FeatureSet.
+const (
+ FeatureSet_FieldPresence_field_number protoreflect.FieldNumber = 1
+ FeatureSet_EnumType_field_number protoreflect.FieldNumber = 2
+ FeatureSet_RepeatedFieldEncoding_field_number protoreflect.FieldNumber = 3
+ FeatureSet_Utf8Validation_field_number protoreflect.FieldNumber = 4
+ FeatureSet_MessageEncoding_field_number protoreflect.FieldNumber = 5
+ FeatureSet_JsonFormat_field_number protoreflect.FieldNumber = 6
+)
+
+// Full and short names for google.protobuf.FeatureSet.FieldPresence.
+const (
+ FeatureSet_FieldPresence_enum_fullname = "google.protobuf.FeatureSet.FieldPresence"
+ FeatureSet_FieldPresence_enum_name = "FieldPresence"
+)
+
+// Enum values for google.protobuf.FeatureSet.FieldPresence.
+const (
+ FeatureSet_FIELD_PRESENCE_UNKNOWN_enum_value = 0
+ FeatureSet_EXPLICIT_enum_value = 1
+ FeatureSet_IMPLICIT_enum_value = 2
+ FeatureSet_LEGACY_REQUIRED_enum_value = 3
+)
+
+// Full and short names for google.protobuf.FeatureSet.EnumType.
+const (
+ FeatureSet_EnumType_enum_fullname = "google.protobuf.FeatureSet.EnumType"
+ FeatureSet_EnumType_enum_name = "EnumType"
+)
+
+// Enum values for google.protobuf.FeatureSet.EnumType.
+const (
+ FeatureSet_ENUM_TYPE_UNKNOWN_enum_value = 0
+ FeatureSet_OPEN_enum_value = 1
+ FeatureSet_CLOSED_enum_value = 2
+)
+
+// Full and short names for google.protobuf.FeatureSet.RepeatedFieldEncoding.
+const (
+ FeatureSet_RepeatedFieldEncoding_enum_fullname = "google.protobuf.FeatureSet.RepeatedFieldEncoding"
+ FeatureSet_RepeatedFieldEncoding_enum_name = "RepeatedFieldEncoding"
+)
+
+// Enum values for google.protobuf.FeatureSet.RepeatedFieldEncoding.
+const (
+ FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN_enum_value = 0
+ FeatureSet_PACKED_enum_value = 1
+ FeatureSet_EXPANDED_enum_value = 2
+)
+
+// Full and short names for google.protobuf.FeatureSet.Utf8Validation.
+const (
+ FeatureSet_Utf8Validation_enum_fullname = "google.protobuf.FeatureSet.Utf8Validation"
+ FeatureSet_Utf8Validation_enum_name = "Utf8Validation"
+)
+
+// Enum values for google.protobuf.FeatureSet.Utf8Validation.
+const (
+ FeatureSet_UTF8_VALIDATION_UNKNOWN_enum_value = 0
+ FeatureSet_VERIFY_enum_value = 2
+ FeatureSet_NONE_enum_value = 3
+)
+
+// Full and short names for google.protobuf.FeatureSet.MessageEncoding.
+const (
+ FeatureSet_MessageEncoding_enum_fullname = "google.protobuf.FeatureSet.MessageEncoding"
+ FeatureSet_MessageEncoding_enum_name = "MessageEncoding"
+)
+
+// Enum values for google.protobuf.FeatureSet.MessageEncoding.
+const (
+ FeatureSet_MESSAGE_ENCODING_UNKNOWN_enum_value = 0
+ FeatureSet_LENGTH_PREFIXED_enum_value = 1
+ FeatureSet_DELIMITED_enum_value = 2
+)
+
+// Full and short names for google.protobuf.FeatureSet.JsonFormat.
+const (
+ FeatureSet_JsonFormat_enum_fullname = "google.protobuf.FeatureSet.JsonFormat"
+ FeatureSet_JsonFormat_enum_name = "JsonFormat"
+)
+
+// Enum values for google.protobuf.FeatureSet.JsonFormat.
+const (
+ FeatureSet_JSON_FORMAT_UNKNOWN_enum_value = 0
+ FeatureSet_ALLOW_enum_value = 1
+ FeatureSet_LEGACY_BEST_EFFORT_enum_value = 2
+)
+
+// Names for google.protobuf.FeatureSetDefaults.
+const (
+ FeatureSetDefaults_message_name protoreflect.Name = "FeatureSetDefaults"
+ FeatureSetDefaults_message_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults"
+)
+
+// Field names for google.protobuf.FeatureSetDefaults.
+const (
+ FeatureSetDefaults_Defaults_field_name protoreflect.Name = "defaults"
+ FeatureSetDefaults_MinimumEdition_field_name protoreflect.Name = "minimum_edition"
+ FeatureSetDefaults_MaximumEdition_field_name protoreflect.Name = "maximum_edition"
+
+ FeatureSetDefaults_Defaults_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.defaults"
+ FeatureSetDefaults_MinimumEdition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.minimum_edition"
+ FeatureSetDefaults_MaximumEdition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.maximum_edition"
+)
+
+// Field numbers for google.protobuf.FeatureSetDefaults.
+const (
+ FeatureSetDefaults_Defaults_field_number protoreflect.FieldNumber = 1
+ FeatureSetDefaults_MinimumEdition_field_number protoreflect.FieldNumber = 4
+ FeatureSetDefaults_MaximumEdition_field_number protoreflect.FieldNumber = 5
+)
+
+// Names for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
+const (
+ FeatureSetDefaults_FeatureSetEditionDefault_message_name protoreflect.Name = "FeatureSetEditionDefault"
+ FeatureSetDefaults_FeatureSetEditionDefault_message_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault"
+)
+
+// Field names for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
+const (
+ FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_name protoreflect.Name = "edition"
+ FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_name protoreflect.Name = "overridable_features"
+ FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_name protoreflect.Name = "fixed_features"
+
+ FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition"
+ FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features"
+ FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features"
+)
+
+// Field numbers for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.
+const (
+ FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number protoreflect.FieldNumber = 3
+ FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_number protoreflect.FieldNumber = 4
+ FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_number protoreflect.FieldNumber = 5
+)
+
// Names for google.protobuf.SourceCodeInfo.
const (
SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo"
@@ -917,3 +1261,10 @@ const (
GeneratedCodeInfo_Annotation_Semantic_enum_fullname = "google.protobuf.GeneratedCodeInfo.Annotation.Semantic"
GeneratedCodeInfo_Annotation_Semantic_enum_name = "Semantic"
)
+
+// Enum values for google.protobuf.GeneratedCodeInfo.Annotation.Semantic.
+const (
+ GeneratedCodeInfo_Annotation_NONE_enum_value = 0
+ GeneratedCodeInfo_Annotation_SET_enum_value = 1
+ GeneratedCodeInfo_Annotation_ALIAS_enum_value = 2
+)
diff --git a/vendor/google.golang.org/protobuf/internal/genid/go_features_gen.go b/vendor/google.golang.org/protobuf/internal/genid/go_features_gen.go
new file mode 100644
index 0000000000..9a652a2b42
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/internal/genid/go_features_gen.go
@@ -0,0 +1,31 @@
+// Copyright 2019 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.
+
+// Code generated by generate-protos. DO NOT EDIT.
+
+package genid
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+const File_google_protobuf_go_features_proto = "google/protobuf/go_features.proto"
+
+// Names for google.protobuf.GoFeatures.
+const (
+ GoFeatures_message_name protoreflect.Name = "GoFeatures"
+ GoFeatures_message_fullname protoreflect.FullName = "google.protobuf.GoFeatures"
+)
+
+// Field names for google.protobuf.GoFeatures.
+const (
+ GoFeatures_LegacyUnmarshalJsonEnum_field_name protoreflect.Name = "legacy_unmarshal_json_enum"
+
+ GoFeatures_LegacyUnmarshalJsonEnum_field_fullname protoreflect.FullName = "google.protobuf.GoFeatures.legacy_unmarshal_json_enum"
+)
+
+// Field numbers for google.protobuf.GoFeatures.
+const (
+ GoFeatures_LegacyUnmarshalJsonEnum_field_number protoreflect.FieldNumber = 1
+)
diff --git a/vendor/google.golang.org/protobuf/internal/genid/struct_gen.go b/vendor/google.golang.org/protobuf/internal/genid/struct_gen.go
index 1a38944b26..ad6f80c460 100644
--- a/vendor/google.golang.org/protobuf/internal/genid/struct_gen.go
+++ b/vendor/google.golang.org/protobuf/internal/genid/struct_gen.go
@@ -18,6 +18,11 @@ const (
NullValue_enum_name = "NullValue"
)
+// Enum values for google.protobuf.NullValue.
+const (
+ NullValue_NULL_VALUE_enum_value = 0
+)
+
// Names for google.protobuf.Struct.
const (
Struct_message_name protoreflect.Name = "Struct"
diff --git a/vendor/google.golang.org/protobuf/internal/genid/type_gen.go b/vendor/google.golang.org/protobuf/internal/genid/type_gen.go
index e0f75fea0a..49bc73e259 100644
--- a/vendor/google.golang.org/protobuf/internal/genid/type_gen.go
+++ b/vendor/google.golang.org/protobuf/internal/genid/type_gen.go
@@ -18,6 +18,13 @@ const (
Syntax_enum_name = "Syntax"
)
+// Enum values for google.protobuf.Syntax.
+const (
+ Syntax_SYNTAX_PROTO2_enum_value = 0
+ Syntax_SYNTAX_PROTO3_enum_value = 1
+ Syntax_SYNTAX_EDITIONS_enum_value = 2
+)
+
// Names for google.protobuf.Type.
const (
Type_message_name protoreflect.Name = "Type"
@@ -105,12 +112,43 @@ const (
Field_Kind_enum_name = "Kind"
)
+// Enum values for google.protobuf.Field.Kind.
+const (
+ Field_TYPE_UNKNOWN_enum_value = 0
+ Field_TYPE_DOUBLE_enum_value = 1
+ Field_TYPE_FLOAT_enum_value = 2
+ Field_TYPE_INT64_enum_value = 3
+ Field_TYPE_UINT64_enum_value = 4
+ Field_TYPE_INT32_enum_value = 5
+ Field_TYPE_FIXED64_enum_value = 6
+ Field_TYPE_FIXED32_enum_value = 7
+ Field_TYPE_BOOL_enum_value = 8
+ Field_TYPE_STRING_enum_value = 9
+ Field_TYPE_GROUP_enum_value = 10
+ Field_TYPE_MESSAGE_enum_value = 11
+ Field_TYPE_BYTES_enum_value = 12
+ Field_TYPE_UINT32_enum_value = 13
+ Field_TYPE_ENUM_enum_value = 14
+ Field_TYPE_SFIXED32_enum_value = 15
+ Field_TYPE_SFIXED64_enum_value = 16
+ Field_TYPE_SINT32_enum_value = 17
+ Field_TYPE_SINT64_enum_value = 18
+)
+
// Full and short names for google.protobuf.Field.Cardinality.
const (
Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality"
Field_Cardinality_enum_name = "Cardinality"
)
+// Enum values for google.protobuf.Field.Cardinality.
+const (
+ Field_CARDINALITY_UNKNOWN_enum_value = 0
+ Field_CARDINALITY_OPTIONAL_enum_value = 1
+ Field_CARDINALITY_REQUIRED_enum_value = 2
+ Field_CARDINALITY_REPEATED_enum_value = 3
+)
+
// Names for google.protobuf.Enum.
const (
Enum_message_name protoreflect.Name = "Enum"
diff --git a/vendor/google.golang.org/protobuf/internal/impl/api_export.go b/vendor/google.golang.org/protobuf/internal/impl/api_export.go
index a371f98de1..5d5771c2ed 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/api_export.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/api_export.go
@@ -22,13 +22,13 @@ type Export struct{}
// NewError formats a string according to the format specifier and arguments and
// returns an error that has a "proto" prefix.
-func (Export) NewError(f string, x ...interface{}) error {
+func (Export) NewError(f string, x ...any) error {
return errors.New(f, x...)
}
// enum is any enum type generated by protoc-gen-go
// and must be a named int32 type.
-type enum = interface{}
+type enum = any
// EnumOf returns the protoreflect.Enum interface over e.
// It returns nil if e is nil.
@@ -81,7 +81,7 @@ func (Export) EnumStringOf(ed protoreflect.EnumDescriptor, n protoreflect.EnumNu
// message is any message type generated by protoc-gen-go
// and must be a pointer to a named struct type.
-type message = interface{}
+type message = any
// legacyMessageWrapper wraps a v2 message as a v1 message.
type legacyMessageWrapper struct{ m protoreflect.ProtoMessage }
diff --git a/vendor/google.golang.org/protobuf/internal/impl/checkinit.go b/vendor/google.golang.org/protobuf/internal/impl/checkinit.go
index bff041edc9..f29e6a8fa8 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/checkinit.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/checkinit.go
@@ -68,7 +68,7 @@ func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error {
}
for _, x := range *ext {
ei := getExtensionFieldInfo(x.Type())
- if ei.funcs.isInit == nil {
+ if ei.funcs.isInit == nil || x.isUnexpandedLazy() {
continue
}
v := x.Value()
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go b/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go
index e74cefdc50..4bb0a7a20c 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go
@@ -21,26 +21,18 @@ type extensionFieldInfo struct {
validation validationInfo
}
-var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo
-
func getExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo {
if xi, ok := xt.(*ExtensionInfo); ok {
xi.lazyInit()
return xi.info
}
- return legacyLoadExtensionFieldInfo(xt)
-}
-
-// legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt.
-func legacyLoadExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo {
- if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok {
- return xi.(*extensionFieldInfo)
- }
- e := makeExtensionFieldInfo(xt.TypeDescriptor())
- if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok {
- return e.(*extensionFieldInfo)
- }
- return e
+ // Ideally we'd cache the resulting *extensionFieldInfo so we don't have to
+ // recompute this metadata repeatedly. But without support for something like
+ // weak references, such a cache would pin temporary values (like dynamic
+ // extension types, constructed for the duration of a user request) to the
+ // heap forever, causing memory usage of the cache to grow unbounded.
+ // See discussion in https://github.com/golang/protobuf/issues/1521.
+ return makeExtensionFieldInfo(xt.TypeDescriptor())
}
func makeExtensionFieldInfo(xd protoreflect.ExtensionDescriptor) *extensionFieldInfo {
@@ -107,6 +99,28 @@ func (f *ExtensionField) canLazy(xt protoreflect.ExtensionType) bool {
return false
}
+// isUnexpandedLazy returns true if the ExensionField is lazy and not
+// yet expanded, which means it's present and already checked for
+// initialized required fields.
+func (f *ExtensionField) isUnexpandedLazy() bool {
+ return f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0
+}
+
+// lazyBuffer retrieves the buffer for a lazy extension if it's not yet expanded.
+//
+// The returned buffer has to be kept over whatever operation we're planning,
+// as re-retrieving it will fail after the message is lazily decoded.
+func (f *ExtensionField) lazyBuffer() []byte {
+ // This function might be in the critical path, so check the atomic without
+ // taking a look first, then only take the lock if needed.
+ if !f.isUnexpandedLazy() {
+ return nil
+ }
+ f.lazy.mu.Lock()
+ defer f.lazy.mu.Unlock()
+ return f.lazy.b
+}
+
func (f *ExtensionField) lazyInit() {
f.lazy.mu.Lock()
defer f.lazy.mu.Unlock()
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_field.go b/vendor/google.golang.org/protobuf/internal/impl/codec_field.go
index 3fadd241e1..78ee47e44b 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_field.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_field.go
@@ -233,9 +233,15 @@ func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
}
func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
+ calculatedSize := f.mi.sizePointer(p.Elem(), opts)
b = protowire.AppendVarint(b, f.wiretag)
- b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts)))
- return f.mi.marshalAppendPointer(b, p.Elem(), opts)
+ b = protowire.AppendVarint(b, uint64(calculatedSize))
+ before := len(b)
+ b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
+ if measuredSize := len(b) - before; calculatedSize != measuredSize && err == nil {
+ return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize)
+ }
+ return b, err
}
func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
@@ -262,14 +268,21 @@ func isInitMessageInfo(p pointer, f *coderFieldInfo) error {
return f.mi.checkInitializedPointer(p.Elem())
}
-func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
- return protowire.SizeBytes(proto.Size(m)) + tagsize
+func sizeMessage(m proto.Message, tagsize int, opts marshalOptions) int {
+ return protowire.SizeBytes(opts.Options().Size(m)) + tagsize
}
func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
+ mopts := opts.Options()
+ calculatedSize := mopts.Size(m)
b = protowire.AppendVarint(b, wiretag)
- b = protowire.AppendVarint(b, uint64(proto.Size(m)))
- return opts.Options().MarshalAppend(b, m)
+ b = protowire.AppendVarint(b, uint64(calculatedSize))
+ before := len(b)
+ b, err := mopts.MarshalAppend(b, m)
+ if measuredSize := len(b) - before; calculatedSize != measuredSize && err == nil {
+ return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize)
+ }
+ return b, err
}
func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
@@ -405,8 +418,8 @@ func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInf
return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts)
}
-func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
- return 2*tagsize + proto.Size(m)
+func sizeGroup(m proto.Message, tagsize int, opts marshalOptions) int {
+ return 2*tagsize + opts.Options().Size(m)
}
func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
@@ -482,10 +495,14 @@ func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshal
b = protowire.AppendVarint(b, f.wiretag)
siz := f.mi.sizePointer(v, opts)
b = protowire.AppendVarint(b, uint64(siz))
+ before := len(b)
b, err = f.mi.marshalAppendPointer(b, v, opts)
if err != nil {
return b, err
}
+ if measuredSize := len(b) - before; siz != measuredSize {
+ return nil, errors.MismatchedSizeCalculation(siz, measuredSize)
+ }
}
return b, nil
}
@@ -520,28 +537,34 @@ func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error {
return nil
}
-func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
+func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, opts marshalOptions) int {
+ mopts := opts.Options()
s := p.PointerSlice()
n := 0
for _, v := range s {
m := asMessage(v.AsValueOf(goType.Elem()))
- n += protowire.SizeBytes(proto.Size(m)) + tagsize
+ n += protowire.SizeBytes(mopts.Size(m)) + tagsize
}
return n
}
func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
+ mopts := opts.Options()
s := p.PointerSlice()
var err error
for _, v := range s {
m := asMessage(v.AsValueOf(goType.Elem()))
b = protowire.AppendVarint(b, wiretag)
- siz := proto.Size(m)
+ siz := mopts.Size(m)
b = protowire.AppendVarint(b, uint64(siz))
- b, err = opts.Options().MarshalAppend(b, m)
+ before := len(b)
+ b, err = mopts.MarshalAppend(b, m)
if err != nil {
return b, err
}
+ if measuredSize := len(b) - before; siz != measuredSize {
+ return nil, errors.MismatchedSizeCalculation(siz, measuredSize)
+ }
}
return b, nil
}
@@ -582,11 +605,12 @@ func isInitMessageSlice(p pointer, goType reflect.Type) error {
// Slices of messages
func sizeMessageSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int {
+ mopts := opts.Options()
list := listv.List()
n := 0
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
- n += protowire.SizeBytes(proto.Size(m)) + tagsize
+ n += protowire.SizeBytes(mopts.Size(m)) + tagsize
}
return n
}
@@ -597,13 +621,17 @@ func appendMessageSliceValue(b []byte, listv protoreflect.Value, wiretag uint64,
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
b = protowire.AppendVarint(b, wiretag)
- siz := proto.Size(m)
+ siz := mopts.Size(m)
b = protowire.AppendVarint(b, uint64(siz))
+ before := len(b)
var err error
b, err = mopts.MarshalAppend(b, m)
if err != nil {
return b, err
}
+ if measuredSize := len(b) - before; siz != measuredSize {
+ return nil, errors.MismatchedSizeCalculation(siz, measuredSize)
+ }
}
return b, nil
}
@@ -651,11 +679,12 @@ var coderMessageSliceValue = valueCoderFuncs{
}
func sizeGroupSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int {
+ mopts := opts.Options()
list := listv.List()
n := 0
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
- n += 2*tagsize + proto.Size(m)
+ n += 2*tagsize + mopts.Size(m)
}
return n
}
@@ -738,12 +767,13 @@ func makeGroupSliceFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type)
}
}
-func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
+func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, opts marshalOptions) int {
+ mopts := opts.Options()
s := p.PointerSlice()
n := 0
for _, v := range s {
m := asMessage(v.AsValueOf(messageType.Elem()))
- n += 2*tagsize + proto.Size(m)
+ n += 2*tagsize + mopts.Size(m)
}
return n
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_gen.go b/vendor/google.golang.org/protobuf/internal/impl/codec_gen.go
index 1a509b63eb..f55dc01e3a 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_gen.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_gen.go
@@ -162,11 +162,20 @@ func appendBoolSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions
func consumeBoolSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.BoolSlice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := 0
+ for _, v := range b {
+ if v < 0x80 {
+ count++
+ }
+ }
+ if count > 0 {
+ p.growBoolSlice(count)
+ }
+ s := *sp
for len(b) > 0 {
var v uint64
var n int
@@ -732,11 +741,20 @@ func appendInt32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeInt32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := 0
+ for _, v := range b {
+ if v < 0x80 {
+ count++
+ }
+ }
+ if count > 0 {
+ p.growInt32Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
var v uint64
var n int
@@ -1138,11 +1156,20 @@ func appendSint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeSint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := 0
+ for _, v := range b {
+ if v < 0x80 {
+ count++
+ }
+ }
+ if count > 0 {
+ p.growInt32Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
var v uint64
var n int
@@ -1544,11 +1571,20 @@ func appendUint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeUint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint32Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := 0
+ for _, v := range b {
+ if v < 0x80 {
+ count++
+ }
+ }
+ if count > 0 {
+ p.growUint32Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
var v uint64
var n int
@@ -1950,11 +1986,20 @@ func appendInt64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeInt64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := 0
+ for _, v := range b {
+ if v < 0x80 {
+ count++
+ }
+ }
+ if count > 0 {
+ p.growInt64Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
var v uint64
var n int
@@ -2356,11 +2401,20 @@ func appendSint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeSint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := 0
+ for _, v := range b {
+ if v < 0x80 {
+ count++
+ }
+ }
+ if count > 0 {
+ p.growInt64Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
var v uint64
var n int
@@ -2762,11 +2816,20 @@ func appendUint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeUint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint64Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := 0
+ for _, v := range b {
+ if v < 0x80 {
+ count++
+ }
+ }
+ if count > 0 {
+ p.growUint64Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
var v uint64
var n int
@@ -3145,11 +3208,15 @@ func appendSfixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpt
func consumeSfixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int32Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := len(b) / protowire.SizeFixed32()
+ if count > 0 {
+ p.growInt32Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b)
if n < 0 {
@@ -3461,11 +3528,15 @@ func appendFixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpti
func consumeFixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint32Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := len(b) / protowire.SizeFixed32()
+ if count > 0 {
+ p.growUint32Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b)
if n < 0 {
@@ -3777,11 +3848,15 @@ func appendFloatSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOption
func consumeFloatSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Float32Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := len(b) / protowire.SizeFixed32()
+ if count > 0 {
+ p.growFloat32Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
v, n := protowire.ConsumeFixed32(b)
if n < 0 {
@@ -4093,11 +4168,15 @@ func appendSfixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpt
func consumeSfixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Int64Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := len(b) / protowire.SizeFixed64()
+ if count > 0 {
+ p.growInt64Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b)
if n < 0 {
@@ -4409,11 +4488,15 @@ func appendFixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOpti
func consumeFixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Uint64Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := len(b) / protowire.SizeFixed64()
+ if count > 0 {
+ p.growUint64Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b)
if n < 0 {
@@ -4725,11 +4808,15 @@ func appendDoubleSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptio
func consumeDoubleSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.Float64Slice()
if wtyp == protowire.BytesType {
- s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
+ count := len(b) / protowire.SizeFixed64()
+ if count > 0 {
+ p.growFloat64Slice(count)
+ }
+ s := *sp
for len(b) > 0 {
v, n := protowire.ConsumeFixed64(b)
if n < 0 {
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go
index 111b9d16f9..fb35f0bae9 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go
@@ -9,6 +9,7 @@ import (
"sort"
"google.golang.org/protobuf/encoding/protowire"
+ "google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/reflect/protoreflect"
)
@@ -240,11 +241,16 @@ func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coder
size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
size += mapi.valFuncs.size(val, mapValTagSize, opts)
b = protowire.AppendVarint(b, uint64(size))
+ before := len(b)
b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
if err != nil {
return nil, err
}
- return mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts)
+ b, err = mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts)
+ if measuredSize := len(b) - before; size != measuredSize && err == nil {
+ return nil, errors.MismatchedSizeCalculation(size, measuredSize)
+ }
+ return b, err
} else {
key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
val := pointerOfValue(valrv)
@@ -259,7 +265,12 @@ func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coder
}
b = protowire.AppendVarint(b, mapi.valWiretag)
b = protowire.AppendVarint(b, uint64(valSize))
- return f.mi.marshalAppendPointer(b, val, opts)
+ before := len(b)
+ b, err = f.mi.marshalAppendPointer(b, val, opts)
+ if measuredSize := len(b) - before; valSize != measuredSize && err == nil {
+ return nil, errors.MismatchedSizeCalculation(valSize, measuredSize)
+ }
+ return b, err
}
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go b/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go
index b7a23faf1e..7a16ec13dd 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go
@@ -26,6 +26,15 @@ func sizeMessageSet(mi *MessageInfo, p pointer, opts marshalOptions) (size int)
}
num, _ := protowire.DecodeTag(xi.wiretag)
size += messageset.SizeField(num)
+ if fullyLazyExtensions(opts) {
+ // Don't expand the extension, instead use the buffer to calculate size
+ if lb := x.lazyBuffer(); lb != nil {
+ // We got hold of the buffer, so it's still lazy.
+ // Don't count the tag size in the extension buffer, it's already added.
+ size += protowire.SizeTag(messageset.FieldMessage) + len(lb) - xi.tagsize
+ continue
+ }
+ }
size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts)
}
@@ -85,6 +94,19 @@ func marshalMessageSetField(mi *MessageInfo, b []byte, x ExtensionField, opts ma
xi := getExtensionFieldInfo(x.Type())
num, _ := protowire.DecodeTag(xi.wiretag)
b = messageset.AppendFieldStart(b, num)
+
+ if fullyLazyExtensions(opts) {
+ // Don't expand the extension if it's still in wire format, instead use the buffer content.
+ if lb := x.lazyBuffer(); lb != nil {
+ // The tag inside the lazy buffer is a different tag (the extension
+ // number), but what we need here is the tag for FieldMessage:
+ b = protowire.AppendVarint(b, protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType))
+ b = append(b, lb[xi.tagsize:]...)
+ b = messageset.AppendFieldEnd(b)
+ return b, nil
+ }
+ }
+
b, err := xi.funcs.marshal(b, x.Value(), protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType), opts)
if err != nil {
return b, err
diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_tables.go b/vendor/google.golang.org/protobuf/internal/impl/codec_tables.go
index 576dcf3aac..13077751e2 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/codec_tables.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/codec_tables.go
@@ -197,7 +197,7 @@ func fieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) (*MessageInfo,
return getMessageInfo(ft), makeMessageFieldCoder(fd, ft)
case fd.Kind() == protoreflect.GroupKind:
return getMessageInfo(ft), makeGroupFieldCoder(fd, ft)
- case fd.Syntax() == protoreflect.Proto3 && fd.ContainingOneof() == nil:
+ case !fd.HasPresence() && fd.ContainingOneof() == nil:
// Populated oneof fields always encode even if set to the zero value,
// which normally are not encoded in proto3.
switch fd.Kind() {
diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert.go b/vendor/google.golang.org/protobuf/internal/impl/convert.go
index 185ef2efa5..e06ece55a2 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/convert.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/convert.go
@@ -14,7 +14,7 @@ import (
// unwrapper unwraps the value to the underlying value.
// This is implemented by List and Map.
type unwrapper interface {
- protoUnwrap() interface{}
+ protoUnwrap() any
}
// A Converter coverts to/from Go reflect.Value types and protobuf protoreflect.Value types.
diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert_list.go b/vendor/google.golang.org/protobuf/internal/impl/convert_list.go
index f89136516f..18cb96fd70 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/convert_list.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/convert_list.go
@@ -136,6 +136,6 @@ func (ls *listReflect) NewElement() protoreflect.Value {
func (ls *listReflect) IsValid() bool {
return !ls.v.IsNil()
}
-func (ls *listReflect) protoUnwrap() interface{} {
+func (ls *listReflect) protoUnwrap() any {
return ls.v.Interface()
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert_map.go b/vendor/google.golang.org/protobuf/internal/impl/convert_map.go
index f30b0a0576..304244a651 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/convert_map.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/convert_map.go
@@ -116,6 +116,6 @@ func (ms *mapReflect) NewValue() protoreflect.Value {
func (ms *mapReflect) IsValid() bool {
return !ms.v.IsNil()
}
-func (ms *mapReflect) protoUnwrap() interface{} {
+func (ms *mapReflect) protoUnwrap() any {
return ms.v.Interface()
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/encode.go b/vendor/google.golang.org/protobuf/internal/impl/encode.go
index 845c67d6e7..febd212247 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/encode.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/encode.go
@@ -49,8 +49,11 @@ func (mi *MessageInfo) sizePointer(p pointer, opts marshalOptions) (size int) {
return 0
}
if opts.UseCachedSize() && mi.sizecacheOffset.IsValid() {
- if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size >= 0 {
- return int(size)
+ // The size cache contains the size + 1, to allow the
+ // zero value to be invalid, while also allowing for a
+ // 0 size to be cached.
+ if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size > 0 {
+ return int(size - 1)
}
}
return mi.sizePointerSlow(p, opts)
@@ -60,7 +63,7 @@ func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int
if flags.ProtoLegacy && mi.isMessageSet {
size = sizeMessageSet(mi, p, opts)
if mi.sizecacheOffset.IsValid() {
- atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size))
+ atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1))
}
return size
}
@@ -84,13 +87,16 @@ func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int
}
}
if mi.sizecacheOffset.IsValid() {
- if size > math.MaxInt32 {
+ if size > (math.MaxInt32 - 1) {
// The size is too large for the int32 sizecache field.
// We will need to recompute the size when encoding;
// unfortunately expensive, but better than invalid output.
- atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), -1)
+ atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), 0)
} else {
- atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size))
+ // The size cache contains the size + 1, to allow the
+ // zero value to be invalid, while also allowing for a
+ // 0 size to be cached.
+ atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1))
}
}
return size
@@ -149,6 +155,14 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt
return b, nil
}
+// fullyLazyExtensions returns true if we should attempt to keep extensions lazy over size and marshal.
+func fullyLazyExtensions(opts marshalOptions) bool {
+ // When deterministic marshaling is requested, force an unmarshal for lazy
+ // extensions to produce a deterministic result, instead of passing through
+ // bytes lazily that may or may not match what Go Protobuf would produce.
+ return opts.flags&piface.MarshalDeterministic == 0
+}
+
func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) {
if ext == nil {
return 0
@@ -158,6 +172,14 @@ func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marsha
if xi.funcs.size == nil {
continue
}
+ if fullyLazyExtensions(opts) {
+ // Don't expand the extension, instead use the buffer to calculate size
+ if lb := x.lazyBuffer(); lb != nil {
+ // We got hold of the buffer, so it's still lazy.
+ n += len(lb)
+ continue
+ }
+ }
n += xi.funcs.size(x.Value(), xi.tagsize, opts)
}
return n
@@ -176,6 +198,13 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField,
var err error
for _, x := range *ext {
xi := getExtensionFieldInfo(x.Type())
+ if fullyLazyExtensions(opts) {
+ // Don't expand the extension if it's still in wire format, instead use the buffer content.
+ if lb := x.lazyBuffer(); lb != nil {
+ b = append(b, lb...)
+ continue
+ }
+ }
b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
}
return b, err
@@ -191,6 +220,13 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField,
for _, k := range keys {
x := (*ext)[int32(k)]
xi := getExtensionFieldInfo(x.Type())
+ if fullyLazyExtensions(opts) {
+ // Don't expand the extension if it's still in wire format, instead use the buffer content.
+ if lb := x.lazyBuffer(); lb != nil {
+ b = append(b, lb...)
+ continue
+ }
+ }
b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
if err != nil {
return b, err
diff --git a/vendor/google.golang.org/protobuf/internal/impl/extension.go b/vendor/google.golang.org/protobuf/internal/impl/extension.go
index cb25b0bae1..e31249f64f 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/extension.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/extension.go
@@ -53,7 +53,7 @@ type ExtensionInfo struct {
// type returned by InterfaceOf may not be identical.
//
// Deprecated: Use InterfaceOf(xt.Zero()) instead.
- ExtensionType interface{}
+ ExtensionType any
// Field is the field number of the extension.
//
@@ -95,16 +95,16 @@ func (xi *ExtensionInfo) New() protoreflect.Value {
func (xi *ExtensionInfo) Zero() protoreflect.Value {
return xi.lazyInit().Zero()
}
-func (xi *ExtensionInfo) ValueOf(v interface{}) protoreflect.Value {
+func (xi *ExtensionInfo) ValueOf(v any) protoreflect.Value {
return xi.lazyInit().PBValueOf(reflect.ValueOf(v))
}
-func (xi *ExtensionInfo) InterfaceOf(v protoreflect.Value) interface{} {
+func (xi *ExtensionInfo) InterfaceOf(v protoreflect.Value) any {
return xi.lazyInit().GoValueOf(v).Interface()
}
func (xi *ExtensionInfo) IsValidValue(v protoreflect.Value) bool {
return xi.lazyInit().IsValidPB(v)
}
-func (xi *ExtensionInfo) IsValidInterface(v interface{}) bool {
+func (xi *ExtensionInfo) IsValidInterface(v any) bool {
return xi.lazyInit().IsValidGo(reflect.ValueOf(v))
}
func (xi *ExtensionInfo) TypeDescriptor() protoreflect.ExtensionTypeDescriptor {
diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go
index c2a803bb2f..81b2b1a763 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go
@@ -97,7 +97,7 @@ func (e *legacyEnumWrapper) Number() protoreflect.EnumNumber {
func (e *legacyEnumWrapper) ProtoReflect() protoreflect.Enum {
return e
}
-func (e *legacyEnumWrapper) protoUnwrap() interface{} {
+func (e *legacyEnumWrapper) protoUnwrap() any {
v := reflect.New(e.goTyp).Elem()
v.SetInt(int64(e.num))
return v.Interface()
@@ -167,6 +167,7 @@ func aberrantLoadEnumDesc(t reflect.Type) protoreflect.EnumDescriptor {
ed := &filedesc.Enum{L2: new(filedesc.EnumL2)}
ed.L0.FullName = AberrantDeriveFullName(t) // e.g., github_com.user.repo.MyEnum
ed.L0.ParentFile = filedesc.SurrogateProto3
+ ed.L1.EditionFeatures = ed.L0.ParentFile.L1.EditionFeatures
ed.L2.Values.List = append(ed.L2.Values.List, filedesc.EnumValue{})
// TODO: Use the presence of a UnmarshalJSON method to determine proto2?
diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go
index 87b30d0504..6e8677ee63 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go
@@ -118,7 +118,7 @@ func (xi *ExtensionInfo) initFromLegacy() {
xd.L1.Number = protoreflect.FieldNumber(xi.Field)
xd.L1.Cardinality = fd.L1.Cardinality
xd.L1.Kind = fd.L1.Kind
- xd.L2.IsPacked = fd.L1.IsPacked
+ xd.L1.EditionFeatures = fd.L1.EditionFeatures
xd.L2.Default = fd.L1.Default
xd.L1.Extendee = Export{}.MessageDescriptorOf(xi.ExtendedType)
xd.L2.Enum = ed
diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go
index 9ab091086c..b649f1124b 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go
@@ -7,7 +7,7 @@ package impl
import (
"bytes"
"compress/gzip"
- "io/ioutil"
+ "io"
"sync"
"google.golang.org/protobuf/internal/filedesc"
@@ -51,7 +51,7 @@ func legacyLoadFileDesc(b []byte) protoreflect.FileDescriptor {
if err != nil {
panic(err)
}
- b2, err := ioutil.ReadAll(zr)
+ b2, err := io.ReadAll(zr)
if err != nil {
panic(err)
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
index 61c483fac0..bf0b6049b4 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
@@ -204,15 +204,21 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName
}
}
+ md.L1.EditionFeatures = md.L0.ParentFile.L1.EditionFeatures
// Obtain a list of oneof wrapper types.
var oneofWrappers []reflect.Type
- for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} {
- if fn, ok := t.MethodByName(method); ok {
- for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
- if vs, ok := v.Interface().([]interface{}); ok {
- for _, v := range vs {
- oneofWrappers = append(oneofWrappers, reflect.TypeOf(v))
- }
+ methods := make([]reflect.Method, 0, 2)
+ if m, ok := t.MethodByName("XXX_OneofFuncs"); ok {
+ methods = append(methods, m)
+ }
+ if m, ok := t.MethodByName("XXX_OneofWrappers"); ok {
+ methods = append(methods, m)
+ }
+ for _, fn := range methods {
+ for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
+ if vs, ok := v.Interface().([]any); ok {
+ for _, v := range vs {
+ oneofWrappers = append(oneofWrappers, reflect.TypeOf(v))
}
}
}
@@ -245,6 +251,7 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName
od := &md.L2.Oneofs.List[n]
od.L0.FullName = md.FullName().Append(protoreflect.Name(tag))
od.L0.ParentFile = md.L0.ParentFile
+ od.L1.EditionFeatures = md.L1.EditionFeatures
od.L0.Parent = md
od.L0.Index = n
@@ -255,6 +262,7 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName
aberrantAppendField(md, f.Type, tag, "", "")
fd := &md.L2.Fields.List[len(md.L2.Fields.List)-1]
fd.L1.ContainingOneof = od
+ fd.L1.EditionFeatures = od.L1.EditionFeatures
od.L1.Fields.List = append(od.L1.Fields.List, fd)
}
}
@@ -302,14 +310,14 @@ func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey,
fd.L0.Parent = md
fd.L0.Index = n
- if fd.L1.IsWeak || fd.L1.HasPacked {
+ if fd.L1.IsWeak || fd.L1.EditionFeatures.IsPacked {
fd.L1.Options = func() protoreflect.ProtoMessage {
opts := descopts.Field.ProtoReflect().New()
if fd.L1.IsWeak {
opts.Set(opts.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true))
}
- if fd.L1.HasPacked {
- opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.IsPacked))
+ if fd.L1.EditionFeatures.IsPacked {
+ opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.EditionFeatures.IsPacked))
}
return opts.Interface()
}
@@ -339,6 +347,7 @@ func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey,
md2.L0.ParentFile = md.L0.ParentFile
md2.L0.Parent = md
md2.L0.Index = n
+ md2.L1.EditionFeatures = md.L1.EditionFeatures
md2.L1.IsMapEntry = true
md2.L2.Options = func() protoreflect.ProtoMessage {
@@ -558,6 +567,6 @@ func (m aberrantMessage) IsValid() bool {
func (m aberrantMessage) ProtoMethods() *protoiface.Methods {
return aberrantProtoMethods
}
-func (m aberrantMessage) protoUnwrap() interface{} {
+func (m aberrantMessage) protoUnwrap() any {
return m.v.Interface()
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message.go b/vendor/google.golang.org/protobuf/internal/impl/message.go
index 4f5fb67a0d..019399d454 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message.go
@@ -35,7 +35,7 @@ type MessageInfo struct {
Exporter exporter
// OneofWrappers is list of pointers to oneof wrapper struct types.
- OneofWrappers []interface{}
+ OneofWrappers []any
initMu sync.Mutex // protects all unexported fields
initDone uint32
@@ -47,7 +47,7 @@ type MessageInfo struct {
// exporter is a function that returns a reference to the ith field of v,
// where v is a pointer to a struct. It returns nil if it does not support
// exporting the requested field (e.g., already exported).
-type exporter func(v interface{}, i int) interface{}
+type exporter func(v any, i int) any
// getMessageInfo returns the MessageInfo for any message type that
// is generated by our implementation of protoc-gen-go (for v2 and on).
@@ -192,12 +192,17 @@ fieldLoop:
// Derive a mapping of oneof wrappers to fields.
oneofWrappers := mi.OneofWrappers
- for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} {
- if fn, ok := reflect.PtrTo(t).MethodByName(method); ok {
- for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
- if vs, ok := v.Interface().([]interface{}); ok {
- oneofWrappers = vs
- }
+ methods := make([]reflect.Method, 0, 2)
+ if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
+ methods = append(methods, m)
+ }
+ if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
+ methods = append(methods, m)
+ }
+ for _, fn := range methods {
+ for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
+ if vs, ok := v.Interface().([]any); ok {
+ oneofWrappers = vs
}
}
}
@@ -251,7 +256,7 @@ func (mi *MessageInfo) Message(i int) protoreflect.MessageType {
type mapEntryType struct {
desc protoreflect.MessageDescriptor
- valType interface{} // zero value of enum or message type
+ valType any // zero value of enum or message type
}
func (mt mapEntryType) New() protoreflect.Message {
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go
index d9ea010bef..ecb4623d70 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go
@@ -20,7 +20,7 @@ type reflectMessageInfo struct {
// fieldTypes contains the zero value of an enum or message field.
// For lists, it contains the element type.
// For maps, it contains the entry value type.
- fieldTypes map[protoreflect.FieldNumber]interface{}
+ fieldTypes map[protoreflect.FieldNumber]any
// denseFields is a subset of fields where:
// 0 < fieldDesc.Number() < len(denseFields)
@@ -28,7 +28,7 @@ type reflectMessageInfo struct {
denseFields []*fieldInfo
// rangeInfos is a list of all fields (not belonging to a oneof) and oneofs.
- rangeInfos []interface{} // either *fieldInfo or *oneofInfo
+ rangeInfos []any // either *fieldInfo or *oneofInfo
getUnknown func(pointer) protoreflect.RawFields
setUnknown func(pointer, protoreflect.RawFields)
@@ -224,7 +224,7 @@ func (mi *MessageInfo) makeFieldTypes(si structInfo) {
}
if ft != nil {
if mi.fieldTypes == nil {
- mi.fieldTypes = make(map[protoreflect.FieldNumber]interface{})
+ mi.fieldTypes = make(map[protoreflect.FieldNumber]any)
}
mi.fieldTypes[fd.Number()] = reflect.Zero(ft).Interface()
}
@@ -247,39 +247,39 @@ func (m *extensionMap) Range(f func(protoreflect.FieldDescriptor, protoreflect.V
}
}
}
-func (m *extensionMap) Has(xt protoreflect.ExtensionType) (ok bool) {
+func (m *extensionMap) Has(xd protoreflect.ExtensionTypeDescriptor) (ok bool) {
if m == nil {
return false
}
- xd := xt.TypeDescriptor()
x, ok := (*m)[int32(xd.Number())]
if !ok {
return false
}
+ if x.isUnexpandedLazy() {
+ // Avoid calling x.Value(), which triggers a lazy unmarshal.
+ return true
+ }
switch {
case xd.IsList():
return x.Value().List().Len() > 0
case xd.IsMap():
return x.Value().Map().Len() > 0
- case xd.Message() != nil:
- return x.Value().Message().IsValid()
}
return true
}
-func (m *extensionMap) Clear(xt protoreflect.ExtensionType) {
- delete(*m, int32(xt.TypeDescriptor().Number()))
+func (m *extensionMap) Clear(xd protoreflect.ExtensionTypeDescriptor) {
+ delete(*m, int32(xd.Number()))
}
-func (m *extensionMap) Get(xt protoreflect.ExtensionType) protoreflect.Value {
- xd := xt.TypeDescriptor()
+func (m *extensionMap) Get(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value {
if m != nil {
if x, ok := (*m)[int32(xd.Number())]; ok {
return x.Value()
}
}
- return xt.Zero()
+ return xd.Type().Zero()
}
-func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value) {
- xd := xt.TypeDescriptor()
+func (m *extensionMap) Set(xd protoreflect.ExtensionTypeDescriptor, v protoreflect.Value) {
+ xt := xd.Type()
isValid := true
switch {
case !xt.IsValidValue(v):
@@ -292,7 +292,7 @@ func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value)
isValid = v.Message().IsValid()
}
if !isValid {
- panic(fmt.Sprintf("%v: assigning invalid value", xt.TypeDescriptor().FullName()))
+ panic(fmt.Sprintf("%v: assigning invalid value", xd.FullName()))
}
if *m == nil {
@@ -302,16 +302,15 @@ func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value)
x.Set(xt, v)
(*m)[int32(xd.Number())] = x
}
-func (m *extensionMap) Mutable(xt protoreflect.ExtensionType) protoreflect.Value {
- xd := xt.TypeDescriptor()
+func (m *extensionMap) Mutable(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value {
if xd.Kind() != protoreflect.MessageKind && xd.Kind() != protoreflect.GroupKind && !xd.IsList() && !xd.IsMap() {
panic("invalid Mutable on field with non-composite type")
}
if x, ok := (*m)[int32(xd.Number())]; ok {
return x.Value()
}
- v := xt.New()
- m.Set(xt, v)
+ v := xd.Type().New()
+ m.Set(xd, v)
return v
}
@@ -394,7 +393,7 @@ var (
// MessageOf returns a reflective view over a message. The input must be a
// pointer to a named Go struct. If the provided type has a ProtoReflect method,
// it must be implemented by calling this method.
-func (mi *MessageInfo) MessageOf(m interface{}) protoreflect.Message {
+func (mi *MessageInfo) MessageOf(m any) protoreflect.Message {
if reflect.TypeOf(m) != mi.GoReflectType {
panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType))
}
@@ -422,13 +421,13 @@ func (m *messageIfaceWrapper) Reset() {
func (m *messageIfaceWrapper) ProtoReflect() protoreflect.Message {
return (*messageReflectWrapper)(m)
}
-func (m *messageIfaceWrapper) protoUnwrap() interface{} {
+func (m *messageIfaceWrapper) protoUnwrap() any {
return m.p.AsIfaceOf(m.mi.GoReflectType.Elem())
}
// checkField verifies that the provided field descriptor is valid.
// Exactly one of the returned values is populated.
-func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionType) {
+func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionTypeDescriptor) {
var fi *fieldInfo
if n := fd.Number(); 0 < n && int(n) < len(mi.denseFields) {
fi = mi.denseFields[n]
@@ -457,7 +456,7 @@ func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo,
if !ok {
panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", fd.FullName()))
}
- return nil, xtd.Type()
+ return nil, xtd
}
panic(fmt.Sprintf("field %v is invalid", fd.FullName()))
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go
index 5e736c60ef..986322b195 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go
@@ -538,6 +538,6 @@ func isZero(v reflect.Value) bool {
}
return true
default:
- panic(&reflect.ValueError{"reflect.Value.IsZero", v.Kind()})
+ panic(&reflect.ValueError{Method: "reflect.Value.IsZero", Kind: v.Kind()})
}
}
diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go
index 741d6e5b6b..99dc23c6f0 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go
@@ -23,12 +23,13 @@ func (m *messageState) New() protoreflect.Message {
func (m *messageState) Interface() protoreflect.ProtoMessage {
return m.protoUnwrap().(protoreflect.ProtoMessage)
}
-func (m *messageState) protoUnwrap() interface{} {
+func (m *messageState) protoUnwrap() any {
return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem())
}
func (m *messageState) ProtoMethods() *protoiface.Methods {
- m.messageInfo().init()
- return &m.messageInfo().methods
+ mi := m.messageInfo()
+ mi.init()
+ return &mi.methods
}
// ProtoMessageInfo is a pseudo-internal API for allowing the v1 code
@@ -41,8 +42,9 @@ func (m *messageState) ProtoMessageInfo() *MessageInfo {
}
func (m *messageState) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
- m.messageInfo().init()
- for _, ri := range m.messageInfo().rangeInfos {
+ mi := m.messageInfo()
+ mi.init()
+ for _, ri := range mi.rangeInfos {
switch ri := ri.(type) {
case *fieldInfo:
if ri.has(m.pointer()) {
@@ -52,77 +54,86 @@ func (m *messageState) Range(f func(protoreflect.FieldDescriptor, protoreflect.V
}
case *oneofInfo:
if n := ri.which(m.pointer()); n > 0 {
- fi := m.messageInfo().fields[n]
+ fi := mi.fields[n]
if !f(fi.fieldDesc, fi.get(m.pointer())) {
return
}
}
}
}
- m.messageInfo().extensionMap(m.pointer()).Range(f)
+ mi.extensionMap(m.pointer()).Range(f)
}
func (m *messageState) Has(fd protoreflect.FieldDescriptor) bool {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.has(m.pointer())
} else {
- return m.messageInfo().extensionMap(m.pointer()).Has(xt)
+ return mi.extensionMap(m.pointer()).Has(xd)
}
}
func (m *messageState) Clear(fd protoreflect.FieldDescriptor) {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
fi.clear(m.pointer())
} else {
- m.messageInfo().extensionMap(m.pointer()).Clear(xt)
+ mi.extensionMap(m.pointer()).Clear(xd)
}
}
func (m *messageState) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.get(m.pointer())
} else {
- return m.messageInfo().extensionMap(m.pointer()).Get(xt)
+ return mi.extensionMap(m.pointer()).Get(xd)
}
}
func (m *messageState) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
fi.set(m.pointer(), v)
} else {
- m.messageInfo().extensionMap(m.pointer()).Set(xt, v)
+ mi.extensionMap(m.pointer()).Set(xd, v)
}
}
func (m *messageState) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.mutable(m.pointer())
} else {
- return m.messageInfo().extensionMap(m.pointer()).Mutable(xt)
+ return mi.extensionMap(m.pointer()).Mutable(xd)
}
}
func (m *messageState) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.newField()
} else {
- return xt.New()
+ return xd.Type().New()
}
}
func (m *messageState) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
- m.messageInfo().init()
- if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
+ mi := m.messageInfo()
+ mi.init()
+ if oi := mi.oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
return od.Fields().ByNumber(oi.which(m.pointer()))
}
panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName()))
}
func (m *messageState) GetUnknown() protoreflect.RawFields {
- m.messageInfo().init()
- return m.messageInfo().getUnknown(m.pointer())
+ mi := m.messageInfo()
+ mi.init()
+ return mi.getUnknown(m.pointer())
}
func (m *messageState) SetUnknown(b protoreflect.RawFields) {
- m.messageInfo().init()
- m.messageInfo().setUnknown(m.pointer(), b)
+ mi := m.messageInfo()
+ mi.init()
+ mi.setUnknown(m.pointer(), b)
}
func (m *messageState) IsValid() bool {
return !m.pointer().IsNil()
@@ -143,12 +154,13 @@ func (m *messageReflectWrapper) Interface() protoreflect.ProtoMessage {
}
return (*messageIfaceWrapper)(m)
}
-func (m *messageReflectWrapper) protoUnwrap() interface{} {
+func (m *messageReflectWrapper) protoUnwrap() any {
return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem())
}
func (m *messageReflectWrapper) ProtoMethods() *protoiface.Methods {
- m.messageInfo().init()
- return &m.messageInfo().methods
+ mi := m.messageInfo()
+ mi.init()
+ return &mi.methods
}
// ProtoMessageInfo is a pseudo-internal API for allowing the v1 code
@@ -161,8 +173,9 @@ func (m *messageReflectWrapper) ProtoMessageInfo() *MessageInfo {
}
func (m *messageReflectWrapper) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
- m.messageInfo().init()
- for _, ri := range m.messageInfo().rangeInfos {
+ mi := m.messageInfo()
+ mi.init()
+ for _, ri := range mi.rangeInfos {
switch ri := ri.(type) {
case *fieldInfo:
if ri.has(m.pointer()) {
@@ -172,77 +185,86 @@ func (m *messageReflectWrapper) Range(f func(protoreflect.FieldDescriptor, proto
}
case *oneofInfo:
if n := ri.which(m.pointer()); n > 0 {
- fi := m.messageInfo().fields[n]
+ fi := mi.fields[n]
if !f(fi.fieldDesc, fi.get(m.pointer())) {
return
}
}
}
}
- m.messageInfo().extensionMap(m.pointer()).Range(f)
+ mi.extensionMap(m.pointer()).Range(f)
}
func (m *messageReflectWrapper) Has(fd protoreflect.FieldDescriptor) bool {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.has(m.pointer())
} else {
- return m.messageInfo().extensionMap(m.pointer()).Has(xt)
+ return mi.extensionMap(m.pointer()).Has(xd)
}
}
func (m *messageReflectWrapper) Clear(fd protoreflect.FieldDescriptor) {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
fi.clear(m.pointer())
} else {
- m.messageInfo().extensionMap(m.pointer()).Clear(xt)
+ mi.extensionMap(m.pointer()).Clear(xd)
}
}
func (m *messageReflectWrapper) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.get(m.pointer())
} else {
- return m.messageInfo().extensionMap(m.pointer()).Get(xt)
+ return mi.extensionMap(m.pointer()).Get(xd)
}
}
func (m *messageReflectWrapper) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
fi.set(m.pointer(), v)
} else {
- m.messageInfo().extensionMap(m.pointer()).Set(xt, v)
+ mi.extensionMap(m.pointer()).Set(xd, v)
}
}
func (m *messageReflectWrapper) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.mutable(m.pointer())
} else {
- return m.messageInfo().extensionMap(m.pointer()).Mutable(xt)
+ return mi.extensionMap(m.pointer()).Mutable(xd)
}
}
func (m *messageReflectWrapper) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
- m.messageInfo().init()
- if fi, xt := m.messageInfo().checkField(fd); fi != nil {
+ mi := m.messageInfo()
+ mi.init()
+ if fi, xd := mi.checkField(fd); fi != nil {
return fi.newField()
} else {
- return xt.New()
+ return xd.Type().New()
}
}
func (m *messageReflectWrapper) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
- m.messageInfo().init()
- if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
+ mi := m.messageInfo()
+ mi.init()
+ if oi := mi.oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
return od.Fields().ByNumber(oi.which(m.pointer()))
}
panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName()))
}
func (m *messageReflectWrapper) GetUnknown() protoreflect.RawFields {
- m.messageInfo().init()
- return m.messageInfo().getUnknown(m.pointer())
+ mi := m.messageInfo()
+ mi.init()
+ return mi.getUnknown(m.pointer())
}
func (m *messageReflectWrapper) SetUnknown(b protoreflect.RawFields) {
- m.messageInfo().init()
- m.messageInfo().setUnknown(m.pointer(), b)
+ mi := m.messageInfo()
+ mi.init()
+ mi.setUnknown(m.pointer(), b)
}
func (m *messageReflectWrapper) IsValid() bool {
return !m.pointer().IsNil()
diff --git a/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go b/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go
index 4c491bdf48..da685e8a29 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go
@@ -16,7 +16,7 @@ import (
const UnsafeEnabled = false
// Pointer is an opaque pointer type.
-type Pointer interface{}
+type Pointer any
// offset represents the offset to a struct field, accessible from a pointer.
// The offset is the field index into a struct.
@@ -62,7 +62,7 @@ func pointerOfValue(v reflect.Value) pointer {
}
// pointerOfIface returns the pointer portion of an interface.
-func pointerOfIface(v interface{}) pointer {
+func pointerOfIface(v any) pointer {
return pointer{v: reflect.ValueOf(v)}
}
@@ -93,7 +93,7 @@ func (p pointer) AsValueOf(t reflect.Type) reflect.Value {
// AsIfaceOf treats p as a pointer to an object of type t and returns the value.
// It is equivalent to p.AsValueOf(t).Interface()
-func (p pointer) AsIfaceOf(t reflect.Type) interface{} {
+func (p pointer) AsIfaceOf(t reflect.Type) any {
return p.AsValueOf(t).Interface()
}
@@ -159,6 +159,42 @@ func (p pointer) SetPointer(v pointer) {
p.v.Elem().Set(v.v)
}
+func growSlice(p pointer, addCap int) {
+ // TODO: Once we only support Go 1.20 and newer, use reflect.Grow.
+ in := p.v.Elem()
+ out := reflect.MakeSlice(in.Type(), in.Len(), in.Len()+addCap)
+ reflect.Copy(out, in)
+ p.v.Elem().Set(out)
+}
+
+func (p pointer) growBoolSlice(addCap int) {
+ growSlice(p, addCap)
+}
+
+func (p pointer) growInt32Slice(addCap int) {
+ growSlice(p, addCap)
+}
+
+func (p pointer) growUint32Slice(addCap int) {
+ growSlice(p, addCap)
+}
+
+func (p pointer) growInt64Slice(addCap int) {
+ growSlice(p, addCap)
+}
+
+func (p pointer) growUint64Slice(addCap int) {
+ growSlice(p, addCap)
+}
+
+func (p pointer) growFloat64Slice(addCap int) {
+ growSlice(p, addCap)
+}
+
+func (p pointer) growFloat32Slice(addCap int) {
+ growSlice(p, addCap)
+}
+
func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") }
func (ms *messageState) pointer() pointer { panic("not supported") }
func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") }
diff --git a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go
index ee0e0573e3..5f20ca5d8a 100644
--- a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go
+++ b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go
@@ -50,7 +50,7 @@ func pointerOfValue(v reflect.Value) pointer {
}
// pointerOfIface returns the pointer portion of an interface.
-func pointerOfIface(v interface{}) pointer {
+func pointerOfIface(v any) pointer {
type ifaceHeader struct {
Type unsafe.Pointer
Data unsafe.Pointer
@@ -80,7 +80,7 @@ func (p pointer) AsValueOf(t reflect.Type) reflect.Value {
// AsIfaceOf treats p as a pointer to an object of type t and returns the value.
// It is equivalent to p.AsValueOf(t).Interface()
-func (p pointer) AsIfaceOf(t reflect.Type) interface{} {
+func (p pointer) AsIfaceOf(t reflect.Type) any {
// TODO: Use tricky unsafe magic to directly create ifaceHeader.
return p.AsValueOf(t).Interface()
}
@@ -138,6 +138,46 @@ func (p pointer) SetPointer(v pointer) {
*(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p)
}
+func (p pointer) growBoolSlice(addCap int) {
+ sp := p.BoolSlice()
+ s := make([]bool, 0, addCap+len(*sp))
+ s = s[:len(*sp)]
+ copy(s, *sp)
+ *sp = s
+}
+
+func (p pointer) growInt32Slice(addCap int) {
+ sp := p.Int32Slice()
+ s := make([]int32, 0, addCap+len(*sp))
+ s = s[:len(*sp)]
+ copy(s, *sp)
+ *sp = s
+}
+
+func (p pointer) growUint32Slice(addCap int) {
+ p.growInt32Slice(addCap)
+}
+
+func (p pointer) growFloat32Slice(addCap int) {
+ p.growInt32Slice(addCap)
+}
+
+func (p pointer) growInt64Slice(addCap int) {
+ sp := p.Int64Slice()
+ s := make([]int64, 0, addCap+len(*sp))
+ s = s[:len(*sp)]
+ copy(s, *sp)
+ *sp = s
+}
+
+func (p pointer) growUint64Slice(addCap int) {
+ p.growInt64Slice(addCap)
+}
+
+func (p pointer) growFloat64Slice(addCap int) {
+ p.growInt64Slice(addCap)
+}
+
// Static check that MessageState does not exceed the size of a pointer.
const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{}))
diff --git a/vendor/google.golang.org/protobuf/internal/order/range.go b/vendor/google.golang.org/protobuf/internal/order/range.go
index 1665a68e5b..a1f09162d0 100644
--- a/vendor/google.golang.org/protobuf/internal/order/range.go
+++ b/vendor/google.golang.org/protobuf/internal/order/range.go
@@ -18,7 +18,7 @@ type messageField struct {
}
var messageFieldPool = sync.Pool{
- New: func() interface{} { return new([]messageField) },
+ New: func() any { return new([]messageField) },
}
type (
@@ -69,7 +69,7 @@ type mapEntry struct {
}
var mapEntryPool = sync.Pool{
- New: func() interface{} { return new([]mapEntry) },
+ New: func() any { return new([]mapEntry) },
}
type (
diff --git a/vendor/google.golang.org/protobuf/internal/strs/strings.go b/vendor/google.golang.org/protobuf/internal/strs/strings.go
index 0b74e76586..a6e7df2443 100644
--- a/vendor/google.golang.org/protobuf/internal/strs/strings.go
+++ b/vendor/google.golang.org/protobuf/internal/strs/strings.go
@@ -17,7 +17,7 @@ import (
// EnforceUTF8 reports whether to enforce strict UTF-8 validation.
func EnforceUTF8(fd protoreflect.FieldDescriptor) bool {
- if flags.ProtoLegacy {
+ if flags.ProtoLegacy || fd.Syntax() == protoreflect.Editions {
if fd, ok := fd.(interface{ EnforceUTF8() bool }); ok {
return fd.EnforceUTF8()
}
diff --git a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go
similarity index 96%
rename from vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go
rename to vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go
index 61a84d3418..a008acd090 100644
--- a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go
+++ b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !purego && !appengine
-// +build !purego,!appengine
+//go:build !purego && !appengine && !go1.21
+// +build !purego,!appengine,!go1.21
package strs
diff --git a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go121.go b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go121.go
new file mode 100644
index 0000000000..60166f2ba3
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go121.go
@@ -0,0 +1,74 @@
+// Copyright 2018 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.
+
+//go:build !purego && !appengine && go1.21
+// +build !purego,!appengine,go1.21
+
+package strs
+
+import (
+ "unsafe"
+
+ "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+// UnsafeString returns an unsafe string reference of b.
+// The caller must treat the input slice as immutable.
+//
+// WARNING: Use carefully. The returned result must not leak to the end user
+// unless the input slice is provably immutable.
+func UnsafeString(b []byte) string {
+ return unsafe.String(unsafe.SliceData(b), len(b))
+}
+
+// UnsafeBytes returns an unsafe bytes slice reference of s.
+// The caller must treat returned slice as immutable.
+//
+// WARNING: Use carefully. The returned result must not leak to the end user.
+func UnsafeBytes(s string) []byte {
+ return unsafe.Slice(unsafe.StringData(s), len(s))
+}
+
+// Builder builds a set of strings with shared lifetime.
+// This differs from strings.Builder, which is for building a single string.
+type Builder struct {
+ buf []byte
+}
+
+// AppendFullName is equivalent to protoreflect.FullName.Append,
+// but optimized for large batches where each name has a shared lifetime.
+func (sb *Builder) AppendFullName(prefix protoreflect.FullName, name protoreflect.Name) protoreflect.FullName {
+ n := len(prefix) + len(".") + len(name)
+ if len(prefix) == 0 {
+ n -= len(".")
+ }
+ sb.grow(n)
+ sb.buf = append(sb.buf, prefix...)
+ sb.buf = append(sb.buf, '.')
+ sb.buf = append(sb.buf, name...)
+ return protoreflect.FullName(sb.last(n))
+}
+
+// MakeString is equivalent to string(b), but optimized for large batches
+// with a shared lifetime.
+func (sb *Builder) MakeString(b []byte) string {
+ sb.grow(len(b))
+ sb.buf = append(sb.buf, b...)
+ return sb.last(len(b))
+}
+
+func (sb *Builder) grow(n int) {
+ if cap(sb.buf)-len(sb.buf) >= n {
+ return
+ }
+
+ // Unlike strings.Builder, we do not need to copy over the contents
+ // of the old buffer since our builder provides no API for
+ // retrieving previously created strings.
+ sb.buf = make([]byte, 0, 2*(cap(sb.buf)+n))
+}
+
+func (sb *Builder) last(n int) string {
+ return UnsafeString(sb.buf[len(sb.buf)-n:])
+}
diff --git a/vendor/google.golang.org/protobuf/internal/version/version.go b/vendor/google.golang.org/protobuf/internal/version/version.go
index 0999f29d50..dbbf1f6862 100644
--- a/vendor/google.golang.org/protobuf/internal/version/version.go
+++ b/vendor/google.golang.org/protobuf/internal/version/version.go
@@ -51,8 +51,8 @@ import (
// 10. Send out the CL for review and submit it.
const (
Major = 1
- Minor = 31
- Patch = 0
+ Minor = 34
+ Patch = 2
PreRelease = ""
)
diff --git a/vendor/google.golang.org/protobuf/proto/decode.go b/vendor/google.golang.org/protobuf/proto/decode.go
index 48d47946bb..d75a6534c1 100644
--- a/vendor/google.golang.org/protobuf/proto/decode.go
+++ b/vendor/google.golang.org/protobuf/proto/decode.go
@@ -51,6 +51,8 @@ type UnmarshalOptions struct {
// Unmarshal parses the wire-format message in b and places the result in m.
// The provided message must be mutable (e.g., a non-nil pointer to a message).
+//
+// See the [UnmarshalOptions] type if you need more control.
func Unmarshal(b []byte, m Message) error {
_, err := UnmarshalOptions{RecursionLimit: protowire.DefaultRecursionLimit}.unmarshal(b, m.ProtoReflect())
return err
@@ -69,7 +71,7 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
// UnmarshalState parses a wire-format message and places the result in m.
//
// This method permits fine-grained control over the unmarshaler.
-// Most users should use Unmarshal instead.
+// Most users should use [Unmarshal] instead.
func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
if o.RecursionLimit == 0 {
o.RecursionLimit = protowire.DefaultRecursionLimit
diff --git a/vendor/google.golang.org/protobuf/proto/doc.go b/vendor/google.golang.org/protobuf/proto/doc.go
index ec71e717fe..80ed16a0c2 100644
--- a/vendor/google.golang.org/protobuf/proto/doc.go
+++ b/vendor/google.golang.org/protobuf/proto/doc.go
@@ -18,27 +18,27 @@
// This package contains functions to convert to and from the wire format,
// an efficient binary serialization of protocol buffers.
//
-// • Size reports the size of a message in the wire format.
+// - [Size] reports the size of a message in the wire format.
//
-// • Marshal converts a message to the wire format.
-// The MarshalOptions type provides more control over wire marshaling.
+// - [Marshal] converts a message to the wire format.
+// The [MarshalOptions] type provides more control over wire marshaling.
//
-// • Unmarshal converts a message from the wire format.
-// The UnmarshalOptions type provides more control over wire unmarshaling.
+// - [Unmarshal] converts a message from the wire format.
+// The [UnmarshalOptions] type provides more control over wire unmarshaling.
//
// # Basic message operations
//
-// • Clone makes a deep copy of a message.
+// - [Clone] makes a deep copy of a message.
//
-// • Merge merges the content of a message into another.
+// - [Merge] merges the content of a message into another.
//
-// • Equal compares two messages. For more control over comparisons
-// and detailed reporting of differences, see package
-// "google.golang.org/protobuf/testing/protocmp".
+// - [Equal] compares two messages. For more control over comparisons
+// and detailed reporting of differences, see package
+// [google.golang.org/protobuf/testing/protocmp].
//
-// • Reset clears the content of a message.
+// - [Reset] clears the content of a message.
//
-// • CheckInitialized reports whether all required fields in a message are set.
+// - [CheckInitialized] reports whether all required fields in a message are set.
//
// # Optional scalar constructors
//
@@ -46,9 +46,9 @@
// as pointers to a value. For example, an optional string field has the
// Go type *string.
//
-// • Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, and String
-// take a value and return a pointer to a new instance of it,
-// to simplify construction of optional field values.
+// - [Bool], [Int32], [Int64], [Uint32], [Uint64], [Float32], [Float64], and [String]
+// take a value and return a pointer to a new instance of it,
+// to simplify construction of optional field values.
//
// Generated enum types usually have an Enum method which performs the
// same operation.
@@ -57,29 +57,29 @@
//
// # Extension accessors
//
-// • HasExtension, GetExtension, SetExtension, and ClearExtension
-// access extension field values in a protocol buffer message.
+// - [HasExtension], [GetExtension], [SetExtension], and [ClearExtension]
+// access extension field values in a protocol buffer message.
//
// Extension fields are only supported in proto2.
//
// # Related packages
//
-// • Package "google.golang.org/protobuf/encoding/protojson" converts messages to
-// and from JSON.
+// - Package [google.golang.org/protobuf/encoding/protojson] converts messages to
+// and from JSON.
//
-// • Package "google.golang.org/protobuf/encoding/prototext" converts messages to
-// and from the text format.
+// - Package [google.golang.org/protobuf/encoding/prototext] converts messages to
+// and from the text format.
//
-// • Package "google.golang.org/protobuf/reflect/protoreflect" provides a
-// reflection interface for protocol buffer data types.
+// - Package [google.golang.org/protobuf/reflect/protoreflect] provides a
+// reflection interface for protocol buffer data types.
//
-// • Package "google.golang.org/protobuf/testing/protocmp" provides features
-// to compare protocol buffer messages with the "github.com/google/go-cmp/cmp"
-// package.
+// - Package [google.golang.org/protobuf/testing/protocmp] provides features
+// to compare protocol buffer messages with the [github.com/google/go-cmp/cmp]
+// package.
//
-// • Package "google.golang.org/protobuf/types/dynamicpb" provides a dynamic
-// message type, suitable for working with messages where the protocol buffer
-// type is only known at runtime.
+// - Package [google.golang.org/protobuf/types/dynamicpb] provides a dynamic
+// message type, suitable for working with messages where the protocol buffer
+// type is only known at runtime.
//
// This module contains additional packages for more specialized use cases.
// Consult the individual package documentation for details.
diff --git a/vendor/google.golang.org/protobuf/proto/encode.go b/vendor/google.golang.org/protobuf/proto/encode.go
index bf7f816d0e..1f847bcc35 100644
--- a/vendor/google.golang.org/protobuf/proto/encode.go
+++ b/vendor/google.golang.org/protobuf/proto/encode.go
@@ -5,12 +5,17 @@
package proto
import (
+ "errors"
+ "fmt"
+
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/encoding/messageset"
"google.golang.org/protobuf/internal/order"
"google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoiface"
+
+ protoerrors "google.golang.org/protobuf/internal/errors"
)
// MarshalOptions configures the marshaler.
@@ -70,7 +75,32 @@ type MarshalOptions struct {
UseCachedSize bool
}
+// flags turns the specified MarshalOptions (user-facing) into
+// protoiface.MarshalInputFlags (used internally by the marshaler).
+//
+// See impl.marshalOptions.Options for the inverse operation.
+func (o MarshalOptions) flags() protoiface.MarshalInputFlags {
+ var flags protoiface.MarshalInputFlags
+
+ // Note: o.AllowPartial is always forced to true by MarshalOptions.marshal,
+ // which is why it is not a part of MarshalInputFlags.
+
+ if o.Deterministic {
+ flags |= protoiface.MarshalDeterministic
+ }
+
+ if o.UseCachedSize {
+ flags |= protoiface.MarshalUseCachedSize
+ }
+
+ return flags
+}
+
// Marshal returns the wire-format encoding of m.
+//
+// This is the most common entry point for encoding a Protobuf message.
+//
+// See the [MarshalOptions] type if you need more control.
func Marshal(m Message) ([]byte, error) {
// Treat nil message interface as an empty message; nothing to output.
if m == nil {
@@ -116,6 +146,9 @@ func emptyBytesForMessage(m Message) []byte {
// MarshalAppend appends the wire-format encoding of m to b,
// returning the result.
+//
+// This is a less common entry point than [Marshal], which is only needed if you
+// need to supply your own buffers for performance reasons.
func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
// Treat nil message interface as an empty message; nothing to append.
if m == nil {
@@ -129,7 +162,7 @@ func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
// MarshalState returns the wire-format encoding of a message.
//
// This method permits fine-grained control over the marshaler.
-// Most users should use Marshal instead.
+// Most users should use [Marshal] instead.
func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
return o.marshal(in.Buf, in.Message)
}
@@ -145,12 +178,7 @@ func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoifac
in := protoiface.MarshalInput{
Message: m,
Buf: b,
- }
- if o.Deterministic {
- in.Flags |= protoiface.MarshalDeterministic
- }
- if o.UseCachedSize {
- in.Flags |= protoiface.MarshalUseCachedSize
+ Flags: o.flags(),
}
if methods.Size != nil {
sout := methods.Size(protoiface.SizeInput{
@@ -168,6 +196,10 @@ func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoifac
out.Buf, err = o.marshalMessageSlow(b, m)
}
if err != nil {
+ var mismatch *protoerrors.SizeMismatchError
+ if errors.As(err, &mismatch) {
+ return out, fmt.Errorf("marshaling %s: %v", string(m.Descriptor().FullName()), err)
+ }
return out, err
}
if allowPartial {
diff --git a/vendor/google.golang.org/protobuf/proto/extension.go b/vendor/google.golang.org/protobuf/proto/extension.go
index 5f293cda86..d248f29284 100644
--- a/vendor/google.golang.org/protobuf/proto/extension.go
+++ b/vendor/google.golang.org/protobuf/proto/extension.go
@@ -11,22 +11,25 @@ import (
// HasExtension reports whether an extension field is populated.
// It returns false if m is invalid or if xt does not extend m.
func HasExtension(m Message, xt protoreflect.ExtensionType) bool {
- // Treat nil message interface as an empty message; no populated fields.
- if m == nil {
+ // Treat nil message interface or descriptor as an empty message; no populated
+ // fields.
+ if m == nil || xt == nil {
return false
}
// As a special-case, we reports invalid or mismatching descriptors
// as always not being populated (since they aren't).
- if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() {
+ mr := m.ProtoReflect()
+ xd := xt.TypeDescriptor()
+ if mr.Descriptor() != xd.ContainingMessage() {
return false
}
- return m.ProtoReflect().Has(xt.TypeDescriptor())
+ return mr.Has(xd)
}
// ClearExtension clears an extension field such that subsequent
-// HasExtension calls return false.
+// [HasExtension] calls return false.
// It panics if m is invalid or if xt does not extend m.
func ClearExtension(m Message, xt protoreflect.ExtensionType) {
m.ProtoReflect().Clear(xt.TypeDescriptor())
@@ -36,7 +39,7 @@ func ClearExtension(m Message, xt protoreflect.ExtensionType) {
// If the field is unpopulated, it returns the default value for
// scalars and an immutable, empty value for lists or messages.
// It panics if xt does not extend m.
-func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} {
+func GetExtension(m Message, xt protoreflect.ExtensionType) any {
// Treat nil message interface as an empty message; return the default.
if m == nil {
return xt.InterfaceOf(xt.Zero())
@@ -48,7 +51,7 @@ func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} {
// SetExtension stores the value of an extension field.
// It panics if m is invalid, xt does not extend m, or if type of v
// is invalid for the specified extension field.
-func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) {
+func SetExtension(m Message, xt protoreflect.ExtensionType, v any) {
xd := xt.TypeDescriptor()
pv := xt.ValueOf(v)
@@ -75,7 +78,7 @@ func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) {
// It returns immediately if f returns false.
// While iterating, mutating operations may only be performed
// on the current extension field.
-func RangeExtensions(m Message, f func(protoreflect.ExtensionType, interface{}) bool) {
+func RangeExtensions(m Message, f func(protoreflect.ExtensionType, any) bool) {
// Treat nil message interface as an empty message; nothing to range over.
if m == nil {
return
diff --git a/vendor/google.golang.org/protobuf/proto/merge.go b/vendor/google.golang.org/protobuf/proto/merge.go
index d761ab331d..3c6fe57807 100644
--- a/vendor/google.golang.org/protobuf/proto/merge.go
+++ b/vendor/google.golang.org/protobuf/proto/merge.go
@@ -21,7 +21,7 @@ import (
// The unknown fields of src are appended to the unknown fields of dst.
//
// It is semantically equivalent to unmarshaling the encoded form of src
-// into dst with the UnmarshalOptions.Merge option specified.
+// into dst with the [UnmarshalOptions.Merge] option specified.
func Merge(dst, src Message) {
// TODO: Should nil src be treated as semantically equivalent to a
// untyped, read-only, empty message? What about a nil dst?
diff --git a/vendor/google.golang.org/protobuf/proto/messageset.go b/vendor/google.golang.org/protobuf/proto/messageset.go
index 312d5d45c6..575d14831f 100644
--- a/vendor/google.golang.org/protobuf/proto/messageset.go
+++ b/vendor/google.golang.org/protobuf/proto/messageset.go
@@ -47,11 +47,16 @@ func (o MarshalOptions) marshalMessageSet(b []byte, m protoreflect.Message) ([]b
func (o MarshalOptions) marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) {
b = messageset.AppendFieldStart(b, fd.Number())
b = protowire.AppendTag(b, messageset.FieldMessage, protowire.BytesType)
- b = protowire.AppendVarint(b, uint64(o.Size(value.Message().Interface())))
+ calculatedSize := o.Size(value.Message().Interface())
+ b = protowire.AppendVarint(b, uint64(calculatedSize))
+ before := len(b)
b, err := o.marshalMessage(b, value.Message())
if err != nil {
return b, err
}
+ if measuredSize := len(b) - before; calculatedSize != measuredSize {
+ return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize)
+ }
b = messageset.AppendFieldEnd(b)
return b, nil
}
diff --git a/vendor/google.golang.org/protobuf/proto/proto.go b/vendor/google.golang.org/protobuf/proto/proto.go
index 1f0d183b10..7543ee6b25 100644
--- a/vendor/google.golang.org/protobuf/proto/proto.go
+++ b/vendor/google.golang.org/protobuf/proto/proto.go
@@ -15,18 +15,20 @@ import (
// protobuf module that accept a Message, except where otherwise specified.
//
// This is the v2 interface definition for protobuf messages.
-// The v1 interface definition is "github.com/golang/protobuf/proto".Message.
+// The v1 interface definition is [github.com/golang/protobuf/proto.Message].
//
-// To convert a v1 message to a v2 message,
-// use "github.com/golang/protobuf/proto".MessageV2.
-// To convert a v2 message to a v1 message,
-// use "github.com/golang/protobuf/proto".MessageV1.
+// - To convert a v1 message to a v2 message,
+// use [google.golang.org/protobuf/protoadapt.MessageV2Of].
+// - To convert a v2 message to a v1 message,
+// use [google.golang.org/protobuf/protoadapt.MessageV1Of].
type Message = protoreflect.ProtoMessage
-// Error matches all errors produced by packages in the protobuf module.
+// Error matches all errors produced by packages in the protobuf module
+// according to [errors.Is].
//
-// That is, errors.Is(err, Error) reports whether an error is produced
-// by this module.
+// Example usage:
+//
+// if errors.Is(err, proto.Error) { ... }
var Error error
func init() {
diff --git a/vendor/google.golang.org/protobuf/proto/size.go b/vendor/google.golang.org/protobuf/proto/size.go
index f1692b49b6..052fb5ae31 100644
--- a/vendor/google.golang.org/protobuf/proto/size.go
+++ b/vendor/google.golang.org/protobuf/proto/size.go
@@ -34,6 +34,7 @@ func (o MarshalOptions) size(m protoreflect.Message) (size int) {
if methods != nil && methods.Size != nil {
out := methods.Size(protoiface.SizeInput{
Message: m,
+ Flags: o.flags(),
})
return out.Size
}
@@ -42,6 +43,7 @@ func (o MarshalOptions) size(m protoreflect.Message) (size int) {
// This case is mainly used for legacy types with a Marshal method.
out, _ := methods.Marshal(protoiface.MarshalInput{
Message: m,
+ Flags: o.flags(),
})
return len(out.Buf)
}
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
index e4dfb12050..8fbecb4f58 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
@@ -3,16 +3,17 @@
// license that can be found in the LICENSE file.
// Package protodesc provides functionality for converting
-// FileDescriptorProto messages to/from protoreflect.FileDescriptor values.
+// FileDescriptorProto messages to/from [protoreflect.FileDescriptor] values.
//
// The google.protobuf.FileDescriptorProto is a protobuf message that describes
// the type information for a .proto file in a form that is easily serializable.
-// The protoreflect.FileDescriptor is a more structured representation of
+// The [protoreflect.FileDescriptor] is a more structured representation of
// the FileDescriptorProto message where references and remote dependencies
// can be directly followed.
package protodesc
import (
+ "google.golang.org/protobuf/internal/editionssupport"
"google.golang.org/protobuf/internal/errors"
"google.golang.org/protobuf/internal/filedesc"
"google.golang.org/protobuf/internal/pragma"
@@ -24,11 +25,11 @@ import (
"google.golang.org/protobuf/types/descriptorpb"
)
-// Resolver is the resolver used by NewFile to resolve dependencies.
+// Resolver is the resolver used by [NewFile] to resolve dependencies.
// The enums and messages provided must belong to some parent file,
// which is also registered.
//
-// It is implemented by protoregistry.Files.
+// It is implemented by [protoregistry.Files].
type Resolver interface {
FindFileByPath(string) (protoreflect.FileDescriptor, error)
FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)
@@ -61,19 +62,19 @@ type FileOptions struct {
AllowUnresolvable bool
}
-// NewFile creates a new protoreflect.FileDescriptor from the provided
-// file descriptor message. See FileOptions.New for more information.
+// NewFile creates a new [protoreflect.FileDescriptor] from the provided
+// file descriptor message. See [FileOptions.New] for more information.
func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) {
return FileOptions{}.New(fd, r)
}
-// NewFiles creates a new protoregistry.Files from the provided
-// FileDescriptorSet message. See FileOptions.NewFiles for more information.
+// NewFiles creates a new [protoregistry.Files] from the provided
+// FileDescriptorSet message. See [FileOptions.NewFiles] for more information.
func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) {
return FileOptions{}.NewFiles(fd)
}
-// New creates a new protoreflect.FileDescriptor from the provided
+// New creates a new [protoreflect.FileDescriptor] from the provided
// file descriptor message. The file must represent a valid proto file according
// to protobuf semantics. The returned descriptor is a deep copy of the input.
//
@@ -91,11 +92,19 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
switch fd.GetSyntax() {
case "proto2", "":
f.L1.Syntax = protoreflect.Proto2
+ f.L1.Edition = filedesc.EditionProto2
case "proto3":
f.L1.Syntax = protoreflect.Proto3
+ f.L1.Edition = filedesc.EditionProto3
+ case "editions":
+ f.L1.Syntax = protoreflect.Editions
+ f.L1.Edition = fromEditionProto(fd.GetEdition())
default:
return nil, errors.New("invalid syntax: %q", fd.GetSyntax())
}
+ if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) {
+ return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition())
+ }
f.L1.Path = fd.GetName()
if f.L1.Path == "" {
return nil, errors.New("file path must be populated")
@@ -108,6 +117,7 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
opts = proto.Clone(opts).(*descriptorpb.FileOptions)
f.L2.Options = func() protoreflect.ProtoMessage { return opts }
}
+ initFileDescFromFeatureSet(f, fd.GetOptions().GetFeatures())
f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency()))
for _, i := range fd.GetPublicDependency() {
@@ -210,10 +220,10 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot
if err := validateEnumDeclarations(f.L1.Enums.List, fd.GetEnumType()); err != nil {
return nil, err
}
- if err := validateMessageDeclarations(f.L1.Messages.List, fd.GetMessageType()); err != nil {
+ if err := validateMessageDeclarations(f, f.L1.Messages.List, fd.GetMessageType()); err != nil {
return nil, err
}
- if err := validateExtensionDeclarations(f.L1.Extensions.List, fd.GetExtension()); err != nil {
+ if err := validateExtensionDeclarations(f, f.L1.Extensions.List, fd.GetExtension()); err != nil {
return nil, err
}
@@ -231,7 +241,7 @@ func (is importSet) importPublic(imps protoreflect.FileImports) {
}
}
-// NewFiles creates a new protoregistry.Files from the provided
+// NewFiles creates a new [protoregistry.Files] from the provided
// FileDescriptorSet message. The descriptor set must include only
// valid files according to protobuf semantics. The returned descriptors
// are a deep copy of the input.
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
index 37efda1afe..8561755427 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
@@ -28,6 +28,7 @@ func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProt
opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
e.L2.Options = func() protoreflect.ProtoMessage { return opts }
}
+ e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures())
for _, s := range ed.GetReservedName() {
e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
}
@@ -68,6 +69,7 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
return nil, err
}
+ m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures())
if opts := md.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
m.L2.Options = func() protoreflect.ProtoMessage { return opts }
@@ -114,6 +116,27 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt
return ms, nil
}
+// canBePacked returns whether the field can use packed encoding:
+// https://protobuf.dev/programming-guides/encoding/#packed
+func canBePacked(fd *descriptorpb.FieldDescriptorProto) bool {
+ if fd.GetLabel() != descriptorpb.FieldDescriptorProto_LABEL_REPEATED {
+ return false // not a repeated field
+ }
+
+ switch protoreflect.Kind(fd.GetType()) {
+ case protoreflect.MessageKind, protoreflect.GroupKind:
+ return false // not a scalar type field
+
+ case protoreflect.StringKind, protoreflect.BytesKind:
+ // string and bytes can explicitly not be declared as packed,
+ // see https://protobuf.dev/programming-guides/encoding/#packed
+ return false
+
+ default:
+ return true
+ }
+}
+
func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
for i, fd := range fds {
@@ -121,13 +144,15 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc
if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil {
return nil, err
}
+ f.L1.EditionFeatures = mergeEditionFeatures(parent, fd.GetOptions().GetFeatures())
f.L1.IsProto3Optional = fd.GetProto3Optional()
if opts := fd.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
f.L1.Options = func() protoreflect.ProtoMessage { return opts }
f.L1.IsWeak = opts.GetWeak()
- f.L1.HasPacked = opts.Packed != nil
- f.L1.IsPacked = opts.GetPacked()
+ if opts.Packed != nil {
+ f.L1.EditionFeatures.IsPacked = opts.GetPacked()
+ }
}
f.L1.Number = protoreflect.FieldNumber(fd.GetNumber())
f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel())
@@ -137,6 +162,14 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc
if fd.JsonName != nil {
f.L1.StringName.InitJSON(fd.GetJsonName())
}
+
+ if f.L1.EditionFeatures.IsLegacyRequired {
+ f.L1.Cardinality = protoreflect.Required
+ }
+
+ if f.L1.Kind == protoreflect.MessageKind && f.L1.EditionFeatures.IsDelimitedEncoded {
+ f.L1.Kind = protoreflect.GroupKind
+ }
}
return fs, nil
}
@@ -148,6 +181,7 @@ func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDesc
if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil {
return nil, err
}
+ o.L1.EditionFeatures = mergeEditionFeatures(parent, od.GetOptions().GetFeatures())
if opts := od.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
o.L1.Options = func() protoreflect.ProtoMessage { return opts }
@@ -164,10 +198,13 @@ func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescript
if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil {
return nil, err
}
+ x.L1.EditionFeatures = mergeEditionFeatures(parent, xd.GetOptions().GetFeatures())
if opts := xd.GetOptions(); opts != nil {
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
x.L2.Options = func() protoreflect.ProtoMessage { return opts }
- x.L2.IsPacked = opts.GetPacked()
+ if opts.Packed != nil {
+ x.L1.EditionFeatures.IsPacked = opts.GetPacked()
+ }
}
x.L1.Number = protoreflect.FieldNumber(xd.GetNumber())
x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel())
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
index 27d7e35012..f3cebab29c 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
@@ -46,6 +46,11 @@ func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*desc
if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil {
return errors.New("message field %q cannot resolve type: %v", f.FullName(), err)
}
+ if f.L1.Kind == protoreflect.GroupKind && (f.IsMap() || f.IsMapEntry()) {
+ // A map field might inherit delimited encoding from a file-wide default feature.
+ // But maps never actually use delimited encoding. (At least for now...)
+ f.L1.Kind = protoreflect.MessageKind
+ }
if fd.DefaultValue != nil {
v, ev, err := unmarshalDefault(fd.GetDefaultValue(), f, r.allowUnresolvable)
if err != nil {
@@ -276,8 +281,8 @@ func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvab
} else if err != nil {
return v, ev, err
}
- if fd.Syntax() == protoreflect.Proto3 {
- return v, ev, errors.New("cannot be specified under proto3 semantics")
+ if !fd.HasPresence() {
+ return v, ev, errors.New("cannot be specified with implicit field presence")
}
if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated {
return v, ev, errors.New("cannot be specified on composite types")
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
index 9af1d56487..6de31c2ebd 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
@@ -45,11 +45,11 @@ func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescri
if allowAlias && !foundAlias {
return errors.New("enum %q allows aliases, but none were found", e.FullName())
}
- if e.Syntax() == protoreflect.Proto3 {
+ if !e.IsClosed() {
if v := e.Values().Get(0); v.Number() != 0 {
- return errors.New("enum %q using proto3 semantics must have zero number for the first value", v.FullName())
+ return errors.New("enum %q using open semantics must have zero number for the first value", v.FullName())
}
- // Verify that value names in proto3 do not conflict if the
+ // Verify that value names in open enums do not conflict if the
// case-insensitive prefix is removed.
// See protoc v3.8.0: src/google/protobuf/descriptor.cc:4991-5055
names := map[string]protoreflect.EnumValueDescriptor{}
@@ -58,7 +58,7 @@ func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescri
v1 := e.Values().Get(i)
s := strs.EnumValueName(strs.TrimEnumPrefix(string(v1.Name()), prefix))
if v2, ok := names[s]; ok && v1.Number() != v2.Number() {
- return errors.New("enum %q using proto3 semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name())
+ return errors.New("enum %q using open semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name())
}
names[s] = v1
}
@@ -80,7 +80,9 @@ func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescri
return nil
}
-func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error {
+func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error {
+ // There are a few limited exceptions only for proto3
+ isProto3 := file.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3)
for i, md := range mds {
m := &ms[i]
@@ -107,25 +109,13 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc
if isMessageSet && !flags.ProtoLegacy {
return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName())
}
- if isMessageSet && (m.Syntax() != protoreflect.Proto2 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) {
+ if isMessageSet && (isProto3 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) {
return errors.New("message %q is an invalid proto1 MessageSet", m.FullName())
}
- if m.Syntax() == protoreflect.Proto3 {
+ if isProto3 {
if m.ExtensionRanges().Len() > 0 {
return errors.New("message %q using proto3 semantics cannot have extension ranges", m.FullName())
}
- // Verify that field names in proto3 do not conflict if lowercased
- // with all underscores removed.
- // See protoc v3.8.0: src/google/protobuf/descriptor.cc:5830-5847
- names := map[string]protoreflect.FieldDescriptor{}
- for i := 0; i < m.Fields().Len(); i++ {
- f1 := m.Fields().Get(i)
- s := strings.Replace(strings.ToLower(string(f1.Name())), "_", "", -1)
- if f2, ok := names[s]; ok {
- return errors.New("message %q using proto3 semantics has conflict: %q with %q", m.FullName(), f1.Name(), f2.Name())
- }
- names[s] = f1
- }
}
for j, fd := range md.GetField() {
@@ -149,7 +139,7 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc
return errors.New("message field %q may not have extendee: %q", f.FullName(), fd.GetExtendee())
}
if f.L1.IsProto3Optional {
- if f.Syntax() != protoreflect.Proto3 {
+ if !isProto3 {
return errors.New("message field %q under proto3 optional semantics must be specified in the proto3 syntax", f.FullName())
}
if f.Cardinality() != protoreflect.Optional {
@@ -162,26 +152,29 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc
if f.IsWeak() && !flags.ProtoLegacy {
return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName())
}
- if f.IsWeak() && (f.Syntax() != protoreflect.Proto2 || !isOptionalMessage(f) || f.ContainingOneof() != nil) {
+ if f.IsWeak() && (!f.HasPresence() || !isOptionalMessage(f) || f.ContainingOneof() != nil) {
return errors.New("message field %q may only be weak for an optional message", f.FullName())
}
if f.IsPacked() && !isPackable(f) {
return errors.New("message field %q is not packable", f.FullName())
}
- if err := checkValidGroup(f); err != nil {
+ if err := checkValidGroup(file, f); err != nil {
return errors.New("message field %q is an invalid group: %v", f.FullName(), err)
}
if err := checkValidMap(f); err != nil {
return errors.New("message field %q is an invalid map: %v", f.FullName(), err)
}
- if f.Syntax() == protoreflect.Proto3 {
+ if isProto3 {
if f.Cardinality() == protoreflect.Required {
return errors.New("message field %q using proto3 semantics cannot be required", f.FullName())
}
- if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().Syntax() != protoreflect.Proto3 {
- return errors.New("message field %q using proto3 semantics may only depend on a proto3 enum", f.FullName())
+ if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().IsClosed() {
+ return errors.New("message field %q using proto3 semantics may only depend on open enums", f.FullName())
}
}
+ if f.Cardinality() == protoreflect.Optional && !f.HasPresence() && f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().IsClosed() {
+ return errors.New("message field %q with implicit presence may only use open enums", f.FullName())
+ }
}
seenSynthetic := false // synthetic oneofs for proto3 optional must come after real oneofs
for j := range md.GetOneofDecl() {
@@ -215,17 +208,17 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc
if err := validateEnumDeclarations(m.L1.Enums.List, md.GetEnumType()); err != nil {
return err
}
- if err := validateMessageDeclarations(m.L1.Messages.List, md.GetNestedType()); err != nil {
+ if err := validateMessageDeclarations(file, m.L1.Messages.List, md.GetNestedType()); err != nil {
return err
}
- if err := validateExtensionDeclarations(m.L1.Extensions.List, md.GetExtension()); err != nil {
+ if err := validateExtensionDeclarations(file, m.L1.Extensions.List, md.GetExtension()); err != nil {
return err
}
}
return nil
}
-func validateExtensionDeclarations(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error {
+func validateExtensionDeclarations(f *filedesc.File, xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error {
for i, xd := range xds {
x := &xs[i]
// NOTE: Avoid using the IsValid method since extensions to MessageSet
@@ -267,13 +260,13 @@ func validateExtensionDeclarations(xs []filedesc.Extension, xds []*descriptorpb.
if x.IsPacked() && !isPackable(x) {
return errors.New("extension field %q is not packable", x.FullName())
}
- if err := checkValidGroup(x); err != nil {
+ if err := checkValidGroup(f, x); err != nil {
return errors.New("extension field %q is an invalid group: %v", x.FullName(), err)
}
if md := x.Message(); md != nil && md.IsMapEntry() {
return errors.New("extension field %q cannot be a map entry", x.FullName())
}
- if x.Syntax() == protoreflect.Proto3 {
+ if f.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3) {
switch x.ContainingMessage().FullName() {
case (*descriptorpb.FileOptions)(nil).ProtoReflect().Descriptor().FullName():
case (*descriptorpb.EnumOptions)(nil).ProtoReflect().Descriptor().FullName():
@@ -309,21 +302,25 @@ func isPackable(fd protoreflect.FieldDescriptor) bool {
// checkValidGroup reports whether fd is a valid group according to the same
// rules that protoc imposes.
-func checkValidGroup(fd protoreflect.FieldDescriptor) error {
+func checkValidGroup(f *filedesc.File, fd protoreflect.FieldDescriptor) error {
md := fd.Message()
switch {
case fd.Kind() != protoreflect.GroupKind:
return nil
- case fd.Syntax() != protoreflect.Proto2:
- return errors.New("invalid under proto2 semantics")
+ case f.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3):
+ return errors.New("invalid under proto3 semantics")
case md == nil || md.IsPlaceholder():
return errors.New("message must be resolvable")
- case fd.FullName().Parent() != md.FullName().Parent():
- return errors.New("message and field must be declared in the same scope")
- case !unicode.IsUpper(rune(md.Name()[0])):
- return errors.New("message name must start with an uppercase")
- case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))):
- return errors.New("field name must be lowercased form of the message name")
+ }
+ if f.L1.Edition < fromEditionProto(descriptorpb.Edition_EDITION_2023) {
+ switch {
+ case fd.FullName().Parent() != md.FullName().Parent():
+ return errors.New("message and field must be declared in the same scope")
+ case !unicode.IsUpper(rune(md.Name()[0])):
+ return errors.New("message name must start with an uppercase")
+ case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))):
+ return errors.New("field name must be lowercased form of the message name")
+ }
}
return nil
}
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go
new file mode 100644
index 0000000000..804830eda3
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go
@@ -0,0 +1,145 @@
+// Copyright 2019 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 protodesc
+
+import (
+ "fmt"
+ "os"
+ "sync"
+
+ "google.golang.org/protobuf/internal/editiondefaults"
+ "google.golang.org/protobuf/internal/filedesc"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/reflect/protoreflect"
+ "google.golang.org/protobuf/types/descriptorpb"
+ gofeaturespb "google.golang.org/protobuf/types/gofeaturespb"
+)
+
+var defaults = &descriptorpb.FeatureSetDefaults{}
+var defaultsCacheMu sync.Mutex
+var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet)
+
+func init() {
+ err := proto.Unmarshal(editiondefaults.Defaults, defaults)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unmarshal editions defaults: %v\n", err)
+ os.Exit(1)
+ }
+}
+
+func fromEditionProto(epb descriptorpb.Edition) filedesc.Edition {
+ return filedesc.Edition(epb)
+}
+
+func toEditionProto(ed filedesc.Edition) descriptorpb.Edition {
+ switch ed {
+ case filedesc.EditionUnknown:
+ return descriptorpb.Edition_EDITION_UNKNOWN
+ case filedesc.EditionProto2:
+ return descriptorpb.Edition_EDITION_PROTO2
+ case filedesc.EditionProto3:
+ return descriptorpb.Edition_EDITION_PROTO3
+ case filedesc.Edition2023:
+ return descriptorpb.Edition_EDITION_2023
+ default:
+ panic(fmt.Sprintf("unknown value for edition: %v", ed))
+ }
+}
+
+func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet {
+ defaultsCacheMu.Lock()
+ defer defaultsCacheMu.Unlock()
+ if def, ok := defaultsCache[ed]; ok {
+ return def
+ }
+ edpb := toEditionProto(ed)
+ if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb {
+ // This should never happen protodesc.(FileOptions).New would fail when
+ // initializing the file descriptor.
+ // This most likely means the embedded defaults were not updated.
+ fmt.Fprintf(os.Stderr, "internal error: unsupported edition %v (did you forget to update the embedded defaults (i.e. the bootstrap descriptor proto)?)\n", edpb)
+ os.Exit(1)
+ }
+ fsed := defaults.GetDefaults()[0]
+ // Using a linear search for now.
+ // Editions are guaranteed to be sorted and thus we could use a binary search.
+ // Given that there are only a handful of editions (with one more per year)
+ // there is not much reason to use a binary search.
+ for _, def := range defaults.GetDefaults() {
+ if def.GetEdition() <= edpb {
+ fsed = def
+ } else {
+ break
+ }
+ }
+ fs := proto.Clone(fsed.GetFixedFeatures()).(*descriptorpb.FeatureSet)
+ proto.Merge(fs, fsed.GetOverridableFeatures())
+ defaultsCache[ed] = fs
+ return fs
+}
+
+// mergeEditionFeatures merges the parent and child feature sets. This function
+// should be used when initializing Go descriptors from descriptor protos which
+// is why the parent is a filedesc.EditionsFeatures (Go representation) while
+// the child is a descriptorproto.FeatureSet (protoc representation).
+// Any feature set by the child overwrites what is set by the parent.
+func mergeEditionFeatures(parentDesc protoreflect.Descriptor, child *descriptorpb.FeatureSet) filedesc.EditionFeatures {
+ var parentFS filedesc.EditionFeatures
+ switch p := parentDesc.(type) {
+ case *filedesc.File:
+ parentFS = p.L1.EditionFeatures
+ case *filedesc.Message:
+ parentFS = p.L1.EditionFeatures
+ default:
+ panic(fmt.Sprintf("unknown parent type %T", parentDesc))
+ }
+ if child == nil {
+ return parentFS
+ }
+ if fp := child.FieldPresence; fp != nil {
+ parentFS.IsFieldPresence = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED ||
+ *fp == descriptorpb.FeatureSet_EXPLICIT
+ parentFS.IsLegacyRequired = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED
+ }
+ if et := child.EnumType; et != nil {
+ parentFS.IsOpenEnum = *et == descriptorpb.FeatureSet_OPEN
+ }
+
+ if rfe := child.RepeatedFieldEncoding; rfe != nil {
+ parentFS.IsPacked = *rfe == descriptorpb.FeatureSet_PACKED
+ }
+
+ if utf8val := child.Utf8Validation; utf8val != nil {
+ parentFS.IsUTF8Validated = *utf8val == descriptorpb.FeatureSet_VERIFY
+ }
+
+ if me := child.MessageEncoding; me != nil {
+ parentFS.IsDelimitedEncoded = *me == descriptorpb.FeatureSet_DELIMITED
+ }
+
+ if jf := child.JsonFormat; jf != nil {
+ parentFS.IsJSONCompliant = *jf == descriptorpb.FeatureSet_ALLOW
+ }
+
+ if goFeatures, ok := proto.GetExtension(child, gofeaturespb.E_Go).(*gofeaturespb.GoFeatures); ok && goFeatures != nil {
+ if luje := goFeatures.LegacyUnmarshalJsonEnum; luje != nil {
+ parentFS.GenerateLegacyUnmarshalJSON = *luje
+ }
+ }
+
+ return parentFS
+}
+
+// initFileDescFromFeatureSet initializes editions related fields in fd based
+// on fs. If fs is nil it is assumed to be an empty featureset and all fields
+// will be initialized with the appropriate default. fd.L1.Edition must be set
+// before calling this function.
+func initFileDescFromFeatureSet(fd *filedesc.File, fs *descriptorpb.FeatureSet) {
+ dfs := getFeatureSetFor(fd.L1.Edition)
+ // initialize the featureset with the defaults
+ fd.L1.EditionFeatures = mergeEditionFeatures(fd, dfs)
+ // overwrite any options explicitly specified
+ fd.L1.EditionFeatures = mergeEditionFeatures(fd, fs)
+}
diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go b/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
index a7c5ceffc9..a5de8d4001 100644
--- a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
+++ b/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
@@ -16,7 +16,7 @@ import (
"google.golang.org/protobuf/types/descriptorpb"
)
-// ToFileDescriptorProto copies a protoreflect.FileDescriptor into a
+// ToFileDescriptorProto copies a [protoreflect.FileDescriptor] into a
// google.protobuf.FileDescriptorProto message.
func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto {
p := &descriptorpb.FileDescriptorProto{
@@ -70,13 +70,23 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD
for i, exts := 0, file.Extensions(); i < exts.Len(); i++ {
p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i)))
}
- if syntax := file.Syntax(); syntax != protoreflect.Proto2 {
+ if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() {
p.Syntax = proto.String(file.Syntax().String())
}
+ if file.Syntax() == protoreflect.Editions {
+ desc := file
+ if fileImportDesc, ok := file.(protoreflect.FileImport); ok {
+ desc = fileImportDesc.FileDescriptor
+ }
+
+ if editionsInterface, ok := desc.(interface{ Edition() int32 }); ok {
+ p.Edition = descriptorpb.Edition(editionsInterface.Edition()).Enum()
+ }
+ }
return p
}
-// ToDescriptorProto copies a protoreflect.MessageDescriptor into a
+// ToDescriptorProto copies a [protoreflect.MessageDescriptor] into a
// google.protobuf.DescriptorProto message.
func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto {
p := &descriptorpb.DescriptorProto{
@@ -119,7 +129,7 @@ func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.Des
return p
}
-// ToFieldDescriptorProto copies a protoreflect.FieldDescriptor into a
+// ToFieldDescriptorProto copies a [protoreflect.FieldDescriptor] into a
// google.protobuf.FieldDescriptorProto message.
func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto {
p := &descriptorpb.FieldDescriptorProto{
@@ -153,6 +163,18 @@ func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.Fi
if field.Syntax() == protoreflect.Proto3 && field.HasOptionalKeyword() {
p.Proto3Optional = proto.Bool(true)
}
+ if field.Syntax() == protoreflect.Editions {
+ // Editions have no group keyword, this type is only set so that downstream users continue
+ // treating this as delimited encoding.
+ if p.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
+ p.Type = descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum()
+ }
+ // Editions have no required keyword, this label is only set so that downstream users continue
+ // treating it as required.
+ if p.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REQUIRED {
+ p.Label = descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
+ }
+ }
if field.HasDefault() {
def, err := defval.Marshal(field.Default(), field.DefaultEnumValue(), field.Kind(), defval.Descriptor)
if err != nil && field.DefaultEnumValue() != nil {
@@ -168,7 +190,7 @@ func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.Fi
return p
}
-// ToOneofDescriptorProto copies a protoreflect.OneofDescriptor into a
+// ToOneofDescriptorProto copies a [protoreflect.OneofDescriptor] into a
// google.protobuf.OneofDescriptorProto message.
func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto {
return &descriptorpb.OneofDescriptorProto{
@@ -177,7 +199,7 @@ func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.On
}
}
-// ToEnumDescriptorProto copies a protoreflect.EnumDescriptor into a
+// ToEnumDescriptorProto copies a [protoreflect.EnumDescriptor] into a
// google.protobuf.EnumDescriptorProto message.
func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto {
p := &descriptorpb.EnumDescriptorProto{
@@ -200,7 +222,7 @@ func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumD
return p
}
-// ToEnumValueDescriptorProto copies a protoreflect.EnumValueDescriptor into a
+// ToEnumValueDescriptorProto copies a [protoreflect.EnumValueDescriptor] into a
// google.protobuf.EnumValueDescriptorProto message.
func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto {
return &descriptorpb.EnumValueDescriptorProto{
@@ -210,7 +232,7 @@ func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descrip
}
}
-// ToServiceDescriptorProto copies a protoreflect.ServiceDescriptor into a
+// ToServiceDescriptorProto copies a [protoreflect.ServiceDescriptor] into a
// google.protobuf.ServiceDescriptorProto message.
func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto {
p := &descriptorpb.ServiceDescriptorProto{
@@ -223,7 +245,7 @@ func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descripto
return p
}
-// ToMethodDescriptorProto copies a protoreflect.MethodDescriptor into a
+// ToMethodDescriptorProto copies a [protoreflect.MethodDescriptor] into a
// google.protobuf.MethodDescriptorProto message.
func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto {
p := &descriptorpb.MethodDescriptorProto{
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go
index 55aa14922b..c85bfaa5bb 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go
@@ -10,46 +10,46 @@
//
// # Protocol Buffer Descriptors
//
-// Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor)
+// Protobuf descriptors (e.g., [EnumDescriptor] or [MessageDescriptor])
// are immutable objects that represent protobuf type information.
// They are wrappers around the messages declared in descriptor.proto.
// Protobuf descriptors alone lack any information regarding Go types.
//
-// Enums and messages generated by this module implement Enum and ProtoMessage,
+// Enums and messages generated by this module implement [Enum] and [ProtoMessage],
// where the Descriptor and ProtoReflect.Descriptor accessors respectively
// return the protobuf descriptor for the values.
//
// The protobuf descriptor interfaces are not meant to be implemented by
// user code since they might need to be extended in the future to support
// additions to the protobuf language.
-// The "google.golang.org/protobuf/reflect/protodesc" package converts between
+// The [google.golang.org/protobuf/reflect/protodesc] package converts between
// google.protobuf.DescriptorProto messages and protobuf descriptors.
//
// # Go Type Descriptors
//
-// A type descriptor (e.g., EnumType or MessageType) is a constructor for
+// A type descriptor (e.g., [EnumType] or [MessageType]) is a constructor for
// a concrete Go type that represents the associated protobuf descriptor.
// There is commonly a one-to-one relationship between protobuf descriptors and
// Go type descriptors, but it can potentially be a one-to-many relationship.
//
-// Enums and messages generated by this module implement Enum and ProtoMessage,
+// Enums and messages generated by this module implement [Enum] and [ProtoMessage],
// where the Type and ProtoReflect.Type accessors respectively
// return the protobuf descriptor for the values.
//
-// The "google.golang.org/protobuf/types/dynamicpb" package can be used to
+// The [google.golang.org/protobuf/types/dynamicpb] package can be used to
// create Go type descriptors from protobuf descriptors.
//
// # Value Interfaces
//
-// The Enum and Message interfaces provide a reflective view over an
+// The [Enum] and [Message] interfaces provide a reflective view over an
// enum or message instance. For enums, it provides the ability to retrieve
// the enum value number for any concrete enum type. For messages, it provides
// the ability to access or manipulate fields of the message.
//
-// To convert a proto.Message to a protoreflect.Message, use the
+// To convert a [google.golang.org/protobuf/proto.Message] to a [protoreflect.Message], use the
// former's ProtoReflect method. Since the ProtoReflect method is new to the
// v2 message interface, it may not be present on older message implementations.
-// The "github.com/golang/protobuf/proto".MessageReflect function can be used
+// The [github.com/golang/protobuf/proto.MessageReflect] function can be used
// to obtain a reflective view on older messages.
//
// # Relationships
@@ -71,12 +71,12 @@
// │ │
// └────────────────── Type() ───────┘
//
-// • An EnumType describes a concrete Go enum type.
+// • An [EnumType] describes a concrete Go enum type.
// It has an EnumDescriptor and can construct an Enum instance.
//
-// • An EnumDescriptor describes an abstract protobuf enum type.
+// • An [EnumDescriptor] describes an abstract protobuf enum type.
//
-// • An Enum is a concrete enum instance. Generated enums implement Enum.
+// • An [Enum] is a concrete enum instance. Generated enums implement Enum.
//
// ┌──────────────── New() ─────────────────┐
// │ │
@@ -90,24 +90,26 @@
// │ │
// └─────────────────── Type() ─────────┘
//
-// • A MessageType describes a concrete Go message type.
-// It has a MessageDescriptor and can construct a Message instance.
-// Just as how Go's reflect.Type is a reflective description of a Go type,
-// a MessageType is a reflective description of a Go type for a protobuf message.
+// • A [MessageType] describes a concrete Go message type.
+// It has a [MessageDescriptor] and can construct a [Message] instance.
+// Just as how Go's [reflect.Type] is a reflective description of a Go type,
+// a [MessageType] is a reflective description of a Go type for a protobuf message.
//
-// • A MessageDescriptor describes an abstract protobuf message type.
-// It has no understanding of Go types. In order to construct a MessageType
-// from just a MessageDescriptor, you can consider looking up the message type
-// in the global registry using protoregistry.GlobalTypes.FindMessageByName
-// or constructing a dynamic MessageType using dynamicpb.NewMessageType.
+// • A [MessageDescriptor] describes an abstract protobuf message type.
+// It has no understanding of Go types. In order to construct a [MessageType]
+// from just a [MessageDescriptor], you can consider looking up the message type
+// in the global registry using the FindMessageByName method on
+// [google.golang.org/protobuf/reflect/protoregistry.GlobalTypes]
+// or constructing a dynamic [MessageType] using
+// [google.golang.org/protobuf/types/dynamicpb.NewMessageType].
//
-// • A Message is a reflective view over a concrete message instance.
-// Generated messages implement ProtoMessage, which can convert to a Message.
-// Just as how Go's reflect.Value is a reflective view over a Go value,
-// a Message is a reflective view over a concrete protobuf message instance.
-// Using Go reflection as an analogy, the ProtoReflect method is similar to
-// calling reflect.ValueOf, and the Message.Interface method is similar to
-// calling reflect.Value.Interface.
+// • A [Message] is a reflective view over a concrete message instance.
+// Generated messages implement [ProtoMessage], which can convert to a [Message].
+// Just as how Go's [reflect.Value] is a reflective view over a Go value,
+// a [Message] is a reflective view over a concrete protobuf message instance.
+// Using Go reflection as an analogy, the [ProtoMessage.ProtoReflect] method is similar to
+// calling [reflect.ValueOf], and the [Message.Interface] method is similar to
+// calling [reflect.Value.Interface].
//
// ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐
// │ V │ V
@@ -119,15 +121,15 @@
// │ │
// └────── implements ────────┘
//
-// • An ExtensionType describes a concrete Go implementation of an extension.
-// It has an ExtensionTypeDescriptor and can convert to/from
-// abstract Values and Go values.
+// • An [ExtensionType] describes a concrete Go implementation of an extension.
+// It has an [ExtensionTypeDescriptor] and can convert to/from
+// an abstract [Value] and a Go value.
//
-// • An ExtensionTypeDescriptor is an ExtensionDescriptor
-// which also has an ExtensionType.
+// • An [ExtensionTypeDescriptor] is an [ExtensionDescriptor]
+// which also has an [ExtensionType].
//
-// • An ExtensionDescriptor describes an abstract protobuf extension field and
-// may not always be an ExtensionTypeDescriptor.
+// • An [ExtensionDescriptor] describes an abstract protobuf extension field and
+// may not always be an [ExtensionTypeDescriptor].
package protoreflect
import (
@@ -142,7 +144,7 @@ type doNotImplement pragma.DoNotImplement
// ProtoMessage is the top-level interface that all proto messages implement.
// This is declared in the protoreflect package to avoid a cyclic dependency;
-// use the proto.Message type instead, which aliases this type.
+// use the [google.golang.org/protobuf/proto.Message] type instead, which aliases this type.
type ProtoMessage interface{ ProtoReflect() Message }
// Syntax is the language version of the proto file.
@@ -151,14 +153,15 @@ type Syntax syntax
type syntax int8 // keep exact type opaque as the int type may change
const (
- Proto2 Syntax = 2
- Proto3 Syntax = 3
+ Proto2 Syntax = 2
+ Proto3 Syntax = 3
+ Editions Syntax = 4
)
// IsValid reports whether the syntax is valid.
func (s Syntax) IsValid() bool {
switch s {
- case Proto2, Proto3:
+ case Proto2, Proto3, Editions:
return true
default:
return false
@@ -172,6 +175,8 @@ func (s Syntax) String() string {
return "proto2"
case Proto3:
return "proto3"
+ case Editions:
+ return "editions"
default:
return fmt.Sprintf("", s)
}
@@ -436,7 +441,7 @@ type Names interface {
// FullName is a qualified name that uniquely identifies a proto declaration.
// A qualified name is the concatenation of the proto package along with the
// fully-declared name (i.e., name of parent preceding the name of the child),
-// with a '.' delimiter placed between each Name.
+// with a '.' delimiter placed between each [Name].
//
// This should not have any leading or trailing dots.
type FullName string // e.g., "google.protobuf.Field.Kind"
@@ -480,7 +485,7 @@ func isLetterDigit(c byte) bool {
}
// Name returns the short name, which is the last identifier segment.
-// A single segment FullName is the Name itself.
+// A single segment FullName is the [Name] itself.
func (n FullName) Name() Name {
if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
return Name(n[i+1:])
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
index 717b106f3d..ea154eec44 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go
@@ -35,7 +35,7 @@ func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte {
b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo)
case 12:
b = p.appendSingularField(b, "syntax", nil)
- case 13:
+ case 14:
b = p.appendSingularField(b, "edition", nil)
}
return b
@@ -160,8 +160,6 @@ func (p *SourcePath) appendFileOptions(b []byte) []byte {
b = p.appendSingularField(b, "java_generic_services", nil)
case 18:
b = p.appendSingularField(b, "py_generic_services", nil)
- case 42:
- b = p.appendSingularField(b, "php_generic_services", nil)
case 23:
b = p.appendSingularField(b, "deprecated", nil)
case 31:
@@ -180,6 +178,8 @@ func (p *SourcePath) appendFileOptions(b []byte) []byte {
b = p.appendSingularField(b, "php_metadata_namespace", nil)
case 45:
b = p.appendSingularField(b, "ruby_package", nil)
+ case 50:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
}
@@ -240,6 +240,8 @@ func (p *SourcePath) appendMessageOptions(b []byte) []byte {
b = p.appendSingularField(b, "map_entry", nil)
case 11:
b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil)
+ case 12:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
}
@@ -285,6 +287,8 @@ func (p *SourcePath) appendEnumOptions(b []byte) []byte {
b = p.appendSingularField(b, "deprecated", nil)
case 6:
b = p.appendSingularField(b, "deprecated_legacy_json_field_conflicts", nil)
+ case 7:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
}
@@ -330,6 +334,8 @@ func (p *SourcePath) appendServiceOptions(b []byte) []byte {
return b
}
switch (*p)[0] {
+ case 34:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 33:
b = p.appendSingularField(b, "deprecated", nil)
case 999:
@@ -361,16 +367,41 @@ func (p *SourcePath) appendFieldOptions(b []byte) []byte {
b = p.appendSingularField(b, "debug_redact", nil)
case 17:
b = p.appendSingularField(b, "retention", nil)
- case 18:
- b = p.appendSingularField(b, "target", nil)
case 19:
b = p.appendRepeatedField(b, "targets", nil)
+ case 20:
+ b = p.appendRepeatedField(b, "edition_defaults", (*SourcePath).appendFieldOptions_EditionDefault)
+ case 21:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
+ case 22:
+ b = p.appendSingularField(b, "feature_support", (*SourcePath).appendFieldOptions_FeatureSupport)
case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
}
return b
}
+func (p *SourcePath) appendFeatureSet(b []byte) []byte {
+ if len(*p) == 0 {
+ return b
+ }
+ switch (*p)[0] {
+ case 1:
+ b = p.appendSingularField(b, "field_presence", nil)
+ case 2:
+ b = p.appendSingularField(b, "enum_type", nil)
+ case 3:
+ b = p.appendSingularField(b, "repeated_field_encoding", nil)
+ case 4:
+ b = p.appendSingularField(b, "utf8_validation", nil)
+ case 5:
+ b = p.appendSingularField(b, "message_encoding", nil)
+ case 6:
+ b = p.appendSingularField(b, "json_format", nil)
+ }
+ return b
+}
+
func (p *SourcePath) appendUninterpretedOption(b []byte) []byte {
if len(*p) == 0 {
return b
@@ -422,6 +453,8 @@ func (p *SourcePath) appendExtensionRangeOptions(b []byte) []byte {
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
case 2:
b = p.appendRepeatedField(b, "declaration", (*SourcePath).appendExtensionRangeOptions_Declaration)
+ case 50:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 3:
b = p.appendSingularField(b, "verification", nil)
}
@@ -433,6 +466,8 @@ func (p *SourcePath) appendOneofOptions(b []byte) []byte {
return b
}
switch (*p)[0] {
+ case 1:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
}
@@ -446,6 +481,12 @@ func (p *SourcePath) appendEnumValueOptions(b []byte) []byte {
switch (*p)[0] {
case 1:
b = p.appendSingularField(b, "deprecated", nil)
+ case 2:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
+ case 3:
+ b = p.appendSingularField(b, "debug_redact", nil)
+ case 4:
+ b = p.appendSingularField(b, "feature_support", (*SourcePath).appendFieldOptions_FeatureSupport)
case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
}
@@ -461,12 +502,44 @@ func (p *SourcePath) appendMethodOptions(b []byte) []byte {
b = p.appendSingularField(b, "deprecated", nil)
case 34:
b = p.appendSingularField(b, "idempotency_level", nil)
+ case 35:
+ b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet)
case 999:
b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption)
}
return b
}
+func (p *SourcePath) appendFieldOptions_EditionDefault(b []byte) []byte {
+ if len(*p) == 0 {
+ return b
+ }
+ switch (*p)[0] {
+ case 3:
+ b = p.appendSingularField(b, "edition", nil)
+ case 2:
+ b = p.appendSingularField(b, "value", nil)
+ }
+ return b
+}
+
+func (p *SourcePath) appendFieldOptions_FeatureSupport(b []byte) []byte {
+ if len(*p) == 0 {
+ return b
+ }
+ switch (*p)[0] {
+ case 1:
+ b = p.appendSingularField(b, "edition_introduced", nil)
+ case 2:
+ b = p.appendSingularField(b, "edition_deprecated", nil)
+ case 3:
+ b = p.appendSingularField(b, "deprecation_warning", nil)
+ case 4:
+ b = p.appendSingularField(b, "edition_removed", nil)
+ }
+ return b
+}
+
func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte {
if len(*p) == 0 {
return b
@@ -491,8 +564,6 @@ func (p *SourcePath) appendExtensionRangeOptions_Declaration(b []byte) []byte {
b = p.appendSingularField(b, "full_name", nil)
case 3:
b = p.appendSingularField(b, "type", nil)
- case 4:
- b = p.appendSingularField(b, "is_repeated", nil)
case 5:
b = p.appendSingularField(b, "reserved", nil)
case 6:
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go
index 3867470d30..cd8fadbaf8 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go
@@ -12,7 +12,7 @@ package protoreflect
// exactly identical. However, it is possible for the same semantically
// identical proto type to be represented by multiple type descriptors.
//
-// For example, suppose we have t1 and t2 which are both MessageDescriptors.
+// For example, suppose we have t1 and t2 which are both an [MessageDescriptor].
// If t1 == t2, then the types are definitely equal and all accessors return
// the same information. However, if t1 != t2, then it is still possible that
// they still represent the same proto type (e.g., t1.FullName == t2.FullName).
@@ -115,7 +115,7 @@ type Descriptor interface {
// corresponds with the google.protobuf.FileDescriptorProto message.
//
// Top-level declarations:
-// EnumDescriptor, MessageDescriptor, FieldDescriptor, and/or ServiceDescriptor.
+// [EnumDescriptor], [MessageDescriptor], [FieldDescriptor], and/or [ServiceDescriptor].
type FileDescriptor interface {
Descriptor // Descriptor.FullName is identical to Package
@@ -180,8 +180,8 @@ type FileImport struct {
// corresponds with the google.protobuf.DescriptorProto message.
//
// Nested declarations:
-// FieldDescriptor, OneofDescriptor, FieldDescriptor, EnumDescriptor,
-// and/or MessageDescriptor.
+// [FieldDescriptor], [OneofDescriptor], [FieldDescriptor], [EnumDescriptor],
+// and/or [MessageDescriptor].
type MessageDescriptor interface {
Descriptor
@@ -214,7 +214,7 @@ type MessageDescriptor interface {
ExtensionRanges() FieldRanges
// ExtensionRangeOptions returns the ith extension range options.
//
- // To avoid a dependency cycle, this method returns a proto.Message value,
+ // To avoid a dependency cycle, this method returns a proto.Message] value,
// which always contains a google.protobuf.ExtensionRangeOptions message.
// This method returns a typed nil-pointer if no options are present.
// The caller must import the descriptorpb package to use this.
@@ -231,9 +231,9 @@ type MessageDescriptor interface {
}
type isMessageDescriptor interface{ ProtoType(MessageDescriptor) }
-// MessageType encapsulates a MessageDescriptor with a concrete Go implementation.
+// MessageType encapsulates a [MessageDescriptor] with a concrete Go implementation.
// It is recommended that implementations of this interface also implement the
-// MessageFieldTypes interface.
+// [MessageFieldTypes] interface.
type MessageType interface {
// New returns a newly allocated empty message.
// It may return nil for synthetic messages representing a map entry.
@@ -249,19 +249,19 @@ type MessageType interface {
Descriptor() MessageDescriptor
}
-// MessageFieldTypes extends a MessageType by providing type information
+// MessageFieldTypes extends a [MessageType] by providing type information
// regarding enums and messages referenced by the message fields.
type MessageFieldTypes interface {
MessageType
- // Enum returns the EnumType for the ith field in Descriptor.Fields.
+ // Enum returns the EnumType for the ith field in MessageDescriptor.Fields.
// It returns nil if the ith field is not an enum kind.
// It panics if out of bounds.
//
// Invariant: mt.Enum(i).Descriptor() == mt.Descriptor().Fields(i).Enum()
Enum(i int) EnumType
- // Message returns the MessageType for the ith field in Descriptor.Fields.
+ // Message returns the MessageType for the ith field in MessageDescriptor.Fields.
// It returns nil if the ith field is not a message or group kind.
// It panics if out of bounds.
//
@@ -286,8 +286,8 @@ type MessageDescriptors interface {
// corresponds with the google.protobuf.FieldDescriptorProto message.
//
// It is used for both normal fields defined within the parent message
-// (e.g., MessageDescriptor.Fields) and fields that extend some remote message
-// (e.g., FileDescriptor.Extensions or MessageDescriptor.Extensions).
+// (e.g., [MessageDescriptor.Fields]) and fields that extend some remote message
+// (e.g., [FileDescriptor.Extensions] or [MessageDescriptor.Extensions]).
type FieldDescriptor interface {
Descriptor
@@ -344,7 +344,7 @@ type FieldDescriptor interface {
// IsMap reports whether this field represents a map,
// where the value type for the associated field is a Map.
// It is equivalent to checking whether Cardinality is Repeated,
- // that the Kind is MessageKind, and that Message.IsMapEntry reports true.
+ // that the Kind is MessageKind, and that MessageDescriptor.IsMapEntry reports true.
IsMap() bool
// MapKey returns the field descriptor for the key in the map entry.
@@ -419,7 +419,7 @@ type OneofDescriptor interface {
// IsSynthetic reports whether this is a synthetic oneof created to support
// proto3 optional semantics. If true, Fields contains exactly one field
- // with HasOptionalKeyword specified.
+ // with FieldDescriptor.HasOptionalKeyword specified.
IsSynthetic() bool
// Fields is a list of fields belonging to this oneof.
@@ -442,10 +442,10 @@ type OneofDescriptors interface {
doNotImplement
}
-// ExtensionDescriptor is an alias of FieldDescriptor for documentation.
+// ExtensionDescriptor is an alias of [FieldDescriptor] for documentation.
type ExtensionDescriptor = FieldDescriptor
-// ExtensionTypeDescriptor is an ExtensionDescriptor with an associated ExtensionType.
+// ExtensionTypeDescriptor is an [ExtensionDescriptor] with an associated [ExtensionType].
type ExtensionTypeDescriptor interface {
ExtensionDescriptor
@@ -470,12 +470,12 @@ type ExtensionDescriptors interface {
doNotImplement
}
-// ExtensionType encapsulates an ExtensionDescriptor with a concrete
+// ExtensionType encapsulates an [ExtensionDescriptor] with a concrete
// Go implementation. The nested field descriptor must be for a extension field.
//
// While a normal field is a member of the parent message that it is declared
-// within (see Descriptor.Parent), an extension field is a member of some other
-// target message (see ExtensionDescriptor.Extendee) and may have no
+// within (see [Descriptor.Parent]), an extension field is a member of some other
+// target message (see [FieldDescriptor.ContainingMessage]) and may have no
// relationship with the parent. However, the full name of an extension field is
// relative to the parent that it is declared within.
//
@@ -510,7 +510,7 @@ type ExtensionType interface {
//
// ValueOf is more extensive than protoreflect.ValueOf for a given field's
// value as it has more type information available.
- ValueOf(interface{}) Value
+ ValueOf(any) Value
// InterfaceOf completely unwraps the Value to the underlying Go type.
// InterfaceOf panics if the input is nil or does not represent the
@@ -519,20 +519,20 @@ type ExtensionType interface {
//
// InterfaceOf is able to unwrap the Value further than Value.Interface
// as it has more type information available.
- InterfaceOf(Value) interface{}
+ InterfaceOf(Value) any
// IsValidValue reports whether the Value is valid to assign to the field.
IsValidValue(Value) bool
// IsValidInterface reports whether the input is valid to assign to the field.
- IsValidInterface(interface{}) bool
+ IsValidInterface(any) bool
}
// EnumDescriptor describes an enum and
// corresponds with the google.protobuf.EnumDescriptorProto message.
//
// Nested declarations:
-// EnumValueDescriptor.
+// [EnumValueDescriptor].
type EnumDescriptor interface {
Descriptor
@@ -544,11 +544,17 @@ type EnumDescriptor interface {
// ReservedRanges is a list of reserved ranges of enum numbers.
ReservedRanges() EnumRanges
+ // IsClosed reports whether this enum uses closed semantics.
+ // See https://protobuf.dev/programming-guides/enum/#definitions.
+ // Note: the Go protobuf implementation is not spec compliant and treats
+ // all enums as open enums.
+ IsClosed() bool
+
isEnumDescriptor
}
type isEnumDescriptor interface{ ProtoType(EnumDescriptor) }
-// EnumType encapsulates an EnumDescriptor with a concrete Go implementation.
+// EnumType encapsulates an [EnumDescriptor] with a concrete Go implementation.
type EnumType interface {
// New returns an instance of this enum type with its value set to n.
New(n EnumNumber) Enum
@@ -610,7 +616,7 @@ type EnumValueDescriptors interface {
// ServiceDescriptor describes a service and
// corresponds with the google.protobuf.ServiceDescriptorProto message.
//
-// Nested declarations: MethodDescriptor.
+// Nested declarations: [MethodDescriptor].
type ServiceDescriptor interface {
Descriptor
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go
index 37601b7819..a7b0d06ff3 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go
@@ -27,16 +27,16 @@ type Enum interface {
// Message is a reflective interface for a concrete message value,
// encapsulating both type and value information for the message.
//
-// Accessor/mutators for individual fields are keyed by FieldDescriptor.
+// Accessor/mutators for individual fields are keyed by [FieldDescriptor].
// For non-extension fields, the descriptor must exactly match the
// field known by the parent message.
-// For extension fields, the descriptor must implement ExtensionTypeDescriptor,
-// extend the parent message (i.e., have the same message FullName), and
+// For extension fields, the descriptor must implement [ExtensionTypeDescriptor],
+// extend the parent message (i.e., have the same message [FullName]), and
// be within the parent's extension range.
//
-// Each field Value can be a scalar or a composite type (Message, List, or Map).
-// See Value for the Go types associated with a FieldDescriptor.
-// Providing a Value that is invalid or of an incorrect type panics.
+// Each field [Value] can be a scalar or a composite type ([Message], [List], or [Map]).
+// See [Value] for the Go types associated with a [FieldDescriptor].
+// Providing a [Value] that is invalid or of an incorrect type panics.
type Message interface {
// Descriptor returns message descriptor, which contains only the protobuf
// type information for the message.
@@ -152,7 +152,7 @@ type Message interface {
// This method may return nil.
//
// The returned methods type is identical to
- // "google.golang.org/protobuf/runtime/protoiface".Methods.
+ // google.golang.org/protobuf/runtime/protoiface.Methods.
// Consult the protoiface package documentation for details.
ProtoMethods() *methods
}
@@ -175,8 +175,8 @@ func (b RawFields) IsValid() bool {
}
// List is a zero-indexed, ordered list.
-// The element Value type is determined by FieldDescriptor.Kind.
-// Providing a Value that is invalid or of an incorrect type panics.
+// The element [Value] type is determined by [FieldDescriptor.Kind].
+// Providing a [Value] that is invalid or of an incorrect type panics.
type List interface {
// Len reports the number of entries in the List.
// Get, Set, and Truncate panic with out of bound indexes.
@@ -226,9 +226,9 @@ type List interface {
}
// Map is an unordered, associative map.
-// The entry MapKey type is determined by FieldDescriptor.MapKey.Kind.
-// The entry Value type is determined by FieldDescriptor.MapValue.Kind.
-// Providing a MapKey or Value that is invalid or of an incorrect type panics.
+// The entry [MapKey] type is determined by [FieldDescriptor.MapKey].Kind.
+// The entry [Value] type is determined by [FieldDescriptor.MapValue].Kind.
+// Providing a [MapKey] or [Value] that is invalid or of an incorrect type panics.
type Map interface {
// Len reports the number of elements in the map.
Len() int
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go
index 591652541f..654599d449 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_equal.go
@@ -24,19 +24,19 @@ import (
// Unlike the == operator, a NaN is equal to another NaN.
//
// - Enums are equal if they contain the same number.
-// Since Value does not contain an enum descriptor,
+// Since [Value] does not contain an enum descriptor,
// enum values do not consider the type of the enum.
//
// - Other scalar values are equal if they contain the same value.
//
-// - Message values are equal if they belong to the same message descriptor,
+// - [Message] values are equal if they belong to the same message descriptor,
// have the same set of populated known and extension field values,
// and the same set of unknown fields values.
//
-// - Lists are equal if they are the same length and
+// - [List] values are equal if they are the same length and
// each corresponding element is equal.
//
-// - Maps are equal if they have the same set of keys and
+// - [Map] values are equal if they have the same set of keys and
// the corresponding value for each key is equal.
func (v1 Value) Equal(v2 Value) bool {
return equalValue(v1, v2)
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go
index 7ced876f4e..75f83a2af0 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go
@@ -32,11 +32,11 @@ const (
type value struct {
pragma.DoNotCompare // 0B
- typ valueType // 8B
- num uint64 // 8B
- str string // 16B
- bin []byte // 24B
- iface interface{} // 16B
+ typ valueType // 8B
+ num uint64 // 8B
+ str string // 16B
+ bin []byte // 24B
+ iface any // 16B
}
func valueOfString(v string) Value {
@@ -45,7 +45,7 @@ func valueOfString(v string) Value {
func valueOfBytes(v []byte) Value {
return Value{typ: bytesType, bin: v}
}
-func valueOfIface(v interface{}) Value {
+func valueOfIface(v any) Value {
return Value{typ: ifaceType, iface: v}
}
@@ -55,6 +55,6 @@ func (v Value) getString() string {
func (v Value) getBytes() []byte {
return v.bin
}
-func (v Value) getIface() interface{} {
+func (v Value) getIface() any {
return v.iface
}
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go
index 08e5ef73fc..9fe83cef5a 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go
@@ -11,7 +11,7 @@ import (
// Value is a union where only one Go type may be set at a time.
// The Value is used to represent all possible values a field may take.
-// The following shows which Go type is used to represent each proto Kind:
+// The following shows which Go type is used to represent each proto [Kind]:
//
// ╔════════════╤═════════════════════════════════════╗
// ║ Go type │ Protobuf kind ║
@@ -31,22 +31,22 @@ import (
//
// Multiple protobuf Kinds may be represented by a single Go type if the type
// can losslessly represent the information for the proto kind. For example,
-// Int64Kind, Sint64Kind, and Sfixed64Kind are all represented by int64,
+// [Int64Kind], [Sint64Kind], and [Sfixed64Kind] are all represented by int64,
// but use different integer encoding methods.
//
-// The List or Map types are used if the field cardinality is repeated.
-// A field is a List if FieldDescriptor.IsList reports true.
-// A field is a Map if FieldDescriptor.IsMap reports true.
+// The [List] or [Map] types are used if the field cardinality is repeated.
+// A field is a [List] if [FieldDescriptor.IsList] reports true.
+// A field is a [Map] if [FieldDescriptor.IsMap] reports true.
//
// Converting to/from a Value and a concrete Go value panics on type mismatch.
-// For example, ValueOf("hello").Int() panics because this attempts to
+// For example, [ValueOf]("hello").Int() panics because this attempts to
// retrieve an int64 from a string.
//
-// List, Map, and Message Values are called "composite" values.
+// [List], [Map], and [Message] Values are called "composite" values.
//
// A composite Value may alias (reference) memory at some location,
// such that changes to the Value updates the that location.
-// A composite value acquired with a Mutable method, such as Message.Mutable,
+// A composite value acquired with a Mutable method, such as [Message.Mutable],
// always references the source object.
//
// For example:
@@ -65,12 +65,12 @@ import (
// // appending to the List here may or may not modify the message.
// list.Append(protoreflect.ValueOfInt32(0))
//
-// Some operations, such as Message.Get, may return an "empty, read-only"
+// Some operations, such as [Message.Get], may return an "empty, read-only"
// composite Value. Modifying an empty, read-only value panics.
type Value value
-// The protoreflect API uses a custom Value union type instead of interface{}
-// to keep the future open for performance optimizations. Using an interface{}
+// The protoreflect API uses a custom Value union type instead of any
+// to keep the future open for performance optimizations. Using an any
// always incurs an allocation for primitives (e.g., int64) since it needs to
// be boxed on the heap (as interfaces can only contain pointers natively).
// Instead, we represent the Value union as a flat struct that internally keeps
@@ -85,7 +85,7 @@ type Value value
// ValueOf returns a Value initialized with the concrete value stored in v.
// This panics if the type does not match one of the allowed types in the
// Value union.
-func ValueOf(v interface{}) Value {
+func ValueOf(v any) Value {
switch v := v.(type) {
case nil:
return Value{}
@@ -192,10 +192,10 @@ func (v Value) IsValid() bool {
return v.typ != nilType
}
-// Interface returns v as an interface{}.
+// Interface returns v as an any.
//
// Invariant: v == ValueOf(v).Interface()
-func (v Value) Interface() interface{} {
+func (v Value) Interface() any {
switch v.typ {
case nilType:
return nil
@@ -306,7 +306,7 @@ func (v Value) Float() float64 {
}
}
-// String returns v as a string. Since this method implements fmt.Stringer,
+// String returns v as a string. Since this method implements [fmt.Stringer],
// this returns the formatted string value for any non-string type.
func (v Value) String() string {
switch v.typ {
@@ -327,7 +327,7 @@ func (v Value) Bytes() []byte {
}
}
-// Enum returns v as a EnumNumber and panics if the type is not a EnumNumber.
+// Enum returns v as a [EnumNumber] and panics if the type is not a [EnumNumber].
func (v Value) Enum() EnumNumber {
switch v.typ {
case enumType:
@@ -337,7 +337,7 @@ func (v Value) Enum() EnumNumber {
}
}
-// Message returns v as a Message and panics if the type is not a Message.
+// Message returns v as a [Message] and panics if the type is not a [Message].
func (v Value) Message() Message {
switch vi := v.getIface().(type) {
case Message:
@@ -347,7 +347,7 @@ func (v Value) Message() Message {
}
}
-// List returns v as a List and panics if the type is not a List.
+// List returns v as a [List] and panics if the type is not a [List].
func (v Value) List() List {
switch vi := v.getIface().(type) {
case List:
@@ -357,7 +357,7 @@ func (v Value) List() List {
}
}
-// Map returns v as a Map and panics if the type is not a Map.
+// Map returns v as a [Map] and panics if the type is not a [Map].
func (v Value) Map() Map {
switch vi := v.getIface().(type) {
case Map:
@@ -367,7 +367,7 @@ func (v Value) Map() Map {
}
}
-// MapKey returns v as a MapKey and panics for invalid MapKey types.
+// MapKey returns v as a [MapKey] and panics for invalid [MapKey] types.
func (v Value) MapKey() MapKey {
switch v.typ {
case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType:
@@ -378,8 +378,8 @@ func (v Value) MapKey() MapKey {
}
// MapKey is used to index maps, where the Go type of the MapKey must match
-// the specified key Kind (see MessageDescriptor.IsMapEntry).
-// The following shows what Go type is used to represent each proto Kind:
+// the specified key [Kind] (see [MessageDescriptor.IsMapEntry]).
+// The following shows what Go type is used to represent each proto [Kind]:
//
// ╔═════════╤═════════════════════════════════════╗
// ║ Go type │ Protobuf kind ║
@@ -392,13 +392,13 @@ func (v Value) MapKey() MapKey {
// ║ string │ StringKind ║
// ╚═════════╧═════════════════════════════════════╝
//
-// A MapKey is constructed and accessed through a Value:
+// A MapKey is constructed and accessed through a [Value]:
//
// k := ValueOf("hash").MapKey() // convert string to MapKey
// s := k.String() // convert MapKey to string
//
-// The MapKey is a strict subset of valid types used in Value;
-// converting a Value to a MapKey with an invalid type panics.
+// The MapKey is a strict subset of valid types used in [Value];
+// converting a [Value] to a MapKey with an invalid type panics.
type MapKey value
// IsValid reports whether k is populated with a value.
@@ -406,8 +406,8 @@ func (k MapKey) IsValid() bool {
return Value(k).IsValid()
}
-// Interface returns k as an interface{}.
-func (k MapKey) Interface() interface{} {
+// Interface returns k as an any.
+func (k MapKey) Interface() any {
return Value(k).Interface()
}
@@ -426,13 +426,13 @@ func (k MapKey) Uint() uint64 {
return Value(k).Uint()
}
-// String returns k as a string. Since this method implements fmt.Stringer,
+// String returns k as a string. Since this method implements [fmt.Stringer],
// this returns the formatted string value for any non-string type.
func (k MapKey) String() string {
return Value(k).String()
}
-// Value returns k as a Value.
+// Value returns k as a [Value].
func (k MapKey) Value() Value {
return Value(k)
}
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go
similarity index 93%
rename from vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe.go
rename to vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go
index 702ddf22a2..7f3583ead8 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !purego && !appengine
-// +build !purego,!appengine
+//go:build !purego && !appengine && !go1.21
+// +build !purego,!appengine,!go1.21
package protoreflect
@@ -45,7 +45,7 @@ var (
// typeOf returns a pointer to the Go type information.
// The pointer is comparable and equal if and only if the types are identical.
-func typeOf(t interface{}) unsafe.Pointer {
+func typeOf(t any) unsafe.Pointer {
return (*ifaceHeader)(unsafe.Pointer(&t)).Type
}
@@ -80,7 +80,7 @@ func valueOfBytes(v []byte) Value {
p := (*sliceHeader)(unsafe.Pointer(&v))
return Value{typ: bytesType, ptr: p.Data, num: uint64(len(v))}
}
-func valueOfIface(v interface{}) Value {
+func valueOfIface(v any) Value {
p := (*ifaceHeader)(unsafe.Pointer(&v))
return Value{typ: p.Type, ptr: p.Data}
}
@@ -93,7 +93,7 @@ func (v Value) getBytes() (x []byte) {
*(*sliceHeader)(unsafe.Pointer(&x)) = sliceHeader{Data: v.ptr, Len: int(v.num), Cap: int(v.num)}
return x
}
-func (v Value) getIface() (x interface{}) {
+func (v Value) getIface() (x any) {
*(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr}
return x
}
diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go121.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go121.go
new file mode 100644
index 0000000000..f7d386990a
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go121.go
@@ -0,0 +1,87 @@
+// Copyright 2018 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.
+
+//go:build !purego && !appengine && go1.21
+// +build !purego,!appengine,go1.21
+
+package protoreflect
+
+import (
+ "unsafe"
+
+ "google.golang.org/protobuf/internal/pragma"
+)
+
+type (
+ ifaceHeader struct {
+ _ [0]any // if interfaces have greater alignment than unsafe.Pointer, this will enforce it.
+ Type unsafe.Pointer
+ Data unsafe.Pointer
+ }
+)
+
+var (
+ nilType = typeOf(nil)
+ boolType = typeOf(*new(bool))
+ int32Type = typeOf(*new(int32))
+ int64Type = typeOf(*new(int64))
+ uint32Type = typeOf(*new(uint32))
+ uint64Type = typeOf(*new(uint64))
+ float32Type = typeOf(*new(float32))
+ float64Type = typeOf(*new(float64))
+ stringType = typeOf(*new(string))
+ bytesType = typeOf(*new([]byte))
+ enumType = typeOf(*new(EnumNumber))
+)
+
+// typeOf returns a pointer to the Go type information.
+// The pointer is comparable and equal if and only if the types are identical.
+func typeOf(t any) unsafe.Pointer {
+ return (*ifaceHeader)(unsafe.Pointer(&t)).Type
+}
+
+// value is a union where only one type can be represented at a time.
+// The struct is 24B large on 64-bit systems and requires the minimum storage
+// necessary to represent each possible type.
+//
+// The Go GC needs to be able to scan variables containing pointers.
+// As such, pointers and non-pointers cannot be intermixed.
+type value struct {
+ pragma.DoNotCompare // 0B
+
+ // typ stores the type of the value as a pointer to the Go type.
+ typ unsafe.Pointer // 8B
+
+ // ptr stores the data pointer for a String, Bytes, or interface value.
+ ptr unsafe.Pointer // 8B
+
+ // num stores a Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, or
+ // Enum value as a raw uint64.
+ //
+ // It is also used to store the length of a String or Bytes value;
+ // the capacity is ignored.
+ num uint64 // 8B
+}
+
+func valueOfString(v string) Value {
+ return Value{typ: stringType, ptr: unsafe.Pointer(unsafe.StringData(v)), num: uint64(len(v))}
+}
+func valueOfBytes(v []byte) Value {
+ return Value{typ: bytesType, ptr: unsafe.Pointer(unsafe.SliceData(v)), num: uint64(len(v))}
+}
+func valueOfIface(v any) Value {
+ p := (*ifaceHeader)(unsafe.Pointer(&v))
+ return Value{typ: p.Type, ptr: p.Data}
+}
+
+func (v Value) getString() string {
+ return unsafe.String((*byte)(v.ptr), v.num)
+}
+func (v Value) getBytes() []byte {
+ return unsafe.Slice((*byte)(v.ptr), v.num)
+}
+func (v Value) getIface() (x any) {
+ *(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr}
+ return x
+}
diff --git a/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go b/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go
index aeb5597744..de17773391 100644
--- a/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go
+++ b/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go
@@ -5,12 +5,12 @@
// Package protoregistry provides data structures to register and lookup
// protobuf descriptor types.
//
-// The Files registry contains file descriptors and provides the ability
+// The [Files] registry contains file descriptors and provides the ability
// to iterate over the files or lookup a specific descriptor within the files.
-// Files only contains protobuf descriptors and has no understanding of Go
+// [Files] only contains protobuf descriptors and has no understanding of Go
// type information that may be associated with each descriptor.
//
-// The Types registry contains descriptor types for which there is a known
+// The [Types] registry contains descriptor types for which there is a known
// Go type associated with that descriptor. It provides the ability to iterate
// over the registered types or lookup a type by name.
package protoregistry
@@ -95,7 +95,7 @@ type Files struct {
// multiple files. Only top-level declarations are registered.
// Note that enum values are in the top-level since that are in the same
// scope as the parent enum.
- descsByName map[protoreflect.FullName]interface{}
+ descsByName map[protoreflect.FullName]any
filesByPath map[string][]protoreflect.FileDescriptor
numFiles int
}
@@ -117,7 +117,7 @@ func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error {
defer globalMutex.Unlock()
}
if r.descsByName == nil {
- r.descsByName = map[protoreflect.FullName]interface{}{
+ r.descsByName = map[protoreflect.FullName]any{
"": &packageDescriptor{},
}
r.filesByPath = make(map[string][]protoreflect.FileDescriptor)
@@ -218,7 +218,7 @@ func (r *Files) checkGenProtoConflict(path string) {
// FindDescriptorByName looks up a descriptor by the full name.
//
-// This returns (nil, NotFound) if not found.
+// This returns (nil, [NotFound]) if not found.
func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
if r == nil {
return nil, NotFound
@@ -310,7 +310,7 @@ func (s *nameSuffix) Pop() (name protoreflect.Name) {
// FindFileByPath looks up a file by the path.
//
-// This returns (nil, NotFound) if not found.
+// This returns (nil, [NotFound]) if not found.
// This returns an error if multiple files have the same path.
func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
if r == nil {
@@ -431,7 +431,7 @@ func rangeTopLevelDescriptors(fd protoreflect.FileDescriptor, f func(protoreflec
// A compliant implementation must deterministically return the same type
// if no error is encountered.
//
-// The Types type implements this interface.
+// The [Types] type implements this interface.
type MessageTypeResolver interface {
// FindMessageByName looks up a message by its full name.
// E.g., "google.protobuf.Any"
@@ -451,7 +451,7 @@ type MessageTypeResolver interface {
// A compliant implementation must deterministically return the same type
// if no error is encountered.
//
-// The Types type implements this interface.
+// The [Types] type implements this interface.
type ExtensionTypeResolver interface {
// FindExtensionByName looks up a extension field by the field's full name.
// Note that this is the full name of the field as determined by
@@ -485,7 +485,7 @@ type Types struct {
}
type (
- typesByName map[protoreflect.FullName]interface{}
+ typesByName map[protoreflect.FullName]any
extensionsByMessage map[protoreflect.FullName]extensionsByNumber
extensionsByNumber map[protoreflect.FieldNumber]protoreflect.ExtensionType
)
@@ -570,7 +570,7 @@ func (r *Types) RegisterExtension(xt protoreflect.ExtensionType) error {
return nil
}
-func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interface{}) error {
+func (r *Types) register(kind string, desc protoreflect.Descriptor, typ any) error {
name := desc.FullName()
prev := r.typesByName[name]
if prev != nil {
@@ -590,7 +590,7 @@ func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interfac
// FindEnumByName looks up an enum by its full name.
// E.g., "google.protobuf.Field.Kind".
//
-// This returns (nil, NotFound) if not found.
+// This returns (nil, [NotFound]) if not found.
func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) {
if r == nil {
return nil, NotFound
@@ -611,7 +611,7 @@ func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumTyp
// FindMessageByName looks up a message by its full name,
// e.g. "google.protobuf.Any".
//
-// This returns (nil, NotFound) if not found.
+// This returns (nil, [NotFound]) if not found.
func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
if r == nil {
return nil, NotFound
@@ -632,7 +632,7 @@ func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.M
// FindMessageByURL looks up a message by a URL identifier.
// See documentation on google.protobuf.Any.type_url for the URL format.
//
-// This returns (nil, NotFound) if not found.
+// This returns (nil, [NotFound]) if not found.
func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
// This function is similar to FindMessageByName but
// truncates anything before and including '/' in the URL.
@@ -662,7 +662,7 @@ func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
// where the extension is declared and is unrelated to the full name of the
// message being extended.
//
-// This returns (nil, NotFound) if not found.
+// This returns (nil, [NotFound]) if not found.
func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
if r == nil {
return nil, NotFound
@@ -703,7 +703,7 @@ func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.E
// FindExtensionByNumber looks up a extension field by the field number
// within some parent message, identified by full name.
//
-// This returns (nil, NotFound) if not found.
+// This returns (nil, [NotFound]) if not found.
func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
if r == nil {
return nil, NotFound
@@ -841,7 +841,7 @@ func (r *Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(p
}
}
-func typeName(t interface{}) string {
+func typeName(t any) string {
switch t.(type) {
case protoreflect.EnumType:
return "enum"
@@ -854,7 +854,7 @@ func typeName(t interface{}) string {
}
}
-func amendErrorWithCaller(err error, prev, curr interface{}) error {
+func amendErrorWithCaller(err error, prev, curr any) error {
prevPkg := goPackage(prev)
currPkg := goPackage(curr)
if prevPkg == "" || currPkg == "" || prevPkg == currPkg {
@@ -863,7 +863,7 @@ func amendErrorWithCaller(err error, prev, curr interface{}) error {
return errors.New("%s\n\tpreviously from: %q\n\tcurrently from: %q", err, prevPkg, currPkg)
}
-func goPackage(v interface{}) string {
+func goPackage(v any) string {
switch d := v.(type) {
case protoreflect.EnumType:
v = d.Descriptor()
diff --git a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
index 04c00f737c..9403eb0750 100644
--- a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
+++ b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
@@ -48,6 +48,108 @@ import (
sync "sync"
)
+// The full set of known editions.
+type Edition int32
+
+const (
+ // A placeholder for an unknown edition value.
+ Edition_EDITION_UNKNOWN Edition = 0
+ // A placeholder edition for specifying default behaviors *before* a feature
+ // was first introduced. This is effectively an "infinite past".
+ Edition_EDITION_LEGACY Edition = 900
+ // Legacy syntax "editions". These pre-date editions, but behave much like
+ // distinct editions. These can't be used to specify the edition of proto
+ // files, but feature definitions must supply proto2/proto3 defaults for
+ // backwards compatibility.
+ Edition_EDITION_PROTO2 Edition = 998
+ Edition_EDITION_PROTO3 Edition = 999
+ // Editions that have been released. The specific values are arbitrary and
+ // should not be depended on, but they will always be time-ordered for easy
+ // comparison.
+ Edition_EDITION_2023 Edition = 1000
+ Edition_EDITION_2024 Edition = 1001
+ // Placeholder editions for testing feature resolution. These should not be
+ // used or relyed on outside of tests.
+ Edition_EDITION_1_TEST_ONLY Edition = 1
+ Edition_EDITION_2_TEST_ONLY Edition = 2
+ Edition_EDITION_99997_TEST_ONLY Edition = 99997
+ Edition_EDITION_99998_TEST_ONLY Edition = 99998
+ Edition_EDITION_99999_TEST_ONLY Edition = 99999
+ // Placeholder for specifying unbounded edition support. This should only
+ // ever be used by plugins that can expect to never require any changes to
+ // support a new edition.
+ Edition_EDITION_MAX Edition = 2147483647
+)
+
+// Enum value maps for Edition.
+var (
+ Edition_name = map[int32]string{
+ 0: "EDITION_UNKNOWN",
+ 900: "EDITION_LEGACY",
+ 998: "EDITION_PROTO2",
+ 999: "EDITION_PROTO3",
+ 1000: "EDITION_2023",
+ 1001: "EDITION_2024",
+ 1: "EDITION_1_TEST_ONLY",
+ 2: "EDITION_2_TEST_ONLY",
+ 99997: "EDITION_99997_TEST_ONLY",
+ 99998: "EDITION_99998_TEST_ONLY",
+ 99999: "EDITION_99999_TEST_ONLY",
+ 2147483647: "EDITION_MAX",
+ }
+ Edition_value = map[string]int32{
+ "EDITION_UNKNOWN": 0,
+ "EDITION_LEGACY": 900,
+ "EDITION_PROTO2": 998,
+ "EDITION_PROTO3": 999,
+ "EDITION_2023": 1000,
+ "EDITION_2024": 1001,
+ "EDITION_1_TEST_ONLY": 1,
+ "EDITION_2_TEST_ONLY": 2,
+ "EDITION_99997_TEST_ONLY": 99997,
+ "EDITION_99998_TEST_ONLY": 99998,
+ "EDITION_99999_TEST_ONLY": 99999,
+ "EDITION_MAX": 2147483647,
+ }
+)
+
+func (x Edition) Enum() *Edition {
+ p := new(Edition)
+ *p = x
+ return p
+}
+
+func (x Edition) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Edition) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_descriptor_proto_enumTypes[0].Descriptor()
+}
+
+func (Edition) Type() protoreflect.EnumType {
+ return &file_google_protobuf_descriptor_proto_enumTypes[0]
+}
+
+func (x Edition) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *Edition) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = Edition(num)
+ return nil
+}
+
+// Deprecated: Use Edition.Descriptor instead.
+func (Edition) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{0}
+}
+
// The verification state of the extension range.
type ExtensionRangeOptions_VerificationState int32
@@ -80,11 +182,11 @@ func (x ExtensionRangeOptions_VerificationState) String() string {
}
func (ExtensionRangeOptions_VerificationState) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[0].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
}
func (ExtensionRangeOptions_VerificationState) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[0]
+ return &file_google_protobuf_descriptor_proto_enumTypes[1]
}
func (x ExtensionRangeOptions_VerificationState) Number() protoreflect.EnumNumber {
@@ -125,9 +227,10 @@ const (
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
+ // Group type is deprecated and not supported after google.protobuf. However, Proto3
// implementations should still be able to parse the group wire format and
- // treat group fields as unknown fields.
+ // treat group fields as unknown fields. In Editions, the group wire format
+ // can be enabled via the `message_encoding` feature.
FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10
FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11 // Length-delimited aggregate.
// New in version 2.
@@ -195,11 +298,11 @@ func (x FieldDescriptorProto_Type) String() string {
}
func (FieldDescriptorProto_Type) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
}
func (FieldDescriptorProto_Type) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[1]
+ return &file_google_protobuf_descriptor_proto_enumTypes[2]
}
func (x FieldDescriptorProto_Type) Number() protoreflect.EnumNumber {
@@ -226,21 +329,24 @@ 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
+ // The required label is only allowed in google.protobuf. In proto3 and Editions
+ // it's explicitly prohibited. In Editions, the `field_presence` feature
+ // can be used to get this behavior.
+ FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2
)
// Enum value maps for FieldDescriptorProto_Label.
var (
FieldDescriptorProto_Label_name = map[int32]string{
1: "LABEL_OPTIONAL",
- 2: "LABEL_REQUIRED",
3: "LABEL_REPEATED",
+ 2: "LABEL_REQUIRED",
}
FieldDescriptorProto_Label_value = map[string]int32{
"LABEL_OPTIONAL": 1,
- "LABEL_REQUIRED": 2,
"LABEL_REPEATED": 3,
+ "LABEL_REQUIRED": 2,
}
)
@@ -255,11 +361,11 @@ func (x FieldDescriptorProto_Label) String() string {
}
func (FieldDescriptorProto_Label) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
}
func (FieldDescriptorProto_Label) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[2]
+ return &file_google_protobuf_descriptor_proto_enumTypes[3]
}
func (x FieldDescriptorProto_Label) Number() protoreflect.EnumNumber {
@@ -316,11 +422,11 @@ func (x FileOptions_OptimizeMode) String() string {
}
func (FileOptions_OptimizeMode) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
}
func (FileOptions_OptimizeMode) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[3]
+ return &file_google_protobuf_descriptor_proto_enumTypes[4]
}
func (x FileOptions_OptimizeMode) Number() protoreflect.EnumNumber {
@@ -382,11 +488,11 @@ func (x FieldOptions_CType) String() string {
}
func (FieldOptions_CType) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
}
func (FieldOptions_CType) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[4]
+ return &file_google_protobuf_descriptor_proto_enumTypes[5]
}
func (x FieldOptions_CType) Number() protoreflect.EnumNumber {
@@ -444,11 +550,11 @@ func (x FieldOptions_JSType) String() string {
}
func (FieldOptions_JSType) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
}
func (FieldOptions_JSType) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[5]
+ return &file_google_protobuf_descriptor_proto_enumTypes[6]
}
func (x FieldOptions_JSType) Number() protoreflect.EnumNumber {
@@ -506,11 +612,11 @@ func (x FieldOptions_OptionRetention) String() string {
}
func (FieldOptions_OptionRetention) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[6].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
}
func (FieldOptions_OptionRetention) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[6]
+ return &file_google_protobuf_descriptor_proto_enumTypes[7]
}
func (x FieldOptions_OptionRetention) Number() protoreflect.EnumNumber {
@@ -590,11 +696,11 @@ func (x FieldOptions_OptionTargetType) String() string {
}
func (FieldOptions_OptionTargetType) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[7].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
}
func (FieldOptions_OptionTargetType) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[7]
+ return &file_google_protobuf_descriptor_proto_enumTypes[8]
}
func (x FieldOptions_OptionTargetType) Number() protoreflect.EnumNumber {
@@ -652,11 +758,11 @@ func (x MethodOptions_IdempotencyLevel) String() string {
}
func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[8].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
}
func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[8]
+ return &file_google_protobuf_descriptor_proto_enumTypes[9]
}
func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber {
@@ -678,6 +784,363 @@ func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) {
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17, 0}
}
+type FeatureSet_FieldPresence int32
+
+const (
+ FeatureSet_FIELD_PRESENCE_UNKNOWN FeatureSet_FieldPresence = 0
+ FeatureSet_EXPLICIT FeatureSet_FieldPresence = 1
+ FeatureSet_IMPLICIT FeatureSet_FieldPresence = 2
+ FeatureSet_LEGACY_REQUIRED FeatureSet_FieldPresence = 3
+)
+
+// Enum value maps for FeatureSet_FieldPresence.
+var (
+ FeatureSet_FieldPresence_name = map[int32]string{
+ 0: "FIELD_PRESENCE_UNKNOWN",
+ 1: "EXPLICIT",
+ 2: "IMPLICIT",
+ 3: "LEGACY_REQUIRED",
+ }
+ FeatureSet_FieldPresence_value = map[string]int32{
+ "FIELD_PRESENCE_UNKNOWN": 0,
+ "EXPLICIT": 1,
+ "IMPLICIT": 2,
+ "LEGACY_REQUIRED": 3,
+ }
+)
+
+func (x FeatureSet_FieldPresence) Enum() *FeatureSet_FieldPresence {
+ p := new(FeatureSet_FieldPresence)
+ *p = x
+ return p
+}
+
+func (x FeatureSet_FieldPresence) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_FieldPresence) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_descriptor_proto_enumTypes[10].Descriptor()
+}
+
+func (FeatureSet_FieldPresence) Type() protoreflect.EnumType {
+ return &file_google_protobuf_descriptor_proto_enumTypes[10]
+}
+
+func (x FeatureSet_FieldPresence) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_FieldPresence) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FeatureSet_FieldPresence(num)
+ return nil
+}
+
+// Deprecated: Use FeatureSet_FieldPresence.Descriptor instead.
+func (FeatureSet_FieldPresence) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0}
+}
+
+type FeatureSet_EnumType int32
+
+const (
+ FeatureSet_ENUM_TYPE_UNKNOWN FeatureSet_EnumType = 0
+ FeatureSet_OPEN FeatureSet_EnumType = 1
+ FeatureSet_CLOSED FeatureSet_EnumType = 2
+)
+
+// Enum value maps for FeatureSet_EnumType.
+var (
+ FeatureSet_EnumType_name = map[int32]string{
+ 0: "ENUM_TYPE_UNKNOWN",
+ 1: "OPEN",
+ 2: "CLOSED",
+ }
+ FeatureSet_EnumType_value = map[string]int32{
+ "ENUM_TYPE_UNKNOWN": 0,
+ "OPEN": 1,
+ "CLOSED": 2,
+ }
+)
+
+func (x FeatureSet_EnumType) Enum() *FeatureSet_EnumType {
+ p := new(FeatureSet_EnumType)
+ *p = x
+ return p
+}
+
+func (x FeatureSet_EnumType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_EnumType) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_descriptor_proto_enumTypes[11].Descriptor()
+}
+
+func (FeatureSet_EnumType) Type() protoreflect.EnumType {
+ return &file_google_protobuf_descriptor_proto_enumTypes[11]
+}
+
+func (x FeatureSet_EnumType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_EnumType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FeatureSet_EnumType(num)
+ return nil
+}
+
+// Deprecated: Use FeatureSet_EnumType.Descriptor instead.
+func (FeatureSet_EnumType) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 1}
+}
+
+type FeatureSet_RepeatedFieldEncoding int32
+
+const (
+ FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN FeatureSet_RepeatedFieldEncoding = 0
+ FeatureSet_PACKED FeatureSet_RepeatedFieldEncoding = 1
+ FeatureSet_EXPANDED FeatureSet_RepeatedFieldEncoding = 2
+)
+
+// Enum value maps for FeatureSet_RepeatedFieldEncoding.
+var (
+ FeatureSet_RepeatedFieldEncoding_name = map[int32]string{
+ 0: "REPEATED_FIELD_ENCODING_UNKNOWN",
+ 1: "PACKED",
+ 2: "EXPANDED",
+ }
+ FeatureSet_RepeatedFieldEncoding_value = map[string]int32{
+ "REPEATED_FIELD_ENCODING_UNKNOWN": 0,
+ "PACKED": 1,
+ "EXPANDED": 2,
+ }
+)
+
+func (x FeatureSet_RepeatedFieldEncoding) Enum() *FeatureSet_RepeatedFieldEncoding {
+ p := new(FeatureSet_RepeatedFieldEncoding)
+ *p = x
+ return p
+}
+
+func (x FeatureSet_RepeatedFieldEncoding) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_RepeatedFieldEncoding) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_descriptor_proto_enumTypes[12].Descriptor()
+}
+
+func (FeatureSet_RepeatedFieldEncoding) Type() protoreflect.EnumType {
+ return &file_google_protobuf_descriptor_proto_enumTypes[12]
+}
+
+func (x FeatureSet_RepeatedFieldEncoding) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_RepeatedFieldEncoding) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FeatureSet_RepeatedFieldEncoding(num)
+ return nil
+}
+
+// Deprecated: Use FeatureSet_RepeatedFieldEncoding.Descriptor instead.
+func (FeatureSet_RepeatedFieldEncoding) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 2}
+}
+
+type FeatureSet_Utf8Validation int32
+
+const (
+ FeatureSet_UTF8_VALIDATION_UNKNOWN FeatureSet_Utf8Validation = 0
+ FeatureSet_VERIFY FeatureSet_Utf8Validation = 2
+ FeatureSet_NONE FeatureSet_Utf8Validation = 3
+)
+
+// Enum value maps for FeatureSet_Utf8Validation.
+var (
+ FeatureSet_Utf8Validation_name = map[int32]string{
+ 0: "UTF8_VALIDATION_UNKNOWN",
+ 2: "VERIFY",
+ 3: "NONE",
+ }
+ FeatureSet_Utf8Validation_value = map[string]int32{
+ "UTF8_VALIDATION_UNKNOWN": 0,
+ "VERIFY": 2,
+ "NONE": 3,
+ }
+)
+
+func (x FeatureSet_Utf8Validation) Enum() *FeatureSet_Utf8Validation {
+ p := new(FeatureSet_Utf8Validation)
+ *p = x
+ return p
+}
+
+func (x FeatureSet_Utf8Validation) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_Utf8Validation) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_descriptor_proto_enumTypes[13].Descriptor()
+}
+
+func (FeatureSet_Utf8Validation) Type() protoreflect.EnumType {
+ return &file_google_protobuf_descriptor_proto_enumTypes[13]
+}
+
+func (x FeatureSet_Utf8Validation) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_Utf8Validation) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FeatureSet_Utf8Validation(num)
+ return nil
+}
+
+// Deprecated: Use FeatureSet_Utf8Validation.Descriptor instead.
+func (FeatureSet_Utf8Validation) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 3}
+}
+
+type FeatureSet_MessageEncoding int32
+
+const (
+ FeatureSet_MESSAGE_ENCODING_UNKNOWN FeatureSet_MessageEncoding = 0
+ FeatureSet_LENGTH_PREFIXED FeatureSet_MessageEncoding = 1
+ FeatureSet_DELIMITED FeatureSet_MessageEncoding = 2
+)
+
+// Enum value maps for FeatureSet_MessageEncoding.
+var (
+ FeatureSet_MessageEncoding_name = map[int32]string{
+ 0: "MESSAGE_ENCODING_UNKNOWN",
+ 1: "LENGTH_PREFIXED",
+ 2: "DELIMITED",
+ }
+ FeatureSet_MessageEncoding_value = map[string]int32{
+ "MESSAGE_ENCODING_UNKNOWN": 0,
+ "LENGTH_PREFIXED": 1,
+ "DELIMITED": 2,
+ }
+)
+
+func (x FeatureSet_MessageEncoding) Enum() *FeatureSet_MessageEncoding {
+ p := new(FeatureSet_MessageEncoding)
+ *p = x
+ return p
+}
+
+func (x FeatureSet_MessageEncoding) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_MessageEncoding) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_descriptor_proto_enumTypes[14].Descriptor()
+}
+
+func (FeatureSet_MessageEncoding) Type() protoreflect.EnumType {
+ return &file_google_protobuf_descriptor_proto_enumTypes[14]
+}
+
+func (x FeatureSet_MessageEncoding) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_MessageEncoding) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FeatureSet_MessageEncoding(num)
+ return nil
+}
+
+// Deprecated: Use FeatureSet_MessageEncoding.Descriptor instead.
+func (FeatureSet_MessageEncoding) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 4}
+}
+
+type FeatureSet_JsonFormat int32
+
+const (
+ FeatureSet_JSON_FORMAT_UNKNOWN FeatureSet_JsonFormat = 0
+ FeatureSet_ALLOW FeatureSet_JsonFormat = 1
+ FeatureSet_LEGACY_BEST_EFFORT FeatureSet_JsonFormat = 2
+)
+
+// Enum value maps for FeatureSet_JsonFormat.
+var (
+ FeatureSet_JsonFormat_name = map[int32]string{
+ 0: "JSON_FORMAT_UNKNOWN",
+ 1: "ALLOW",
+ 2: "LEGACY_BEST_EFFORT",
+ }
+ FeatureSet_JsonFormat_value = map[string]int32{
+ "JSON_FORMAT_UNKNOWN": 0,
+ "ALLOW": 1,
+ "LEGACY_BEST_EFFORT": 2,
+ }
+)
+
+func (x FeatureSet_JsonFormat) Enum() *FeatureSet_JsonFormat {
+ p := new(FeatureSet_JsonFormat)
+ *p = x
+ return p
+}
+
+func (x FeatureSet_JsonFormat) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FeatureSet_JsonFormat) Descriptor() protoreflect.EnumDescriptor {
+ return file_google_protobuf_descriptor_proto_enumTypes[15].Descriptor()
+}
+
+func (FeatureSet_JsonFormat) Type() protoreflect.EnumType {
+ return &file_google_protobuf_descriptor_proto_enumTypes[15]
+}
+
+func (x FeatureSet_JsonFormat) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FeatureSet_JsonFormat) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FeatureSet_JsonFormat(num)
+ return nil
+}
+
+// Deprecated: Use FeatureSet_JsonFormat.Descriptor instead.
+func (FeatureSet_JsonFormat) EnumDescriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 5}
+}
+
// Represents the identified object's effect on the element in the original
// .proto file.
type GeneratedCodeInfo_Annotation_Semantic int32
@@ -716,11 +1179,11 @@ func (x GeneratedCodeInfo_Annotation_Semantic) String() string {
}
func (GeneratedCodeInfo_Annotation_Semantic) Descriptor() protoreflect.EnumDescriptor {
- return file_google_protobuf_descriptor_proto_enumTypes[9].Descriptor()
+ return file_google_protobuf_descriptor_proto_enumTypes[16].Descriptor()
}
func (GeneratedCodeInfo_Annotation_Semantic) Type() protoreflect.EnumType {
- return &file_google_protobuf_descriptor_proto_enumTypes[9]
+ return &file_google_protobuf_descriptor_proto_enumTypes[16]
}
func (x GeneratedCodeInfo_Annotation_Semantic) Number() protoreflect.EnumNumber {
@@ -739,7 +1202,7 @@ func (x *GeneratedCodeInfo_Annotation_Semantic) UnmarshalJSON(b []byte) error {
// Deprecated: Use GeneratedCodeInfo_Annotation_Semantic.Descriptor instead.
func (GeneratedCodeInfo_Annotation_Semantic) EnumDescriptor() ([]byte, []int) {
- return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20, 0, 0}
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{22, 0, 0}
}
// The protocol compiler can output a FileDescriptorSet containing the .proto
@@ -822,8 +1285,8 @@ type FileDescriptorProto struct {
//
// If `edition` is present, this value must be "editions".
Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"`
- // The edition of the proto file, which is an opaque string.
- Edition *string `protobuf:"bytes,13,opt,name=edition" json:"edition,omitempty"`
+ // The edition of the proto file.
+ Edition *Edition `protobuf:"varint,14,opt,name=edition,enum=google.protobuf.Edition" json:"edition,omitempty"`
}
func (x *FileDescriptorProto) Reset() {
@@ -942,11 +1405,11 @@ func (x *FileDescriptorProto) GetSyntax() string {
return ""
}
-func (x *FileDescriptorProto) GetEdition() string {
+func (x *FileDescriptorProto) GetEdition() Edition {
if x != nil && x.Edition != nil {
return *x.Edition
}
- return ""
+ return Edition_EDITION_UNKNOWN
}
// Describes a message type.
@@ -1079,13 +1542,14 @@ type ExtensionRangeOptions 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"`
- // go/protobuf-stripping-extension-declarations
- // Like Metadata, but we use a repeated field to hold all extension
- // declarations. This should avoid the size increases of transforming a large
- // extension range into small ranges in generated binaries.
+ // For external users: DO NOT USE. We are in the process of open sourcing
+ // extension declaration and executing internal cleanups before it can be
+ // used externally.
Declaration []*ExtensionRangeOptions_Declaration `protobuf:"bytes,2,rep,name=declaration" json:"declaration,omitempty"`
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,50,opt,name=features" json:"features,omitempty"`
// The verification state of the range.
- // TODO(b/278783756): flip the default to DECLARATION once all empty ranges
+ // TODO: flip the default to DECLARATION once all empty ranges
// are marked as UNVERIFIED.
Verification *ExtensionRangeOptions_VerificationState `protobuf:"varint,3,opt,name=verification,enum=google.protobuf.ExtensionRangeOptions_VerificationState,def=1" json:"verification,omitempty"`
}
@@ -1141,6 +1605,13 @@ func (x *ExtensionRangeOptions) GetDeclaration() []*ExtensionRangeOptions_Declar
return nil
}
+func (x *ExtensionRangeOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
func (x *ExtensionRangeOptions) GetVerification() ExtensionRangeOptions_VerificationState {
if x != nil && x.Verification != nil {
return *x.Verification
@@ -1186,12 +1657,12 @@ type FieldDescriptorProto struct {
// If true, this is a proto3 "optional". When a proto3 field is optional, it
// tracks presence regardless of field type.
//
- // When proto3_optional is true, this field must be belong to a oneof to
- // signal to old proto3 clients that presence is tracked for this field. This
- // oneof is known as a "synthetic" oneof, and this field must be its sole
- // member (each proto3 optional field gets its own synthetic oneof). Synthetic
- // oneofs exist in the descriptor only, and do not generate any API. Synthetic
- // oneofs must be ordered after all "real" oneofs.
+ // When proto3_optional is true, this field must belong to a oneof to signal
+ // to old proto3 clients that presence is tracked for this field. This oneof
+ // is known as a "synthetic" oneof, and this field must be its sole member
+ // (each proto3 optional field gets its own synthetic oneof). Synthetic oneofs
+ // exist in the descriptor only, and do not generate any API. Synthetic oneofs
+ // must be ordered after all "real" oneofs.
//
// For message fields, proto3_optional doesn't create any semantic change,
// since non-repeated message fields always track presence. However it still
@@ -1711,12 +2182,16 @@ type FileOptions struct {
//
// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
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.
+ // A proto2 file can set this to true to opt in to UTF-8 checking for Java,
+ // which will throw an exception if invalid UTF-8 is parsed from the wire or
+ // assigned to a string field.
+ //
+ // TODO: clarify exactly what kinds of field types this option
+ // applies to, and update these docs accordingly.
+ //
+ // Proto3 files already perform these checks. Setting the option explicitly to
+ // false has no effect: it cannot be used to opt proto3 files out of UTF-8
+ // checks.
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
@@ -1738,7 +2213,6 @@ type FileOptions struct {
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"`
- PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_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
@@ -1772,6 +2246,8 @@ type FileOptions struct {
// is empty. When this option is not set, the package name will be used for
// determining the ruby package.
RubyPackage *string `protobuf:"bytes,45,opt,name=ruby_package,json=rubyPackage" json:"ruby_package,omitempty"`
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,50,opt,name=features" json:"features,omitempty"`
// The parser stores options it doesn't recognize here.
// See the documentation for the "Options" section above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
@@ -1785,7 +2261,6 @@ const (
Default_FileOptions_CcGenericServices = bool(false)
Default_FileOptions_JavaGenericServices = bool(false)
Default_FileOptions_PyGenericServices = bool(false)
- Default_FileOptions_PhpGenericServices = bool(false)
Default_FileOptions_Deprecated = bool(false)
Default_FileOptions_CcEnableArenas = bool(true)
)
@@ -1893,13 +2368,6 @@ func (x *FileOptions) GetPyGenericServices() bool {
return Default_FileOptions_PyGenericServices
}
-func (x *FileOptions) GetPhpGenericServices() bool {
- if x != nil && x.PhpGenericServices != nil {
- return *x.PhpGenericServices
- }
- return Default_FileOptions_PhpGenericServices
-}
-
func (x *FileOptions) GetDeprecated() bool {
if x != nil && x.Deprecated != nil {
return *x.Deprecated
@@ -1963,6 +2431,13 @@ func (x *FileOptions) GetRubyPackage() string {
return ""
}
+func (x *FileOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
func (x *FileOptions) GetUninterpretedOption() []*UninterpretedOption {
if x != nil {
return x.UninterpretedOption
@@ -2006,10 +2481,6 @@ type MessageOptions struct {
// 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"`
- // 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.
- //
// Whether the message is an automatically generated map entry type for the
// maps field.
//
@@ -2030,6 +2501,10 @@ type MessageOptions struct {
// use a native map in the target language to hold the keys and values.
// The reflection APIs in such implementations 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"`
// Enable the legacy handling of JSON field name conflicts. This lowercases
// and strips underscored from the fields before comparison in proto3 only.
@@ -2039,11 +2514,13 @@ type MessageOptions struct {
// This should only be used as a temporary measure against broken builds due
// to the change in behavior for JSON field name conflicts.
//
- // TODO(b/261750190) This is legacy behavior we plan to remove once downstream
+ // TODO This is legacy behavior we plan to remove once downstream
// teams have had time to migrate.
//
// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
DeprecatedLegacyJsonFieldConflicts *bool `protobuf:"varint,11,opt,name=deprecated_legacy_json_field_conflicts,json=deprecatedLegacyJsonFieldConflicts" json:"deprecated_legacy_json_field_conflicts,omitempty"`
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,12,opt,name=features" json:"features,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"`
}
@@ -2123,6 +2600,13 @@ func (x *MessageOptions) GetDeprecatedLegacyJsonFieldConflicts() bool {
return false
}
+func (x *MessageOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
func (x *MessageOptions) GetUninterpretedOption() []*UninterpretedOption {
if x != nil {
return x.UninterpretedOption
@@ -2147,7 +2631,9 @@ type FieldOptions struct {
// 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.
+ // false will avoid using packed encoding. This option is prohibited in
+ // Editions, but the `repeated_field_encoding` feature can be used to control
+ // the behavior.
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
@@ -2178,19 +2664,11 @@ type FieldOptions struct {
// 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.
- //
- // As of May 2022, lazy verifies the contents of the byte stream during
- // parsing. An invalid byte stream will cause the overall parsing to fail.
+ // Note that lazy message fields are still eagerly verified to check
+ // ill-formed wireformat or missing required fields. Calling IsInitialized()
+ // on the outer message would fail if the inner message has missing required
+ // fields. Failed verification would result in parsing failure (except when
+ // uninitialized messages are acceptable).
Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"`
// unverified_lazy does no correctness checks on the byte stream. This should
// only be used where lazy with verification is prohibitive for performance
@@ -2205,11 +2683,13 @@ type FieldOptions struct {
Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
// Indicate that the field value should not be printed out when using debug
// formats, e.g. when the field contains sensitive credentials.
- DebugRedact *bool `protobuf:"varint,16,opt,name=debug_redact,json=debugRedact,def=0" json:"debug_redact,omitempty"`
- Retention *FieldOptions_OptionRetention `protobuf:"varint,17,opt,name=retention,enum=google.protobuf.FieldOptions_OptionRetention" json:"retention,omitempty"`
- // Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
- Target *FieldOptions_OptionTargetType `protobuf:"varint,18,opt,name=target,enum=google.protobuf.FieldOptions_OptionTargetType" json:"target,omitempty"`
- Targets []FieldOptions_OptionTargetType `protobuf:"varint,19,rep,name=targets,enum=google.protobuf.FieldOptions_OptionTargetType" json:"targets,omitempty"`
+ DebugRedact *bool `protobuf:"varint,16,opt,name=debug_redact,json=debugRedact,def=0" json:"debug_redact,omitempty"`
+ Retention *FieldOptions_OptionRetention `protobuf:"varint,17,opt,name=retention,enum=google.protobuf.FieldOptions_OptionRetention" json:"retention,omitempty"`
+ Targets []FieldOptions_OptionTargetType `protobuf:"varint,19,rep,name=targets,enum=google.protobuf.FieldOptions_OptionTargetType" json:"targets,omitempty"`
+ EditionDefaults []*FieldOptions_EditionDefault `protobuf:"bytes,20,rep,name=edition_defaults,json=editionDefaults" json:"edition_defaults,omitempty"`
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,21,opt,name=features" json:"features,omitempty"`
+ FeatureSupport *FieldOptions_FeatureSupport `protobuf:"bytes,22,opt,name=feature_support,json=featureSupport" json:"feature_support,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"`
}
@@ -2320,17 +2800,30 @@ func (x *FieldOptions) GetRetention() FieldOptions_OptionRetention {
return FieldOptions_RETENTION_UNKNOWN
}
-// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
-func (x *FieldOptions) GetTarget() FieldOptions_OptionTargetType {
- if x != nil && x.Target != nil {
- return *x.Target
+func (x *FieldOptions) GetTargets() []FieldOptions_OptionTargetType {
+ if x != nil {
+ return x.Targets
}
- return FieldOptions_TARGET_TYPE_UNKNOWN
+ return nil
}
-func (x *FieldOptions) GetTargets() []FieldOptions_OptionTargetType {
+func (x *FieldOptions) GetEditionDefaults() []*FieldOptions_EditionDefault {
if x != nil {
- return x.Targets
+ return x.EditionDefaults
+ }
+ return nil
+}
+
+func (x *FieldOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
+func (x *FieldOptions) GetFeatureSupport() *FieldOptions_FeatureSupport {
+ if x != nil {
+ return x.FeatureSupport
}
return nil
}
@@ -2348,6 +2841,8 @@ type OneofOptions struct {
unknownFields protoimpl.UnknownFields
extensionFields protoimpl.ExtensionFields
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,1,opt,name=features" json:"features,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"`
}
@@ -2384,6 +2879,13 @@ func (*OneofOptions) Descriptor() ([]byte, []int) {
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{13}
}
+func (x *OneofOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
func (x *OneofOptions) GetUninterpretedOption() []*UninterpretedOption {
if x != nil {
return x.UninterpretedOption
@@ -2409,11 +2911,13 @@ type EnumOptions struct {
// and strips underscored from the fields before comparison in proto3 only.
// The new behavior takes `json_name` into account and applies to proto2 as
// well.
- // TODO(b/261750190) Remove this legacy behavior once downstream teams have
+ // TODO Remove this legacy behavior once downstream teams have
// had time to migrate.
//
// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
DeprecatedLegacyJsonFieldConflicts *bool `protobuf:"varint,6,opt,name=deprecated_legacy_json_field_conflicts,json=deprecatedLegacyJsonFieldConflicts" json:"deprecated_legacy_json_field_conflicts,omitempty"`
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,7,opt,name=features" json:"features,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"`
}
@@ -2477,6 +2981,13 @@ func (x *EnumOptions) GetDeprecatedLegacyJsonFieldConflicts() bool {
return false
}
+func (x *EnumOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
func (x *EnumOptions) GetUninterpretedOption() []*UninterpretedOption {
if x != nil {
return x.UninterpretedOption
@@ -2495,13 +3006,22 @@ type EnumValueOptions struct {
// 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"`
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,2,opt,name=features" json:"features,omitempty"`
+ // Indicate that fields annotated with this enum value should not be printed
+ // out when using debug formats, e.g. when the field contains sensitive
+ // credentials.
+ DebugRedact *bool `protobuf:"varint,3,opt,name=debug_redact,json=debugRedact,def=0" json:"debug_redact,omitempty"`
+ // Information about the support window of a feature value.
+ FeatureSupport *FieldOptions_FeatureSupport `protobuf:"bytes,4,opt,name=feature_support,json=featureSupport" json:"feature_support,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"`
}
// Default values for EnumValueOptions fields.
const (
- Default_EnumValueOptions_Deprecated = bool(false)
+ Default_EnumValueOptions_Deprecated = bool(false)
+ Default_EnumValueOptions_DebugRedact = bool(false)
)
func (x *EnumValueOptions) Reset() {
@@ -2543,6 +3063,27 @@ func (x *EnumValueOptions) GetDeprecated() bool {
return Default_EnumValueOptions_Deprecated
}
+func (x *EnumValueOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
+func (x *EnumValueOptions) GetDebugRedact() bool {
+ if x != nil && x.DebugRedact != nil {
+ return *x.DebugRedact
+ }
+ return Default_EnumValueOptions_DebugRedact
+}
+
+func (x *EnumValueOptions) GetFeatureSupport() *FieldOptions_FeatureSupport {
+ if x != nil {
+ return x.FeatureSupport
+ }
+ return nil
+}
+
func (x *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption {
if x != nil {
return x.UninterpretedOption
@@ -2556,6 +3097,8 @@ type ServiceOptions struct {
unknownFields protoimpl.UnknownFields
extensionFields protoimpl.ExtensionFields
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,34,opt,name=features" json:"features,omitempty"`
// 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,
@@ -2602,6 +3145,13 @@ func (*ServiceOptions) Descriptor() ([]byte, []int) {
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{16}
}
+func (x *ServiceOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
func (x *ServiceOptions) GetDeprecated() bool {
if x != nil && x.Deprecated != nil {
return *x.Deprecated
@@ -2628,6 +3178,8 @@ type MethodOptions struct {
// 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"`
+ // Any features defined in the specific edition.
+ Features *FeatureSet `protobuf:"bytes,35,opt,name=features" json:"features,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"`
}
@@ -2684,6 +3236,13 @@ func (x *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel {
return Default_MethodOptions_IdempotencyLevel
}
+func (x *MethodOptions) GetFeatures() *FeatureSet {
+ if x != nil {
+ return x.Features
+ }
+ return nil
+}
+
func (x *MethodOptions) GetUninterpretedOption() []*UninterpretedOption {
if x != nil {
return x.UninterpretedOption
@@ -2794,6 +3353,171 @@ func (x *UninterpretedOption) GetAggregateValue() string {
return ""
}
+// TODO Enums in C++ gencode (and potentially other languages) are
+// not well scoped. This means that each of the feature enums below can clash
+// with each other. The short names we've chosen maximize call-site
+// readability, but leave us very open to this scenario. A future feature will
+// be designed and implemented to handle this, hopefully before we ever hit a
+// conflict here.
+type FeatureSet struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+ extensionFields protoimpl.ExtensionFields
+
+ FieldPresence *FeatureSet_FieldPresence `protobuf:"varint,1,opt,name=field_presence,json=fieldPresence,enum=google.protobuf.FeatureSet_FieldPresence" json:"field_presence,omitempty"`
+ EnumType *FeatureSet_EnumType `protobuf:"varint,2,opt,name=enum_type,json=enumType,enum=google.protobuf.FeatureSet_EnumType" json:"enum_type,omitempty"`
+ RepeatedFieldEncoding *FeatureSet_RepeatedFieldEncoding `protobuf:"varint,3,opt,name=repeated_field_encoding,json=repeatedFieldEncoding,enum=google.protobuf.FeatureSet_RepeatedFieldEncoding" json:"repeated_field_encoding,omitempty"`
+ Utf8Validation *FeatureSet_Utf8Validation `protobuf:"varint,4,opt,name=utf8_validation,json=utf8Validation,enum=google.protobuf.FeatureSet_Utf8Validation" json:"utf8_validation,omitempty"`
+ MessageEncoding *FeatureSet_MessageEncoding `protobuf:"varint,5,opt,name=message_encoding,json=messageEncoding,enum=google.protobuf.FeatureSet_MessageEncoding" json:"message_encoding,omitempty"`
+ JsonFormat *FeatureSet_JsonFormat `protobuf:"varint,6,opt,name=json_format,json=jsonFormat,enum=google.protobuf.FeatureSet_JsonFormat" json:"json_format,omitempty"`
+}
+
+func (x *FeatureSet) Reset() {
+ *x = FeatureSet{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[19]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FeatureSet) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureSet) ProtoMessage() {}
+
+func (x *FeatureSet) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[19]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureSet.ProtoReflect.Descriptor instead.
+func (*FeatureSet) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *FeatureSet) GetFieldPresence() FeatureSet_FieldPresence {
+ if x != nil && x.FieldPresence != nil {
+ return *x.FieldPresence
+ }
+ return FeatureSet_FIELD_PRESENCE_UNKNOWN
+}
+
+func (x *FeatureSet) GetEnumType() FeatureSet_EnumType {
+ if x != nil && x.EnumType != nil {
+ return *x.EnumType
+ }
+ return FeatureSet_ENUM_TYPE_UNKNOWN
+}
+
+func (x *FeatureSet) GetRepeatedFieldEncoding() FeatureSet_RepeatedFieldEncoding {
+ if x != nil && x.RepeatedFieldEncoding != nil {
+ return *x.RepeatedFieldEncoding
+ }
+ return FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN
+}
+
+func (x *FeatureSet) GetUtf8Validation() FeatureSet_Utf8Validation {
+ if x != nil && x.Utf8Validation != nil {
+ return *x.Utf8Validation
+ }
+ return FeatureSet_UTF8_VALIDATION_UNKNOWN
+}
+
+func (x *FeatureSet) GetMessageEncoding() FeatureSet_MessageEncoding {
+ if x != nil && x.MessageEncoding != nil {
+ return *x.MessageEncoding
+ }
+ return FeatureSet_MESSAGE_ENCODING_UNKNOWN
+}
+
+func (x *FeatureSet) GetJsonFormat() FeatureSet_JsonFormat {
+ if x != nil && x.JsonFormat != nil {
+ return *x.JsonFormat
+ }
+ return FeatureSet_JSON_FORMAT_UNKNOWN
+}
+
+// A compiled specification for the defaults of a set of features. These
+// messages are generated from FeatureSet extensions and can be used to seed
+// feature resolution. The resolution with this object becomes a simple search
+// for the closest matching edition, followed by proto merges.
+type FeatureSetDefaults struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Defaults []*FeatureSetDefaults_FeatureSetEditionDefault `protobuf:"bytes,1,rep,name=defaults" json:"defaults,omitempty"`
+ // The minimum supported edition (inclusive) when this was constructed.
+ // Editions before this will not have defaults.
+ MinimumEdition *Edition `protobuf:"varint,4,opt,name=minimum_edition,json=minimumEdition,enum=google.protobuf.Edition" json:"minimum_edition,omitempty"`
+ // The maximum known edition (inclusive) when this was constructed. Editions
+ // after this will not have reliable defaults.
+ MaximumEdition *Edition `protobuf:"varint,5,opt,name=maximum_edition,json=maximumEdition,enum=google.protobuf.Edition" json:"maximum_edition,omitempty"`
+}
+
+func (x *FeatureSetDefaults) Reset() {
+ *x = FeatureSetDefaults{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[20]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FeatureSetDefaults) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureSetDefaults) ProtoMessage() {}
+
+func (x *FeatureSetDefaults) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[20]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureSetDefaults.ProtoReflect.Descriptor instead.
+func (*FeatureSetDefaults) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *FeatureSetDefaults) GetDefaults() []*FeatureSetDefaults_FeatureSetEditionDefault {
+ if x != nil {
+ return x.Defaults
+ }
+ return nil
+}
+
+func (x *FeatureSetDefaults) GetMinimumEdition() Edition {
+ if x != nil && x.MinimumEdition != nil {
+ return *x.MinimumEdition
+ }
+ return Edition_EDITION_UNKNOWN
+}
+
+func (x *FeatureSetDefaults) GetMaximumEdition() Edition {
+ if x != nil && x.MaximumEdition != nil {
+ return *x.MaximumEdition
+ }
+ return Edition_EDITION_UNKNOWN
+}
+
// Encapsulates information about the original source file from which a
// FileDescriptorProto was generated.
type SourceCodeInfo struct {
@@ -2855,7 +3579,7 @@ type SourceCodeInfo struct {
func (x *SourceCodeInfo) Reset() {
*x = SourceCodeInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[19]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2868,7 +3592,7 @@ func (x *SourceCodeInfo) String() string {
func (*SourceCodeInfo) ProtoMessage() {}
func (x *SourceCodeInfo) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[19]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2881,7 +3605,7 @@ func (x *SourceCodeInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use SourceCodeInfo.ProtoReflect.Descriptor instead.
func (*SourceCodeInfo) Descriptor() ([]byte, []int) {
- return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19}
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{21}
}
func (x *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
@@ -2907,7 +3631,7 @@ type GeneratedCodeInfo struct {
func (x *GeneratedCodeInfo) Reset() {
*x = GeneratedCodeInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[20]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2920,7 +3644,7 @@ func (x *GeneratedCodeInfo) String() string {
func (*GeneratedCodeInfo) ProtoMessage() {}
func (x *GeneratedCodeInfo) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[20]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2933,7 +3657,7 @@ func (x *GeneratedCodeInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use GeneratedCodeInfo.ProtoReflect.Descriptor instead.
func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) {
- return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20}
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{22}
}
func (x *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
@@ -2956,7 +3680,7 @@ type DescriptorProto_ExtensionRange struct {
func (x *DescriptorProto_ExtensionRange) Reset() {
*x = DescriptorProto_ExtensionRange{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[21]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2969,7 +3693,7 @@ func (x *DescriptorProto_ExtensionRange) String() string {
func (*DescriptorProto_ExtensionRange) ProtoMessage() {}
func (x *DescriptorProto_ExtensionRange) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[21]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[23]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -3021,7 +3745,7 @@ type DescriptorProto_ReservedRange struct {
func (x *DescriptorProto_ReservedRange) Reset() {
*x = DescriptorProto_ReservedRange{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[22]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -3034,7 +3758,7 @@ func (x *DescriptorProto_ReservedRange) String() string {
func (*DescriptorProto_ReservedRange) ProtoMessage() {}
func (x *DescriptorProto_ReservedRange) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[22]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -3078,10 +3802,6 @@ type ExtensionRangeOptions_Declaration struct {
// Metadata.type, Declaration.type must have a leading dot for messages
// and enums.
Type *string `protobuf:"bytes,3,opt,name=type" json:"type,omitempty"`
- // Deprecated. Please use "repeated".
- //
- // Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
- IsRepeated *bool `protobuf:"varint,4,opt,name=is_repeated,json=isRepeated" json:"is_repeated,omitempty"`
// If true, indicates that the number is reserved in the extension range,
// and any extension field with the number will fail to compile. Set this
// when a declared extension field is deleted.
@@ -3094,7 +3814,7 @@ type ExtensionRangeOptions_Declaration struct {
func (x *ExtensionRangeOptions_Declaration) Reset() {
*x = ExtensionRangeOptions_Declaration{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[23]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -3107,7 +3827,7 @@ func (x *ExtensionRangeOptions_Declaration) String() string {
func (*ExtensionRangeOptions_Declaration) ProtoMessage() {}
func (x *ExtensionRangeOptions_Declaration) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[23]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[25]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -3144,14 +3864,6 @@ func (x *ExtensionRangeOptions_Declaration) GetType() string {
return ""
}
-// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
-func (x *ExtensionRangeOptions_Declaration) GetIsRepeated() bool {
- if x != nil && x.IsRepeated != nil {
- return *x.IsRepeated
- }
- return false
-}
-
func (x *ExtensionRangeOptions_Declaration) GetReserved() bool {
if x != nil && x.Reserved != nil {
return *x.Reserved
@@ -3184,7 +3896,7 @@ type EnumDescriptorProto_EnumReservedRange struct {
func (x *EnumDescriptorProto_EnumReservedRange) Reset() {
*x = EnumDescriptorProto_EnumReservedRange{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[24]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -3197,7 +3909,7 @@ func (x *EnumDescriptorProto_EnumReservedRange) String() string {
func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {}
func (x *EnumDescriptorProto_EnumReservedRange) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[24]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[26]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -3227,6 +3939,143 @@ func (x *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 {
return 0
}
+type FieldOptions_EditionDefault struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Edition *Edition `protobuf:"varint,3,opt,name=edition,enum=google.protobuf.Edition" json:"edition,omitempty"`
+ Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` // Textproto value.
+}
+
+func (x *FieldOptions_EditionDefault) Reset() {
+ *x = FieldOptions_EditionDefault{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[27]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FieldOptions_EditionDefault) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FieldOptions_EditionDefault) ProtoMessage() {}
+
+func (x *FieldOptions_EditionDefault) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[27]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FieldOptions_EditionDefault.ProtoReflect.Descriptor instead.
+func (*FieldOptions_EditionDefault) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 0}
+}
+
+func (x *FieldOptions_EditionDefault) GetEdition() Edition {
+ if x != nil && x.Edition != nil {
+ return *x.Edition
+ }
+ return Edition_EDITION_UNKNOWN
+}
+
+func (x *FieldOptions_EditionDefault) GetValue() string {
+ if x != nil && x.Value != nil {
+ return *x.Value
+ }
+ return ""
+}
+
+// Information about the support window of a feature.
+type FieldOptions_FeatureSupport struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The edition that this feature was first available in. In editions
+ // earlier than this one, the default assigned to EDITION_LEGACY will be
+ // used, and proto files will not be able to override it.
+ EditionIntroduced *Edition `protobuf:"varint,1,opt,name=edition_introduced,json=editionIntroduced,enum=google.protobuf.Edition" json:"edition_introduced,omitempty"`
+ // The edition this feature becomes deprecated in. Using this after this
+ // edition may trigger warnings.
+ EditionDeprecated *Edition `protobuf:"varint,2,opt,name=edition_deprecated,json=editionDeprecated,enum=google.protobuf.Edition" json:"edition_deprecated,omitempty"`
+ // The deprecation warning text if this feature is used after the edition it
+ // was marked deprecated in.
+ DeprecationWarning *string `protobuf:"bytes,3,opt,name=deprecation_warning,json=deprecationWarning" json:"deprecation_warning,omitempty"`
+ // The edition this feature is no longer available in. In editions after
+ // this one, the last default assigned will be used, and proto files will
+ // not be able to override it.
+ EditionRemoved *Edition `protobuf:"varint,4,opt,name=edition_removed,json=editionRemoved,enum=google.protobuf.Edition" json:"edition_removed,omitempty"`
+}
+
+func (x *FieldOptions_FeatureSupport) Reset() {
+ *x = FieldOptions_FeatureSupport{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[28]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FieldOptions_FeatureSupport) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FieldOptions_FeatureSupport) ProtoMessage() {}
+
+func (x *FieldOptions_FeatureSupport) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[28]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FieldOptions_FeatureSupport.ProtoReflect.Descriptor instead.
+func (*FieldOptions_FeatureSupport) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 1}
+}
+
+func (x *FieldOptions_FeatureSupport) GetEditionIntroduced() Edition {
+ if x != nil && x.EditionIntroduced != nil {
+ return *x.EditionIntroduced
+ }
+ return Edition_EDITION_UNKNOWN
+}
+
+func (x *FieldOptions_FeatureSupport) GetEditionDeprecated() Edition {
+ if x != nil && x.EditionDeprecated != nil {
+ return *x.EditionDeprecated
+ }
+ return Edition_EDITION_UNKNOWN
+}
+
+func (x *FieldOptions_FeatureSupport) GetDeprecationWarning() string {
+ if x != nil && x.DeprecationWarning != nil {
+ return *x.DeprecationWarning
+ }
+ return ""
+}
+
+func (x *FieldOptions_FeatureSupport) GetEditionRemoved() Edition {
+ if x != nil && x.EditionRemoved != nil {
+ return *x.EditionRemoved
+ }
+ return Edition_EDITION_UNKNOWN
+}
+
// 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).
@@ -3244,7 +4093,7 @@ type UninterpretedOption_NamePart struct {
func (x *UninterpretedOption_NamePart) Reset() {
*x = UninterpretedOption_NamePart{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[25]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -3257,7 +4106,7 @@ func (x *UninterpretedOption_NamePart) String() string {
func (*UninterpretedOption_NamePart) ProtoMessage() {}
func (x *UninterpretedOption_NamePart) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[25]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[29]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -3287,6 +4136,75 @@ func (x *UninterpretedOption_NamePart) GetIsExtension() bool {
return false
}
+// A map from every known edition with a unique set of defaults to its
+// defaults. Not all editions may be contained here. For a given edition,
+// the defaults at the closest matching edition ordered at or before it should
+// be used. This field must be in strict ascending order by edition.
+type FeatureSetDefaults_FeatureSetEditionDefault struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Edition *Edition `protobuf:"varint,3,opt,name=edition,enum=google.protobuf.Edition" json:"edition,omitempty"`
+ // Defaults of features that can be overridden in this edition.
+ OverridableFeatures *FeatureSet `protobuf:"bytes,4,opt,name=overridable_features,json=overridableFeatures" json:"overridable_features,omitempty"`
+ // Defaults of features that can't be overridden in this edition.
+ FixedFeatures *FeatureSet `protobuf:"bytes,5,opt,name=fixed_features,json=fixedFeatures" json:"fixed_features,omitempty"`
+}
+
+func (x *FeatureSetDefaults_FeatureSetEditionDefault) Reset() {
+ *x = FeatureSetDefaults_FeatureSetEditionDefault{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FeatureSetDefaults_FeatureSetEditionDefault) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FeatureSetDefaults_FeatureSetEditionDefault) ProtoMessage() {}
+
+func (x *FeatureSetDefaults_FeatureSetEditionDefault) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[30]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FeatureSetDefaults_FeatureSetEditionDefault.ProtoReflect.Descriptor instead.
+func (*FeatureSetDefaults_FeatureSetEditionDefault) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20, 0}
+}
+
+func (x *FeatureSetDefaults_FeatureSetEditionDefault) GetEdition() Edition {
+ if x != nil && x.Edition != nil {
+ return *x.Edition
+ }
+ return Edition_EDITION_UNKNOWN
+}
+
+func (x *FeatureSetDefaults_FeatureSetEditionDefault) GetOverridableFeatures() *FeatureSet {
+ if x != nil {
+ return x.OverridableFeatures
+ }
+ return nil
+}
+
+func (x *FeatureSetDefaults_FeatureSetEditionDefault) GetFixedFeatures() *FeatureSet {
+ if x != nil {
+ return x.FixedFeatures
+ }
+ return nil
+}
+
type SourceCodeInfo_Location struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -3296,7 +4214,7 @@ type SourceCodeInfo_Location struct {
// location.
//
// Each element is a field number or an index. They form a path from
- // the root FileDescriptorProto to the place where the definition occurs.
+ // the root FileDescriptorProto to the place where the definition appears.
// For example, this path:
//
// [ 4, 3, 2, 7, 1 ]
@@ -3388,7 +4306,7 @@ type SourceCodeInfo_Location struct {
func (x *SourceCodeInfo_Location) Reset() {
*x = SourceCodeInfo_Location{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[26]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -3401,7 +4319,7 @@ func (x *SourceCodeInfo_Location) String() string {
func (*SourceCodeInfo_Location) ProtoMessage() {}
func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[26]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[31]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -3414,7 +4332,7 @@ func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message {
// Deprecated: Use SourceCodeInfo_Location.ProtoReflect.Descriptor instead.
func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) {
- return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0}
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{21, 0}
}
func (x *SourceCodeInfo_Location) GetPath() []int32 {
@@ -3475,7 +4393,7 @@ type GeneratedCodeInfo_Annotation struct {
func (x *GeneratedCodeInfo_Annotation) Reset() {
*x = GeneratedCodeInfo_Annotation{}
if protoimpl.UnsafeEnabled {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[27]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -3488,7 +4406,7 @@ func (x *GeneratedCodeInfo_Annotation) String() string {
func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message {
- mi := &file_google_protobuf_descriptor_proto_msgTypes[27]
+ mi := &file_google_protobuf_descriptor_proto_msgTypes[32]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -3501,7 +4419,7 @@ func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message {
// Deprecated: Use GeneratedCodeInfo_Annotation.ProtoReflect.Descriptor instead.
func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
- return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20, 0}
+ return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{22, 0}
}
func (x *GeneratedCodeInfo_Annotation) GetPath() []int32 {
@@ -3550,7 +4468,7 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69,
- 0x6c, 0x65, 0x22, 0xfe, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72,
+ 0x6c, 0x65, 0x22, 0x98, 0x05, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18,
0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
@@ -3588,250 +4506,250 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{
0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66,
0x6f, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66,
0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x64, 0x69,
- 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74,
- 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66,
- 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65,
- 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65,
- 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f,
- 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
- 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
- 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a,
- 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50,
- 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65,
- 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54,
- 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
- 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67,
+ 0x09, 0x52, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x12, 0x32, 0x0a, 0x07, 0x65, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x06,
+ 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x12, 0x43, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18,
+ 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78,
+ 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65,
+ 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45,
- 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x65,
- 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x44, 0x0a,
- 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44,
- 0x65, 0x63, 0x6c, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x55,
- 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65,
- 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0a,
+ 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e,
+ 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a,
+ 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65,
+ 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+ 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+ 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66,
+ 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e,
+ 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
+ 0x74, 0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c, 0x12, 0x39, 0x0a,
+ 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+ 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
+ 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
+ 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
+ 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+ 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03,
+ 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x40,
+ 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65,
+ 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x1a, 0x37, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67,
+ 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0xcc, 0x04, 0x0a, 0x15, 0x45, 0x78,
+ 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
+ 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+ 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x59, 0x0a,
+ 0x0b, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61,
+ 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x6c, 0x61,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x03, 0x88, 0x01, 0x02, 0x52, 0x0b, 0x64, 0x65, 0x63,
+ 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x73, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x73, 0x12, 0x6d, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73,
+ 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
+ 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x3a, 0x0a, 0x55, 0x4e, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x42, 0x03, 0x88,
+ 0x01, 0x02, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x1a, 0x94, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x75, 0x6c, 0x6c,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c,
+ 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65,
+ 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65,
+ 0x64, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x34, 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69, 0x66,
+ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b,
+ 0x44, 0x45, 0x43, 0x4c, 0x41, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0e, 0x0a,
+ 0x0a, 0x55, 0x4e, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x01, 0x2a, 0x09, 0x08,
+ 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xc1, 0x06, 0x0a, 0x14, 0x46, 0x69, 0x65,
+ 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a,
+ 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+ 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c,
+ 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
+ 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a,
+ 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66,
+ 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12,
+ 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x5f,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0xb6,
+ 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f,
+ 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
+ 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
+ 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45,
+ 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50,
+ 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50,
+ 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54,
+ 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d, 0x0a,
+ 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b,
+ 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a,
+ 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10, 0x0a,
+ 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12,
+ 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12,
+ 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x0d,
+ 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12,
+ 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32,
+ 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45,
+ 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49,
+ 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
+ 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c,
+ 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e,
+ 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45,
+ 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45,
+ 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x02, 0x22, 0x63, 0x0a, 0x14,
+ 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50,
+ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f,
+ 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
+ 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36,
+ 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65,
0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65,
- 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65,
- 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78,
- 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05,
- 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61,
- 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x03, 0x65, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
- 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a,
- 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22,
- 0xad, 0x04, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e,
- 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
- 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13,
- 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x12, 0x59, 0x0a, 0x0b, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e,
- 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x2e, 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x03, 0x88, 0x01,
- 0x02, 0x52, 0x0b, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68,
- 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
- 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x56, 0x65, 0x72,
- 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3a, 0x0a,
- 0x55, 0x4e, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x45, 0x44, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69,
- 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xb3, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x63,
- 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62,
- 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
- 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a,
- 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
- 0x65, 0x12, 0x23, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65,
- 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x34,
- 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x45, 0x43, 0x4c, 0x41, 0x52, 0x41, 0x54, 0x49,
- 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49,
- 0x45, 0x44, 0x10, 0x01, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
- 0xc1, 0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06,
- 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75,
- 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c,
- 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70,
- 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65,
- 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65,
- 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x69,
- 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f,
- 0x66, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73, 0x6f, 0x6e, 0x4e,
- 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18,
- 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f,
- 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12,
- 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12,
- 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12,
- 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04,
- 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05,
- 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34,
- 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44,
- 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f,
- 0x4c, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49,
- 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f,
- 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53,
- 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42,
- 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55,
- 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f,
- 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
- 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50,
- 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b,
- 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a,
- 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22, 0x43,
- 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c,
- 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4c,
- 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x02, 0x12,
- 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45,
- 0x44, 0x10, 0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
- 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
- 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
- 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45, 0x6e, 0x75,
- 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
- 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a,
- 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18,
- 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
- 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72,
- 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d,
- 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20,
- 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d,
- 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65,
- 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03,
- 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x83,
- 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
- 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
- 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
- 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
- 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74,
- 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89,
- 0x02, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e,
+ 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
+ 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75, 0x6d,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50,
+ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01,
+ 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
- 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f,
- 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x07,
- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06,
+ 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d,
+ 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50,
+ 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a, 0x07,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
- 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
- 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53,
- 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01,
- 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65,
- 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x22, 0x91, 0x09, 0x0a, 0x0b, 0x46,
- 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61,
- 0x76, 0x61, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a,
- 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73,
- 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a, 0x61, 0x76,
- 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12,
- 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65,
- 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
- 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c,
- 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67,
- 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x5f, 0x61,
- 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18,
- 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45,
- 0x71, 0x75, 0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a, 0x0a, 0x16,
- 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63,
- 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
- 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x43,
- 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69,
- 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29,
- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74,
- 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44,
- 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x1d, 0x0a,
- 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13,
- 0x63, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
- 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
- 0x52, 0x11, 0x63, 0x63, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69,
- 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65,
- 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01,
- 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47,
- 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x35,
- 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
- 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c,
- 0x73, 0x65, 0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72,
- 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70, 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e,
- 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20,
- 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68, 0x70, 0x47,
+ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x68,
+ 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74,
+ 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74,
+ 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x70, 0x75,
+ 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
+ 0x30, 0x0a, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
+ 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
+ 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e,
+ 0x67, 0x12, 0x30, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65,
+ 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c,
+ 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
+ 0x69, 0x6e, 0x67, 0x22, 0xad, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x70, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50,
+ 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f,
+ 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a, 0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43,
+ 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76, 0x61,
+ 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18,
+ 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61,
+ 0x76, 0x61, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12,
+ 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
+ 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68,
+ 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76, 0x61,
+ 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x41, 0x6e,
+ 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a, 0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74,
+ 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38, 0x18,
+ 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61,
+ 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66,
+ 0x38, 0x12, 0x53, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x6f,
+ 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f,
+ 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x69, 0x6d,
+ 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63,
+ 0x6b, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50, 0x61,
+ 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x65,
+ 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01,
+ 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65, 0x6e,
+ 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x15,
+ 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c,
+ 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65,
+ 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x12,
+ 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x70, 0x79, 0x47,
0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x25,
0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01,
0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65,
@@ -3856,88 +4774,130 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{
0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73,
0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63,
0x6b, 0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x75, 0x62, 0x79,
- 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74,
+ 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x73, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
+ 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+ 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
+ 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70,
+ 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x50,
+ 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49,
+ 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e,
+ 0x54, 0x49, 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
+ 0x02, 0x4a, 0x04, 0x08, 0x2a, 0x10, 0x2b, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x52, 0x14, 0x70,
+ 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
+ 0x63, 0x65, 0x73, 0x22, 0xf4, 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61,
+ 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f,
+ 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64,
+ 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
+ 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+ 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
+ 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
+ 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70,
+ 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61,
+ 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x56, 0x0a, 0x26, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63,
+ 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f, 0x6e,
+ 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73,
+ 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72,
+ 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e,
+ 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x37,
+ 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64,
- 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09,
- 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4c,
- 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08,
- 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xbb,
- 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74,
- 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65, 0x73, 0x73, 0x61,
- 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12,
- 0x4c, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
- 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
- 0x1c, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x25, 0x0a,
- 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63,
- 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65, 0x6e, 0x74, 0x72,
- 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72,
- 0x79, 0x12, 0x56, 0x0a, 0x26, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f,
- 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x65, 0x6c,
- 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28,
- 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
- 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64,
- 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
- 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13,
- 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04,
- 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07,
- 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0x85, 0x09, 0x0a,
- 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a,
- 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67,
- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
- 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70,
- 0x65, 0x3a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65,
- 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79,
- 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04,
+ 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04,
+ 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0x9d, 0x0d, 0x0a, 0x0c, 0x46,
+ 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65,
+ 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a,
+ 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16,
+ 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
+ 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65,
+ 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53,
+ 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x12,
+ 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
+ 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x2e, 0x0a, 0x0f, 0x75, 0x6e,
+ 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x0f, 0x20,
+ 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x75, 0x6e, 0x76, 0x65,
+ 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
+ 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
+ 0x64, 0x12, 0x19, 0x0a, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x28, 0x0a, 0x0c,
+ 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x10, 0x20, 0x01,
+ 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67,
+ 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x12, 0x4b, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74,
+ 0x69, 0x6f, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c,
+ 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+ 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x13,
+ 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
+ 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x57, 0x0a,
+ 0x10, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
+ 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65,
+ 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x0f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65,
+ 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12,
+ 0x55, 0x0a, 0x0f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f,
+ 0x72, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64,
- 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09,
- 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70,
- 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a,
- 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x2e, 0x0a, 0x0f,
- 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18,
- 0x0f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x75, 0x6e,
- 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a,
- 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
- 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
- 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28,
- 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x28,
- 0x0a, 0x0c, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x10,
- 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x62,
- 0x75, 0x67, 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x12, 0x4b, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65,
- 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f,
- 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
- 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65,
- 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18,
- 0x12, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65,
- 0x74, 0x54, 0x79, 0x70, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65,
- 0x74, 0x12, 0x48, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x13, 0x20, 0x03,
- 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79,
- 0x70, 0x65, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75,
- 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
+ 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53,
+ 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53,
+ 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
+ 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
+ 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
- 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a,
+ 0x1a, 0x5a, 0x0a, 0x0e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75,
+ 0x6c, 0x74, 0x12, 0x32, 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x65,
+ 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x96, 0x02, 0x0a,
+ 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12,
+ 0x47, 0x0a, 0x12, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e,
+ 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x12, 0x65, 0x64, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11,
+ 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
+ 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12,
+ 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x61, 0x72, 0x6e, 0x69,
+ 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65,
+ 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
+ 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a,
0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f,
0x52, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50,
0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65,
@@ -3967,14 +4927,18 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{
0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x54,
0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f,
0x44, 0x10, 0x09, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04,
- 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
+ 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x12, 0x10, 0x13, 0x22, 0xac, 0x01, 0x0a, 0x0c, 0x4f,
+ 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09,
- 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98, 0x02, 0x0a, 0x0b, 0x45, 0x6e,
+ 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xd1, 0x02, 0x0a, 0x0b, 0x45, 0x6e,
0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c,
0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a,
0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
@@ -3985,130 +4949,284 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{
0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28,
0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65,
0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64,
- 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
- 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13,
- 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04,
- 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70,
- 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
- 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64,
- 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
- 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
- 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
- 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10,
- 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
- 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
- 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
- 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
- 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
- 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24,
+ 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65,
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+ 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+ 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8,
+ 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xd8, 0x02,
+ 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
+ 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65,
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0c, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x72, 0x65, 0x64, 0x61,
+ 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+ 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x12, 0x55, 0x0a, 0x0f,
+ 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70,
+ 0x6f, 0x72, 0x74, 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70,
+ 0x6f, 0x72, 0x74, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
+ 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+ 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08,
+ 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xd5, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
+ 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+ 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75,
+ 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
+ 0x22, 0x99, 0x03, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64,
+ 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
+ 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a, 0x11, 0x69, 0x64, 0x65,
+ 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79,
+ 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e,
+ 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d,
+ 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x37, 0x0a, 0x08,
+ 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
- 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80,
- 0x80, 0x80, 0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63,
- 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73,
- 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a,
- 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76,
- 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f,
- 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74,
- 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50,
- 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10,
- 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c,
- 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
- 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
+ 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22,
+ 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65,
+ 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e,
+ 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f,
+ 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x10,
+ 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10,
+ 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03, 0x0a,
+ 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+ 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72,
+ 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74,
+ 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69,
+ 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10,
+ 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74,
+ 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65,
+ 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21,
+ 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74,
+ 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61,
+ 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a, 0x0a,
+ 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d,
+ 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61,
+ 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74,
+ 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73,
+ 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x0a, 0x0a, 0x0a, 0x46, 0x65,
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x91, 0x01, 0x0a, 0x0e, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x46,
+ 0x69, 0x65, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x3f, 0x88, 0x01,
+ 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, 0x58, 0x50, 0x4c,
+ 0x49, 0x43, 0x49, 0x54, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x49, 0x4d, 0x50, 0x4c,
+ 0x49, 0x43, 0x49, 0x54, 0x18, 0xe7, 0x07, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, 0x58, 0x50, 0x4c,
+ 0x49, 0x43, 0x49, 0x54, 0x18, 0xe8, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0d, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x6c, 0x0a, 0x09,
+ 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
- 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
- 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64,
- 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17,
- 0x0a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e,
- 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49,
- 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a,
- 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8,
- 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e,
- 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
- 0x41, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
+ 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x75,
+ 0x6d, 0x54, 0x79, 0x70, 0x65, 0x42, 0x29, 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0x98, 0x01, 0x01,
+ 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x18, 0xe6, 0x07, 0xa2, 0x01,
+ 0x09, 0x12, 0x04, 0x4f, 0x50, 0x45, 0x4e, 0x18, 0xe7, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07,
+ 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x98, 0x01, 0x0a, 0x17, 0x72,
+ 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x65, 0x6e,
+ 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74,
+ 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x42,
+ 0x2d, 0x88, 0x01, 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45,
+ 0x58, 0x50, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x50,
+ 0x41, 0x43, 0x4b, 0x45, 0x44, 0x18, 0xe7, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x15,
+ 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x6e, 0x63,
+ 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x7e, 0x0a, 0x0f, 0x75, 0x74, 0x66, 0x38, 0x5f, 0x76, 0x61,
+ 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x55, 0x74, 0x66, 0x38,
+ 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x88, 0x01, 0x01, 0x98,
+ 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x18, 0xe6,
+ 0x07, 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x18, 0xe7, 0x07, 0xb2,
+ 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0e, 0x75, 0x74, 0x66, 0x38, 0x56, 0x61, 0x6c, 0x69, 0x64,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x7e, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x26, 0x88, 0x01,
+ 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x14, 0x12, 0x0f, 0x4c, 0x45, 0x4e, 0x47,
+ 0x54, 0x48, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x45, 0x44, 0x18, 0xe6, 0x07, 0xb2, 0x01,
+ 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x63,
+ 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x82, 0x01, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66,
+ 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65,
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x6f, 0x72,
+ 0x6d, 0x61, 0x74, 0x42, 0x39, 0x88, 0x01, 0x01, 0x98, 0x01, 0x03, 0x98, 0x01, 0x06, 0x98, 0x01,
+ 0x01, 0xa2, 0x01, 0x17, 0x12, 0x12, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x42, 0x45, 0x53,
+ 0x54, 0x5f, 0x45, 0x46, 0x46, 0x4f, 0x52, 0x54, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05,
+ 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x18, 0xe7, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0a,
+ 0x6a, 0x73, 0x6f, 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x5c, 0x0a, 0x0d, 0x46, 0x69,
+ 0x65, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x46,
+ 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x43, 0x45, 0x5f, 0x55, 0x4e,
+ 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x58, 0x50, 0x4c, 0x49,
+ 0x43, 0x49, 0x54, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x43, 0x49,
+ 0x54, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x52, 0x45,
+ 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x03, 0x22, 0x37, 0x0a, 0x08, 0x45, 0x6e, 0x75, 0x6d,
+ 0x54, 0x79, 0x70, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50,
+ 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4f,
+ 0x50, 0x45, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x10,
+ 0x02, 0x22, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65,
+ 0x6c, 0x64, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45,
+ 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x45, 0x4e, 0x43,
+ 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12,
+ 0x0a, 0x0a, 0x06, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45,
+ 0x58, 0x50, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x02, 0x22, 0x49, 0x0a, 0x0e, 0x55, 0x74, 0x66,
+ 0x38, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x55,
+ 0x54, 0x46, 0x38, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55,
+ 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45, 0x52, 0x49,
+ 0x46, 0x59, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x03, 0x22, 0x04,
+ 0x08, 0x01, 0x10, 0x01, 0x22, 0x53, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45,
+ 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x53, 0x53, 0x41,
+ 0x47, 0x45, 0x5f, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e,
+ 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x45, 0x4e, 0x47, 0x54, 0x48, 0x5f,
+ 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x45,
+ 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x48, 0x0a, 0x0a, 0x4a, 0x73, 0x6f,
+ 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x13, 0x4a, 0x53, 0x4f, 0x4e, 0x5f,
+ 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
+ 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4c,
+ 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x42, 0x45, 0x53, 0x54, 0x5f, 0x45, 0x46, 0x46, 0x4f, 0x52,
+ 0x54, 0x10, 0x02, 0x2a, 0x06, 0x08, 0xe8, 0x07, 0x10, 0x8b, 0x4e, 0x2a, 0x06, 0x08, 0x8b, 0x4e,
+ 0x10, 0x90, 0x4e, 0x2a, 0x06, 0x08, 0x90, 0x4e, 0x10, 0x91, 0x4e, 0x4a, 0x06, 0x08, 0xe7, 0x07,
+ 0x10, 0xe8, 0x07, 0x22, 0xef, 0x03, 0x0a, 0x12, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53,
+ 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x08, 0x64, 0x65,
+ 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
+ 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x45, 0x64, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x08, 0x64, 0x65, 0x66, 0x61,
+ 0x75, 0x6c, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f,
+ 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72,
- 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64,
- 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a,
- 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74,
- 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6e,
- 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76,
- 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x75,
- 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52,
- 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c,
- 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
- 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67,
- 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65,
- 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72,
- 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72,
- 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
- 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e,
- 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43,
- 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01,
- 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61,
- 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61,
- 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05,
- 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x65,
- 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d,
- 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e,
- 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e,
- 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65,
- 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18,
- 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65,
- 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xd0,
- 0x02, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65,
- 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72,
- 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e,
- 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x1a, 0xeb, 0x01, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05,
- 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67, 0x69,
- 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
- 0x65, 0x6e, 0x64, 0x12, 0x52, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
- 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x52, 0x08, 0x73,
- 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, 0x28, 0x0a, 0x08, 0x53, 0x65, 0x6d, 0x61, 0x6e,
- 0x74, 0x69, 0x63, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x07, 0x0a,
- 0x03, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x49, 0x41, 0x53, 0x10,
- 0x02, 0x42, 0x7e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x2d, 0x67, 0x6f,
- 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02,
- 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
- 0x6e,
+ 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d,
+ 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d,
+ 0x75, 0x6d, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e,
+ 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x69,
+ 0x6d, 0x75, 0x6d, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xf8, 0x01, 0x0a, 0x18, 0x46,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x32, 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x14, 0x6f,
+ 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74,
+ 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x13, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x61,
+ 0x62, 0x6c, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x66,
+ 0x69, 0x78, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74,
+ 0x52, 0x0d, 0x66, 0x69, 0x78, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x4a,
+ 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x08, 0x66, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce,
+ 0x01, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70,
+ 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70,
+ 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c,
+ 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69,
+ 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
+ 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64,
+ 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+ 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44,
+ 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22,
+ 0xd0, 0x02, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64,
+ 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65,
+ 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e,
+ 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xeb, 0x01, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28,
+ 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05,
+ 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67,
+ 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x03, 0x65, 0x6e, 0x64, 0x12, 0x52, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x52, 0x08,
+ 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, 0x28, 0x0a, 0x08, 0x53, 0x65, 0x6d, 0x61,
+ 0x6e, 0x74, 0x69, 0x63, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x07,
+ 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x49, 0x41, 0x53,
+ 0x10, 0x02, 0x2a, 0xa7, 0x02, 0x0a, 0x07, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13,
+ 0x0a, 0x0f, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
+ 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0e, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c,
+ 0x45, 0x47, 0x41, 0x43, 0x59, 0x10, 0x84, 0x07, 0x12, 0x13, 0x0a, 0x0e, 0x45, 0x44, 0x49, 0x54,
+ 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x32, 0x10, 0xe6, 0x07, 0x12, 0x13, 0x0a,
+ 0x0e, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x33, 0x10,
+ 0xe7, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x32, 0x30,
+ 0x32, 0x33, 0x10, 0xe8, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e,
+ 0x5f, 0x32, 0x30, 0x32, 0x34, 0x10, 0xe9, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x44, 0x49, 0x54,
+ 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10,
+ 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x32, 0x5f, 0x54,
+ 0x45, 0x53, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x17, 0x45, 0x44,
+ 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x37, 0x5f, 0x54, 0x45, 0x53, 0x54,
+ 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x9d, 0x8d, 0x06, 0x12, 0x1d, 0x0a, 0x17, 0x45, 0x44, 0x49,
+ 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f,
+ 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x9e, 0x8d, 0x06, 0x12, 0x1d, 0x0a, 0x17, 0x45, 0x44, 0x49, 0x54,
+ 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x39, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x4f,
+ 0x4e, 0x4c, 0x59, 0x10, 0x9f, 0x8d, 0x06, 0x12, 0x13, 0x0a, 0x0b, 0x45, 0x44, 0x49, 0x54, 0x49,
+ 0x4f, 0x4e, 0x5f, 0x4d, 0x41, 0x58, 0x10, 0xff, 0xff, 0xff, 0xff, 0x07, 0x42, 0x7e, 0x0a, 0x13,
+ 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x2d, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x47, 0x50, 0x42, 0xaa,
+ 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
}
var (
@@ -4123,103 +5241,143 @@ func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte {
return file_google_protobuf_descriptor_proto_rawDescData
}
-var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 10)
-var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 28)
-var file_google_protobuf_descriptor_proto_goTypes = []interface{}{
- (ExtensionRangeOptions_VerificationState)(0), // 0: google.protobuf.ExtensionRangeOptions.VerificationState
- (FieldDescriptorProto_Type)(0), // 1: google.protobuf.FieldDescriptorProto.Type
- (FieldDescriptorProto_Label)(0), // 2: google.protobuf.FieldDescriptorProto.Label
- (FileOptions_OptimizeMode)(0), // 3: google.protobuf.FileOptions.OptimizeMode
- (FieldOptions_CType)(0), // 4: google.protobuf.FieldOptions.CType
- (FieldOptions_JSType)(0), // 5: google.protobuf.FieldOptions.JSType
- (FieldOptions_OptionRetention)(0), // 6: google.protobuf.FieldOptions.OptionRetention
- (FieldOptions_OptionTargetType)(0), // 7: google.protobuf.FieldOptions.OptionTargetType
- (MethodOptions_IdempotencyLevel)(0), // 8: google.protobuf.MethodOptions.IdempotencyLevel
- (GeneratedCodeInfo_Annotation_Semantic)(0), // 9: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
- (*FileDescriptorSet)(nil), // 10: google.protobuf.FileDescriptorSet
- (*FileDescriptorProto)(nil), // 11: google.protobuf.FileDescriptorProto
- (*DescriptorProto)(nil), // 12: google.protobuf.DescriptorProto
- (*ExtensionRangeOptions)(nil), // 13: google.protobuf.ExtensionRangeOptions
- (*FieldDescriptorProto)(nil), // 14: google.protobuf.FieldDescriptorProto
- (*OneofDescriptorProto)(nil), // 15: google.protobuf.OneofDescriptorProto
- (*EnumDescriptorProto)(nil), // 16: google.protobuf.EnumDescriptorProto
- (*EnumValueDescriptorProto)(nil), // 17: google.protobuf.EnumValueDescriptorProto
- (*ServiceDescriptorProto)(nil), // 18: google.protobuf.ServiceDescriptorProto
- (*MethodDescriptorProto)(nil), // 19: google.protobuf.MethodDescriptorProto
- (*FileOptions)(nil), // 20: google.protobuf.FileOptions
- (*MessageOptions)(nil), // 21: google.protobuf.MessageOptions
- (*FieldOptions)(nil), // 22: google.protobuf.FieldOptions
- (*OneofOptions)(nil), // 23: google.protobuf.OneofOptions
- (*EnumOptions)(nil), // 24: google.protobuf.EnumOptions
- (*EnumValueOptions)(nil), // 25: google.protobuf.EnumValueOptions
- (*ServiceOptions)(nil), // 26: google.protobuf.ServiceOptions
- (*MethodOptions)(nil), // 27: google.protobuf.MethodOptions
- (*UninterpretedOption)(nil), // 28: google.protobuf.UninterpretedOption
- (*SourceCodeInfo)(nil), // 29: google.protobuf.SourceCodeInfo
- (*GeneratedCodeInfo)(nil), // 30: google.protobuf.GeneratedCodeInfo
- (*DescriptorProto_ExtensionRange)(nil), // 31: google.protobuf.DescriptorProto.ExtensionRange
- (*DescriptorProto_ReservedRange)(nil), // 32: google.protobuf.DescriptorProto.ReservedRange
- (*ExtensionRangeOptions_Declaration)(nil), // 33: google.protobuf.ExtensionRangeOptions.Declaration
- (*EnumDescriptorProto_EnumReservedRange)(nil), // 34: google.protobuf.EnumDescriptorProto.EnumReservedRange
- (*UninterpretedOption_NamePart)(nil), // 35: google.protobuf.UninterpretedOption.NamePart
- (*SourceCodeInfo_Location)(nil), // 36: google.protobuf.SourceCodeInfo.Location
- (*GeneratedCodeInfo_Annotation)(nil), // 37: google.protobuf.GeneratedCodeInfo.Annotation
+var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 17)
+var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
+var file_google_protobuf_descriptor_proto_goTypes = []any{
+ (Edition)(0), // 0: google.protobuf.Edition
+ (ExtensionRangeOptions_VerificationState)(0), // 1: google.protobuf.ExtensionRangeOptions.VerificationState
+ (FieldDescriptorProto_Type)(0), // 2: google.protobuf.FieldDescriptorProto.Type
+ (FieldDescriptorProto_Label)(0), // 3: google.protobuf.FieldDescriptorProto.Label
+ (FileOptions_OptimizeMode)(0), // 4: google.protobuf.FileOptions.OptimizeMode
+ (FieldOptions_CType)(0), // 5: google.protobuf.FieldOptions.CType
+ (FieldOptions_JSType)(0), // 6: google.protobuf.FieldOptions.JSType
+ (FieldOptions_OptionRetention)(0), // 7: google.protobuf.FieldOptions.OptionRetention
+ (FieldOptions_OptionTargetType)(0), // 8: google.protobuf.FieldOptions.OptionTargetType
+ (MethodOptions_IdempotencyLevel)(0), // 9: google.protobuf.MethodOptions.IdempotencyLevel
+ (FeatureSet_FieldPresence)(0), // 10: google.protobuf.FeatureSet.FieldPresence
+ (FeatureSet_EnumType)(0), // 11: google.protobuf.FeatureSet.EnumType
+ (FeatureSet_RepeatedFieldEncoding)(0), // 12: google.protobuf.FeatureSet.RepeatedFieldEncoding
+ (FeatureSet_Utf8Validation)(0), // 13: google.protobuf.FeatureSet.Utf8Validation
+ (FeatureSet_MessageEncoding)(0), // 14: google.protobuf.FeatureSet.MessageEncoding
+ (FeatureSet_JsonFormat)(0), // 15: google.protobuf.FeatureSet.JsonFormat
+ (GeneratedCodeInfo_Annotation_Semantic)(0), // 16: google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+ (*FileDescriptorSet)(nil), // 17: google.protobuf.FileDescriptorSet
+ (*FileDescriptorProto)(nil), // 18: google.protobuf.FileDescriptorProto
+ (*DescriptorProto)(nil), // 19: google.protobuf.DescriptorProto
+ (*ExtensionRangeOptions)(nil), // 20: google.protobuf.ExtensionRangeOptions
+ (*FieldDescriptorProto)(nil), // 21: google.protobuf.FieldDescriptorProto
+ (*OneofDescriptorProto)(nil), // 22: google.protobuf.OneofDescriptorProto
+ (*EnumDescriptorProto)(nil), // 23: google.protobuf.EnumDescriptorProto
+ (*EnumValueDescriptorProto)(nil), // 24: google.protobuf.EnumValueDescriptorProto
+ (*ServiceDescriptorProto)(nil), // 25: google.protobuf.ServiceDescriptorProto
+ (*MethodDescriptorProto)(nil), // 26: google.protobuf.MethodDescriptorProto
+ (*FileOptions)(nil), // 27: google.protobuf.FileOptions
+ (*MessageOptions)(nil), // 28: google.protobuf.MessageOptions
+ (*FieldOptions)(nil), // 29: google.protobuf.FieldOptions
+ (*OneofOptions)(nil), // 30: google.protobuf.OneofOptions
+ (*EnumOptions)(nil), // 31: google.protobuf.EnumOptions
+ (*EnumValueOptions)(nil), // 32: google.protobuf.EnumValueOptions
+ (*ServiceOptions)(nil), // 33: google.protobuf.ServiceOptions
+ (*MethodOptions)(nil), // 34: google.protobuf.MethodOptions
+ (*UninterpretedOption)(nil), // 35: google.protobuf.UninterpretedOption
+ (*FeatureSet)(nil), // 36: google.protobuf.FeatureSet
+ (*FeatureSetDefaults)(nil), // 37: google.protobuf.FeatureSetDefaults
+ (*SourceCodeInfo)(nil), // 38: google.protobuf.SourceCodeInfo
+ (*GeneratedCodeInfo)(nil), // 39: google.protobuf.GeneratedCodeInfo
+ (*DescriptorProto_ExtensionRange)(nil), // 40: google.protobuf.DescriptorProto.ExtensionRange
+ (*DescriptorProto_ReservedRange)(nil), // 41: google.protobuf.DescriptorProto.ReservedRange
+ (*ExtensionRangeOptions_Declaration)(nil), // 42: google.protobuf.ExtensionRangeOptions.Declaration
+ (*EnumDescriptorProto_EnumReservedRange)(nil), // 43: google.protobuf.EnumDescriptorProto.EnumReservedRange
+ (*FieldOptions_EditionDefault)(nil), // 44: google.protobuf.FieldOptions.EditionDefault
+ (*FieldOptions_FeatureSupport)(nil), // 45: google.protobuf.FieldOptions.FeatureSupport
+ (*UninterpretedOption_NamePart)(nil), // 46: google.protobuf.UninterpretedOption.NamePart
+ (*FeatureSetDefaults_FeatureSetEditionDefault)(nil), // 47: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+ (*SourceCodeInfo_Location)(nil), // 48: google.protobuf.SourceCodeInfo.Location
+ (*GeneratedCodeInfo_Annotation)(nil), // 49: google.protobuf.GeneratedCodeInfo.Annotation
}
var file_google_protobuf_descriptor_proto_depIdxs = []int32{
- 11, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
- 12, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
- 16, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
- 18, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
- 14, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
- 20, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
- 29, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
- 14, // 7: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
- 14, // 8: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
- 12, // 9: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
- 16, // 10: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
- 31, // 11: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
- 15, // 12: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
- 21, // 13: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
- 32, // 14: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
- 28, // 15: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 33, // 16: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
- 0, // 17: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
- 2, // 18: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
- 1, // 19: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
- 22, // 20: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
- 23, // 21: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
- 17, // 22: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
- 24, // 23: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
- 34, // 24: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
- 25, // 25: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
- 19, // 26: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
- 26, // 27: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
- 27, // 28: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
- 3, // 29: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
- 28, // 30: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 28, // 31: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 4, // 32: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
- 5, // 33: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
- 6, // 34: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
- 7, // 35: google.protobuf.FieldOptions.target:type_name -> google.protobuf.FieldOptions.OptionTargetType
- 7, // 36: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
- 28, // 37: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 28, // 38: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 28, // 39: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 28, // 40: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 28, // 41: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 8, // 42: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
- 28, // 43: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
- 35, // 44: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
- 36, // 45: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
- 37, // 46: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
- 13, // 47: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
- 9, // 48: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
- 49, // [49:49] is the sub-list for method output_type
- 49, // [49:49] is the sub-list for method input_type
- 49, // [49:49] is the sub-list for extension type_name
- 49, // [49:49] is the sub-list for extension extendee
- 0, // [0:49] is the sub-list for field type_name
+ 18, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto
+ 19, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto
+ 23, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+ 25, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto
+ 21, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+ 27, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions
+ 38, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo
+ 0, // 7: google.protobuf.FileDescriptorProto.edition:type_name -> google.protobuf.Edition
+ 21, // 8: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto
+ 21, // 9: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto
+ 19, // 10: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto
+ 23, // 11: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto
+ 40, // 12: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange
+ 22, // 13: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto
+ 28, // 14: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions
+ 41, // 15: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange
+ 35, // 16: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 42, // 17: google.protobuf.ExtensionRangeOptions.declaration:type_name -> google.protobuf.ExtensionRangeOptions.Declaration
+ 36, // 18: google.protobuf.ExtensionRangeOptions.features:type_name -> google.protobuf.FeatureSet
+ 1, // 19: google.protobuf.ExtensionRangeOptions.verification:type_name -> google.protobuf.ExtensionRangeOptions.VerificationState
+ 3, // 20: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label
+ 2, // 21: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type
+ 29, // 22: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions
+ 30, // 23: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions
+ 24, // 24: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto
+ 31, // 25: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions
+ 43, // 26: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange
+ 32, // 27: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions
+ 26, // 28: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto
+ 33, // 29: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions
+ 34, // 30: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions
+ 4, // 31: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode
+ 36, // 32: google.protobuf.FileOptions.features:type_name -> google.protobuf.FeatureSet
+ 35, // 33: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 36, // 34: google.protobuf.MessageOptions.features:type_name -> google.protobuf.FeatureSet
+ 35, // 35: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 5, // 36: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType
+ 6, // 37: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType
+ 7, // 38: google.protobuf.FieldOptions.retention:type_name -> google.protobuf.FieldOptions.OptionRetention
+ 8, // 39: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType
+ 44, // 40: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault
+ 36, // 41: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet
+ 45, // 42: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+ 35, // 43: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 36, // 44: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet
+ 35, // 45: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 36, // 46: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet
+ 35, // 47: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 36, // 48: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet
+ 45, // 49: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport
+ 35, // 50: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 36, // 51: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet
+ 35, // 52: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 9, // 53: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel
+ 36, // 54: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet
+ 35, // 55: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption
+ 46, // 56: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart
+ 10, // 57: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence
+ 11, // 58: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType
+ 12, // 59: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding
+ 13, // 60: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation
+ 14, // 61: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding
+ 15, // 62: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat
+ 47, // 63: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault
+ 0, // 64: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition
+ 0, // 65: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition
+ 48, // 66: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location
+ 49, // 67: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation
+ 20, // 68: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions
+ 0, // 69: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition
+ 0, // 70: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition
+ 0, // 71: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition
+ 0, // 72: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition
+ 0, // 73: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition
+ 36, // 74: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet
+ 36, // 75: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet
+ 16, // 76: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic
+ 77, // [77:77] is the sub-list for method output_type
+ 77, // [77:77] is the sub-list for method input_type
+ 77, // [77:77] is the sub-list for extension type_name
+ 77, // [77:77] is the sub-list for extension extendee
+ 0, // [0:77] is the sub-list for field type_name
}
func init() { file_google_protobuf_descriptor_proto_init() }
@@ -4228,7 +5386,7 @@ func file_google_protobuf_descriptor_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_descriptor_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*FileDescriptorSet); i {
case 0:
return &v.state
@@ -4240,7 +5398,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*FileDescriptorProto); i {
case 0:
return &v.state
@@ -4252,7 +5410,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*DescriptorProto); i {
case 0:
return &v.state
@@ -4264,7 +5422,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*ExtensionRangeOptions); i {
case 0:
return &v.state
@@ -4278,7 +5436,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*FieldDescriptorProto); i {
case 0:
return &v.state
@@ -4290,7 +5448,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*OneofDescriptorProto); i {
case 0:
return &v.state
@@ -4302,7 +5460,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*EnumDescriptorProto); i {
case 0:
return &v.state
@@ -4314,7 +5472,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*EnumValueDescriptorProto); i {
case 0:
return &v.state
@@ -4326,7 +5484,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[8].Exporter = func(v any, i int) any {
switch v := v.(*ServiceDescriptorProto); i {
case 0:
return &v.state
@@ -4338,7 +5496,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[9].Exporter = func(v any, i int) any {
switch v := v.(*MethodDescriptorProto); i {
case 0:
return &v.state
@@ -4350,7 +5508,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[10].Exporter = func(v any, i int) any {
switch v := v.(*FileOptions); i {
case 0:
return &v.state
@@ -4364,7 +5522,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[11].Exporter = func(v any, i int) any {
switch v := v.(*MessageOptions); i {
case 0:
return &v.state
@@ -4378,7 +5536,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[12].Exporter = func(v any, i int) any {
switch v := v.(*FieldOptions); i {
case 0:
return &v.state
@@ -4392,7 +5550,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[13].Exporter = func(v any, i int) any {
switch v := v.(*OneofOptions); i {
case 0:
return &v.state
@@ -4406,7 +5564,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[14].Exporter = func(v any, i int) any {
switch v := v.(*EnumOptions); i {
case 0:
return &v.state
@@ -4420,7 +5578,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[15].Exporter = func(v any, i int) any {
switch v := v.(*EnumValueOptions); i {
case 0:
return &v.state
@@ -4434,7 +5592,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[16].Exporter = func(v any, i int) any {
switch v := v.(*ServiceOptions); i {
case 0:
return &v.state
@@ -4448,7 +5606,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[17].Exporter = func(v any, i int) any {
switch v := v.(*MethodOptions); i {
case 0:
return &v.state
@@ -4462,7 +5620,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[18].Exporter = func(v any, i int) any {
switch v := v.(*UninterpretedOption); i {
case 0:
return &v.state
@@ -4474,7 +5632,33 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[19].Exporter = func(v any, i int) any {
+ switch v := v.(*FeatureSet); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ case 3:
+ return &v.extensionFields
+ default:
+ return nil
+ }
+ }
+ file_google_protobuf_descriptor_proto_msgTypes[20].Exporter = func(v any, i int) any {
+ switch v := v.(*FeatureSetDefaults); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_google_protobuf_descriptor_proto_msgTypes[21].Exporter = func(v any, i int) any {
switch v := v.(*SourceCodeInfo); i {
case 0:
return &v.state
@@ -4486,7 +5670,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[22].Exporter = func(v any, i int) any {
switch v := v.(*GeneratedCodeInfo); i {
case 0:
return &v.state
@@ -4498,7 +5682,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[23].Exporter = func(v any, i int) any {
switch v := v.(*DescriptorProto_ExtensionRange); i {
case 0:
return &v.state
@@ -4510,7 +5694,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[24].Exporter = func(v any, i int) any {
switch v := v.(*DescriptorProto_ReservedRange); i {
case 0:
return &v.state
@@ -4522,7 +5706,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[25].Exporter = func(v any, i int) any {
switch v := v.(*ExtensionRangeOptions_Declaration); i {
case 0:
return &v.state
@@ -4534,7 +5718,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[26].Exporter = func(v any, i int) any {
switch v := v.(*EnumDescriptorProto_EnumReservedRange); i {
case 0:
return &v.state
@@ -4546,7 +5730,31 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[27].Exporter = func(v any, i int) any {
+ switch v := v.(*FieldOptions_EditionDefault); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_google_protobuf_descriptor_proto_msgTypes[28].Exporter = func(v any, i int) any {
+ switch v := v.(*FieldOptions_FeatureSupport); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_google_protobuf_descriptor_proto_msgTypes[29].Exporter = func(v any, i int) any {
switch v := v.(*UninterpretedOption_NamePart); i {
case 0:
return &v.state
@@ -4558,7 +5766,19 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[30].Exporter = func(v any, i int) any {
+ switch v := v.(*FeatureSetDefaults_FeatureSetEditionDefault); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_google_protobuf_descriptor_proto_msgTypes[31].Exporter = func(v any, i int) any {
switch v := v.(*SourceCodeInfo_Location); i {
case 0:
return &v.state
@@ -4570,7 +5790,7 @@ func file_google_protobuf_descriptor_proto_init() {
return nil
}
}
- file_google_protobuf_descriptor_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_descriptor_proto_msgTypes[32].Exporter = func(v any, i int) any {
switch v := v.(*GeneratedCodeInfo_Annotation); i {
case 0:
return &v.state
@@ -4588,8 +5808,8 @@ func file_google_protobuf_descriptor_proto_init() {
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_google_protobuf_descriptor_proto_rawDesc,
- NumEnums: 10,
- NumMessages: 28,
+ NumEnums: 17,
+ NumMessages: 33,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/vendor/google.golang.org/protobuf/types/dynamicpb/dynamic.go b/vendor/google.golang.org/protobuf/types/dynamicpb/dynamic.go
index f77ef0de15..1ba1dfa5ad 100644
--- a/vendor/google.golang.org/protobuf/types/dynamicpb/dynamic.go
+++ b/vendor/google.golang.org/protobuf/types/dynamicpb/dynamic.go
@@ -49,12 +49,13 @@ type extensionType struct {
// A Message is a dynamically constructed protocol buffer message.
//
-// Message implements the proto.Message interface, and may be used with all
-// standard proto package functions such as Marshal, Unmarshal, and so forth.
+// Message implements the [google.golang.org/protobuf/proto.Message] interface,
+// and may be used with all standard proto package functions
+// such as Marshal, Unmarshal, and so forth.
//
-// Message also implements the protoreflect.Message interface. See the protoreflect
-// package documentation for that interface for how to get and set fields and
-// otherwise interact with the contents of a Message.
+// Message also implements the [protoreflect.Message] interface.
+// See the [protoreflect] package documentation for that interface for how to
+// get and set fields and otherwise interact with the contents of a Message.
//
// Reflection API functions which construct messages, such as NewField,
// return new dynamic messages of the appropriate type. Functions which take
@@ -87,7 +88,7 @@ func NewMessage(desc protoreflect.MessageDescriptor) *Message {
// ProtoMessage implements the legacy message interface.
func (m *Message) ProtoMessage() {}
-// ProtoReflect implements the protoreflect.ProtoMessage interface.
+// ProtoReflect implements the [protoreflect.ProtoMessage] interface.
func (m *Message) ProtoReflect() protoreflect.Message {
return m
}
@@ -115,25 +116,25 @@ func (m *Message) Type() protoreflect.MessageType {
}
// New returns a newly allocated empty message with the same descriptor.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) New() protoreflect.Message {
return m.Type().New()
}
// Interface returns the message.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) Interface() protoreflect.ProtoMessage {
return m
}
-// ProtoMethods is an internal detail of the protoreflect.Message interface.
+// ProtoMethods is an internal detail of the [protoreflect.Message] interface.
// Users should never call this directly.
func (m *Message) ProtoMethods() *protoiface.Methods {
return nil
}
// Range visits every populated field in undefined order.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
for num, v := range m.known {
fd := m.ext[num]
@@ -150,7 +151,7 @@ func (m *Message) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value)
}
// Has reports whether a field is populated.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) Has(fd protoreflect.FieldDescriptor) bool {
m.checkField(fd)
if fd.IsExtension() && m.ext[fd.Number()] != fd {
@@ -164,7 +165,7 @@ func (m *Message) Has(fd protoreflect.FieldDescriptor) bool {
}
// Clear clears a field.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) Clear(fd protoreflect.FieldDescriptor) {
m.checkField(fd)
num := fd.Number()
@@ -173,7 +174,7 @@ func (m *Message) Clear(fd protoreflect.FieldDescriptor) {
}
// Get returns the value of a field.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
m.checkField(fd)
num := fd.Number()
@@ -212,7 +213,7 @@ func (m *Message) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
}
// Mutable returns a mutable reference to a repeated, map, or message field.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
m.checkField(fd)
if !fd.IsMap() && !fd.IsList() && fd.Message() == nil {
@@ -241,7 +242,7 @@ func (m *Message) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
}
// Set stores a value in a field.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
m.checkField(fd)
if m.known == nil {
@@ -284,7 +285,7 @@ func (m *Message) clearOtherOneofFields(fd protoreflect.FieldDescriptor) {
}
// NewField returns a new value for assignable to the field of a given descriptor.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
m.checkField(fd)
switch {
@@ -293,7 +294,7 @@ func (m *Message) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
case fd.IsMap():
return protoreflect.ValueOfMap(&dynamicMap{
desc: fd,
- mapv: make(map[interface{}]protoreflect.Value),
+ mapv: make(map[any]protoreflect.Value),
})
case fd.IsList():
return protoreflect.ValueOfList(&dynamicList{desc: fd})
@@ -305,7 +306,7 @@ func (m *Message) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
}
// WhichOneof reports which field in a oneof is populated, returning nil if none are populated.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
for i := 0; i < od.Fields().Len(); i++ {
fd := od.Fields().Get(i)
@@ -317,13 +318,13 @@ func (m *Message) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.Field
}
// GetUnknown returns the raw unknown fields.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) GetUnknown() protoreflect.RawFields {
return m.unknown
}
// SetUnknown sets the raw unknown fields.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) SetUnknown(r protoreflect.RawFields) {
if m.known == nil {
panic(errors.New("%v: modification of read-only message", m.typ.desc.FullName()))
@@ -332,7 +333,7 @@ func (m *Message) SetUnknown(r protoreflect.RawFields) {
}
// IsValid reports whether the message is valid.
-// See protoreflect.Message for details.
+// See [protoreflect.Message] for details.
func (m *Message) IsValid() bool {
return m.known != nil
}
@@ -449,7 +450,7 @@ func (x *dynamicList) IsValid() bool {
type dynamicMap struct {
desc protoreflect.FieldDescriptor
- mapv map[interface{}]protoreflect.Value
+ mapv map[any]protoreflect.Value
}
func (x *dynamicMap) Get(k protoreflect.MapKey) protoreflect.Value { return x.mapv[k.Interface()] }
@@ -498,7 +499,7 @@ func isSet(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
return v.List().Len() > 0
case fd.ContainingOneof() != nil:
return true
- case fd.Syntax() == protoreflect.Proto3 && !fd.IsExtension():
+ case !fd.HasPresence() && !fd.IsExtension():
switch fd.Kind() {
case protoreflect.BoolKind:
return v.Bool()
@@ -633,11 +634,11 @@ func newListEntry(fd protoreflect.FieldDescriptor) protoreflect.Value {
//
// The InterfaceOf and ValueOf methods of the extension type are defined as:
//
-// func (xt extensionType) ValueOf(iv interface{}) protoreflect.Value {
+// func (xt extensionType) ValueOf(iv any) protoreflect.Value {
// return protoreflect.ValueOf(iv)
// }
//
-// func (xt extensionType) InterfaceOf(v protoreflect.Value) interface{} {
+// func (xt extensionType) InterfaceOf(v protoreflect.Value) any {
// return v.Interface()
// }
//
@@ -657,7 +658,7 @@ func (xt extensionType) New() protoreflect.Value {
case xt.desc.IsMap():
return protoreflect.ValueOfMap(&dynamicMap{
desc: xt.desc,
- mapv: make(map[interface{}]protoreflect.Value),
+ mapv: make(map[any]protoreflect.Value),
})
case xt.desc.IsList():
return protoreflect.ValueOfList(&dynamicList{desc: xt.desc})
@@ -685,18 +686,18 @@ func (xt extensionType) TypeDescriptor() protoreflect.ExtensionTypeDescriptor {
return xt.desc
}
-func (xt extensionType) ValueOf(iv interface{}) protoreflect.Value {
+func (xt extensionType) ValueOf(iv any) protoreflect.Value {
v := protoreflect.ValueOf(iv)
typecheck(xt.desc, v)
return v
}
-func (xt extensionType) InterfaceOf(v protoreflect.Value) interface{} {
+func (xt extensionType) InterfaceOf(v protoreflect.Value) any {
typecheck(xt.desc, v)
return v.Interface()
}
-func (xt extensionType) IsValidInterface(iv interface{}) bool {
+func (xt extensionType) IsValidInterface(iv any) bool {
return typeIsValid(xt.desc, protoreflect.ValueOf(iv)) == nil
}
diff --git a/vendor/google.golang.org/protobuf/types/dynamicpb/types.go b/vendor/google.golang.org/protobuf/types/dynamicpb/types.go
index 5a8010f18f..c432817bb9 100644
--- a/vendor/google.golang.org/protobuf/types/dynamicpb/types.go
+++ b/vendor/google.golang.org/protobuf/types/dynamicpb/types.go
@@ -23,13 +23,20 @@ type extField struct {
// A Types is a collection of dynamically constructed descriptors.
// Its methods are safe for concurrent use.
//
-// Types implements protoregistry.MessageTypeResolver and protoregistry.ExtensionTypeResolver.
-// A Types may be used as a proto.UnmarshalOptions.Resolver.
+// Types implements [protoregistry.MessageTypeResolver] and [protoregistry.ExtensionTypeResolver].
+// A Types may be used as a [google.golang.org/protobuf/proto.UnmarshalOptions.Resolver].
type Types struct {
+ // atomicExtFiles is used with sync/atomic and hence must be the first word
+ // of the struct to guarantee 64-bit alignment.
+ //
+ // TODO(stapelberg): once we only support Go 1.19 and newer, switch this
+ // field to be of type atomic.Uint64 to guarantee alignment on
+ // stack-allocated values, too.
+ atomicExtFiles uint64
+ extMu sync.Mutex
+
files *protoregistry.Files
- extMu sync.Mutex
- atomicExtFiles uint64
extensionsByMessage map[extField]protoreflect.ExtensionDescriptor
}
@@ -45,7 +52,7 @@ func NewTypes(f *protoregistry.Files) *Types {
// FindEnumByName looks up an enum by its full name;
// e.g., "google.protobuf.Field.Kind".
//
-// This returns (nil, protoregistry.NotFound) if not found.
+// This returns (nil, [protoregistry.NotFound]) if not found.
func (t *Types) FindEnumByName(name protoreflect.FullName) (protoreflect.EnumType, error) {
d, err := t.files.FindDescriptorByName(name)
if err != nil {
@@ -63,7 +70,7 @@ func (t *Types) FindEnumByName(name protoreflect.FullName) (protoreflect.EnumTyp
// where the extension is declared and is unrelated to the full name of the
// message being extended.
//
-// This returns (nil, protoregistry.NotFound) if not found.
+// This returns (nil, [protoregistry.NotFound]) if not found.
func (t *Types) FindExtensionByName(name protoreflect.FullName) (protoreflect.ExtensionType, error) {
d, err := t.files.FindDescriptorByName(name)
if err != nil {
@@ -79,7 +86,7 @@ func (t *Types) FindExtensionByName(name protoreflect.FullName) (protoreflect.Ex
// FindExtensionByNumber looks up an extension field by the field number
// within some parent message, identified by full name.
//
-// This returns (nil, protoregistry.NotFound) if not found.
+// This returns (nil, [protoregistry.NotFound]) if not found.
func (t *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
// Construct the extension number map lazily, since not every user will need it.
// Update the map if new files are added to the registry.
@@ -96,7 +103,7 @@ func (t *Types) FindExtensionByNumber(message protoreflect.FullName, field proto
// FindMessageByName looks up a message by its full name;
// e.g. "google.protobuf.Any".
//
-// This returns (nil, protoregistry.NotFound) if not found.
+// This returns (nil, [protoregistry.NotFound]) if not found.
func (t *Types) FindMessageByName(name protoreflect.FullName) (protoreflect.MessageType, error) {
d, err := t.files.FindDescriptorByName(name)
if err != nil {
@@ -112,7 +119,7 @@ func (t *Types) FindMessageByName(name protoreflect.FullName) (protoreflect.Mess
// FindMessageByURL looks up a message by a URL identifier.
// See documentation on google.protobuf.Any.type_url for the URL format.
//
-// This returns (nil, protoregistry.NotFound) if not found.
+// This returns (nil, [protoregistry.NotFound]) if not found.
func (t *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
// This function is similar to FindMessageByName but
// truncates anything before and including '/' in the URL.
diff --git a/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go b/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go
new file mode 100644
index 0000000000..a2ca940c50
--- /dev/null
+++ b/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go
@@ -0,0 +1,181 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/go_features.proto
+
+package gofeaturespb
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ descriptorpb "google.golang.org/protobuf/types/descriptorpb"
+ reflect "reflect"
+ sync "sync"
+)
+
+type GoFeatures struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Whether or not to generate the deprecated UnmarshalJSON method for enums.
+ LegacyUnmarshalJsonEnum *bool `protobuf:"varint,1,opt,name=legacy_unmarshal_json_enum,json=legacyUnmarshalJsonEnum" json:"legacy_unmarshal_json_enum,omitempty"`
+}
+
+func (x *GoFeatures) Reset() {
+ *x = GoFeatures{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_google_protobuf_go_features_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GoFeatures) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GoFeatures) ProtoMessage() {}
+
+func (x *GoFeatures) ProtoReflect() protoreflect.Message {
+ mi := &file_google_protobuf_go_features_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GoFeatures.ProtoReflect.Descriptor instead.
+func (*GoFeatures) Descriptor() ([]byte, []int) {
+ return file_google_protobuf_go_features_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *GoFeatures) GetLegacyUnmarshalJsonEnum() bool {
+ if x != nil && x.LegacyUnmarshalJsonEnum != nil {
+ return *x.LegacyUnmarshalJsonEnum
+ }
+ return false
+}
+
+var file_google_protobuf_go_features_proto_extTypes = []protoimpl.ExtensionInfo{
+ {
+ ExtendedType: (*descriptorpb.FeatureSet)(nil),
+ ExtensionType: (*GoFeatures)(nil),
+ Field: 1002,
+ Name: "pb.go",
+ Tag: "bytes,1002,opt,name=go",
+ Filename: "google/protobuf/go_features.proto",
+ },
+}
+
+// Extension fields to descriptorpb.FeatureSet.
+var (
+ // optional pb.GoFeatures go = 1002;
+ E_Go = &file_google_protobuf_go_features_proto_extTypes[0]
+)
+
+var File_google_protobuf_go_features_proto protoreflect.FileDescriptor
+
+var file_google_protobuf_go_features_proto_rawDesc = []byte{
+ 0x0a, 0x21, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2f, 0x67, 0x6f, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcd, 0x01, 0x0a, 0x0a, 0x47, 0x6f,
+ 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0xbe, 0x01, 0x0a, 0x1a, 0x6c, 0x65, 0x67,
+ 0x61, 0x63, 0x79, 0x5f, 0x75, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x5f, 0x6a, 0x73,
+ 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x80, 0x01,
+ 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x74, 0x72,
+ 0x75, 0x65, 0x18, 0x84, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x18,
+ 0xe7, 0x07, 0xb2, 0x01, 0x5b, 0x08, 0xe8, 0x07, 0x10, 0xe8, 0x07, 0x1a, 0x53, 0x54, 0x68, 0x65,
+ 0x20, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61,
+ 0x6c, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x41, 0x50, 0x49, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x70,
+ 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61,
+ 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x52, 0x17, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61,
+ 0x6c, 0x4a, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x3c, 0x0a, 0x02, 0x67, 0x6f, 0x12,
+ 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x18, 0xea, 0x07, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x73, 0x52, 0x02, 0x67, 0x6f, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x67, 0x6f, 0x66, 0x65,
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x70, 0x62,
+}
+
+var (
+ file_google_protobuf_go_features_proto_rawDescOnce sync.Once
+ file_google_protobuf_go_features_proto_rawDescData = file_google_protobuf_go_features_proto_rawDesc
+)
+
+func file_google_protobuf_go_features_proto_rawDescGZIP() []byte {
+ file_google_protobuf_go_features_proto_rawDescOnce.Do(func() {
+ file_google_protobuf_go_features_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_go_features_proto_rawDescData)
+ })
+ return file_google_protobuf_go_features_proto_rawDescData
+}
+
+var file_google_protobuf_go_features_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_google_protobuf_go_features_proto_goTypes = []any{
+ (*GoFeatures)(nil), // 0: pb.GoFeatures
+ (*descriptorpb.FeatureSet)(nil), // 1: google.protobuf.FeatureSet
+}
+var file_google_protobuf_go_features_proto_depIdxs = []int32{
+ 1, // 0: pb.go:extendee -> google.protobuf.FeatureSet
+ 0, // 1: pb.go:type_name -> pb.GoFeatures
+ 2, // [2:2] is the sub-list for method output_type
+ 2, // [2:2] is the sub-list for method input_type
+ 1, // [1:2] is the sub-list for extension type_name
+ 0, // [0:1] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_google_protobuf_go_features_proto_init() }
+func file_google_protobuf_go_features_proto_init() {
+ if File_google_protobuf_go_features_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_google_protobuf_go_features_proto_msgTypes[0].Exporter = func(v any, i int) any {
+ switch v := v.(*GoFeatures); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_google_protobuf_go_features_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 1,
+ NumServices: 0,
+ },
+ GoTypes: file_google_protobuf_go_features_proto_goTypes,
+ DependencyIndexes: file_google_protobuf_go_features_proto_depIdxs,
+ MessageInfos: file_google_protobuf_go_features_proto_msgTypes,
+ ExtensionInfos: file_google_protobuf_go_features_proto_extTypes,
+ }.Build()
+ File_google_protobuf_go_features_proto = out.File
+ file_google_protobuf_go_features_proto_rawDesc = nil
+ file_google_protobuf_go_features_proto_goTypes = nil
+ file_google_protobuf_go_features_proto_depIdxs = nil
+}
diff --git a/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go b/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go
index 580b232f47..7172b43d38 100644
--- a/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go
+++ b/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go
@@ -237,7 +237,8 @@ type Any struct {
//
// Note: this functionality is not currently available in the official
// protobuf release, and it is not used for type URLs beginning with
- // type.googleapis.com.
+ // type.googleapis.com. As of May 2023, there are no widely used type server
+ // implementations and no plans to implement one.
//
// Schemes other than `http`, `https` (or the empty scheme) might be
// used with implementation specific semantics.
@@ -444,7 +445,7 @@ func file_google_protobuf_any_proto_rawDescGZIP() []byte {
}
var file_google_protobuf_any_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_google_protobuf_any_proto_goTypes = []interface{}{
+var file_google_protobuf_any_proto_goTypes = []any{
(*Any)(nil), // 0: google.protobuf.Any
}
var file_google_protobuf_any_proto_depIdxs = []int32{
@@ -461,7 +462,7 @@ func file_google_protobuf_any_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_any_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_any_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Any); i {
case 0:
return &v.state
diff --git a/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go b/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go
index df709a8dd4..1b71bcd910 100644
--- a/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go
+++ b/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go
@@ -323,7 +323,7 @@ func file_google_protobuf_duration_proto_rawDescGZIP() []byte {
}
var file_google_protobuf_duration_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_google_protobuf_duration_proto_goTypes = []interface{}{
+var file_google_protobuf_duration_proto_goTypes = []any{
(*Duration)(nil), // 0: google.protobuf.Duration
}
var file_google_protobuf_duration_proto_depIdxs = []int32{
@@ -340,7 +340,7 @@ func file_google_protobuf_duration_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_duration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_duration_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Duration); i {
case 0:
return &v.state
diff --git a/vendor/google.golang.org/protobuf/types/known/emptypb/empty.pb.go b/vendor/google.golang.org/protobuf/types/known/emptypb/empty.pb.go
index 9a7277ba39..d87b4fb828 100644
--- a/vendor/google.golang.org/protobuf/types/known/emptypb/empty.pb.go
+++ b/vendor/google.golang.org/protobuf/types/known/emptypb/empty.pb.go
@@ -115,7 +115,7 @@ func file_google_protobuf_empty_proto_rawDescGZIP() []byte {
}
var file_google_protobuf_empty_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_google_protobuf_empty_proto_goTypes = []interface{}{
+var file_google_protobuf_empty_proto_goTypes = []any{
(*Empty)(nil), // 0: google.protobuf.Empty
}
var file_google_protobuf_empty_proto_depIdxs = []int32{
@@ -132,7 +132,7 @@ func file_google_protobuf_empty_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_empty_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_empty_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Empty); i {
case 0:
return &v.state
diff --git a/vendor/google.golang.org/protobuf/types/known/fieldmaskpb/field_mask.pb.go b/vendor/google.golang.org/protobuf/types/known/fieldmaskpb/field_mask.pb.go
index e8789cb331..ac1e91bb6d 100644
--- a/vendor/google.golang.org/protobuf/types/known/fieldmaskpb/field_mask.pb.go
+++ b/vendor/google.golang.org/protobuf/types/known/fieldmaskpb/field_mask.pb.go
@@ -537,7 +537,7 @@ func file_google_protobuf_field_mask_proto_rawDescGZIP() []byte {
}
var file_google_protobuf_field_mask_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_google_protobuf_field_mask_proto_goTypes = []interface{}{
+var file_google_protobuf_field_mask_proto_goTypes = []any{
(*FieldMask)(nil), // 0: google.protobuf.FieldMask
}
var file_google_protobuf_field_mask_proto_depIdxs = []int32{
@@ -554,7 +554,7 @@ func file_google_protobuf_field_mask_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_field_mask_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_field_mask_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*FieldMask); i {
case 0:
return &v.state
diff --git a/vendor/google.golang.org/protobuf/types/known/structpb/struct.pb.go b/vendor/google.golang.org/protobuf/types/known/structpb/struct.pb.go
index d2bac8b88e..d45361cbc7 100644
--- a/vendor/google.golang.org/protobuf/types/known/structpb/struct.pb.go
+++ b/vendor/google.golang.org/protobuf/types/known/structpb/struct.pb.go
@@ -49,11 +49,11 @@
// The standard Go "encoding/json" package has functionality to serialize
// arbitrary types to a large degree. The Value.AsInterface, Struct.AsMap, and
// ListValue.AsSlice methods can convert the protobuf message representation into
-// a form represented by interface{}, map[string]interface{}, and []interface{}.
+// a form represented by any, map[string]any, and []any.
// This form can be used with other packages that operate on such data structures
// and also directly with the standard json package.
//
-// In order to convert the interface{}, map[string]interface{}, and []interface{}
+// In order to convert the any, map[string]any, and []any
// forms back as Value, Struct, and ListValue messages, use the NewStruct,
// NewList, and NewValue constructor functions.
//
@@ -88,28 +88,28 @@
//
// To construct a Value message representing the above JSON object:
//
-// m, err := structpb.NewValue(map[string]interface{}{
+// m, err := structpb.NewValue(map[string]any{
// "firstName": "John",
// "lastName": "Smith",
// "isAlive": true,
// "age": 27,
-// "address": map[string]interface{}{
+// "address": map[string]any{
// "streetAddress": "21 2nd Street",
// "city": "New York",
// "state": "NY",
// "postalCode": "10021-3100",
// },
-// "phoneNumbers": []interface{}{
-// map[string]interface{}{
+// "phoneNumbers": []any{
+// map[string]any{
// "type": "home",
// "number": "212 555-1234",
// },
-// map[string]interface{}{
+// map[string]any{
// "type": "office",
// "number": "646 555-4567",
// },
// },
-// "children": []interface{}{},
+// "children": []any{},
// "spouse": nil,
// })
// if err != nil {
@@ -197,7 +197,7 @@ type Struct struct {
// NewStruct constructs a Struct from a general-purpose Go map.
// The map keys must be valid UTF-8.
// The map values are converted using NewValue.
-func NewStruct(v map[string]interface{}) (*Struct, error) {
+func NewStruct(v map[string]any) (*Struct, error) {
x := &Struct{Fields: make(map[string]*Value, len(v))}
for k, v := range v {
if !utf8.ValidString(k) {
@@ -214,9 +214,9 @@ func NewStruct(v map[string]interface{}) (*Struct, error) {
// AsMap converts x to a general-purpose Go map.
// The map values are converted by calling Value.AsInterface.
-func (x *Struct) AsMap() map[string]interface{} {
+func (x *Struct) AsMap() map[string]any {
f := x.GetFields()
- vs := make(map[string]interface{}, len(f))
+ vs := make(map[string]any, len(f))
for k, v := range f {
vs[k] = v.AsInterface()
}
@@ -306,13 +306,13 @@ type Value struct {
// ║ float32, float64 │ stored as NumberValue ║
// ║ string │ stored as StringValue; must be valid UTF-8 ║
// ║ []byte │ stored as StringValue; base64-encoded ║
-// ║ map[string]interface{} │ stored as StructValue ║
-// ║ []interface{} │ stored as ListValue ║
+// ║ map[string]any │ stored as StructValue ║
+// ║ []any │ stored as ListValue ║
// ╚════════════════════════╧════════════════════════════════════════════╝
//
// When converting an int64 or uint64 to a NumberValue, numeric precision loss
// is possible since they are stored as a float64.
-func NewValue(v interface{}) (*Value, error) {
+func NewValue(v any) (*Value, error) {
switch v := v.(type) {
case nil:
return NewNullValue(), nil
@@ -342,13 +342,13 @@ func NewValue(v interface{}) (*Value, error) {
case []byte:
s := base64.StdEncoding.EncodeToString(v)
return NewStringValue(s), nil
- case map[string]interface{}:
+ case map[string]any:
v2, err := NewStruct(v)
if err != nil {
return nil, err
}
return NewStructValue(v2), nil
- case []interface{}:
+ case []any:
v2, err := NewList(v)
if err != nil {
return nil, err
@@ -396,7 +396,7 @@ func NewListValue(v *ListValue) *Value {
//
// Floating-point values (i.e., "NaN", "Infinity", and "-Infinity") are
// converted as strings to remain compatible with MarshalJSON.
-func (x *Value) AsInterface() interface{} {
+func (x *Value) AsInterface() any {
switch v := x.GetKind().(type) {
case *Value_NumberValue:
if v != nil {
@@ -580,7 +580,7 @@ type ListValue struct {
// NewList constructs a ListValue from a general-purpose Go slice.
// The slice elements are converted using NewValue.
-func NewList(v []interface{}) (*ListValue, error) {
+func NewList(v []any) (*ListValue, error) {
x := &ListValue{Values: make([]*Value, len(v))}
for i, v := range v {
var err error
@@ -594,9 +594,9 @@ func NewList(v []interface{}) (*ListValue, error) {
// AsSlice converts x to a general-purpose Go slice.
// The slice elements are converted by calling Value.AsInterface.
-func (x *ListValue) AsSlice() []interface{} {
+func (x *ListValue) AsSlice() []any {
vals := x.GetValues()
- vs := make([]interface{}, len(vals))
+ vs := make([]any, len(vals))
for i, v := range vals {
vs[i] = v.AsInterface()
}
@@ -716,7 +716,7 @@ func file_google_protobuf_struct_proto_rawDescGZIP() []byte {
var file_google_protobuf_struct_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_google_protobuf_struct_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
-var file_google_protobuf_struct_proto_goTypes = []interface{}{
+var file_google_protobuf_struct_proto_goTypes = []any{
(NullValue)(0), // 0: google.protobuf.NullValue
(*Struct)(nil), // 1: google.protobuf.Struct
(*Value)(nil), // 2: google.protobuf.Value
@@ -743,7 +743,7 @@ func file_google_protobuf_struct_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_struct_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_struct_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Struct); i {
case 0:
return &v.state
@@ -755,7 +755,7 @@ func file_google_protobuf_struct_proto_init() {
return nil
}
}
- file_google_protobuf_struct_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_struct_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*Value); i {
case 0:
return &v.state
@@ -767,7 +767,7 @@ func file_google_protobuf_struct_proto_init() {
return nil
}
}
- file_google_protobuf_struct_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_struct_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*ListValue); i {
case 0:
return &v.state
@@ -780,7 +780,7 @@ func file_google_protobuf_struct_proto_init() {
}
}
}
- file_google_protobuf_struct_proto_msgTypes[1].OneofWrappers = []interface{}{
+ file_google_protobuf_struct_proto_msgTypes[1].OneofWrappers = []any{
(*Value_NullValue)(nil),
(*Value_NumberValue)(nil),
(*Value_StringValue)(nil),
diff --git a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go
index 81511a3363..83a5a645b0 100644
--- a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go
+++ b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go
@@ -332,7 +332,7 @@ func file_google_protobuf_timestamp_proto_rawDescGZIP() []byte {
}
var file_google_protobuf_timestamp_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_google_protobuf_timestamp_proto_goTypes = []interface{}{
+var file_google_protobuf_timestamp_proto_goTypes = []any{
(*Timestamp)(nil), // 0: google.protobuf.Timestamp
}
var file_google_protobuf_timestamp_proto_depIdxs = []int32{
@@ -349,7 +349,7 @@ func file_google_protobuf_timestamp_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_timestamp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_timestamp_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Timestamp); i {
case 0:
return &v.state
diff --git a/vendor/google.golang.org/protobuf/types/known/wrapperspb/wrappers.pb.go b/vendor/google.golang.org/protobuf/types/known/wrapperspb/wrappers.pb.go
index 762a87130f..e473f826aa 100644
--- a/vendor/google.golang.org/protobuf/types/known/wrapperspb/wrappers.pb.go
+++ b/vendor/google.golang.org/protobuf/types/known/wrapperspb/wrappers.pb.go
@@ -605,7 +605,7 @@ func file_google_protobuf_wrappers_proto_rawDescGZIP() []byte {
}
var file_google_protobuf_wrappers_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
-var file_google_protobuf_wrappers_proto_goTypes = []interface{}{
+var file_google_protobuf_wrappers_proto_goTypes = []any{
(*DoubleValue)(nil), // 0: google.protobuf.DoubleValue
(*FloatValue)(nil), // 1: google.protobuf.FloatValue
(*Int64Value)(nil), // 2: google.protobuf.Int64Value
@@ -630,7 +630,7 @@ func file_google_protobuf_wrappers_proto_init() {
return
}
if !protoimpl.UnsafeEnabled {
- file_google_protobuf_wrappers_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*DoubleValue); i {
case 0:
return &v.state
@@ -642,7 +642,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*FloatValue); i {
case 0:
return &v.state
@@ -654,7 +654,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*Int64Value); i {
case 0:
return &v.state
@@ -666,7 +666,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*UInt64Value); i {
case 0:
return &v.state
@@ -678,7 +678,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*Int32Value); i {
case 0:
return &v.state
@@ -690,7 +690,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*UInt32Value); i {
case 0:
return &v.state
@@ -702,7 +702,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*BoolValue); i {
case 0:
return &v.state
@@ -714,7 +714,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*StringValue); i {
case 0:
return &v.state
@@ -726,7 +726,7 @@ func file_google_protobuf_wrappers_proto_init() {
return nil
}
}
- file_google_protobuf_wrappers_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ file_google_protobuf_wrappers_proto_msgTypes[8].Exporter = func(v any, i int) any {
switch v := v.(*BytesValue); i {
case 0:
return &v.state
diff --git a/vendor/gopkg.in/square/go-jose.v2/.gitcookies.sh.enc b/vendor/gopkg.in/go-jose/go-jose.v2/.gitcookies.sh.enc
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/.gitcookies.sh.enc
rename to vendor/gopkg.in/go-jose/go-jose.v2/.gitcookies.sh.enc
diff --git a/vendor/gopkg.in/square/go-jose.v2/.gitignore b/vendor/gopkg.in/go-jose/go-jose.v2/.gitignore
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/.gitignore
rename to vendor/gopkg.in/go-jose/go-jose.v2/.gitignore
diff --git a/vendor/gopkg.in/square/go-jose.v2/.travis.yml b/vendor/gopkg.in/go-jose/go-jose.v2/.travis.yml
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/.travis.yml
rename to vendor/gopkg.in/go-jose/go-jose.v2/.travis.yml
diff --git a/vendor/gopkg.in/go-jose/go-jose.v2/CHANGELOG.md b/vendor/gopkg.in/go-jose/go-jose.v2/CHANGELOG.md
new file mode 100644
index 0000000000..8e6e913239
--- /dev/null
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/CHANGELOG.md
@@ -0,0 +1,84 @@
+# v4.0.1
+
+## Fixed
+
+ - An attacker could send a JWE containing compressed data that used large
+ amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`.
+ Those functions now return an error if the decompressed data would exceed
+ 250kB or 10x the compressed size (whichever is larger). Thanks to
+ Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj)
+ for reporting.
+
+# v4.0.0
+
+This release makes some breaking changes in order to more thoroughly
+address the vulnerabilities discussed in [Three New Attacks Against JSON Web
+Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot
+token".
+
+## Changed
+
+ - Limit JWT encryption types (exclude password or public key types) (#78)
+ - Enforce minimum length for HMAC keys (#85)
+ - jwt: match any audience in a list, rather than requiring all audiences (#81)
+ - jwt: accept only Compact Serialization (#75)
+ - jws: Add expected algorithms for signatures (#74)
+ - Require specifying expected algorithms for ParseEncrypted,
+ ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned,
+ jwt.ParseSignedAndEncrypted (#69, #74)
+ - Usually there is a small, known set of appropriate algorithms for a program
+ to use and it's a mistake to allow unexpected algorithms. For instance the
+ "billion hash attack" relies in part on programs accepting the PBES2
+ encryption algorithm and doing the necessary work even if they weren't
+ specifically configured to allow PBES2.
+ - Revert "Strip padding off base64 strings" (#82)
+ - The specs require base64url encoding without padding.
+ - Minimum supported Go version is now 1.21
+
+## Added
+
+ - ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON.
+ - These allow parsing a specific serialization, as opposed to ParseSigned and
+ ParseEncrypted, which try to automatically detect which serialization was
+ provided. It's common to require a specific serialization for a specific
+ protocol - for instance JWT requires Compact serialization.
+
+[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
+
+# v3.0.3
+
+## Fixed
+
+ - Limit decompression output size to prevent a DoS. Backport from v4.0.1.
+
+# v3.0.2
+
+## Fixed
+
+ - DecryptMulti: handle decompression error (#19)
+
+## Changed
+
+ - jwe/CompactSerialize: improve performance (#67)
+ - Increase the default number of PBKDF2 iterations to 600k (#48)
+ - Return the proper algorithm for ECDSA keys (#45)
+
+## Added
+
+ - Add Thumbprint support for opaque signers (#38)
+
+# v3.0.1
+
+## Fixed
+
+ - Security issue: an attacker specifying a large "p2c" value can cause
+ JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
+ amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the
+ disclosure and to Tom Tervoort for originally publishing the category of attack.
+ https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
+
+# v2.6.3
+
+## Fixed
+
+ - Limit decompression output size to prevent a DoS. Backport from v4.0.1.
diff --git a/vendor/gopkg.in/square/go-jose.v2/CONTRIBUTING.md b/vendor/gopkg.in/go-jose/go-jose.v2/CONTRIBUTING.md
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/CONTRIBUTING.md
rename to vendor/gopkg.in/go-jose/go-jose.v2/CONTRIBUTING.md
diff --git a/vendor/gopkg.in/go-jose/go-jose.v2/LICENSE b/vendor/gopkg.in/go-jose/go-jose.v2/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/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/gopkg.in/go-jose/go-jose.v2/README.md b/vendor/gopkg.in/go-jose/go-jose.v2/README.md
new file mode 100644
index 0000000000..b877f412c4
--- /dev/null
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/README.md
@@ -0,0 +1,4 @@
+# go-jose v2
+
+Version 2 of this library is no longer supported. [Please use v4
+instead](https://pkg.go.dev/github.com/go-jose/go-jose/v4).
diff --git a/vendor/gopkg.in/square/go-jose.v2/asymmetric.go b/vendor/gopkg.in/go-jose/go-jose.v2/asymmetric.go
similarity index 93%
rename from vendor/gopkg.in/square/go-jose.v2/asymmetric.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/asymmetric.go
index b69aa0369c..43f9ce2fc7 100644
--- a/vendor/gopkg.in/square/go-jose.v2/asymmetric.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/asymmetric.go
@@ -29,8 +29,8 @@ import (
"math/big"
"golang.org/x/crypto/ed25519"
- josecipher "gopkg.in/square/go-jose.v2/cipher"
- "gopkg.in/square/go-jose.v2/json"
+ josecipher "gopkg.in/go-jose/go-jose.v2/cipher"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// A generic RSA-based encrypter/verifier
@@ -285,6 +285,9 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm
switch alg {
case RS256, RS384, RS512:
+ // TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
+ // random parameter is legacy and ignored, and it can be nil.
+ // https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
case PS256, PS384, PS512:
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
@@ -413,28 +416,28 @@ func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
epk, err := headers.getEPK()
if err != nil {
- return nil, errors.New("square/go-jose: invalid epk header")
+ return nil, errors.New("go-jose/go-jose: invalid epk header")
}
if epk == nil {
- return nil, errors.New("square/go-jose: missing epk header")
+ return nil, errors.New("go-jose/go-jose: missing epk header")
}
publicKey, ok := epk.Key.(*ecdsa.PublicKey)
if publicKey == nil || !ok {
- return nil, errors.New("square/go-jose: invalid epk header")
+ return nil, errors.New("go-jose/go-jose: invalid epk header")
}
if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
- return nil, errors.New("square/go-jose: invalid public key in epk header")
+ return nil, errors.New("go-jose/go-jose: invalid public key in epk header")
}
apuData, err := headers.getAPU()
if err != nil {
- return nil, errors.New("square/go-jose: invalid apu header")
+ return nil, errors.New("go-jose/go-jose: invalid apu header")
}
apvData, err := headers.getAPV()
if err != nil {
- return nil, errors.New("square/go-jose: invalid apv header")
+ return nil, errors.New("go-jose/go-jose: invalid apv header")
}
deriveKey := func(algID string, size int) []byte {
@@ -489,7 +492,7 @@ func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
}
ok := ed25519.Verify(ctx.publicKey, payload, signature)
if !ok {
- return errors.New("square/go-jose: ed25519 signature failed to verify")
+ return errors.New("go-jose/go-jose: ed25519 signature failed to verify")
}
return nil
}
@@ -513,7 +516,7 @@ func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm)
curveBits := ctx.privateKey.Curve.Params().BitSize
if expectedBitSize != curveBits {
- return Signature{}, fmt.Errorf("square/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
+ return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
}
hasher := hash.New()
@@ -571,7 +574,7 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
}
if len(signature) != 2*keySize {
- return fmt.Errorf("square/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
+ return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
}
hasher := hash.New()
@@ -585,7 +588,7 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
match := ecdsa.Verify(ctx.publicKey, hashed, r, s)
if !match {
- return errors.New("square/go-jose: ecdsa signature failed to verify")
+ return errors.New("go-jose/go-jose: ecdsa signature failed to verify")
}
return nil
diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go b/vendor/gopkg.in/go-jose/go-jose.v2/cipher/cbc_hmac.go
similarity index 92%
rename from vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/cipher/cbc_hmac.go
index f6465c041f..87065a5b96 100644
--- a/vendor/gopkg.in/square/go-jose.v2/cipher/cbc_hmac.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/cipher/cbc_hmac.go
@@ -101,14 +101,14 @@ func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
// Open decrypts and authenticates the ciphertext.
func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(ciphertext) < ctx.authtagBytes {
- return nil, errors.New("square/go-jose: invalid ciphertext (too short)")
+ return nil, errors.New("go-jose/go-jose: invalid ciphertext (too short)")
}
offset := len(ciphertext) - ctx.authtagBytes
expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset])
match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:])
if match != 1 {
- return nil, errors.New("square/go-jose: invalid ciphertext (auth tag mismatch)")
+ return nil, errors.New("go-jose/go-jose: invalid ciphertext (auth tag mismatch)")
}
cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce)
@@ -117,7 +117,7 @@ func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
buffer := append([]byte{}, []byte(ciphertext[:offset])...)
if len(buffer)%ctx.blockCipher.BlockSize() > 0 {
- return nil, errors.New("square/go-jose: invalid ciphertext (invalid length)")
+ return nil, errors.New("go-jose/go-jose: invalid ciphertext (invalid length)")
}
cbc.CryptBlocks(buffer, buffer)
@@ -177,19 +177,19 @@ func padBuffer(buffer []byte, blockSize int) []byte {
// Remove padding
func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) {
if len(buffer)%blockSize != 0 {
- return nil, errors.New("square/go-jose: invalid padding")
+ return nil, errors.New("go-jose/go-jose: invalid padding")
}
last := buffer[len(buffer)-1]
count := int(last)
if count == 0 || count > blockSize || count > len(buffer) {
- return nil, errors.New("square/go-jose: invalid padding")
+ return nil, errors.New("go-jose/go-jose: invalid padding")
}
padding := bytes.Repeat([]byte{last}, count)
if !bytes.HasSuffix(buffer, padding) {
- return nil, errors.New("square/go-jose: invalid padding")
+ return nil, errors.New("go-jose/go-jose: invalid padding")
}
return buffer[:len(buffer)-count], nil
diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf.go b/vendor/gopkg.in/go-jose/go-jose.v2/cipher/concat_kdf.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/cipher/concat_kdf.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/cipher/concat_kdf.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go b/vendor/gopkg.in/go-jose/go-jose.v2/cipher/ecdh_es.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/cipher/ecdh_es.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap.go b/vendor/gopkg.in/go-jose/go-jose.v2/cipher/key_wrap.go
similarity index 91%
rename from vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/cipher/key_wrap.go
index 1d36d50151..668358f981 100644
--- a/vendor/gopkg.in/square/go-jose.v2/cipher/key_wrap.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/cipher/key_wrap.go
@@ -28,7 +28,7 @@ var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}
// KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher.
func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
if len(cek)%8 != 0 {
- return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks")
+ return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
}
n := len(cek) / 8
@@ -68,7 +68,7 @@ func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
// KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher.
func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
if len(ciphertext)%8 != 0 {
- return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks")
+ return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
}
n := (len(ciphertext) / 8) - 1
@@ -97,7 +97,7 @@ func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
}
if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 {
- return nil, errors.New("square/go-jose: failed to unwrap key")
+ return nil, errors.New("go-jose/go-jose: failed to unwrap key")
}
out := make([]byte, n*8)
diff --git a/vendor/gopkg.in/square/go-jose.v2/crypter.go b/vendor/gopkg.in/go-jose/go-jose.v2/crypter.go
similarity index 91%
rename from vendor/gopkg.in/square/go-jose.v2/crypter.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/crypter.go
index be7433e28f..0ae2e5ebaa 100644
--- a/vendor/gopkg.in/square/go-jose.v2/crypter.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/crypter.go
@@ -23,7 +23,7 @@ import (
"fmt"
"reflect"
- "gopkg.in/square/go-jose.v2/json"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// Encrypter represents an encrypter which produces an encrypted JWE object.
@@ -202,7 +202,7 @@ func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *Encrypter
return nil, ErrUnsupportedAlgorithm
}
if rcpts == nil || len(rcpts) == 0 {
- return nil, fmt.Errorf("square/go-jose: recipients is nil or empty")
+ return nil, fmt.Errorf("go-jose/go-jose: recipients is nil or empty")
}
encrypter := &genericEncrypter{
@@ -234,7 +234,7 @@ func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) {
switch recipient.Algorithm {
case DIRECT, ECDH_ES:
- return fmt.Errorf("square/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm)
+ return fmt.Errorf("go-jose/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm)
}
recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key)
@@ -326,7 +326,7 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
obj.recipients = make([]recipientInfo, len(ctx.recipients))
if len(ctx.recipients) == 0 {
- return nil, fmt.Errorf("square/go-jose: no recipients to encrypt to")
+ return nil, fmt.Errorf("go-jose/go-jose: no recipients to encrypt to")
}
cek, headers, err := ctx.keyGenerator.genKey()
@@ -406,20 +406,23 @@ func (ctx *genericEncrypter) Options() EncrypterOptions {
// Decrypt and validate the object and return the plaintext. Note that this
// function does not support multi-recipient, if you desire multi-recipient
// decryption use DecryptMulti instead.
+//
+// Automatically decompresses plaintext, but returns an error if the decompressed
+// data would be >250kB or >10x the size of the compressed data, whichever is larger.
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
headers := obj.mergedHeaders(nil)
if len(obj.recipients) > 1 {
- return nil, errors.New("square/go-jose: too many recipients in payload; expecting only one")
+ return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one")
}
critical, err := headers.getCritical()
if err != nil {
- return nil, fmt.Errorf("square/go-jose: invalid crit header")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
}
if len(critical) > 0 {
- return nil, fmt.Errorf("square/go-jose: unsupported crit header")
+ return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
}
decrypter, err := newDecrypter(decryptionKey)
@@ -429,7 +432,7 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
cipher := getContentCipher(headers.getEncryption())
if cipher == nil {
- return nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(headers.getEncryption()))
+ return nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(headers.getEncryption()))
}
generator := randomKeyGenerator{
@@ -470,16 +473,19 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
// with support for multiple recipients. It returns the index of the recipient
// for which the decryption was successful, the merged headers for that recipient,
// and the plaintext.
+//
+// Automatically decompresses plaintext, but returns an error if the decompressed
+// data would be >250kB or >3x the size of the compressed data, whichever is larger.
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
globalHeaders := obj.mergedHeaders(nil)
critical, err := globalHeaders.getCritical()
if err != nil {
- return -1, Header{}, nil, fmt.Errorf("square/go-jose: invalid crit header")
+ return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
}
if len(critical) > 0 {
- return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported crit header")
+ return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
}
decrypter, err := newDecrypter(decryptionKey)
@@ -490,7 +496,7 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
encryption := globalHeaders.getEncryption()
cipher := getContentCipher(encryption)
if cipher == nil {
- return -1, Header{}, nil, fmt.Errorf("square/go-jose: unsupported enc value '%s'", string(encryption))
+ return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(encryption))
}
generator := randomKeyGenerator{
@@ -535,7 +541,7 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
sanitized, err := headers.sanitized()
if err != nil {
- return -1, Header{}, nil, fmt.Errorf("square/go-jose: failed to sanitize header: %v", err)
+ return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to sanitize header: %v", err)
}
return index, sanitized, plaintext, err
diff --git a/vendor/gopkg.in/square/go-jose.v2/doc.go b/vendor/gopkg.in/go-jose/go-jose.v2/doc.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/doc.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/doc.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/encoding.go b/vendor/gopkg.in/go-jose/go-jose.v2/encoding.go
similarity index 85%
rename from vendor/gopkg.in/square/go-jose.v2/encoding.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/encoding.go
index 70f7385c41..636f6c8f56 100644
--- a/vendor/gopkg.in/square/go-jose.v2/encoding.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/encoding.go
@@ -21,12 +21,13 @@ import (
"compress/flate"
"encoding/base64"
"encoding/binary"
+ "fmt"
"io"
"math/big"
"strings"
"unicode"
- "gopkg.in/square/go-jose.v2/json"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// Helper function to serialize known-good objects.
@@ -41,7 +42,7 @@ func mustSerializeJSON(value interface{}) []byte {
// MarshalJSON will happily serialize it as the top-level value "null". If
// that value is then embedded in another operation, for instance by being
// base64-encoded and fed as input to a signing algorithm
- // (https://github.com/square/go-jose/issues/22), the result will be
+ // (https://github.com/go-jose/go-jose/issues/22), the result will be
// incorrect. Because this method is intended for known-good objects, and a nil
// pointer is not a known-good object, we are free to panic in this case.
// Note: It's not possible to directly check whether the data pointed at by an
@@ -85,7 +86,7 @@ func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
}
}
-// Compress with DEFLATE
+// deflate compresses the input.
func deflate(input []byte) ([]byte, error) {
output := new(bytes.Buffer)
@@ -97,15 +98,27 @@ func deflate(input []byte) ([]byte, error) {
return output.Bytes(), err
}
-// Decompress with DEFLATE
+// inflate decompresses the input.
+//
+// Errors if the decompressed data would be >250kB or >10x the size of the
+// compressed data, whichever is larger.
func inflate(input []byte) ([]byte, error) {
output := new(bytes.Buffer)
reader := flate.NewReader(bytes.NewBuffer(input))
- _, err := io.Copy(output, reader)
- if err != nil {
+ maxCompressedSize := 10 * int64(len(input))
+ if maxCompressedSize < 250000 {
+ maxCompressedSize = 250000
+ }
+
+ limit := maxCompressedSize + 1
+ n, err := io.CopyN(output, reader, limit)
+ if err != nil && err != io.EOF {
return nil, err
}
+ if n == limit {
+ return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize)
+ }
err = reader.Close()
return output.Bytes(), err
@@ -127,7 +140,7 @@ func newBuffer(data []byte) *byteBuffer {
func newFixedSizeBuffer(data []byte, length int) *byteBuffer {
if len(data) > length {
- panic("square/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)")
+ panic("go-jose/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)")
}
pad := make([]byte, length-len(data))
return newBuffer(append(pad, data...))
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/LICENSE b/vendor/gopkg.in/go-jose/go-jose.v2/json/LICENSE
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/LICENSE
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/LICENSE
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/README.md b/vendor/gopkg.in/go-jose/go-jose.v2/json/README.md
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/README.md
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/README.md
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/decode.go b/vendor/gopkg.in/go-jose/go-jose.v2/json/decode.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/decode.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/decode.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/encode.go b/vendor/gopkg.in/go-jose/go-jose.v2/json/encode.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/encode.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/encode.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/indent.go b/vendor/gopkg.in/go-jose/go-jose.v2/json/indent.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/indent.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/indent.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/scanner.go b/vendor/gopkg.in/go-jose/go-jose.v2/json/scanner.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/scanner.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/scanner.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/stream.go b/vendor/gopkg.in/go-jose/go-jose.v2/json/stream.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/stream.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/stream.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/json/tags.go b/vendor/gopkg.in/go-jose/go-jose.v2/json/tags.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/json/tags.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/json/tags.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/jwe.go b/vendor/gopkg.in/go-jose/go-jose.v2/jwe.go
similarity index 95%
rename from vendor/gopkg.in/square/go-jose.v2/jwe.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/jwe.go
index b5a6dcdf4d..a8966ab8e9 100644
--- a/vendor/gopkg.in/square/go-jose.v2/jwe.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/jwe.go
@@ -21,7 +21,7 @@ import (
"fmt"
"strings"
- "gopkg.in/square/go-jose.v2/json"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
@@ -146,7 +146,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected)
if err != nil {
- return nil, fmt.Errorf("square/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64())
+ return nil, fmt.Errorf("go-jose/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64())
}
}
@@ -156,7 +156,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
mergedHeaders := obj.mergedHeaders(nil)
obj.Header, err = mergedHeaders.sanitized()
if err != nil {
- return nil, fmt.Errorf("square/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders)
+ return nil, fmt.Errorf("go-jose/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders)
}
if len(parsed.Recipients) == 0 {
@@ -187,7 +187,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
for _, recipient := range obj.recipients {
headers := obj.mergedHeaders(&recipient)
if headers.getAlgorithm() == "" || headers.getEncryption() == "" {
- return nil, fmt.Errorf("square/go-jose: message is missing alg/enc headers")
+ return nil, fmt.Errorf("go-jose/go-jose: message is missing alg/enc headers")
}
}
@@ -203,7 +203,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
parts := strings.Split(input, ".")
if len(parts) != 5 {
- return nil, fmt.Errorf("square/go-jose: compact JWE format must have five parts")
+ return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
}
rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
diff --git a/vendor/gopkg.in/square/go-jose.v2/jwk.go b/vendor/gopkg.in/go-jose/go-jose.v2/jwk.go
similarity index 83%
rename from vendor/gopkg.in/square/go-jose.v2/jwk.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/jwk.go
index 222e260cb5..ea3d863406 100644
--- a/vendor/gopkg.in/square/go-jose.v2/jwk.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/jwk.go
@@ -36,7 +36,7 @@ import (
"golang.org/x/crypto/ed25519"
- "gopkg.in/square/go-jose.v2/json"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
@@ -110,7 +110,7 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
case []byte:
raw, err = fromSymmetricKey(key)
default:
- return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
+ return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
}
if err != nil {
@@ -129,13 +129,13 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
x5tSHA256Len := len(k.CertificateThumbprintSHA256)
if x5tSHA1Len > 0 {
if x5tSHA1Len != sha1.Size {
- return nil, fmt.Errorf("square/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
+ return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
}
raw.X5tSHA1 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA1)
}
if x5tSHA256Len > 0 {
if x5tSHA256Len != sha256.Size {
- return nil, fmt.Errorf("square/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
+ return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
}
raw.X5tSHA256 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA256)
}
@@ -149,10 +149,10 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
expectedSHA256 := sha256.Sum256(k.Certificates[0].Raw)
if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) {
- return nil, errors.New("square/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
+ return nil, errors.New("go-jose/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
}
if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) {
- return nil, errors.New("square/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
+ return nil, errors.New("go-jose/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
}
}
@@ -171,7 +171,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
certs, err := parseCertificateChain(raw.X5c)
if err != nil {
- return fmt.Errorf("square/go-jose: failed to unmarshal x5c field: %s", err)
+ return fmt.Errorf("go-jose/go-jose: failed to unmarshal x5c field: %s", err)
}
var key interface{}
@@ -211,7 +211,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
}
case "oct":
if certPub != nil {
- return errors.New("square/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
+ return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
}
key, err = raw.symmetricKey()
case "OKP":
@@ -226,10 +226,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
keyPub = key
}
} else {
- err = fmt.Errorf("square/go-jose: unknown curve %s'", raw.Crv)
+ err = fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv)
}
default:
- err = fmt.Errorf("square/go-jose: unknown json web key type '%s'", raw.Kty)
+ err = fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty)
}
if err != nil {
@@ -238,7 +238,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
if certPub != nil && keyPub != nil {
if !reflect.DeepEqual(certPub, keyPub) {
- return errors.New("square/go-jose: invalid JWK, public keys in key and x5c fields do not match")
+ return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields to not match")
}
}
@@ -250,7 +250,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1)
if err != nil {
- return errors.New("square/go-jose: invalid JWK, x5t header has invalid encoding")
+ return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding")
}
// RFC 7517, Section 4.8 is ambiguous as to whether the digest output should be byte or hex,
@@ -260,7 +260,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
if len(x5tSHA1bytes) == 2*sha1.Size {
hx, err := hex.DecodeString(string(x5tSHA1bytes))
if err != nil {
- return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t: %v", err)
+ return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t: %v", err)
}
x5tSHA1bytes = hx
@@ -270,13 +270,13 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256)
if err != nil {
- return errors.New("square/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
+ return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
}
if len(x5tSHA256bytes) == 2*sha256.Size {
hx256, err := hex.DecodeString(string(x5tSHA256bytes))
if err != nil {
- return fmt.Errorf("square/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err)
+ return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err)
}
x5tSHA256bytes = hx256
}
@@ -286,10 +286,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
x5tSHA1Len := len(k.CertificateThumbprintSHA1)
x5tSHA256Len := len(k.CertificateThumbprintSHA256)
if x5tSHA1Len > 0 && x5tSHA1Len != sha1.Size {
- return errors.New("square/go-jose: invalid JWK, x5t header is of incorrect size")
+ return errors.New("go-jose/go-jose: invalid JWK, x5t header is of incorrect size")
}
if x5tSHA256Len > 0 && x5tSHA256Len != sha256.Size {
- return errors.New("square/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
+ return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
}
// If certificate chain *and* thumbprints are set, verify correctness.
@@ -299,11 +299,11 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
sha256sum := sha256.Sum256(leaf.Raw)
if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(sha1sum[:], k.CertificateThumbprintSHA1) {
- return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t value")
+ return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t value")
}
if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(sha256sum[:], k.CertificateThumbprintSHA256) {
- return errors.New("square/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value")
+ return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value")
}
}
@@ -342,7 +342,7 @@ func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
}
if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength {
- return "", errors.New("square/go-jose: invalid elliptic key (too large)")
+ return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
}
return fmt.Sprintf(ecThumbprintTemplate, crv,
@@ -359,7 +359,7 @@ func rsaThumbprintInput(n *big.Int, e int) (string, error) {
func edThumbprintInput(ed ed25519.PublicKey) (string, error) {
crv := "Ed25519"
if len(ed) > 32 {
- return "", errors.New("square/go-jose: invalid elliptic key (too large)")
+ return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
}
return fmt.Sprintf(edThumbprintTemplate, crv,
newFixedSizeBuffer(ed, 32).base64()), nil
@@ -384,7 +384,7 @@ func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
case ed25519.PrivateKey:
input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
default:
- return nil, fmt.Errorf("square/go-jose: unknown key type '%s'", reflect.TypeOf(key))
+ return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
}
if err != nil {
@@ -463,7 +463,7 @@ func (k *JSONWebKey) Valid() bool {
func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) {
if key.N == nil || key.E == nil {
- return nil, fmt.Errorf("square/go-jose: invalid RSA key, missing n/e values")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, missing n/e values")
}
return &rsa.PublicKey{
@@ -498,29 +498,29 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
case "P-521":
curve = elliptic.P521()
default:
- return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv)
+ return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
}
if key.X == nil || key.Y == nil {
- return nil, errors.New("square/go-jose: invalid EC key, missing x/y values")
+ return nil, errors.New("go-jose/go-jose: invalid EC key, missing x/y values")
}
// The length of this octet string MUST be the full size of a coordinate for
// the curve specified in the "crv" parameter.
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
if curveSize(curve) != len(key.X.data) {
- return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for x")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for x")
}
if curveSize(curve) != len(key.Y.data) {
- return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for y")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for y")
}
x := key.X.bigInt()
y := key.Y.bigInt()
if !curve.IsOnCurve(x, y) {
- return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve")
+ return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
}
return &ecdsa.PublicKey{
@@ -532,7 +532,7 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
if pub == nil || pub.X == nil || pub.Y == nil {
- return nil, fmt.Errorf("square/go-jose: invalid EC key (nil, or X/Y missing)")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (nil, or X/Y missing)")
}
name, err := curveName(pub.Curve)
@@ -546,7 +546,7 @@ func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
yBytes := pub.Y.Bytes()
if len(xBytes) > size || len(yBytes) > size {
- return nil, fmt.Errorf("square/go-jose: invalid EC key (X/Y too large)")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (X/Y too large)")
}
key := &rawJSONWebKey{
@@ -569,7 +569,7 @@ func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
}
if len(missing) > 0 {
- return nil, fmt.Errorf("square/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
+ return nil, fmt.Errorf("go-jose/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
}
privateKey := make([]byte, ed25519.PrivateKeySize)
@@ -581,7 +581,7 @@ func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) {
if key.X == nil {
- return nil, fmt.Errorf("square/go-jose: invalid Ed key, missing x value")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid Ed key, missing x value")
}
publicKey := make([]byte, ed25519.PublicKeySize)
copy(publicKey[0:32], key.X.bytes())
@@ -605,7 +605,7 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
}
if len(missing) > 0 {
- return nil, fmt.Errorf("square/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
+ return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
}
rv := &rsa.PrivateKey{
@@ -675,34 +675,34 @@ func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) {
case "P-521":
curve = elliptic.P521()
default:
- return nil, fmt.Errorf("square/go-jose: unsupported elliptic curve '%s'", key.Crv)
+ return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
}
if key.X == nil || key.Y == nil || key.D == nil {
- return nil, fmt.Errorf("square/go-jose: invalid EC private key, missing x/y/d values")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, missing x/y/d values")
}
// The length of this octet string MUST be the full size of a coordinate for
// the curve specified in the "crv" parameter.
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
if curveSize(curve) != len(key.X.data) {
- return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for x")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for x")
}
if curveSize(curve) != len(key.Y.data) {
- return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for y")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for y")
}
// https://tools.ietf.org/html/rfc7518#section-6.2.2.1
if dSize(curve) != len(key.D.data) {
- return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for d")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for d")
}
x := key.X.bigInt()
y := key.Y.bigInt()
if !curve.IsOnCurve(x, y) {
- return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve")
+ return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
}
return &ecdsa.PrivateKey{
@@ -722,7 +722,7 @@ func fromEcPrivateKey(ec *ecdsa.PrivateKey) (*rawJSONWebKey, error) {
}
if ec.D == nil {
- return nil, fmt.Errorf("square/go-jose: invalid EC private key")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key")
}
raw.D = newFixedSizeBuffer(ec.D.Bytes(), dSize(ec.PublicKey.Curve))
@@ -754,7 +754,7 @@ func fromSymmetricKey(key []byte) (*rawJSONWebKey, error) {
func (key rawJSONWebKey) symmetricKey() ([]byte, error) {
if key.K == nil {
- return nil, fmt.Errorf("square/go-jose: invalid OCT (symmetric) key, missing k value")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid OCT (symmetric) key, missing k value")
}
return key.K.bytes(), nil
}
diff --git a/vendor/gopkg.in/square/go-jose.v2/jws.go b/vendor/gopkg.in/go-jose/go-jose.v2/jws.go
similarity index 95%
rename from vendor/gopkg.in/square/go-jose.v2/jws.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/jws.go
index 7e261f937e..1a24fa468a 100644
--- a/vendor/gopkg.in/square/go-jose.v2/jws.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/jws.go
@@ -23,7 +23,7 @@ import (
"fmt"
"strings"
- "gopkg.in/square/go-jose.v2/json"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
@@ -88,7 +88,7 @@ func ParseSigned(signature string) (*JSONWebSignature, error) {
// ParseDetached parses a signed message in compact serialization format with detached payload.
func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) {
if payload == nil {
- return nil, errors.New("square/go-jose: nil payload")
+ return nil, errors.New("go-jose/go-jose: nil payload")
}
return parseSignedCompact(stripWhitespace(signature), payload)
}
@@ -151,7 +151,7 @@ func parseSignedFull(input string) (*JSONWebSignature, error) {
// sanitized produces a cleaned-up JWS object from the raw JSON.
func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
if parsed.Payload == nil {
- return nil, fmt.Errorf("square/go-jose: missing payload in JWS message")
+ return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message")
}
obj := &JSONWebSignature{
@@ -215,7 +215,7 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
jwk := signature.Header.JSONWebKey
if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
- return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key")
+ return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
}
obj.Signatures = append(obj.Signatures, signature)
@@ -260,7 +260,7 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
jwk := obj.Signatures[i].Header.JSONWebKey
if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
- return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key")
+ return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
}
// Copy value of sig
@@ -277,11 +277,11 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) {
parts := strings.Split(input, ".")
if len(parts) != 3 {
- return nil, fmt.Errorf("square/go-jose: compact JWS format must have three parts")
+ return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
}
if parts[1] != "" && payload != nil {
- return nil, fmt.Errorf("square/go-jose: payload is not detached")
+ return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
}
rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
diff --git a/vendor/gopkg.in/square/go-jose.v2/opaque.go b/vendor/gopkg.in/go-jose/go-jose.v2/opaque.go
similarity index 100%
rename from vendor/gopkg.in/square/go-jose.v2/opaque.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/opaque.go
diff --git a/vendor/gopkg.in/square/go-jose.v2/shared.go b/vendor/gopkg.in/go-jose/go-jose.v2/shared.go
similarity index 95%
rename from vendor/gopkg.in/square/go-jose.v2/shared.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/shared.go
index f72e5a53d1..0fa66a44bd 100644
--- a/vendor/gopkg.in/square/go-jose.v2/shared.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/shared.go
@@ -23,7 +23,7 @@ import (
"errors"
"fmt"
- "gopkg.in/square/go-jose.v2/json"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// KeyAlgorithm represents a key management algorithm.
@@ -45,32 +45,32 @@ var (
// ErrCryptoFailure represents an error in cryptographic primitive. This
// occurs when, for example, a message had an invalid authentication tag or
// could not be decrypted.
- ErrCryptoFailure = errors.New("square/go-jose: error in cryptographic primitive")
+ ErrCryptoFailure = errors.New("go-jose/go-jose: error in cryptographic primitive")
// ErrUnsupportedAlgorithm indicates that a selected algorithm is not
// supported. This occurs when trying to instantiate an encrypter for an
// algorithm that is not yet implemented.
- ErrUnsupportedAlgorithm = errors.New("square/go-jose: unknown/unsupported algorithm")
+ ErrUnsupportedAlgorithm = errors.New("go-jose/go-jose: unknown/unsupported algorithm")
// ErrUnsupportedKeyType indicates that the given key type/format is not
// supported. This occurs when trying to instantiate an encrypter and passing
// it a key of an unrecognized type or with unsupported parameters, such as
// an RSA private key with more than two primes.
- ErrUnsupportedKeyType = errors.New("square/go-jose: unsupported key type/format")
+ ErrUnsupportedKeyType = errors.New("go-jose/go-jose: unsupported key type/format")
// ErrInvalidKeySize indicates that the given key is not the correct size
// for the selected algorithm. This can occur, for example, when trying to
// encrypt with AES-256 but passing only a 128-bit key as input.
- ErrInvalidKeySize = errors.New("square/go-jose: invalid key size for algorithm")
+ ErrInvalidKeySize = errors.New("go-jose/go-jose: invalid key size for algorithm")
// ErrNotSupported serialization of object is not supported. This occurs when
// trying to compact-serialize an object which can't be represented in
// compact form.
- ErrNotSupported = errors.New("square/go-jose: compact serialization not supported for object")
+ ErrNotSupported = errors.New("go-jose/go-jose: compact serialization not supported for object")
// ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a
// nonce header parameter was included in an unprotected header object.
- ErrUnprotectedNonce = errors.New("square/go-jose: Nonce parameter included in unprotected header")
+ ErrUnprotectedNonce = errors.New("go-jose/go-jose: Nonce parameter included in unprotected header")
)
// Key management algorithms
@@ -194,7 +194,7 @@ type Header struct {
// not be validated with the given verify options.
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
if len(h.certificates) == 0 {
- return nil, errors.New("square/go-jose: no x5c header present in message")
+ return nil, errors.New("go-jose/go-jose: no x5c header present in message")
}
leaf := h.certificates[0]
@@ -496,7 +496,7 @@ func curveName(crv elliptic.Curve) (string, error) {
case elliptic.P521():
return "P-521", nil
default:
- return "", fmt.Errorf("square/go-jose: unsupported/unknown elliptic curve")
+ return "", fmt.Errorf("go-jose/go-jose: unsupported/unknown elliptic curve")
}
}
diff --git a/vendor/gopkg.in/square/go-jose.v2/signing.go b/vendor/gopkg.in/go-jose/go-jose.v2/signing.go
similarity index 95%
rename from vendor/gopkg.in/square/go-jose.v2/signing.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/signing.go
index bad820cea3..5195a1a916 100644
--- a/vendor/gopkg.in/square/go-jose.v2/signing.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/signing.go
@@ -26,7 +26,7 @@ import (
"golang.org/x/crypto/ed25519"
- "gopkg.in/square/go-jose.v2/json"
+ "gopkg.in/go-jose/go-jose.v2/json"
)
// NonceSource represents a source of random nonces to go into JWS objects
@@ -227,7 +227,7 @@ func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigIn
// This should be impossible, but let's check anyway.
if !recipient.publicKey().IsPublic() {
- return recipientSigInfo{}, errors.New("square/go-jose: public key was unexpectedly not public")
+ return recipientSigInfo{}, errors.New("go-jose/go-jose: public key was unexpectedly not public")
}
}
return recipient, nil
@@ -251,7 +251,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
// result of the JOSE spec. We've decided that this library will only include one or
// the other to avoid this confusion.
//
- // See https://github.com/square/go-jose/issues/157 for more context.
+ // See https://github.com/go-jose/go-jose/issues/157 for more context.
if ctx.embedJWK {
protected[headerJWK] = recipient.publicKey()
} else {
@@ -265,7 +265,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
if ctx.nonceSource != nil {
nonce, err := ctx.nonceSource.Nonce()
if err != nil {
- return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err)
+ return nil, fmt.Errorf("go-jose/go-jose: Error generating nonce: %v", err)
}
protected[headerNonce] = nonce
}
@@ -279,7 +279,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
if b64, ok := protected[headerB64]; ok {
if needsBase64, ok = b64.(bool); !ok {
- return nil, errors.New("square/go-jose: Invalid b64 header parameter")
+ return nil, errors.New("go-jose/go-jose: Invalid b64 header parameter")
}
}
@@ -303,7 +303,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
for k, v := range protected {
b, err := json.Marshal(v)
if err != nil {
- return nil, fmt.Errorf("square/go-jose: Error marshalling item %#v: %v", k, err)
+ return nil, fmt.Errorf("go-jose/go-jose: Error marshalling item %#v: %v", k, err)
}
(*signatureInfo.protected)[k] = makeRawMessage(b)
}
@@ -354,7 +354,7 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
}
if len(obj.Signatures) > 1 {
- return errors.New("square/go-jose: too many signatures in payload; expecting only one")
+ return errors.New("go-jose/go-jose: too many signatures in payload; expecting only one")
}
signature := obj.Signatures[0]
diff --git a/vendor/gopkg.in/square/go-jose.v2/symmetric.go b/vendor/gopkg.in/go-jose/go-jose.v2/symmetric.go
similarity index 92%
rename from vendor/gopkg.in/square/go-jose.v2/symmetric.go
rename to vendor/gopkg.in/go-jose/go-jose.v2/symmetric.go
index 264a0fe37c..52c8b62bf4 100644
--- a/vendor/gopkg.in/square/go-jose.v2/symmetric.go
+++ b/vendor/gopkg.in/go-jose/go-jose.v2/symmetric.go
@@ -31,7 +31,7 @@ import (
"io"
"golang.org/x/crypto/pbkdf2"
- "gopkg.in/square/go-jose.v2/cipher"
+ "gopkg.in/go-jose/go-jose.v2/cipher"
)
// Random reader (stubbed out in tests)
@@ -356,11 +356,11 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
iv, err := headers.getIV()
if err != nil {
- return nil, fmt.Errorf("square/go-jose: invalid IV: %v", err)
+ return nil, fmt.Errorf("go-jose/go-jose: invalid IV: %v", err)
}
tag, err := headers.getTag()
if err != nil {
- return nil, fmt.Errorf("square/go-jose: invalid tag: %v", err)
+ return nil, fmt.Errorf("go-jose/go-jose: invalid tag: %v", err)
}
parts := &aeadParts{
@@ -389,18 +389,23 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
p2s, err := headers.getP2S()
if err != nil {
- return nil, fmt.Errorf("square/go-jose: invalid P2S: %v", err)
+ return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: %v", err)
}
if p2s == nil || len(p2s.data) == 0 {
- return nil, fmt.Errorf("square/go-jose: invalid P2S: must be present")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: must be present")
}
p2c, err := headers.getP2C()
if err != nil {
- return nil, fmt.Errorf("square/go-jose: invalid P2C: %v", err)
+ return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: %v", err)
}
if p2c <= 0 {
- return nil, fmt.Errorf("square/go-jose: invalid P2C: must be a positive integer")
+ return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: must be a positive integer")
+ }
+ if p2c > 1000000 {
+ // An unauthenticated attacker can set a high P2C value. Set an upper limit to avoid
+ // DoS attacks.
+ return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: too high")
}
// salt is UTF8(Alg) || 0x00 || Salt Input
@@ -431,7 +436,7 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
mac, err := ctx.hmac(payload, alg)
if err != nil {
- return Signature{}, errors.New("square/go-jose: failed to compute hmac")
+ return Signature{}, errors.New("go-jose/go-jose: failed to compute hmac")
}
return Signature{
@@ -444,16 +449,16 @@ func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Sig
func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureAlgorithm) error {
expected, err := ctx.hmac(payload, alg)
if err != nil {
- return errors.New("square/go-jose: failed to compute hmac")
+ return errors.New("go-jose/go-jose: failed to compute hmac")
}
if len(mac) != len(expected) {
- return errors.New("square/go-jose: invalid hmac")
+ return errors.New("go-jose/go-jose: invalid hmac")
}
match := subtle.ConstantTimeCompare(mac, expected)
if match != 1 {
- return errors.New("square/go-jose: invalid hmac")
+ return errors.New("go-jose/go-jose: invalid hmac")
}
return nil
diff --git a/vendor/gopkg.in/square/go-jose.v2/BUG-BOUNTY.md b/vendor/gopkg.in/square/go-jose.v2/BUG-BOUNTY.md
deleted file mode 100644
index 3305db0f65..0000000000
--- a/vendor/gopkg.in/square/go-jose.v2/BUG-BOUNTY.md
+++ /dev/null
@@ -1,10 +0,0 @@
-Serious about security
-======================
-
-Square recognizes the important contributions the security research community
-can make. We therefore encourage reporting security issues with the code
-contained in this repository.
-
-If you believe you have discovered a security vulnerability, please follow the
-guidelines at .
-
diff --git a/vendor/gopkg.in/square/go-jose.v2/README.md b/vendor/gopkg.in/square/go-jose.v2/README.md
deleted file mode 100644
index 1791bfa8f6..0000000000
--- a/vendor/gopkg.in/square/go-jose.v2/README.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# Go JOSE
-
-[![godoc](http://img.shields.io/badge/godoc-version_1-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v1)
-[![godoc](http://img.shields.io/badge/godoc-version_2-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v2)
-[![license](http://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/square/go-jose/master/LICENSE)
-[![build](https://travis-ci.org/square/go-jose.svg?branch=v2)](https://travis-ci.org/square/go-jose)
-[![coverage](https://coveralls.io/repos/github/square/go-jose/badge.svg?branch=v2)](https://coveralls.io/r/square/go-jose)
-
-Package jose aims to provide an implementation of the Javascript Object Signing
-and Encryption set of standards. This includes support for JSON Web Encryption,
-JSON Web Signature, and JSON Web Token standards.
-
-**Disclaimer**: This library contains encryption software that is subject to
-the U.S. Export Administration Regulations. You may not export, re-export,
-transfer or download this code or any part of it in violation of any United
-States law, directive or regulation. In particular this software may not be
-exported or re-exported in any form or on any media to Iran, North Sudan,
-Syria, Cuba, or North Korea, or to denied persons or entities mentioned on any
-US maintained blocked list.
-
-## Overview
-
-The implementation follows the
-[JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516) (RFC 7516),
-[JSON Web Signature](http://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
-[JSON Web Token](http://dx.doi.org/10.17487/RFC7519) (RFC 7519).
-Tables of supported algorithms are shown below. The library supports both
-the compact and full serialization formats, and has optional support for
-multiple recipients. It also comes with a small command-line utility
-([`jose-util`](https://github.com/square/go-jose/tree/v2/jose-util))
-for dealing with JOSE messages in a shell.
-
-**Note**: We use a forked version of the `encoding/json` package from the Go
-standard library which uses case-sensitive matching for member names (instead
-of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html)).
-This is to avoid differences in interpretation of messages between go-jose and
-libraries in other languages.
-
-### Versions
-
-We use [gopkg.in](https://gopkg.in) for versioning.
-
-[Version 2](https://gopkg.in/square/go-jose.v2)
-([branch](https://github.com/square/go-jose/tree/v2),
-[doc](https://godoc.org/gopkg.in/square/go-jose.v2)) is the current version:
-
- import "gopkg.in/square/go-jose.v2"
-
-The old `v1` branch ([go-jose.v1](https://gopkg.in/square/go-jose.v1)) will
-still receive backported bug fixes and security fixes, but otherwise
-development is frozen. All new feature development takes place on the `v2`
-branch. Version 2 also contains additional sub-packages such as the
-[jwt](https://godoc.org/gopkg.in/square/go-jose.v2/jwt) implementation
-contributed by [@shaxbee](https://github.com/shaxbee).
-
-### Supported algorithms
-
-See below for a table of supported algorithms. Algorithm identifiers match
-the names in the [JSON Web Algorithms](http://dx.doi.org/10.17487/RFC7518)
-standard where possible. The Godoc reference has a list of constants.
-
- Key encryption | Algorithm identifier(s)
- :------------------------- | :------------------------------
- RSA-PKCS#1v1.5 | RSA1_5
- RSA-OAEP | RSA-OAEP, RSA-OAEP-256
- AES key wrap | A128KW, A192KW, A256KW
- AES-GCM key wrap | A128GCMKW, A192GCMKW, A256GCMKW
- ECDH-ES + AES key wrap | ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW
- ECDH-ES (direct) | ECDH-ES1
- Direct encryption | dir1
-
-1. Not supported in multi-recipient mode
-
- Signing / MAC | Algorithm identifier(s)
- :------------------------- | :------------------------------
- RSASSA-PKCS#1v1.5 | RS256, RS384, RS512
- RSASSA-PSS | PS256, PS384, PS512
- HMAC | HS256, HS384, HS512
- ECDSA | ES256, ES384, ES512
- Ed25519 | EdDSA2
-
-2. Only available in version 2 of the package
-
- Content encryption | Algorithm identifier(s)
- :------------------------- | :------------------------------
- AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512
- AES-GCM | A128GCM, A192GCM, A256GCM
-
- Compression | Algorithm identifiers(s)
- :------------------------- | -------------------------------
- DEFLATE (RFC 1951) | DEF
-
-### Supported key types
-
-See below for a table of supported key types. These are understood by the
-library, and can be passed to corresponding functions such as `NewEncrypter` or
-`NewSigner`. Each of these keys can also be wrapped in a JWK if desired, which
-allows attaching a key id.
-
- Algorithm(s) | Corresponding types
- :------------------------- | -------------------------------
- RSA | *[rsa.PublicKey](http://golang.org/pkg/crypto/rsa/#PublicKey), *[rsa.PrivateKey](http://golang.org/pkg/crypto/rsa/#PrivateKey)
- ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey)
- EdDSA1 | [ed25519.PublicKey](https://godoc.org/golang.org/x/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://godoc.org/golang.org/x/crypto/ed25519#PrivateKey)
- AES, HMAC | []byte
-
-1. Only available in version 2 of the package
-
-## Examples
-
-[![godoc](http://img.shields.io/badge/godoc-version_1-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v1)
-[![godoc](http://img.shields.io/badge/godoc-version_2-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v2)
-
-Examples can be found in the Godoc
-reference for this package. The
-[`jose-util`](https://github.com/square/go-jose/tree/v2/jose-util)
-subdirectory also contains a small command-line utility which might be useful
-as an example.
diff --git a/vendor/k8s.io/client-go/tools/watch/informerwatcher.go b/vendor/k8s.io/client-go/tools/watch/informerwatcher.go
new file mode 100644
index 0000000000..5e6aad5cf1
--- /dev/null
+++ b/vendor/k8s.io/client-go/tools/watch/informerwatcher.go
@@ -0,0 +1,150 @@
+/*
+Copyright 2017 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package watch
+
+import (
+ "sync"
+
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/watch"
+ "k8s.io/client-go/tools/cache"
+)
+
+func newEventProcessor(out chan<- watch.Event) *eventProcessor {
+ return &eventProcessor{
+ out: out,
+ cond: sync.NewCond(&sync.Mutex{}),
+ done: make(chan struct{}),
+ }
+}
+
+// eventProcessor buffers events and writes them to an out chan when a reader
+// is waiting. Because of the requirement to buffer events, it synchronizes
+// input with a condition, and synchronizes output with a channels. It needs to
+// be able to yield while both waiting on an input condition and while blocked
+// on writing to the output channel.
+type eventProcessor struct {
+ out chan<- watch.Event
+
+ cond *sync.Cond
+ buff []watch.Event
+
+ done chan struct{}
+}
+
+func (e *eventProcessor) run() {
+ for {
+ batch := e.takeBatch()
+ e.writeBatch(batch)
+ if e.stopped() {
+ return
+ }
+ }
+}
+
+func (e *eventProcessor) takeBatch() []watch.Event {
+ e.cond.L.Lock()
+ defer e.cond.L.Unlock()
+
+ for len(e.buff) == 0 && !e.stopped() {
+ e.cond.Wait()
+ }
+
+ batch := e.buff
+ e.buff = nil
+ return batch
+}
+
+func (e *eventProcessor) writeBatch(events []watch.Event) {
+ for _, event := range events {
+ select {
+ case e.out <- event:
+ case <-e.done:
+ return
+ }
+ }
+}
+
+func (e *eventProcessor) push(event watch.Event) {
+ e.cond.L.Lock()
+ defer e.cond.L.Unlock()
+ defer e.cond.Signal()
+ e.buff = append(e.buff, event)
+}
+
+func (e *eventProcessor) stopped() bool {
+ select {
+ case <-e.done:
+ return true
+ default:
+ return false
+ }
+}
+
+func (e *eventProcessor) stop() {
+ close(e.done)
+ e.cond.Signal()
+}
+
+// NewIndexerInformerWatcher will create an IndexerInformer and wrap it into watch.Interface
+// so you can use it anywhere where you'd have used a regular Watcher returned from Watch method.
+// it also returns a channel you can use to wait for the informers to fully shutdown.
+func NewIndexerInformerWatcher(lw cache.ListerWatcher, objType runtime.Object) (cache.Indexer, cache.Controller, watch.Interface, <-chan struct{}) {
+ ch := make(chan watch.Event)
+ w := watch.NewProxyWatcher(ch)
+ e := newEventProcessor(ch)
+
+ indexer, informer := cache.NewIndexerInformer(lw, objType, 0, cache.ResourceEventHandlerFuncs{
+ AddFunc: func(obj interface{}) {
+ e.push(watch.Event{
+ Type: watch.Added,
+ Object: obj.(runtime.Object),
+ })
+ },
+ UpdateFunc: func(old, new interface{}) {
+ e.push(watch.Event{
+ Type: watch.Modified,
+ Object: new.(runtime.Object),
+ })
+ },
+ DeleteFunc: func(obj interface{}) {
+ staleObj, stale := obj.(cache.DeletedFinalStateUnknown)
+ if stale {
+ // We have no means of passing the additional information down using
+ // watch API based on watch.Event but the caller can filter such
+ // objects by checking if metadata.deletionTimestamp is set
+ obj = staleObj.Obj
+ }
+
+ e.push(watch.Event{
+ Type: watch.Deleted,
+ Object: obj.(runtime.Object),
+ })
+ },
+ }, cache.Indexers{})
+
+ go e.run()
+
+ doneCh := make(chan struct{})
+ go func() {
+ defer close(doneCh)
+ defer e.stop()
+ informer.Run(w.StopChan())
+ }()
+
+ return indexer, informer, w, doneCh
+}
diff --git a/vendor/k8s.io/client-go/tools/watch/retrywatcher.go b/vendor/k8s.io/client-go/tools/watch/retrywatcher.go
new file mode 100644
index 0000000000..d81dc43570
--- /dev/null
+++ b/vendor/k8s.io/client-go/tools/watch/retrywatcher.go
@@ -0,0 +1,295 @@
+/*
+Copyright 2017 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package watch
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "time"
+
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/util/dump"
+ "k8s.io/apimachinery/pkg/util/net"
+ "k8s.io/apimachinery/pkg/util/wait"
+ "k8s.io/apimachinery/pkg/watch"
+ "k8s.io/client-go/tools/cache"
+ "k8s.io/klog/v2"
+)
+
+// resourceVersionGetter is an interface used to get resource version from events.
+// We can't reuse an interface from meta otherwise it would be a cyclic dependency and we need just this one method
+type resourceVersionGetter interface {
+ GetResourceVersion() string
+}
+
+// RetryWatcher will make sure that in case the underlying watcher is closed (e.g. due to API timeout or etcd timeout)
+// it will get restarted from the last point without the consumer even knowing about it.
+// RetryWatcher does that by inspecting events and keeping track of resourceVersion.
+// Especially useful when using watch.UntilWithoutRetry where premature termination is causing issues and flakes.
+// Please note that this is not resilient to etcd cache not having the resource version anymore - you would need to
+// use Informers for that.
+type RetryWatcher struct {
+ lastResourceVersion string
+ watcherClient cache.Watcher
+ resultChan chan watch.Event
+ stopChan chan struct{}
+ doneChan chan struct{}
+ minRestartDelay time.Duration
+}
+
+// NewRetryWatcher creates a new RetryWatcher.
+// It will make sure that watches gets restarted in case of recoverable errors.
+// The initialResourceVersion will be given to watch method when first called.
+func NewRetryWatcher(initialResourceVersion string, watcherClient cache.Watcher) (*RetryWatcher, error) {
+ return newRetryWatcher(initialResourceVersion, watcherClient, 1*time.Second)
+}
+
+func newRetryWatcher(initialResourceVersion string, watcherClient cache.Watcher, minRestartDelay time.Duration) (*RetryWatcher, error) {
+ switch initialResourceVersion {
+ case "", "0":
+ // TODO: revisit this if we ever get WATCH v2 where it means start "now"
+ // without doing the synthetic list of objects at the beginning (see #74022)
+ return nil, fmt.Errorf("initial RV %q is not supported due to issues with underlying WATCH", initialResourceVersion)
+ default:
+ break
+ }
+
+ rw := &RetryWatcher{
+ lastResourceVersion: initialResourceVersion,
+ watcherClient: watcherClient,
+ stopChan: make(chan struct{}),
+ doneChan: make(chan struct{}),
+ resultChan: make(chan watch.Event, 0),
+ minRestartDelay: minRestartDelay,
+ }
+
+ go rw.receive()
+ return rw, nil
+}
+
+func (rw *RetryWatcher) send(event watch.Event) bool {
+ // Writing to an unbuffered channel is blocking operation
+ // and we need to check if stop wasn't requested while doing so.
+ select {
+ case rw.resultChan <- event:
+ return true
+ case <-rw.stopChan:
+ return false
+ }
+}
+
+// doReceive returns true when it is done, false otherwise.
+// If it is not done the second return value holds the time to wait before calling it again.
+func (rw *RetryWatcher) doReceive() (bool, time.Duration) {
+ watcher, err := rw.watcherClient.Watch(metav1.ListOptions{
+ ResourceVersion: rw.lastResourceVersion,
+ AllowWatchBookmarks: true,
+ })
+ // We are very unlikely to hit EOF here since we are just establishing the call,
+ // but it may happen that the apiserver is just shutting down (e.g. being restarted)
+ // This is consistent with how it is handled for informers
+ switch err {
+ case nil:
+ break
+
+ case io.EOF:
+ // watch closed normally
+ return false, 0
+
+ case io.ErrUnexpectedEOF:
+ klog.V(1).InfoS("Watch closed with unexpected EOF", "err", err)
+ return false, 0
+
+ default:
+ msg := "Watch failed"
+ if net.IsProbableEOF(err) || net.IsTimeout(err) {
+ klog.V(5).InfoS(msg, "err", err)
+ // Retry
+ return false, 0
+ }
+
+ klog.ErrorS(err, msg)
+ // Retry
+ return false, 0
+ }
+
+ if watcher == nil {
+ klog.ErrorS(nil, "Watch returned nil watcher")
+ // Retry
+ return false, 0
+ }
+
+ ch := watcher.ResultChan()
+ defer watcher.Stop()
+
+ for {
+ select {
+ case <-rw.stopChan:
+ klog.V(4).InfoS("Stopping RetryWatcher.")
+ return true, 0
+ case event, ok := <-ch:
+ if !ok {
+ klog.V(4).InfoS("Failed to get event! Re-creating the watcher.", "resourceVersion", rw.lastResourceVersion)
+ return false, 0
+ }
+
+ // We need to inspect the event and get ResourceVersion out of it
+ switch event.Type {
+ case watch.Added, watch.Modified, watch.Deleted, watch.Bookmark:
+ metaObject, ok := event.Object.(resourceVersionGetter)
+ if !ok {
+ _ = rw.send(watch.Event{
+ Type: watch.Error,
+ Object: &apierrors.NewInternalError(errors.New("retryWatcher: doesn't support resourceVersion")).ErrStatus,
+ })
+ // We have to abort here because this might cause lastResourceVersion inconsistency by skipping a potential RV with valid data!
+ return true, 0
+ }
+
+ resourceVersion := metaObject.GetResourceVersion()
+ if resourceVersion == "" {
+ _ = rw.send(watch.Event{
+ Type: watch.Error,
+ Object: &apierrors.NewInternalError(fmt.Errorf("retryWatcher: object %#v doesn't support resourceVersion", event.Object)).ErrStatus,
+ })
+ // We have to abort here because this might cause lastResourceVersion inconsistency by skipping a potential RV with valid data!
+ return true, 0
+ }
+
+ // All is fine; send the non-bookmark events and update resource version.
+ if event.Type != watch.Bookmark {
+ ok = rw.send(event)
+ if !ok {
+ return true, 0
+ }
+ }
+ rw.lastResourceVersion = resourceVersion
+
+ continue
+
+ case watch.Error:
+ // This round trip allows us to handle unstructured status
+ errObject := apierrors.FromObject(event.Object)
+ statusErr, ok := errObject.(*apierrors.StatusError)
+ if !ok {
+ klog.Error(fmt.Sprintf("Received an error which is not *metav1.Status but %s", dump.Pretty(event.Object)))
+ // Retry unknown errors
+ return false, 0
+ }
+
+ status := statusErr.ErrStatus
+
+ statusDelay := time.Duration(0)
+ if status.Details != nil {
+ statusDelay = time.Duration(status.Details.RetryAfterSeconds) * time.Second
+ }
+
+ switch status.Code {
+ case http.StatusGone:
+ // Never retry RV too old errors
+ _ = rw.send(event)
+ return true, 0
+
+ case http.StatusGatewayTimeout, http.StatusInternalServerError:
+ // Retry
+ return false, statusDelay
+
+ default:
+ // We retry by default. RetryWatcher is meant to proceed unless it is certain
+ // that it can't. If we are not certain, we proceed with retry and leave it
+ // up to the user to timeout if needed.
+
+ // Log here so we have a record of hitting the unexpected error
+ // and we can whitelist some error codes if we missed any that are expected.
+ klog.V(5).Info(fmt.Sprintf("Retrying after unexpected error: %s", dump.Pretty(event.Object)))
+
+ // Retry
+ return false, statusDelay
+ }
+
+ default:
+ klog.Errorf("Failed to recognize Event type %q", event.Type)
+ _ = rw.send(watch.Event{
+ Type: watch.Error,
+ Object: &apierrors.NewInternalError(fmt.Errorf("retryWatcher failed to recognize Event type %q", event.Type)).ErrStatus,
+ })
+ // We are unable to restart the watch and have to stop the loop or this might cause lastResourceVersion inconsistency by skipping a potential RV with valid data!
+ return true, 0
+ }
+ }
+ }
+}
+
+// receive reads the result from a watcher, restarting it if necessary.
+func (rw *RetryWatcher) receive() {
+ defer close(rw.doneChan)
+ defer close(rw.resultChan)
+
+ klog.V(4).Info("Starting RetryWatcher.")
+ defer klog.V(4).Info("Stopping RetryWatcher.")
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ go func() {
+ select {
+ case <-rw.stopChan:
+ cancel()
+ return
+ case <-ctx.Done():
+ return
+ }
+ }()
+
+ // We use non sliding until so we don't introduce delays on happy path when WATCH call
+ // timeouts or gets closed and we need to reestablish it while also avoiding hot loops.
+ wait.NonSlidingUntilWithContext(ctx, func(ctx context.Context) {
+ done, retryAfter := rw.doReceive()
+ if done {
+ cancel()
+ return
+ }
+
+ timer := time.NewTimer(retryAfter)
+ select {
+ case <-ctx.Done():
+ timer.Stop()
+ return
+ case <-timer.C:
+ }
+
+ klog.V(4).Infof("Restarting RetryWatcher at RV=%q", rw.lastResourceVersion)
+ }, rw.minRestartDelay)
+}
+
+// ResultChan implements Interface.
+func (rw *RetryWatcher) ResultChan() <-chan watch.Event {
+ return rw.resultChan
+}
+
+// Stop implements Interface.
+func (rw *RetryWatcher) Stop() {
+ close(rw.stopChan)
+}
+
+// Done allows the caller to be notified when Retry watcher stops.
+func (rw *RetryWatcher) Done() <-chan struct{} {
+ return rw.doneChan
+}
diff --git a/vendor/k8s.io/client-go/tools/watch/until.go b/vendor/k8s.io/client-go/tools/watch/until.go
new file mode 100644
index 0000000000..a2474556b0
--- /dev/null
+++ b/vendor/k8s.io/client-go/tools/watch/until.go
@@ -0,0 +1,168 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package watch
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/util/wait"
+ "k8s.io/apimachinery/pkg/watch"
+ "k8s.io/client-go/tools/cache"
+ "k8s.io/klog/v2"
+)
+
+// PreconditionFunc returns true if the condition has been reached, false if it has not been reached yet,
+// or an error if the condition failed or detected an error state.
+type PreconditionFunc func(store cache.Store) (bool, error)
+
+// ConditionFunc returns true if the condition has been reached, false if it has not been reached yet,
+// or an error if the condition cannot be checked and should terminate. In general, it is better to define
+// level driven conditions over edge driven conditions (pod has ready=true, vs pod modified and ready changed
+// from false to true).
+type ConditionFunc func(event watch.Event) (bool, error)
+
+// ErrWatchClosed is returned when the watch channel is closed before timeout in UntilWithoutRetry.
+var ErrWatchClosed = errors.New("watch closed before UntilWithoutRetry timeout")
+
+// UntilWithoutRetry reads items from the watch until each provided condition succeeds, and then returns the last watch
+// encountered. The first condition that returns an error terminates the watch (and the event is also returned).
+// If no event has been received, the returned event will be nil.
+// Conditions are satisfied sequentially so as to provide a useful primitive for higher level composition.
+// Waits until context deadline or until context is canceled.
+//
+// Warning: Unless you have a very specific use case (probably a special Watcher) don't use this function!!!
+// Warning: This will fail e.g. on API timeouts and/or 'too old resource version' error.
+// Warning: You are most probably looking for a function *Until* or *UntilWithSync* below,
+// Warning: solving such issues.
+// TODO: Consider making this function private to prevent misuse when the other occurrences in our codebase are gone.
+func UntilWithoutRetry(ctx context.Context, watcher watch.Interface, conditions ...ConditionFunc) (*watch.Event, error) {
+ ch := watcher.ResultChan()
+ defer watcher.Stop()
+ var lastEvent *watch.Event
+ for _, condition := range conditions {
+ // check the next condition against the previous event and short circuit waiting for the next watch
+ if lastEvent != nil {
+ done, err := condition(*lastEvent)
+ if err != nil {
+ return lastEvent, err
+ }
+ if done {
+ continue
+ }
+ }
+ ConditionSucceeded:
+ for {
+ select {
+ case event, ok := <-ch:
+ if !ok {
+ return lastEvent, ErrWatchClosed
+ }
+ lastEvent = &event
+
+ done, err := condition(event)
+ if err != nil {
+ return lastEvent, err
+ }
+ if done {
+ break ConditionSucceeded
+ }
+
+ case <-ctx.Done():
+ return lastEvent, wait.ErrWaitTimeout
+ }
+ }
+ }
+ return lastEvent, nil
+}
+
+// Until wraps the watcherClient's watch function with RetryWatcher making sure that watcher gets restarted in case of errors.
+// The initialResourceVersion will be given to watch method when first called. It shall not be "" or "0"
+// given the underlying WATCH call issues (#74022).
+// Remaining behaviour is identical to function UntilWithoutRetry. (See above.)
+// Until can deal with API timeouts and lost connections.
+// It guarantees you to see all events and in the order they happened.
+// Due to this guarantee there is no way it can deal with 'Resource version too old error'. It will fail in this case.
+// (See `UntilWithSync` if you'd prefer to recover from all the errors including RV too old by re-listing
+// those items. In normal code you should care about being level driven so you'd not care about not seeing all the edges.)
+//
+// The most frequent usage for Until would be a test where you want to verify exact order of events ("edges").
+func Until(ctx context.Context, initialResourceVersion string, watcherClient cache.Watcher, conditions ...ConditionFunc) (*watch.Event, error) {
+ w, err := NewRetryWatcher(initialResourceVersion, watcherClient)
+ if err != nil {
+ return nil, err
+ }
+
+ return UntilWithoutRetry(ctx, w, conditions...)
+}
+
+// UntilWithSync creates an informer from lw, optionally checks precondition when the store is synced,
+// and watches the output until each provided condition succeeds, in a way that is identical
+// to function UntilWithoutRetry. (See above.)
+// UntilWithSync can deal with all errors like API timeout, lost connections and 'Resource version too old'.
+// It is the only function that can recover from 'Resource version too old', Until and UntilWithoutRetry will
+// just fail in that case. On the other hand it can't provide you with guarantees as strong as using simple
+// Watch method with Until. It can skip some intermediate events in case of watch function failing but it will
+// re-list to recover and you always get an event, if there has been a change, after recovery.
+// Also with the current implementation based on DeltaFIFO, order of the events you receive is guaranteed only for
+// particular object, not between more of them even it's the same resource.
+// The most frequent usage would be a command that needs to watch the "state of the world" and should't fail, like:
+// waiting for object reaching a state, "small" controllers, ...
+func UntilWithSync(ctx context.Context, lw cache.ListerWatcher, objType runtime.Object, precondition PreconditionFunc, conditions ...ConditionFunc) (*watch.Event, error) {
+ indexer, informer, watcher, done := NewIndexerInformerWatcher(lw, objType)
+ // We need to wait for the internal informers to fully stop so it's easier to reason about
+ // and it works with non-thread safe clients.
+ defer func() { <-done }()
+ // Proxy watcher can be stopped multiple times so it's fine to use defer here to cover alternative branches and
+ // let UntilWithoutRetry to stop it
+ defer watcher.Stop()
+
+ if precondition != nil {
+ if !cache.WaitForCacheSync(ctx.Done(), informer.HasSynced) {
+ return nil, fmt.Errorf("UntilWithSync: unable to sync caches: %w", ctx.Err())
+ }
+
+ done, err := precondition(indexer)
+ if err != nil {
+ return nil, err
+ }
+
+ if done {
+ return nil, nil
+ }
+ }
+
+ return UntilWithoutRetry(ctx, watcher, conditions...)
+}
+
+// ContextWithOptionalTimeout wraps context.WithTimeout and handles infinite timeouts expressed as 0 duration.
+func ContextWithOptionalTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc) {
+ if timeout < 0 {
+ // This should be handled in validation
+ klog.Errorf("Timeout for context shall not be negative!")
+ timeout = 0
+ }
+
+ if timeout == 0 {
+ return context.WithCancel(parent)
+ }
+
+ return context.WithTimeout(parent, timeout)
+}
diff --git a/vendor/k8s.io/client-go/util/certificate/csr/csr.go b/vendor/k8s.io/client-go/util/certificate/csr/csr.go
new file mode 100644
index 0000000000..0390d1c02f
--- /dev/null
+++ b/vendor/k8s.io/client-go/util/certificate/csr/csr.go
@@ -0,0 +1,364 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package csr
+
+import (
+ "context"
+ "crypto"
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "reflect"
+ "time"
+
+ certificatesv1 "k8s.io/api/certificates/v1"
+ certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/fields"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/util/wait"
+ "k8s.io/apimachinery/pkg/watch"
+ clientset "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/tools/cache"
+ watchtools "k8s.io/client-go/tools/watch"
+ certutil "k8s.io/client-go/util/cert"
+ "k8s.io/klog/v2"
+ "k8s.io/utils/pointer"
+)
+
+// RequestCertificate will either use an existing (if this process has run
+// before but not to completion) or create a certificate signing request using the
+// PEM encoded CSR and send it to API server. An optional requestedDuration may be passed
+// to set the spec.expirationSeconds field on the CSR to control the lifetime of the issued
+// certificate. This is not guaranteed as the signer may choose to ignore the request.
+func RequestCertificate(client clientset.Interface, csrData []byte, name, signerName string, requestedDuration *time.Duration, usages []certificatesv1.KeyUsage, privateKey interface{}) (reqName string, reqUID types.UID, err error) {
+ csr := &certificatesv1.CertificateSigningRequest{
+ // Username, UID, Groups will be injected by API server.
+ TypeMeta: metav1.TypeMeta{Kind: "CertificateSigningRequest"},
+ ObjectMeta: metav1.ObjectMeta{
+ Name: name,
+ },
+ Spec: certificatesv1.CertificateSigningRequestSpec{
+ Request: csrData,
+ Usages: usages,
+ SignerName: signerName,
+ },
+ }
+ if len(csr.Name) == 0 {
+ csr.GenerateName = "csr-"
+ }
+ if requestedDuration != nil {
+ csr.Spec.ExpirationSeconds = DurationToExpirationSeconds(*requestedDuration)
+ }
+
+ reqName, reqUID, err = create(client, csr)
+ switch {
+ case err == nil:
+ return reqName, reqUID, err
+
+ case apierrors.IsAlreadyExists(err) && len(name) > 0:
+ klog.Infof("csr for this node already exists, reusing")
+ req, err := get(client, name)
+ if err != nil {
+ return "", "", formatError("cannot retrieve certificate signing request: %v", err)
+ }
+ if err := ensureCompatible(req, csr, privateKey); err != nil {
+ return "", "", fmt.Errorf("retrieved csr is not compatible: %v", err)
+ }
+ klog.Infof("csr for this node is still valid")
+ return req.Name, req.UID, nil
+
+ default:
+ return "", "", formatError("cannot create certificate signing request: %v", err)
+ }
+}
+
+func DurationToExpirationSeconds(duration time.Duration) *int32 {
+ return pointer.Int32(int32(duration / time.Second))
+}
+
+func ExpirationSecondsToDuration(expirationSeconds int32) time.Duration {
+ return time.Duration(expirationSeconds) * time.Second
+}
+
+func get(client clientset.Interface, name string) (*certificatesv1.CertificateSigningRequest, error) {
+ v1req, v1err := client.CertificatesV1().CertificateSigningRequests().Get(context.TODO(), name, metav1.GetOptions{})
+ if v1err == nil || !apierrors.IsNotFound(v1err) {
+ return v1req, v1err
+ }
+
+ v1beta1req, v1beta1err := client.CertificatesV1beta1().CertificateSigningRequests().Get(context.TODO(), name, metav1.GetOptions{})
+ if v1beta1err != nil {
+ return nil, v1beta1err
+ }
+
+ v1req = &certificatesv1.CertificateSigningRequest{
+ ObjectMeta: v1beta1req.ObjectMeta,
+ Spec: certificatesv1.CertificateSigningRequestSpec{
+ Request: v1beta1req.Spec.Request,
+ },
+ }
+ if v1beta1req.Spec.SignerName != nil {
+ v1req.Spec.SignerName = *v1beta1req.Spec.SignerName
+ }
+ for _, usage := range v1beta1req.Spec.Usages {
+ v1req.Spec.Usages = append(v1req.Spec.Usages, certificatesv1.KeyUsage(usage))
+ }
+ return v1req, nil
+}
+
+func create(client clientset.Interface, csr *certificatesv1.CertificateSigningRequest) (reqName string, reqUID types.UID, err error) {
+ // only attempt a create via v1 if we specified signerName and usages and are not using the legacy unknown signerName
+ if len(csr.Spec.Usages) > 0 && len(csr.Spec.SignerName) > 0 && csr.Spec.SignerName != "kubernetes.io/legacy-unknown" {
+ v1req, v1err := client.CertificatesV1().CertificateSigningRequests().Create(context.TODO(), csr, metav1.CreateOptions{})
+ switch {
+ case v1err != nil && apierrors.IsNotFound(v1err):
+ // v1 CSR API was not found, continue to try v1beta1
+
+ case v1err != nil:
+ // other creation error
+ return "", "", v1err
+
+ default:
+ // success
+ return v1req.Name, v1req.UID, v1err
+ }
+ }
+
+ // convert relevant bits to v1beta1
+ v1beta1csr := &certificatesv1beta1.CertificateSigningRequest{
+ ObjectMeta: csr.ObjectMeta,
+ Spec: certificatesv1beta1.CertificateSigningRequestSpec{
+ SignerName: &csr.Spec.SignerName,
+ Request: csr.Spec.Request,
+ },
+ }
+ for _, usage := range csr.Spec.Usages {
+ v1beta1csr.Spec.Usages = append(v1beta1csr.Spec.Usages, certificatesv1beta1.KeyUsage(usage))
+ }
+
+ // create v1beta1
+ v1beta1req, v1beta1err := client.CertificatesV1beta1().CertificateSigningRequests().Create(context.TODO(), v1beta1csr, metav1.CreateOptions{})
+ if v1beta1err != nil {
+ return "", "", v1beta1err
+ }
+ return v1beta1req.Name, v1beta1req.UID, nil
+}
+
+// WaitForCertificate waits for a certificate to be issued until timeout, or returns an error.
+func WaitForCertificate(ctx context.Context, client clientset.Interface, reqName string, reqUID types.UID) (certData []byte, err error) {
+ fieldSelector := fields.OneTermEqualSelector("metadata.name", reqName).String()
+
+ var lw *cache.ListWatch
+ var obj runtime.Object
+ for {
+ // see if the v1 API is available
+ if _, err := client.CertificatesV1().CertificateSigningRequests().List(ctx, metav1.ListOptions{FieldSelector: fieldSelector}); err == nil {
+ // watch v1 objects
+ obj = &certificatesv1.CertificateSigningRequest{}
+ lw = &cache.ListWatch{
+ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
+ options.FieldSelector = fieldSelector
+ return client.CertificatesV1().CertificateSigningRequests().List(ctx, options)
+ },
+ WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
+ options.FieldSelector = fieldSelector
+ return client.CertificatesV1().CertificateSigningRequests().Watch(ctx, options)
+ },
+ }
+ break
+ } else {
+ klog.V(2).Infof("error fetching v1 certificate signing request: %v", err)
+ }
+
+ // return if we've timed out
+ if err := ctx.Err(); err != nil {
+ return nil, wait.ErrWaitTimeout
+ }
+
+ // see if the v1beta1 API is available
+ if _, err := client.CertificatesV1beta1().CertificateSigningRequests().List(ctx, metav1.ListOptions{FieldSelector: fieldSelector}); err == nil {
+ // watch v1beta1 objects
+ obj = &certificatesv1beta1.CertificateSigningRequest{}
+ lw = &cache.ListWatch{
+ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
+ options.FieldSelector = fieldSelector
+ return client.CertificatesV1beta1().CertificateSigningRequests().List(ctx, options)
+ },
+ WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
+ options.FieldSelector = fieldSelector
+ return client.CertificatesV1beta1().CertificateSigningRequests().Watch(ctx, options)
+ },
+ }
+ break
+ } else {
+ klog.V(2).Infof("error fetching v1beta1 certificate signing request: %v", err)
+ }
+
+ // return if we've timed out
+ if err := ctx.Err(); err != nil {
+ return nil, wait.ErrWaitTimeout
+ }
+
+ // wait and try again
+ time.Sleep(time.Second)
+ }
+
+ var issuedCertificate []byte
+ _, err = watchtools.UntilWithSync(
+ ctx,
+ lw,
+ obj,
+ nil,
+ func(event watch.Event) (bool, error) {
+ switch event.Type {
+ case watch.Modified, watch.Added:
+ case watch.Deleted:
+ return false, fmt.Errorf("csr %q was deleted", reqName)
+ default:
+ return false, nil
+ }
+
+ switch csr := event.Object.(type) {
+ case *certificatesv1.CertificateSigningRequest:
+ if csr.UID != reqUID {
+ return false, fmt.Errorf("csr %q changed UIDs", csr.Name)
+ }
+ approved := false
+ for _, c := range csr.Status.Conditions {
+ if c.Type == certificatesv1.CertificateDenied {
+ return false, fmt.Errorf("certificate signing request is denied, reason: %v, message: %v", c.Reason, c.Message)
+ }
+ if c.Type == certificatesv1.CertificateFailed {
+ return false, fmt.Errorf("certificate signing request failed, reason: %v, message: %v", c.Reason, c.Message)
+ }
+ if c.Type == certificatesv1.CertificateApproved {
+ approved = true
+ }
+ }
+ if approved {
+ if len(csr.Status.Certificate) > 0 {
+ klog.V(2).Infof("certificate signing request %s is issued", csr.Name)
+ issuedCertificate = csr.Status.Certificate
+ return true, nil
+ }
+ klog.V(2).Infof("certificate signing request %s is approved, waiting to be issued", csr.Name)
+ }
+
+ case *certificatesv1beta1.CertificateSigningRequest:
+ if csr.UID != reqUID {
+ return false, fmt.Errorf("csr %q changed UIDs", csr.Name)
+ }
+ approved := false
+ for _, c := range csr.Status.Conditions {
+ if c.Type == certificatesv1beta1.CertificateDenied {
+ return false, fmt.Errorf("certificate signing request is denied, reason: %v, message: %v", c.Reason, c.Message)
+ }
+ if c.Type == certificatesv1beta1.CertificateFailed {
+ return false, fmt.Errorf("certificate signing request failed, reason: %v, message: %v", c.Reason, c.Message)
+ }
+ if c.Type == certificatesv1beta1.CertificateApproved {
+ approved = true
+ }
+ }
+ if approved {
+ if len(csr.Status.Certificate) > 0 {
+ klog.V(2).Infof("certificate signing request %s is issued", csr.Name)
+ issuedCertificate = csr.Status.Certificate
+ return true, nil
+ }
+ klog.V(2).Infof("certificate signing request %s is approved, waiting to be issued", csr.Name)
+ }
+
+ default:
+ return false, fmt.Errorf("unexpected type received: %T", event.Object)
+ }
+
+ return false, nil
+ },
+ )
+ if err == wait.ErrWaitTimeout {
+ return nil, wait.ErrWaitTimeout
+ }
+ if err != nil {
+ return nil, formatError("cannot watch on the certificate signing request: %v", err)
+ }
+
+ return issuedCertificate, nil
+}
+
+// ensureCompatible ensures that a CSR object is compatible with an original CSR
+func ensureCompatible(new, orig *certificatesv1.CertificateSigningRequest, privateKey interface{}) error {
+ newCSR, err := parseCSR(new.Spec.Request)
+ if err != nil {
+ return fmt.Errorf("unable to parse new csr: %v", err)
+ }
+ origCSR, err := parseCSR(orig.Spec.Request)
+ if err != nil {
+ return fmt.Errorf("unable to parse original csr: %v", err)
+ }
+ if !reflect.DeepEqual(newCSR.Subject, origCSR.Subject) {
+ return fmt.Errorf("csr subjects differ: new: %#v, orig: %#v", newCSR.Subject, origCSR.Subject)
+ }
+ if len(new.Spec.SignerName) > 0 && len(orig.Spec.SignerName) > 0 && new.Spec.SignerName != orig.Spec.SignerName {
+ return fmt.Errorf("csr signerNames differ: new %q, orig: %q", new.Spec.SignerName, orig.Spec.SignerName)
+ }
+ signer, ok := privateKey.(crypto.Signer)
+ if !ok {
+ return fmt.Errorf("privateKey is not a signer")
+ }
+ newCSR.PublicKey = signer.Public()
+ if err := newCSR.CheckSignature(); err != nil {
+ return fmt.Errorf("error validating signature new CSR against old key: %v", err)
+ }
+ if len(new.Status.Certificate) > 0 {
+ certs, err := certutil.ParseCertsPEM(new.Status.Certificate)
+ if err != nil {
+ return fmt.Errorf("error parsing signed certificate for CSR: %v", err)
+ }
+ now := time.Now()
+ for _, cert := range certs {
+ if now.After(cert.NotAfter) {
+ return fmt.Errorf("one of the certificates for the CSR has expired: %s", cert.NotAfter)
+ }
+ }
+ }
+ return nil
+}
+
+// formatError preserves the type of an API message but alters the message. Expects
+// a single argument format string, and returns the wrapped error.
+func formatError(format string, err error) error {
+ if s, ok := err.(apierrors.APIStatus); ok {
+ se := &apierrors.StatusError{ErrStatus: s.Status()}
+ se.ErrStatus.Message = fmt.Sprintf(format, se.ErrStatus.Message)
+ return se
+ }
+ return fmt.Errorf(format, err)
+}
+
+// parseCSR extracts the CSR from the API object and decodes it.
+func parseCSR(pemData []byte) (*x509.CertificateRequest, error) {
+ // extract PEM from request object
+ block, _ := pem.Decode(pemData)
+ if block == nil || block.Type != "CERTIFICATE REQUEST" {
+ return nil, fmt.Errorf("PEM block type must be CERTIFICATE REQUEST")
+ }
+ return x509.ParseCertificateRequest(block.Bytes)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 09c536a2a1..f86c7d289a 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -161,8 +161,8 @@ github.com/IBM-Cloud/power-go-client/power/client/service_instances
github.com/IBM-Cloud/power-go-client/power/client/storage_types
github.com/IBM-Cloud/power-go-client/power/client/swagger_spec
github.com/IBM-Cloud/power-go-client/power/models
-# github.com/IBM/go-sdk-core/v5 v5.14.1
-## explicit; go 1.19
+# github.com/IBM/go-sdk-core/v5 v5.17.4
+## explicit; go 1.20
github.com/IBM/go-sdk-core/v5/core
# github.com/IBM/ibm-cos-sdk-go v1.9.4
## explicit; go 1.11
@@ -384,6 +384,12 @@ github.com/docker/go-metrics
# github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7
## explicit
github.com/docker/libtrust
+# github.com/dustin/go-humanize v1.0.1
+## explicit; go 1.16
+github.com/dustin/go-humanize
+# github.com/elazarl/goproxy v0.0.0-20240618083138-03be62527ccb
+## explicit
+github.com/elazarl/goproxy
# github.com/emicklei/go-restful/v3 v3.11.0
## explicit; go 1.13
github.com/emicklei/go-restful/v3
@@ -403,6 +409,12 @@ github.com/felixge/httpsnoop
# github.com/fsnotify/fsnotify v1.7.0
## explicit; go 1.17
github.com/fsnotify/fsnotify
+# github.com/gabriel-vasile/mimetype v1.4.3
+## explicit; go 1.20
+github.com/gabriel-vasile/mimetype
+github.com/gabriel-vasile/mimetype/internal/charset
+github.com/gabriel-vasile/mimetype/internal/json
+github.com/gabriel-vasile/mimetype/internal/magic
# github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
## explicit
github.com/ghodss/yaml
@@ -430,8 +442,8 @@ github.com/go-openapi/analysis/internal/flatten/operations
github.com/go-openapi/analysis/internal/flatten/replace
github.com/go-openapi/analysis/internal/flatten/schutils
github.com/go-openapi/analysis/internal/flatten/sortref
-# github.com/go-openapi/errors v0.20.3
-## explicit; go 1.14
+# github.com/go-openapi/errors v0.21.0
+## explicit; go 1.19
github.com/go-openapi/errors
# github.com/go-openapi/jsonpointer v0.20.0
## explicit; go 1.18
@@ -457,7 +469,7 @@ github.com/go-openapi/runtime/yamlpc
# github.com/go-openapi/spec v0.20.4
## explicit; go 1.13
github.com/go-openapi/spec
-# github.com/go-openapi/strfmt v0.21.7
+# github.com/go-openapi/strfmt v0.22.1
## explicit; go 1.19
github.com/go-openapi/strfmt
# github.com/go-openapi/swag v0.22.4
@@ -473,7 +485,7 @@ github.com/go-playground/locales/currency
# github.com/go-playground/universal-translator v0.18.1
## explicit; go 1.18
github.com/go-playground/universal-translator
-# github.com/go-playground/validator/v10 v10.13.0
+# github.com/go-playground/validator/v10 v10.19.0
## explicit; go 1.18
github.com/go-playground/validator/v10
# github.com/gobuffalo/flect v1.0.2
@@ -497,14 +509,17 @@ github.com/golang-jwt/jwt/v5
# github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
## explicit
github.com/golang/groupcache/lru
-# github.com/golang/protobuf v1.5.3
-## explicit; go 1.9
+# github.com/golang/protobuf v1.5.4
+## explicit; go 1.17
+github.com/golang/protobuf/descriptor
github.com/golang/protobuf/jsonpb
github.com/golang/protobuf/proto
+github.com/golang/protobuf/protoc-gen-go/descriptor
github.com/golang/protobuf/ptypes
github.com/golang/protobuf/ptypes/any
github.com/golang/protobuf/ptypes/duration
github.com/golang/protobuf/ptypes/timestamp
+github.com/golang/protobuf/ptypes/wrappers
# github.com/google/btree v1.1.2
## explicit; go 1.18
github.com/google/btree
@@ -550,18 +565,30 @@ github.com/google/gofuzz/bytesource
# github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
## explicit; go 1.13
github.com/google/shlex
-# github.com/google/uuid v1.4.0
+# github.com/google/uuid v1.6.0
## explicit
github.com/google/uuid
# github.com/gorilla/mux v1.8.0
## explicit; go 1.12
github.com/gorilla/mux
+# github.com/gorilla/websocket v1.4.2
+## explicit; go 1.12
+github.com/gorilla/websocket
# github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79
## explicit
github.com/gregjones/httpcache
+# github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
+## explicit; go 1.14
+github.com/grpc-ecosystem/go-grpc-middleware
+github.com/grpc-ecosystem/go-grpc-middleware/logging/settable
# github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
## explicit
github.com/grpc-ecosystem/go-grpc-prometheus
+# github.com/grpc-ecosystem/grpc-gateway v1.16.0
+## explicit; go 1.14
+github.com/grpc-ecosystem/grpc-gateway/internal
+github.com/grpc-ecosystem/grpc-gateway/runtime
+github.com/grpc-ecosystem/grpc-gateway/utilities
# github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2
## explicit; go 1.17
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
@@ -570,8 +597,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2/utilities
# github.com/hashicorp/go-cleanhttp v0.5.2
## explicit; go 1.13
github.com/hashicorp/go-cleanhttp
-# github.com/hashicorp/go-retryablehttp v0.7.4
-## explicit; go 1.13
+# github.com/hashicorp/go-retryablehttp v0.7.7
+## explicit; go 1.19
github.com/hashicorp/go-retryablehttp
# github.com/hashicorp/go-uuid v1.0.1
## explicit
@@ -585,15 +612,15 @@ github.com/inconshreveable/mousetrap
# github.com/jmespath/go-jmespath v0.4.0
## explicit; go 1.14
github.com/jmespath/go-jmespath
+# github.com/jonboulle/clockwork v0.2.2
+## explicit; go 1.13
+github.com/jonboulle/clockwork
# github.com/jongio/azidext/go/azidext v0.5.0
## explicit; go 1.18
github.com/jongio/azidext/go/azidext
# github.com/josharian/intern v1.0.0
## explicit; go 1.5
github.com/josharian/intern
-# github.com/jpillora/backoff v1.0.0
-## explicit; go 1.13
-github.com/jpillora/backoff
# github.com/json-iterator/go v1.1.12
## explicit; go 1.12
github.com/json-iterator/go
@@ -604,9 +631,10 @@ github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1
## explicit; go 1.11
github.com/kylelemons/godebug/diff
github.com/kylelemons/godebug/pretty
-# github.com/leodido/go-urn v1.2.3
-## explicit; go 1.16
+# github.com/leodido/go-urn v1.4.0
+## explicit; go 1.18
github.com/leodido/go-urn
+github.com/leodido/go-urn/scim/schema
# github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
## explicit
github.com/liggitt/tabwriter
@@ -647,9 +675,6 @@ github.com/monochromegane/go-gitignore
# github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
## explicit
github.com/munnerz/goautoneg
-# github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
-## explicit
-github.com/mwitkow/go-conntrack
# github.com/oklog/ulid v1.3.1
## explicit
github.com/oklog/ulid
@@ -672,7 +697,7 @@ github.com/opencontainers/go-digest
## explicit; go 1.17
github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1
-# github.com/openshift/api v0.0.0-20231206170337-f356bd9e2ff6
+# github.com/openshift/api v0.0.0-20240215031714-be926bb0d751
## explicit; go 1.20
github.com/openshift/api
github.com/openshift/api/annotations
@@ -759,8 +784,8 @@ github.com/openshift/client-go/user/applyconfigurations/internal
github.com/openshift/client-go/user/applyconfigurations/user/v1
github.com/openshift/client-go/user/clientset/versioned/scheme
github.com/openshift/client-go/user/clientset/versioned/typed/user/v1
-# github.com/openshift/cloud-credential-operator v0.0.0-20220708202639-ef451d260cf6
-## explicit; go 1.18
+# github.com/openshift/cloud-credential-operator v0.0.0-20240504012628-26d4761a9f4e
+## explicit; go 1.20
github.com/openshift/cloud-credential-operator/pkg/apis/cloudcredential/v1
github.com/openshift/cloud-credential-operator/pkg/cmd/provisioning
github.com/openshift/cloud-credential-operator/pkg/cmd/provisioning/ibmcloud
@@ -776,10 +801,12 @@ github.com/openshift/cluster-node-tuning-operator/pkg/apis/tuned/v1
# github.com/openshift/custom-resource-status v1.1.2
## explicit; go 1.12
github.com/openshift/custom-resource-status/conditions/v1
-# github.com/openshift/library-go v0.0.0-20231128230659-785a9313da6c
+# github.com/openshift/library-go v0.0.0-20231214171439-128164517bf7
## explicit; go 1.20
github.com/openshift/library-go/pkg/authorization/hardcodedauthorizer
github.com/openshift/library-go/pkg/certs
+github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphanalysis
+github.com/openshift/library-go/pkg/certs/cert-inspection/certgraphapi
github.com/openshift/library-go/pkg/config/client
github.com/openshift/library-go/pkg/config/clusterstatus
github.com/openshift/library-go/pkg/config/configdefaults
@@ -802,7 +829,6 @@ github.com/openshift/library-go/pkg/operator/resource/resourceread
github.com/openshift/library-go/pkg/operator/resourcesynccontroller
github.com/openshift/library-go/pkg/operator/v1helpers
github.com/openshift/library-go/pkg/serviceability
-github.com/openshift/library-go/test/library/metrics
# github.com/opentracing/opentracing-go v1.2.0
## explicit; go 1.14
github.com/opentracing/opentracing-go
@@ -829,6 +855,9 @@ github.com/pkg/errors
# github.com/pkg/profile v1.3.0
## explicit
github.com/pkg/profile
+# github.com/pmezard/go-difflib v1.0.0
+## explicit
+github.com/pmezard/go-difflib/difflib
# github.com/ppc64le-cloud/powervs-utils v0.0.0-20230306072409-bc42a581099f
## explicit; go 1.15
github.com/ppc64le-cloud/powervs-utils
@@ -851,7 +880,6 @@ github.com/prometheus/client_golang/prometheus/testutil/promlint
github.com/prometheus/client_model/go
# github.com/prometheus/common v0.45.0
## explicit; go 1.20
-github.com/prometheus/common/config
github.com/prometheus/common/expfmt
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
github.com/prometheus/common/model
@@ -869,6 +897,9 @@ github.com/russross/blackfriday/v2
# github.com/sirupsen/logrus v1.9.0
## explicit; go 1.13
github.com/sirupsen/logrus
+# github.com/soheilhy/cmux v0.1.5
+## explicit; go 1.11
+github.com/soheilhy/cmux
# github.com/spf13/cobra v1.8.0
## explicit; go 1.15
github.com/spf13/cobra
@@ -878,6 +909,13 @@ github.com/spf13/pflag
# github.com/stoewer/go-strcase v1.2.0
## explicit; go 1.11
github.com/stoewer/go-strcase
+# github.com/stretchr/testify v1.8.4
+## explicit; go 1.20
+github.com/stretchr/testify/assert
+github.com/stretchr/testify/require
+# github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75
+## explicit; go 1.15
+github.com/tmc/grpc-websocket-proxy/wsproxy
# github.com/tombuildsstuff/giovanni v0.18.0
## explicit; go 1.13
github.com/tombuildsstuff/giovanni/storage/2019-12-12/blob/blobs
@@ -887,33 +925,122 @@ github.com/tombuildsstuff/giovanni/version
# github.com/vincent-petithory/dataurl v1.0.0
## explicit
github.com/vincent-petithory/dataurl
+# github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2
+## explicit
+github.com/xiang90/probing
# github.com/xlab/treeprint v1.2.0
## explicit; go 1.13
github.com/xlab/treeprint
-# go.etcd.io/etcd/api/v3 v3.5.9
-## explicit; go 1.19
+# go.etcd.io/bbolt v1.3.8
+## explicit; go 1.17
+go.etcd.io/bbolt
+# go.etcd.io/etcd/api/v3 v3.5.10
+## explicit; go 1.20
go.etcd.io/etcd/api/v3/authpb
go.etcd.io/etcd/api/v3/etcdserverpb
+go.etcd.io/etcd/api/v3/etcdserverpb/gw
go.etcd.io/etcd/api/v3/membershippb
go.etcd.io/etcd/api/v3/mvccpb
go.etcd.io/etcd/api/v3/v3rpc/rpctypes
go.etcd.io/etcd/api/v3/version
-# go.etcd.io/etcd/client/pkg/v3 v3.5.9
-## explicit; go 1.19
+# go.etcd.io/etcd/client/pkg/v3 v3.5.10
+## explicit; go 1.20
go.etcd.io/etcd/client/pkg/v3/fileutil
go.etcd.io/etcd/client/pkg/v3/logutil
+go.etcd.io/etcd/client/pkg/v3/pathutil
+go.etcd.io/etcd/client/pkg/v3/srv
go.etcd.io/etcd/client/pkg/v3/systemd
+go.etcd.io/etcd/client/pkg/v3/testutil
go.etcd.io/etcd/client/pkg/v3/tlsutil
go.etcd.io/etcd/client/pkg/v3/transport
go.etcd.io/etcd/client/pkg/v3/types
-# go.etcd.io/etcd/client/v3 v3.5.9
-## explicit; go 1.19
+# go.etcd.io/etcd/client/v2 v2.305.10
+## explicit; go 1.20
+go.etcd.io/etcd/client/v2
+# go.etcd.io/etcd/client/v3 v3.5.10
+## explicit; go 1.20
go.etcd.io/etcd/client/v3
+go.etcd.io/etcd/client/v3/concurrency
go.etcd.io/etcd/client/v3/credentials
go.etcd.io/etcd/client/v3/internal/endpoint
go.etcd.io/etcd/client/v3/internal/resolver
-# go.mongodb.org/mongo-driver v1.12.1
-## explicit; go 1.13
+go.etcd.io/etcd/client/v3/namespace
+go.etcd.io/etcd/client/v3/naming/endpoints
+go.etcd.io/etcd/client/v3/naming/endpoints/internal
+# go.etcd.io/etcd/pkg/v3 v3.5.10
+## explicit; go 1.20
+go.etcd.io/etcd/pkg/v3/adt
+go.etcd.io/etcd/pkg/v3/contention
+go.etcd.io/etcd/pkg/v3/cpuutil
+go.etcd.io/etcd/pkg/v3/crc
+go.etcd.io/etcd/pkg/v3/debugutil
+go.etcd.io/etcd/pkg/v3/flags
+go.etcd.io/etcd/pkg/v3/grpc_testing
+go.etcd.io/etcd/pkg/v3/httputil
+go.etcd.io/etcd/pkg/v3/idutil
+go.etcd.io/etcd/pkg/v3/ioutil
+go.etcd.io/etcd/pkg/v3/netutil
+go.etcd.io/etcd/pkg/v3/pbutil
+go.etcd.io/etcd/pkg/v3/runtime
+go.etcd.io/etcd/pkg/v3/schedule
+go.etcd.io/etcd/pkg/v3/traceutil
+go.etcd.io/etcd/pkg/v3/wait
+# go.etcd.io/etcd/raft/v3 v3.5.10
+## explicit; go 1.20
+go.etcd.io/etcd/raft/v3
+go.etcd.io/etcd/raft/v3/confchange
+go.etcd.io/etcd/raft/v3/quorum
+go.etcd.io/etcd/raft/v3/raftpb
+go.etcd.io/etcd/raft/v3/tracker
+# go.etcd.io/etcd/server/v3 v3.5.10
+## explicit; go 1.20
+go.etcd.io/etcd/server/v3/auth
+go.etcd.io/etcd/server/v3/config
+go.etcd.io/etcd/server/v3/datadir
+go.etcd.io/etcd/server/v3/embed
+go.etcd.io/etcd/server/v3/etcdserver
+go.etcd.io/etcd/server/v3/etcdserver/api
+go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp
+go.etcd.io/etcd/server/v3/etcdserver/api/membership
+go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp
+go.etcd.io/etcd/server/v3/etcdserver/api/snap
+go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb
+go.etcd.io/etcd/server/v3/etcdserver/api/v2auth
+go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery
+go.etcd.io/etcd/server/v3/etcdserver/api/v2error
+go.etcd.io/etcd/server/v3/etcdserver/api/v2http
+go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes
+go.etcd.io/etcd/server/v3/etcdserver/api/v2stats
+go.etcd.io/etcd/server/v3/etcdserver/api/v2store
+go.etcd.io/etcd/server/v3/etcdserver/api/v2v3
+go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm
+go.etcd.io/etcd/server/v3/etcdserver/api/v3client
+go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor
+go.etcd.io/etcd/server/v3/etcdserver/api/v3election
+go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb
+go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw
+go.etcd.io/etcd/server/v3/etcdserver/api/v3lock
+go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb
+go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw
+go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc
+go.etcd.io/etcd/server/v3/etcdserver/cindex
+go.etcd.io/etcd/server/v3/lease
+go.etcd.io/etcd/server/v3/lease/leasehttp
+go.etcd.io/etcd/server/v3/lease/leasepb
+go.etcd.io/etcd/server/v3/mvcc
+go.etcd.io/etcd/server/v3/mvcc/backend
+go.etcd.io/etcd/server/v3/mvcc/buckets
+go.etcd.io/etcd/server/v3/proxy/grpcproxy
+go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter
+go.etcd.io/etcd/server/v3/proxy/grpcproxy/cache
+go.etcd.io/etcd/server/v3/verify
+go.etcd.io/etcd/server/v3/wal
+go.etcd.io/etcd/server/v3/wal/walpb
+# go.etcd.io/etcd/tests/v3 v3.5.10
+## explicit; go 1.20
+go.etcd.io/etcd/tests/v3/integration
+# go.mongodb.org/mongo-driver v1.14.0
+## explicit; go 1.18
go.mongodb.org/mongo-driver/bson
go.mongodb.org/mongo-driver/bson/bsoncodec
go.mongodb.org/mongo-driver/bson/bsonoptions
@@ -944,6 +1071,7 @@ go.opentelemetry.io/otel/semconv/internal
go.opentelemetry.io/otel/semconv/v1.12.0
go.opentelemetry.io/otel/semconv/v1.17.0
go.opentelemetry.io/otel/semconv/v1.21.0
+go.opentelemetry.io/otel/semconv/v1.4.0
# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0
## explicit; go 1.20
go.opentelemetry.io/otel/exporters/otlp/otlptrace
@@ -1000,7 +1128,7 @@ go.uber.org/zap/internal/ztest
go.uber.org/zap/zapcore
go.uber.org/zap/zapgrpc
go.uber.org/zap/zaptest
-# golang.org/x/crypto v0.16.0
+# golang.org/x/crypto v0.21.0
## explicit; go 1.18
golang.org/x/crypto/bcrypt
golang.org/x/crypto/blake2b
@@ -1027,7 +1155,7 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/exp/constraints
golang.org/x/exp/maps
golang.org/x/exp/slices
-# golang.org/x/net v0.19.0
+# golang.org/x/net v0.23.0
## explicit; go 1.18
golang.org/x/net/context
golang.org/x/net/html
@@ -1046,20 +1174,19 @@ golang.org/x/net/websocket
# golang.org/x/oauth2 v0.14.0
## explicit; go 1.18
golang.org/x/oauth2
-golang.org/x/oauth2/clientcredentials
golang.org/x/oauth2/internal
# golang.org/x/sync v0.5.0
## explicit; go 1.18
golang.org/x/sync/errgroup
golang.org/x/sync/singleflight
-# golang.org/x/sys v0.15.0
+# golang.org/x/sys v0.20.0
## explicit; go 1.18
golang.org/x/sys/cpu
golang.org/x/sys/plan9
golang.org/x/sys/unix
golang.org/x/sys/windows
golang.org/x/sys/windows/registry
-# golang.org/x/term v0.15.0
+# golang.org/x/term v0.18.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/text v0.14.0
@@ -1111,6 +1238,7 @@ google.golang.org/appengine/urlfetch
# google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5
## explicit; go 1.19
google.golang.org/genproto/internal
+google.golang.org/genproto/protobuf/field_mask
# google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5
## explicit; go 1.19
google.golang.org/genproto/googleapis/api
@@ -1140,6 +1268,7 @@ google.golang.org/grpc/encoding
google.golang.org/grpc/encoding/gzip
google.golang.org/grpc/encoding/proto
google.golang.org/grpc/grpclog
+google.golang.org/grpc/health
google.golang.org/grpc/health/grpc_health_v1
google.golang.org/grpc/internal
google.golang.org/grpc/internal/backoff
@@ -1166,6 +1295,8 @@ google.golang.org/grpc/internal/status
google.golang.org/grpc/internal/syscall
google.golang.org/grpc/internal/transport
google.golang.org/grpc/internal/transport/networktype
+google.golang.org/grpc/interop/grpc_testing
+google.golang.org/grpc/interop/grpc_testing/core
google.golang.org/grpc/keepalive
google.golang.org/grpc/metadata
google.golang.org/grpc/peer
@@ -1175,14 +1306,16 @@ google.golang.org/grpc/serviceconfig
google.golang.org/grpc/stats
google.golang.org/grpc/status
google.golang.org/grpc/tap
-# google.golang.org/protobuf v1.31.0
-## explicit; go 1.11
+# google.golang.org/protobuf v1.34.2
+## explicit; go 1.20
google.golang.org/protobuf/encoding/protojson
google.golang.org/protobuf/encoding/prototext
google.golang.org/protobuf/encoding/protowire
google.golang.org/protobuf/internal/descfmt
google.golang.org/protobuf/internal/descopts
google.golang.org/protobuf/internal/detrand
+google.golang.org/protobuf/internal/editiondefaults
+google.golang.org/protobuf/internal/editionssupport
google.golang.org/protobuf/internal/encoding/defval
google.golang.org/protobuf/internal/encoding/json
google.golang.org/protobuf/internal/encoding/messageset
@@ -1207,6 +1340,7 @@ google.golang.org/protobuf/runtime/protoiface
google.golang.org/protobuf/runtime/protoimpl
google.golang.org/protobuf/types/descriptorpb
google.golang.org/protobuf/types/dynamicpb
+google.golang.org/protobuf/types/gofeaturespb
google.golang.org/protobuf/types/known/anypb
google.golang.org/protobuf/types/known/durationpb
google.golang.org/protobuf/types/known/emptypb
@@ -1217,6 +1351,11 @@ google.golang.org/protobuf/types/known/wrapperspb
# gopkg.in/evanphx/json-patch.v5 v5.7.0
## explicit
gopkg.in/evanphx/json-patch.v5
+# gopkg.in/go-jose/go-jose.v2 v2.6.3
+## explicit
+gopkg.in/go-jose/go-jose.v2
+gopkg.in/go-jose/go-jose.v2/cipher
+gopkg.in/go-jose/go-jose.v2/json
# gopkg.in/inf.v0 v0.9.1
## explicit
gopkg.in/inf.v0
@@ -1226,11 +1365,6 @@ gopkg.in/ini.v1
# gopkg.in/natefinch/lumberjack.v2 v2.2.1
## explicit; go 1.13
gopkg.in/natefinch/lumberjack.v2
-# gopkg.in/square/go-jose.v2 v2.6.0
-## explicit
-gopkg.in/square/go-jose.v2
-gopkg.in/square/go-jose.v2/cipher
-gopkg.in/square/go-jose.v2/json
# gopkg.in/yaml.v2 v2.4.0
## explicit; go 1.15
gopkg.in/yaml.v2
@@ -1787,9 +1921,11 @@ k8s.io/client-go/tools/record
k8s.io/client-go/tools/record/util
k8s.io/client-go/tools/reference
k8s.io/client-go/tools/remotecommand
+k8s.io/client-go/tools/watch
k8s.io/client-go/transport
k8s.io/client-go/transport/spdy
k8s.io/client-go/util/cert
+k8s.io/client-go/util/certificate/csr
k8s.io/client-go/util/connrotation
k8s.io/client-go/util/exec
k8s.io/client-go/util/flowcontrol
@@ -1914,9 +2050,6 @@ kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1
# kubevirt.io/controller-lifecycle-operator-sdk v0.2.1
## explicit; go 1.14
kubevirt.io/controller-lifecycle-operator-sdk/pkg/sdk/api
-# sigs.k8s.io/apiserver-network-proxy v0.0.24
-## explicit; go 1.16
-sigs.k8s.io/apiserver-network-proxy/pkg/util
# sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 => sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.1
## explicit; go 1.20
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client
diff --git a/vendor/sigs.k8s.io/apiserver-network-proxy/pkg/util/certificates.go b/vendor/sigs.k8s.io/apiserver-network-proxy/pkg/util/certificates.go
deleted file mode 100644
index 9ac48da6c7..0000000000
--- a/vendor/sigs.k8s.io/apiserver-network-proxy/pkg/util/certificates.go
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-Copyright 2019 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES 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 (
- "crypto/tls"
- "crypto/x509"
- "fmt"
- "io/ioutil"
- "path/filepath"
-)
-
-// getCACertPool loads CA certificates to pool
-func getCACertPool(caFile string) (*x509.CertPool, error) {
- certPool := x509.NewCertPool()
- caCert, err := ioutil.ReadFile(filepath.Clean(caFile))
- if err != nil {
- return nil, fmt.Errorf("failed to read CA cert %s: %v", caFile, err)
- }
- ok := certPool.AppendCertsFromPEM(caCert)
- if !ok {
- return nil, fmt.Errorf("failed to append CA cert to the cert pool")
- }
- return certPool, nil
-}
-
-// GetClientTLSConfig returns tlsConfig based on x509 certs
-func GetClientTLSConfig(caFile, certFile, keyFile, serverName string, protos []string) (*tls.Config, error) {
- certPool, err := getCACertPool(caFile)
- if err != nil {
- return nil, err
- }
-
- tlsConfig := &tls.Config{
- RootCAs: certPool,
- MinVersion: tls.VersionTLS12,
- }
- if len(protos) != 0 {
- tlsConfig.NextProtos = protos
- }
- if certFile == "" && keyFile == "" {
- // return TLS config based on CA only
- return tlsConfig, nil
- }
-
- cert, err := tls.LoadX509KeyPair(certFile, keyFile)
- if err != nil {
- return nil, fmt.Errorf("failed to load X509 key pair %s and %s: %v", certFile, keyFile, err)
- }
-
- tlsConfig.ServerName = serverName
- tlsConfig.Certificates = []tls.Certificate{cert}
- return tlsConfig, nil
-}
diff --git a/vendor/sigs.k8s.io/apiserver-network-proxy/pkg/util/net.go b/vendor/sigs.k8s.io/apiserver-network-proxy/pkg/util/net.go
deleted file mode 100644
index 26a1d55642..0000000000
--- a/vendor/sigs.k8s.io/apiserver-network-proxy/pkg/util/net.go
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-Copyright 2020 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES 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 (
- "strings"
-)
-
-// containIPv6Addr checks if the given host identity contains an
-// IPv6 address
-func containIPv6Addr(host string) bool {
- // the shortest IPv6 address is ::
- return len(strings.Split(host, ":")) > 2
-}
-
-// containPortIPv6 checks if the host that contains an IPv6 address
-// also contains a port number
-func containPortIPv6(host string) bool {
- // based on to RFC 3986, section 3.2.2, host identified by an
- // IPv6 is distinguished by enclosing the IP literal within square
- // brackets ("[" and "]")
- return strings.ContainsRune(host, '[')
-}
-
-// RemovePortFromHost removes port number from the host address that
-// may be of the form ":" where the can be an either
-// an IPv4/6 address or a domain name
-func RemovePortFromHost(host string) string {
- if !containIPv6Addr(host) {
- return strings.Split(host, ":")[0]
- }
- if containPortIPv6(host) {
- host = host[:strings.LastIndexByte(host, ':')]
- }
- return strings.Trim(host, "[]")
-}