Bump Godeps

This commit is contained in:
Jeff Mitchell 2015-10-23 09:14:09 -04:00
parent 3dd27c3900
commit be255ad46c
51 changed files with 1484 additions and 948 deletions

66
Godeps/Godeps.json generated
View File

@ -15,58 +15,58 @@
},
{
"ImportPath": "github.com/aws/aws-sdk-go/aws",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/endpoints",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/ec2query",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/query",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/rest",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/restxml",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/internal/signer/v4",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/service/iam",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
"Comment": "v0.9.15",
"Rev": "7ab6754ddaaa7972ac1c896ddd7f796cc726e79d"
"Comment": "v0.9.16-1-g66c840e",
"Rev": "66c840e9981dd121a4239fc25e33b6c1c1caa781"
},
{
"ImportPath": "github.com/coreos/go-etcd/etcd",
@ -93,8 +93,8 @@
},
{
"ImportPath": "github.com/gocql/gocql",
"Comment": "1st_gen_framing-282-g6e86253",
"Rev": "6e86253e1c7c91bcdcfe3afd6417d3ddfbe5771c"
"Comment": "1st_gen_framing-323-g8041a37",
"Rev": "8041a37b40f2ca115d6c2902b279250eb627d7af"
},
{
"ImportPath": "github.com/golang/snappy",
@ -102,7 +102,7 @@
},
{
"ImportPath": "github.com/google/go-github/github",
"Rev": "9420d0f48acb838ccf8a7f8dde9eaee19af71132"
"Rev": "84fc80440d3bb3a82d297b827308ce11dcf047eb"
},
{
"ImportPath": "github.com/google/go-querystring/query",
@ -110,13 +110,17 @@
},
{
"ImportPath": "github.com/hashicorp/consul/api",
"Comment": "v0.5.2-334-gd6af59c",
"Rev": "d6af59cdedcc01e71bccf90061decbb724425fe5"
"Comment": "v0.5.2-469-g6a350d5",
"Rev": "6a350d5d19a41f94e0c99a933410e8545c4e7a51"
},
{
"ImportPath": "github.com/hashicorp/errwrap",
"Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55"
},
{
"ImportPath": "github.com/hashicorp/go-cleanhttp",
"Rev": "5df5ddc69534f1a4697289f1dca2193fbb40213f"
},
{
"ImportPath": "github.com/hashicorp/go-multierror",
"Rev": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5"
@ -147,8 +151,8 @@
},
{
"ImportPath": "github.com/lib/pq",
"Comment": "go1.0-cutoff-60-gffe986a",
"Rev": "ffe986aba3e6cfcded8b06615965941408891ef0"
"Comment": "go1.0-cutoff-61-g83c4f41",
"Rev": "83c4f410d0aed80a0f44bac6a576a7f2435791f3"
},
{
"ImportPath": "github.com/mitchellh/cli",
@ -213,11 +217,11 @@
},
{
"ImportPath": "golang.org/x/net/context",
"Rev": "21c3935a8fc0f954d03e6b8a560c9600ffee38d2"
"Rev": "2cba614e8ff920c60240d2677bc019af32ee04e5"
},
{
"ImportPath": "golang.org/x/oauth2",
"Rev": "ef4eca6b097fad7cec79afcc278d213a6de1c960"
"Rev": "038cb4adce85ed41e285c2e7cc6221a92bfa44aa"
},
{
"ImportPath": "gopkg.in/asn1-ber.v1",

View File

@ -7,8 +7,8 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials"
)
// The default number of retries for a service. The value of -1 indicates that
// the service specific retry default will be used.
// DefaultRetries is the default number of retries for a service. The value of
// -1 indicates that the service specific retry default will be used.
const DefaultRetries = -1
// A Config provides service configuration for service clients. By default,

View File

@ -20,7 +20,7 @@ type lener interface {
Len() int
}
// BuildContentLength builds the content length of a request based on the body,
// BuildContentLengthHandler builds the content length of a request based on the body,
// or will use the HTTPRequest.Header's "Content-Length" if defined. If unable
// to determine request body length and no "Content-Length" was specified it will panic.
var BuildContentLengthHandler = request.NamedHandler{"core.BuildContentLengthHandler", func(r *request.Request) {

View File

@ -10,7 +10,7 @@ import (
"github.com/aws/aws-sdk-go/aws/request"
)
// ValidateParameters is a request handler to validate the input parameters.
// ValidateParametersHandler is a request handler to validate the input parameters.
// Validating parameters only has meaning if done prior to the request being sent.
var ValidateParametersHandler = request.NamedHandler{"core.ValidateParametersHandler", func(r *request.Request) {
if r.ParamsFilled() {

View File

@ -53,8 +53,8 @@ import (
"time"
)
// Create an empty Credential object that can be used as dummy placeholder
// credentials for requests that do not need signed.
// AnonymousCredentials is an empty Credential object that can be used as
// dummy placeholder credentials for requests that do not need signed.
//
// This Credentials can be used to configure a service to not sign requests
// when making service API calls. For example, when accessing public

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "0.9.15"
const SDKVersion = "0.9.16"

View File

@ -3572,23 +3572,23 @@ func (c *IAM) SimulateCustomPolicyRequest(input *SimulateCustomPolicyInput) (req
return
}
// Simulate a set of IAM policies against a list of API actions and AWS resources
// to determine the policies' effective permissions. The policies are provided
// as a list of strings.
// Simulate how a set of IAM policies and optionally a resource-based policy
// works with a list of API actions and AWS resources to determine the policies'
// effective permissions. The policies are provided as strings.
//
// The simulation does not perform the API actions, it only checks the authorization
// The simulation does not perform the API actions; it only checks the authorization
// to determine if the simulated policies allow or deny the actions.
//
// If you want to simulate existing policies attached to an IAM user, group,
// or role, use SimulatePrincipalPolicy instead.
//
// Context keys are variables maintained by AWS and its services that provide
// details about the context of an API query request, and can be evaluated by
// using the Condition element of an IAM policy. To get the list of context
// keys required by the policies to simulate them correctly, use GetContextKeysForCustomPolicy.
// details about the context of an API query request. You can use the Condition
// element of an IAM policy to evaluate context keys. To get the list of context
// keys that the policies require for correct simulation, use GetContextKeysForCustomPolicy.
//
// If the output is long, you can paginate the results using the MaxItems and
// Marker parameters.
// If the output is long, you can use MaxItems and Marker parameters to paginate
// the results.
func (c *IAM) SimulateCustomPolicy(input *SimulateCustomPolicyInput) (*SimulatePolicyResponse, error) {
req, out := c.SimulateCustomPolicyRequest(input)
err := req.Send()
@ -3615,16 +3615,19 @@ func (c *IAM) SimulatePrincipalPolicyRequest(input *SimulatePrincipalPolicyInput
return
}
// Simulate the set of IAM policies attached to an IAM entity against a list
// of API actions and AWS resources to determine the policies' effective permissions.
// The entity can be an IAM user, group, or role. If you specify a user, then
// the simulation also includes all of the policies attached to groups that
// the user is a member of.
// Simulate how a set of IAM policies attached to an IAM entity works with a
// list of API actions and AWS resources to determine the policies' effective
// permissions. The entity can be an IAM user, group, or role. If you specify
// a user, then the simulation also includes all of the policies that are attached
// to groups that the user belongs to .
//
// You can optionally include a list of one or more additional policies specified
// as strings to include in the simulation. If you want to simulate only policies
// specified as strings, use SimulateCustomPolicy instead.
//
// You can also optionally include one resource-based policy to be evaluated
// with each of the resources included in the simulation.
//
// The simulation does not perform the API actions, it only checks the authorization
// to determine if the simulated policies allow or deny the actions.
//
@ -3633,12 +3636,12 @@ func (c *IAM) SimulatePrincipalPolicyRequest(input *SimulatePrincipalPolicyInput
// allowing them to use SimulateCustomPolicy instead.
//
// Context keys are variables maintained by AWS and its services that provide
// details about the context of an API query request, and can be evaluated by
// using the Condition element of an IAM policy. To get the list of context
// keys required by the policies to simulate them correctly, use GetContextKeysForPrincipalPolicy.
// details about the context of an API query request. You can use the Condition
// element of an IAM policy to evaluate context keys. To get the list of context
// keys that the policies require for correct simulation, use GetContextKeysForPrincipalPolicy.
//
// If the output is long, you can paginate the results using the MaxItems and
// Marker parameters.
// If the output is long, you can use the MaxItems and Marker parameters to
// paginate the results.
func (c *IAM) SimulatePrincipalPolicy(input *SimulatePrincipalPolicyInput) (*SimulatePolicyResponse, error) {
req, out := c.SimulatePrincipalPolicyRequest(input)
err := req.Send()
@ -6335,6 +6338,14 @@ type EvaluationResult struct {
// The result of the simulation.
EvalDecision *string `type:"string" required:"true" enum:"PolicyEvaluationDecisionType"`
// Additional details about the results of the evaluation decision. When there
// are both IAM policies and resource policies, this parameter explains how
// each set of policies contributes to the final evaluation decision. When simulating
// cross-account access to a resource, both the resource-based policy and the
// caller's IAM policy must grant access. See How IAM Roles Differ from Resource-based
// Policies
EvalDecisionDetails map[string]*string `type:"map"`
// The ARN of the resource that the indicated API action was tested on.
EvalResourceName *string `min:"1" type:"string" required:"true"`
@ -6471,19 +6482,19 @@ type GetAccountAuthorizationDetailsInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
metadataGetAccountAuthorizationDetailsInput `json:"-" xml:"-"`
@ -6901,19 +6912,19 @@ type GetGroupInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
metadataGetGroupInput `json:"-" xml:"-"`
@ -7757,19 +7768,19 @@ func (s InstanceProfile) GoString() string {
type ListAccessKeysInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the user.
@ -7829,19 +7840,19 @@ func (s ListAccessKeysOutput) GoString() string {
type ListAccountAliasesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
metadataListAccountAliasesInput `json:"-" xml:"-"`
@ -7902,19 +7913,19 @@ type ListAttachedGroupPoliciesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. This parameter is optional. If
@ -7975,19 +7986,19 @@ func (s ListAttachedGroupPoliciesOutput) GoString() string {
type ListAttachedRolePoliciesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. This parameter is optional. If
@ -8051,19 +8062,19 @@ func (s ListAttachedRolePoliciesOutput) GoString() string {
type ListAttachedUserPoliciesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. This parameter is optional. If
@ -8134,19 +8145,19 @@ type ListEntitiesForPolicyInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. This parameter is optional. If
@ -8223,19 +8234,19 @@ type ListGroupPoliciesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
metadataListGroupPoliciesInput `json:"-" xml:"-"`
@ -8292,19 +8303,19 @@ func (s ListGroupPoliciesOutput) GoString() string {
type ListGroupsForUserInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the user to list groups for.
@ -8364,19 +8375,19 @@ func (s ListGroupsForUserOutput) GoString() string {
type ListGroupsInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. For example, the prefix /division_abc/subdivision_xyz/
@ -8440,19 +8451,19 @@ func (s ListGroupsOutput) GoString() string {
type ListInstanceProfilesForRoleInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the role to list instance profiles for.
@ -8512,19 +8523,19 @@ func (s ListInstanceProfilesForRoleOutput) GoString() string {
type ListInstanceProfilesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. For example, the prefix /application_abc/component_xyz/
@ -8588,19 +8599,19 @@ func (s ListInstanceProfilesOutput) GoString() string {
type ListMFADevicesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the user whose MFA devices you want to list.
@ -8700,19 +8711,19 @@ func (s ListOpenIDConnectProvidersOutput) GoString() string {
type ListPoliciesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// A flag to filter the results to only the attached policies.
@ -8789,19 +8800,19 @@ func (s ListPoliciesOutput) GoString() string {
type ListPolicyVersionsInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
@ -8869,19 +8880,19 @@ func (s ListPolicyVersionsOutput) GoString() string {
type ListRolePoliciesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the role to list policies for.
@ -8941,19 +8952,19 @@ func (s ListRolePoliciesOutput) GoString() string {
type ListRolesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. For example, the prefix /application_abc/component_xyz/
@ -9057,19 +9068,19 @@ func (s ListSAMLProvidersOutput) GoString() string {
type ListSSHPublicKeysInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the IAM user to list SSH public keys for. If none is specified,
@ -9131,19 +9142,19 @@ func (s ListSSHPublicKeysOutput) GoString() string {
type ListServerCertificatesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. For example: /company/servercerts
@ -9207,19 +9218,19 @@ func (s ListServerCertificatesOutput) GoString() string {
type ListSigningCertificatesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the user.
@ -9279,19 +9290,19 @@ func (s ListSigningCertificatesOutput) GoString() string {
type ListUserPoliciesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The name of the user to list policies for.
@ -9351,19 +9362,19 @@ func (s ListUserPoliciesOutput) GoString() string {
type ListUsersInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// The path prefix for filtering the results. For example: /division_abc/subdivision_xyz/,
@ -9432,19 +9443,19 @@ type ListVirtualMFADevicesInput struct {
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
metadataListVirtualMFADevicesInput `json:"-" xml:"-"`
@ -10693,35 +10704,48 @@ func (s SigningCertificate) GoString() string {
type SimulateCustomPolicyInput struct {
// A list of names of API actions to evaluate in the simulation. Each action
// is evaluated for each resource. Each action must include the service identifier,
// such as iam:CreateUser.
// is evaluated against each resource. Each action must include the service
// identifier, such as iam:CreateUser.
ActionNames []*string `type:"list" required:"true"`
// A list of context keys and corresponding values that are used by the simulation.
// The ARN of the user that you want to use as the simulated caller of the APIs.
// CallerArn is required if you include a ResourcePolicy so that the policy's
// Principal element has a value to use in evaluating the policy.
//
// You can specify only the ARN of an IAM user. You cannot specify the ARN
// of an assumed role, federated user, or a service principal.
CallerArn *string `min:"1" type:"string"`
// A list of context keys and corresponding values for the simulation to use.
// Whenever a context key is evaluated by a Condition element in one of the
// simulated IAM permission policies, the corresponding value is supplied.
ContextEntries []*ContextEntry `type:"list"`
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// A list of policy documents to include in the simulation. Each document is
// specified as a string containing the complete, valid JSON text of an IAM
// policy.
// policy. Do not include any resource-based policies in this parameter. Any
// resource-based policy must be submitted with the ResourcePolicy parameter.
// The policies cannot be "scope-down" policies, such as you could include in
// a call to GetFederationToken (http://docs.aws.amazon.com/IAM/latest/APIReference/API_GetFederationToken.html)
// or one of the AssumeRole (http://docs.aws.amazon.com/IAM/latest/APIReference/API_AssumeRole.html)
// APIs to restrict what a user can do while using the temporary credentials.
PolicyInputList []*string `type:"list" required:"true"`
// A list of ARNs of AWS resources to include in the simulation. If this parameter
@ -10729,8 +10753,31 @@ type SimulateCustomPolicyInput struct {
// the ActionNames parameter is evaluated for each resource in this list. The
// simulation determines the access result (allowed or denied) of each combination
// and reports it in the response.
//
// The simulation does not automatically retrieve policies for the specified
// resources. If you want to include a resource policy in the simulation, then
// you must include the policy as a string in the ResourcePolicy parameter.
//
// If you include a ResourcePolicy, then it must be applicable to all of the
// resources included in the simulation or you receive an invalid input error.
ResourceArns []*string `type:"list"`
// An AWS account ID that specifies the owner of any simulated resource that
// does not identify its owner in the resource ARN, such as an S3 bucket or
// object. If ResourceOwner is specified, it is also used as the account owner
// of any ResourcePolicy included in the simulation. If the ResourceOwner parameter
// is not specified, then the owner of the resources and the resource policy
// defaults to the account of the identity provided in CallerArn. This parameter
// is required only if you specify a resource-based policy and account that
// owns the resource is different from the account that owns the simulated calling
// user CallerArn.
ResourceOwner *string `min:"1" type:"string"`
// A resource-based policy to include in the simulation provided as a string.
// Each resource in the simulation is treated as if it had this policy attached.
// You can include only one resource-based policy in a simulation.
ResourcePolicy *string `min:"1" type:"string"`
metadataSimulateCustomPolicyInput `json:"-" xml:"-"`
}
@ -10789,26 +10836,41 @@ type SimulatePrincipalPolicyInput struct {
// such as iam:CreateUser.
ActionNames []*string `type:"list" required:"true"`
// A list of context keys and corresponding values that are used by the simulation.
// The ARN of the user that you want to specify as the simulated caller of the
// APIs. If you do not specify a CallerArn, it defaults to the ARN of the user
// that you specify in PolicySourceArn, if you specified a user. If you include
// both a PolicySourceArn (for example, arn:aws:iam::123456789012:user/David)
// and a CallerArn (for example, arn:aws:iam::123456789012:user/Bob), the result
// is that you simulate calling the APIs as Bob, as if Bob had David's policies.
//
// You can specify only the ARN of an IAM user. You cannot specify the ARN
// of an assumed role, federated user, or a service principal.
//
// CallerArn is required if you include a ResourcePolicy and the PolicySourceArn
// is not the ARN for an IAM user. This is required so that the resource-based
// policy's Principal element has a value to use in evaluating the policy.
CallerArn *string `min:"1" type:"string"`
// A list of context keys and corresponding values for the simulation to use.
// Whenever a context key is evaluated by a Condition element in one of the
// simulated IAM permission policies, the corresponding value is supplied.
// simulated policies, the corresponding value is supplied.
ContextEntries []*ContextEntry `type:"list"`
// Use this parameter only when paginating results and only after you receive
// a response indicating that the results are truncated. Set it to the value
// of the Marker element in the response you received to inform the next call
// about where to start.
// of the Marker element in the response that you received to indicate where
// the next call should start.
Marker *string `min:"1" type:"string"`
// Use this only when paginating results to indicate the maximum number of items
// you want in the response. If there are additional items beyond the maximum
// you specify, the IsTruncated response element is true.
// you want in the response. If additional items exist beyond the maximum you
// specify, the IsTruncated response element is true.
//
// This parameter is optional. If you do not include it, it defaults to 100.
// Note that IAM might return fewer results, even when there are more results
// available. If this is the case, the IsTruncated response element returns
// true and Marker contains a value to include in the subsequent call that tells
// the service where to continue from.
// available. In that case, the IsTruncated response element returns true and
// Marker contains a value to include in the subsequent call that tells the
// service where to continue from.
MaxItems *int64 `min:"1" type:"integer"`
// An optional list of additional policy documents to include in the simulation.
@ -10818,9 +10880,9 @@ type SimulatePrincipalPolicyInput struct {
// The Amazon Resource Name (ARN) of a user, group, or role whose policies you
// want to include in the simulation. If you specify a user, group, or role,
// the simulation includes all policies associated with that entity. If you
// specify a user, the simulation also includes all policies attached to any
// groups the user is a member of.
// the simulation includes all policies that are associated with that entity.
// If you specify a user, the simulation also includes all policies that are
// attached to any groups the user belongs to.
PolicySourceArn *string `min:"20" type:"string" required:"true"`
// A list of ARNs of AWS resources to include in the simulation. If this parameter
@ -10828,8 +10890,28 @@ type SimulatePrincipalPolicyInput struct {
// the ActionNames parameter is evaluated for each resource in this list. The
// simulation determines the access result (allowed or denied) of each combination
// and reports it in the response.
//
// The simulation does not automatically retrieve policies for the specified
// resources. If you want to include a resource policy in the simulation, then
// you must include the policy as a string in the ResourcePolicy parameter.
ResourceArns []*string `type:"list"`
// An AWS account ID that specifies the owner of any simulated resource that
// does not identify its owner in the resource ARN, such as an S3 bucket or
// object. If ResourceOwner is specified, it is also used as the account owner
// of any ResourcePolicy included in the simulation. If the ResourceOwner parameter
// is not specified, then the owner of the resources and the resource policy
// defaults to the account of the identity provided in CallerArn. This parameter
// is required only if you specify a resource-based policy and account that
// owns the resource is different from the account that owns the simulated calling
// user CallerArn.
ResourceOwner *string `min:"1" type:"string"`
// A resource-based policy to include in the simulation provided as a string.
// Each resource in the simulation is treated as if it had this policy attached.
// You can include only one resource-based policy in a simulation.
ResourcePolicy *string `min:"1" type:"string"`
metadataSimulatePrincipalPolicyInput `json:"-" xml:"-"`
}
@ -11831,6 +11913,8 @@ const (
// @enum PolicySourceType
PolicySourceTypeUserManaged = "user-managed"
// @enum PolicySourceType
PolicySourceTypeResource = "resource"
// @enum PolicySourceType
PolicySourceTypeNone = "none"
)

View File

@ -13,13 +13,16 @@ import (
"github.com/aws/aws-sdk-go/service/s3/s3iface"
)
// The default range of bytes to get at a time when using Download().
// DefaultDownloadPartSize is the default range of bytes to get at a time when
// using Download().
var DefaultDownloadPartSize int64 = 1024 * 1024 * 5
// The default number of goroutines to spin up when using Download().
// DefaultDownloadConcurrency is the default number of goroutines to spin up
// when using Download().
var DefaultDownloadConcurrency = 5
// The default set of options used when opts is nil in Download().
// DefaultDownloadOptions is the default set of options used when opts is nil
// in Download().
var DefaultDownloadOptions = &DownloadOptions{
PartSize: DefaultDownloadPartSize,
Concurrency: DefaultDownloadConcurrency,

View File

@ -14,19 +14,24 @@ import (
"github.com/aws/aws-sdk-go/service/s3/s3iface"
)
// The maximum allowed number of parts in a multi-part upload on Amazon S3.
// MaxUploadParts is the maximum allowed number of parts in a multi-part upload
// on Amazon S3.
var MaxUploadParts = 10000
// The minimum allowed part size when uploading a part to Amazon S3.
// MinUploadPartSize is the minimum allowed part size when uploading a part to
// Amazon S3.
var MinUploadPartSize int64 = 1024 * 1024 * 5
// The default part size to buffer chunks of a payload into.
// DefaultUploadPartSize is the default part size to buffer chunks of a
// payload into.
var DefaultUploadPartSize = MinUploadPartSize
// The default number of goroutines to spin up when using Upload().
// DefaultUploadConcurrency is the default number of goroutines to spin up when
// using Upload().
var DefaultUploadConcurrency = 5
// The default set of options used when opts is nil in Upload().
// DefaultUploadOptions is the default set of options used when opts is nil in
// Upload().
var DefaultUploadOptions = &UploadOptions{
PartSize: DefaultUploadPartSize,
Concurrency: DefaultUploadConcurrency,

View File

@ -13,10 +13,14 @@ env:
global:
- GOMAXPROCS=2
matrix:
- CASS=2.0.17 AUTH=false
- CASS=2.1.9 AUTH=false
- CASS=2.1.9 AUTH=true
- CASS=2.2.1 AUTH=false
- CASS=2.0.17
AUTH=false
- CASS=2.1.11
AUTH=false
- CASS=2.1.11
AUTH=true
- CASS=2.2.3
AUTH=false
go:
- 1.4
@ -35,7 +39,7 @@ install:
script:
- set -e
- go test -v -tags unit
- PATH=$PATH:$HOME/.local/bin bash -x integration.sh $CASS $AUTH
- PATH=$PATH:$HOME/.local/bin bash integration.sh $CASS $AUTH
- go vet .
notifications:

View File

@ -55,3 +55,4 @@ Adrian Casajus <adriancasajus@gmail.com>
John Weldon <johnweldon4@gmail.com>
Adrien Bustany <adrien@bustany.org>
Andrey Smirnov <smirnov.andrey@gmail.com>
Adam Weiner <adamsweiner@gmail.com>

View File

@ -50,6 +50,33 @@ type DiscoveryConfig struct {
Sleep time.Duration
}
// PoolConfig configures the connection pool used by the driver, it defaults to
// using a round robbin host selection policy and a round robbin connection selection
// policy for each host.
type PoolConfig struct {
// HostSelectionPolicy sets the policy for selecting which host to use for a
// given query (default: RoundRobinHostPolicy())
HostSelectionPolicy HostSelectionPolicy
// ConnSelectionPolicy sets the policy factory for selecting a connection to use for
// each host for a query (default: RoundRobinConnPolicy())
ConnSelectionPolicy func() ConnSelectionPolicy
}
func (p PoolConfig) buildPool(cfg *ClusterConfig) (*policyConnPool, error) {
hostSelection := p.HostSelectionPolicy
if hostSelection == nil {
hostSelection = RoundRobinHostPolicy()
}
connSelection := p.ConnSelectionPolicy
if connSelection == nil {
connSelection = RoundRobinConnPolicy()
}
return newPolicyConnPool(cfg, hostSelection, connSelection)
}
// ClusterConfig is a struct to configure the default cluster implementation
// of gocoql. It has a varity of attributes that can be used to modify the
// behavior to fit the most common use cases. Applications that requre a
@ -68,7 +95,6 @@ type ClusterConfig struct {
Authenticator Authenticator // authenticator (default: nil)
RetryPolicy RetryPolicy // Default retry policy to use for queries (default: 0)
SocketKeepalive time.Duration // The keepalive period to use, enabled if > 0 (default: 0)
ConnPoolType NewPoolFunc // The function used to create the connection pool for the session (default: NewSimplePool)
DiscoverHosts bool // If set, gocql will attempt to automatically discover other members of the Cassandra cluster (default: false)
MaxPreparedStmts int // Sets the maximum cache size for prepared statements globally for gocql (default: 1000)
MaxRoutingKeyInfo int // Sets the maximum cache size for query info about statements for each session (default: 1000)
@ -77,6 +103,12 @@ type ClusterConfig struct {
Discovery DiscoveryConfig
SslOpts *SslOptions
DefaultTimestamp bool // Sends a client side timestamp for all requests which overrides the timestamp at which it arrives at the server. (default: true, only enabled for protocol 3 and above)
// PoolConfig configures the underlying connection pool, allowing the
// configuration of host selection and connection selection policies.
PoolConfig PoolConfig
// internal config for testing
disableControlConn bool
}
// NewCluster generates a new config for the default cluster implementation.
@ -89,7 +121,6 @@ func NewCluster(hosts ...string) *ClusterConfig {
Port: 9042,
NumConns: 2,
Consistency: Quorum,
ConnPoolType: NewSimplePool,
DiscoverHosts: false,
MaxPreparedStmts: defaultMaxPreparedStmts,
MaxRoutingKeyInfo: 1000,

View File

@ -99,6 +99,7 @@ type Conn struct {
conn net.Conn
r *bufio.Reader
timeout time.Duration
cfg *ConnConfig
headerBuf []byte
@ -121,7 +122,7 @@ type Conn struct {
// Connect establishes a connection to a Cassandra node.
// You must also call the Serve method before you can execute any queries.
func Connect(addr string, cfg ConnConfig, errorHandler ConnErrorHandler) (*Conn, error) {
func Connect(addr string, cfg *ConnConfig, errorHandler ConnErrorHandler) (*Conn, error) {
var (
err error
conn net.Conn
@ -166,6 +167,7 @@ func Connect(addr string, cfg ConnConfig, errorHandler ConnErrorHandler) (*Conn,
c := &Conn{
conn: conn,
r: bufio.NewReader(conn),
cfg: cfg,
uniq: make(chan int, cfg.NumStreams),
calls: make([]callReq, cfg.NumStreams),
timeout: cfg.Timeout,
@ -191,7 +193,7 @@ func Connect(addr string, cfg ConnConfig, errorHandler ConnErrorHandler) (*Conn,
go c.serve()
if err := c.startup(&cfg); err != nil {
if err := c.startup(); err != nil {
conn.Close()
return nil, err
}
@ -231,16 +233,21 @@ func (c *Conn) Read(p []byte) (n int, err error) {
return
}
func (c *Conn) startup(cfg *ConnConfig) error {
func (c *Conn) startup() error {
m := map[string]string{
"CQL_VERSION": cfg.CQLVersion,
"CQL_VERSION": c.cfg.CQLVersion,
}
if c.compressor != nil {
m["COMPRESSION"] = c.compressor.Name()
}
frame, err := c.exec(&writeStartupFrame{opts: m}, nil)
framer, err := c.exec(&writeStartupFrame{opts: m}, nil)
if err != nil {
return err
}
frame, err := framer.parseFrame()
if err != nil {
return err
}
@ -270,7 +277,12 @@ func (c *Conn) authenticateHandshake(authFrame *authenticateFrame) error {
req := &writeAuthResponseFrame{data: resp}
for {
frame, err := c.exec(req, nil)
framer, err := c.exec(req, nil)
if err != nil {
return err
}
frame, err := framer.parseFrame()
if err != nil {
return err
}
@ -295,6 +307,8 @@ func (c *Conn) authenticateHandshake(authFrame *authenticateFrame) error {
default:
return fmt.Errorf("unknown frame response during authentication: %v", v)
}
framerPool.Put(framer)
}
}
@ -385,6 +399,7 @@ func (c *Conn) recv() error {
if err := framer.readFrame(&head); err != nil {
return err
}
defer framerPool.Put(framer)
frame, err := framer.parseFrame()
if err != nil {
@ -435,7 +450,6 @@ type callReq struct {
func (c *Conn) releaseStream(stream int) {
call := &c.calls[stream]
framerPool.Put(call.framer)
call.framer = nil
select {
@ -450,7 +464,7 @@ func (c *Conn) handleTimeout() {
}
}
func (c *Conn) exec(req frameWriter, tracer Tracer) (frame, error) {
func (c *Conn) exec(req frameWriter, tracer Tracer) (*framer, error) {
// TODO: move tracer onto conn
var stream int
select {
@ -512,19 +526,10 @@ func (c *Conn) exec(req frameWriter, tracer Tracer) (frame, error) {
return nil, NewErrProtocol("unexpected protocol version in response: got %d expected %d", v, c.version)
}
frame, err := framer.parseFrame()
if err != nil {
return nil, err
}
if len(framer.traceID) > 0 {
tracer.Trace(framer.traceID)
}
return frame, nil
return framer, nil
}
func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame, error) {
func (c *Conn) prepareStatement(stmt string, tracer Tracer) (*QueryInfo, error) {
stmtsLRU.Lock()
if stmtsLRU.lru == nil {
initStmtsLRU(defaultMaxPreparedStmts)
@ -536,7 +541,7 @@ func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame
stmtsLRU.Unlock()
flight := val.(*inflightPrepare)
flight.wg.Wait()
return flight.info, flight.err
return &flight.info, flight.err
}
flight := new(inflightPrepare)
@ -548,16 +553,36 @@ func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame
statement: stmt,
}
resp, err := c.exec(prep, trace)
framer, err := c.exec(prep, tracer)
if err != nil {
flight.err = err
flight.wg.Done()
return nil, err
}
switch x := resp.(type) {
frame, err := framer.parseFrame()
if err != nil {
flight.err = err
flight.wg.Done()
return nil, err
}
// TODO(zariel): tidy this up, simplify handling of frame parsing so its not duplicated
// everytime we need to parse a frame.
if len(framer.traceID) > 0 {
tracer.Trace(framer.traceID)
}
switch x := frame.(type) {
case *resultPreparedFrame:
flight.info = x
// defensivly copy as we will recycle the underlying buffer after we
// return.
flight.info.Id = copyBytes(x.preparedID)
// the type info's should _not_ have a reference to the framers read buffer,
// therefore we can just copy them directly.
flight.info.Args = x.reqMeta.columns
flight.info.PKeyColumns = x.reqMeta.pkeyColumns
flight.info.Rval = x.respMeta.columns
case error:
flight.err = x
default:
@ -571,7 +596,9 @@ func (c *Conn) prepareStatement(stmt string, trace Tracer) (*resultPreparedFrame
stmtsLRU.Unlock()
}
return flight.info, flight.err
framerPool.Put(framer)
return &flight.info, flight.err
}
func (c *Conn) executeQuery(qry *Query) *Iter {
@ -603,24 +630,19 @@ func (c *Conn) executeQuery(qry *Query) *Iter {
if qry.binding == nil {
values = qry.values
} else {
binding := &QueryInfo{
Id: info.preparedID,
Args: info.reqMeta.columns,
Rval: info.respMeta.columns,
}
values, err = qry.binding(binding)
values, err = qry.binding(info)
if err != nil {
return &Iter{err: err}
}
}
if len(values) != len(info.reqMeta.columns) {
if len(values) != len(info.Args) {
return &Iter{err: ErrQueryArgLength}
}
params.values = make([]queryValues, len(values))
for i := 0; i < len(values); i++ {
val, err := Marshal(info.reqMeta.columns[i].TypeInfo, values[i])
val, err := Marshal(info.Args[i].TypeInfo, values[i])
if err != nil {
return &Iter{err: err}
}
@ -631,7 +653,7 @@ func (c *Conn) executeQuery(qry *Query) *Iter {
}
frame = &writeExecuteFrame{
preparedID: info.preparedID,
preparedID: info.Id,
params: params,
}
} else {
@ -641,18 +663,28 @@ func (c *Conn) executeQuery(qry *Query) *Iter {
}
}
resp, err := c.exec(frame, qry.trace)
framer, err := c.exec(frame, qry.trace)
if err != nil {
return &Iter{err: err}
}
resp, err := framer.parseFrame()
if err != nil {
return &Iter{err: err}
}
if len(framer.traceID) > 0 {
qry.trace.Trace(framer.traceID)
}
switch x := resp.(type) {
case *resultVoidFrame:
return &Iter{}
return &Iter{framer: framer}
case *resultRowsFrame:
iter := &Iter{
meta: x.meta,
rows: x.rows,
meta: x.meta,
rows: x.rows,
framer: framer,
}
if len(x.meta.pagingState) > 0 && !qry.disableAutoPage {
@ -668,8 +700,8 @@ func (c *Conn) executeQuery(qry *Query) *Iter {
}
return iter
case *resultKeyspaceFrame, *resultSchemaChangeFrame, *schemaChangeKeyspace, *schemaChangeTable:
return &Iter{}
case *resultKeyspaceFrame, *resultSchemaChangeFrame, *schemaChangeKeyspace, *schemaChangeTable, *schemaChangeFunction:
return &Iter{framer: framer}
case *RequestErrUnprepared:
stmtsLRU.Lock()
stmtCacheKey := c.addr + c.currentKeyspace + qry.stmt
@ -679,11 +711,14 @@ func (c *Conn) executeQuery(qry *Query) *Iter {
return c.executeQuery(qry)
}
stmtsLRU.Unlock()
return &Iter{err: x}
return &Iter{err: x, framer: framer}
case error:
return &Iter{err: x}
return &Iter{err: x, framer: framer}
default:
return &Iter{err: NewErrProtocol("Unknown type in response to execute query (%T): %s", x, x)}
return &Iter{
err: NewErrProtocol("Unknown type in response to execute query (%T): %s", x, x),
framer: framer,
}
}
}
@ -710,7 +745,12 @@ func (c *Conn) UseKeyspace(keyspace string) error {
q := &writeQueryFrame{statement: `USE "` + keyspace + `"`}
q.params.consistency = Any
resp, err := c.exec(q, nil)
framer, err := c.exec(q, nil)
if err != nil {
return err
}
resp, err := framer.parseFrame()
if err != nil {
return err
}
@ -728,9 +768,9 @@ func (c *Conn) UseKeyspace(keyspace string) error {
return nil
}
func (c *Conn) executeBatch(batch *Batch) error {
func (c *Conn) executeBatch(batch *Batch) (*Iter, error) {
if c.version == protoVersion1 {
return ErrUnsupported
return nil, ErrUnsupported
}
n := len(batch.Entries)
@ -750,37 +790,32 @@ func (c *Conn) executeBatch(batch *Batch) error {
if len(entry.Args) > 0 || entry.binding != nil {
info, err := c.prepareStatement(entry.Stmt, nil)
if err != nil {
return err
return nil, err
}
var args []interface{}
if entry.binding == nil {
args = entry.Args
} else {
binding := &QueryInfo{
Id: info.preparedID,
Args: info.reqMeta.columns,
Rval: info.respMeta.columns,
}
args, err = entry.binding(binding)
args, err = entry.binding(info)
if err != nil {
return err
return nil, err
}
}
if len(args) != len(info.reqMeta.columns) {
return ErrQueryArgLength
if len(args) != len(info.Args) {
return nil, ErrQueryArgLength
}
b.preparedID = info.preparedID
stmts[string(info.preparedID)] = entry.Stmt
b.preparedID = info.Id
stmts[string(info.Id)] = entry.Stmt
b.values = make([]queryValues, len(info.reqMeta.columns))
b.values = make([]queryValues, len(info.Args))
for j := 0; j < len(info.reqMeta.columns); j++ {
val, err := Marshal(info.reqMeta.columns[j].TypeInfo, args[j])
for j := 0; j < len(info.Args); j++ {
val, err := Marshal(info.Args[j].TypeInfo, args[j])
if err != nil {
return err
return nil, err
}
b.values[j].value = val
@ -792,14 +827,20 @@ func (c *Conn) executeBatch(batch *Batch) error {
}
// TODO: should batch support tracing?
resp, err := c.exec(req, nil)
framer, err := c.exec(req, nil)
if err != nil {
return err
return nil, err
}
resp, err := framer.parseFrame()
if err != nil {
return nil, err
}
switch x := resp.(type) {
case *resultVoidFrame:
return nil
framerPool.Put(framer)
return nil, nil
case *RequestErrUnprepared:
stmt, found := stmts[string(x.StatementId)]
if found {
@ -807,15 +848,28 @@ func (c *Conn) executeBatch(batch *Batch) error {
stmtsLRU.lru.Remove(c.addr + c.currentKeyspace + stmt)
stmtsLRU.Unlock()
}
framerPool.Put(framer)
if found {
return c.executeBatch(batch)
} else {
return x
return nil, x
}
case *resultRowsFrame:
iter := &Iter{
meta: x.meta,
rows: x.rows,
framer: framer,
}
return iter, nil
case error:
return x
framerPool.Put(framer)
return nil, x
default:
return NewErrProtocol("Unknown type in response to batch statement: %s", x)
framerPool.Put(framer)
return nil, NewErrProtocol("Unknown type in response to batch statement: %s", x)
}
}
@ -833,7 +887,7 @@ func (c *Conn) setKeepalive(d time.Duration) error {
}
type inflightPrepare struct {
info *resultPreparedFrame
info QueryInfo
err error
wg sync.WaitGroup
}

View File

@ -17,89 +17,6 @@ import (
"time"
)
/*ConnectionPool represents the interface gocql will use to work with a collection of connections.
Purpose
The connection pool in gocql opens and closes connections as well as selects an available connection
for gocql to execute a query against. The pool is also responsible for handling connection errors that
are caught by the connection experiencing the error.
A connection pool should make a copy of the variables used from the ClusterConfig provided to the pool
upon creation. ClusterConfig is a pointer and can be modified after the creation of the pool. This can
lead to issues with variables being modified outside the expectations of the ConnectionPool type.
Example of Single Connection Pool:
type SingleConnection struct {
conn *Conn
cfg *ClusterConfig
}
func NewSingleConnection(cfg *ClusterConfig) ConnectionPool {
addr := JoinHostPort(cfg.Hosts[0], cfg.Port)
connCfg := ConnConfig{
ProtoVersion: cfg.ProtoVersion,
CQLVersion: cfg.CQLVersion,
Timeout: cfg.Timeout,
NumStreams: cfg.NumStreams,
Compressor: cfg.Compressor,
Authenticator: cfg.Authenticator,
Keepalive: cfg.SocketKeepalive,
}
pool := SingleConnection{cfg:cfg}
pool.conn = Connect(addr,connCfg,pool)
return &pool
}
func (s *SingleConnection) HandleError(conn *Conn, err error, closed bool) {
if closed {
connCfg := ConnConfig{
ProtoVersion: cfg.ProtoVersion,
CQLVersion: cfg.CQLVersion,
Timeout: cfg.Timeout,
NumStreams: cfg.NumStreams,
Compressor: cfg.Compressor,
Authenticator: cfg.Authenticator,
Keepalive: cfg.SocketKeepalive,
}
s.conn = Connect(conn.Address(),connCfg,s)
}
}
func (s *SingleConnection) Pick(qry *Query) *Conn {
if s.conn.isClosed {
return nil
}
return s.conn
}
func (s *SingleConnection) Size() int {
return 1
}
func (s *SingleConnection) Close() {
s.conn.Close()
}
This is a very simple example of a type that exposes the connection pool interface. To assign
this type as the connection pool to use you would assign it to the ClusterConfig like so:
cluster := NewCluster("127.0.0.1")
cluster.ConnPoolType = NewSingleConnection
...
session, err := cluster.CreateSession()
To see a more complete example of a ConnectionPool implementation please see the SimplePool type.
*/
type ConnectionPool interface {
SetHosts
Pick(*Query) *Conn
Size() int
Close()
}
// interface to implement to receive the host information
type SetHosts interface {
SetHosts(hosts []HostInfo)
@ -110,35 +27,6 @@ type SetPartitioner interface {
SetPartitioner(partitioner string)
}
//NewPoolFunc is the type used by ClusterConfig to create a pool of a specific type.
type NewPoolFunc func(*ClusterConfig) (ConnectionPool, error)
//SimplePool is the current implementation of the connection pool inside gocql. This
//pool is meant to be a simple default used by gocql so users can get up and running
//quickly.
type SimplePool struct {
cfg *ClusterConfig
hostPool *RoundRobin
connPool map[string]*RoundRobin
conns map[*Conn]struct{}
keyspace string
hostMu sync.RWMutex
// this is the set of current hosts which the pool will attempt to connect to
hosts map[string]*HostInfo
// protects hostpool, connPoll, conns, quit
mu sync.Mutex
cFillingPool chan int
quit bool
quitWait chan bool
quitOnce sync.Once
tlsConfig *tls.Config
}
func setupTLSConfig(sslOpts *SslOptions) (*tls.Config, error) {
// ca cert is optional
if sslOpts.CaPath != "" {
@ -169,313 +57,10 @@ func setupTLSConfig(sslOpts *SslOptions) (*tls.Config, error) {
return &sslOpts.Config, nil
}
//NewSimplePool is the function used by gocql to create the simple connection pool.
//This is the default if no other pool type is specified.
func NewSimplePool(cfg *ClusterConfig) (ConnectionPool, error) {
pool := &SimplePool{
cfg: cfg,
hostPool: NewRoundRobin(),
connPool: make(map[string]*RoundRobin),
conns: make(map[*Conn]struct{}),
quitWait: make(chan bool),
cFillingPool: make(chan int, 1),
keyspace: cfg.Keyspace,
hosts: make(map[string]*HostInfo),
}
for _, host := range cfg.Hosts {
// seed hosts have unknown topology
// TODO: Handle populating this during SetHosts
pool.hosts[host] = &HostInfo{Peer: host}
}
if cfg.SslOpts != nil {
config, err := setupTLSConfig(cfg.SslOpts)
if err != nil {
return nil, err
}
pool.tlsConfig = config
}
//Walk through connecting to hosts. As soon as one host connects
//defer the remaining connections to cluster.fillPool()
for i := 0; i < len(cfg.Hosts); i++ {
addr := JoinHostPort(cfg.Hosts[i], cfg.Port)
if pool.connect(addr) == nil {
pool.cFillingPool <- 1
go pool.fillPool()
break
}
}
return pool, nil
}
func (c *SimplePool) connect(addr string) error {
cfg := ConnConfig{
ProtoVersion: c.cfg.ProtoVersion,
CQLVersion: c.cfg.CQLVersion,
Timeout: c.cfg.Timeout,
NumStreams: c.cfg.NumStreams,
Compressor: c.cfg.Compressor,
Authenticator: c.cfg.Authenticator,
Keepalive: c.cfg.SocketKeepalive,
tlsConfig: c.tlsConfig,
}
conn, err := Connect(addr, cfg, c)
if err != nil {
log.Printf("connect: failed to connect to %q: %v", addr, err)
return err
}
return c.addConn(conn)
}
func (c *SimplePool) addConn(conn *Conn) error {
c.mu.Lock()
defer c.mu.Unlock()
if c.quit {
conn.Close()
return nil
}
//Set the connection's keyspace if any before adding it to the pool
if c.keyspace != "" {
if err := conn.UseKeyspace(c.keyspace); err != nil {
log.Printf("error setting connection keyspace. %v", err)
conn.Close()
return err
}
}
connPool := c.connPool[conn.Address()]
if connPool == nil {
connPool = NewRoundRobin()
c.connPool[conn.Address()] = connPool
c.hostPool.AddNode(connPool)
}
connPool.AddNode(conn)
c.conns[conn] = struct{}{}
return nil
}
//fillPool manages the pool of connections making sure that each host has the correct
//amount of connections defined. Also the method will test a host with one connection
//instead of flooding the host with number of connections defined in the cluster config
func (c *SimplePool) fillPool() {
//Debounce large amounts of requests to fill pool
select {
case <-time.After(1 * time.Millisecond):
return
case <-c.cFillingPool:
defer func() { c.cFillingPool <- 1 }()
}
c.mu.Lock()
isClosed := c.quit
c.mu.Unlock()
//Exit if cluster(session) is closed
if isClosed {
return
}
c.hostMu.RLock()
//Walk through list of defined hosts
var wg sync.WaitGroup
for host := range c.hosts {
addr := JoinHostPort(host, c.cfg.Port)
numConns := 1
//See if the host already has connections in the pool
c.mu.Lock()
conns, ok := c.connPool[addr]
c.mu.Unlock()
if ok {
//if the host has enough connections just exit
numConns = conns.Size()
if numConns >= c.cfg.NumConns {
continue
}
} else {
//See if the host is reachable
if err := c.connect(addr); err != nil {
continue
}
}
//This is reached if the host is responsive and needs more connections
//Create connections for host synchronously to mitigate flooding the host.
wg.Add(1)
go func(a string, conns int) {
defer wg.Done()
for ; conns < c.cfg.NumConns; conns++ {
c.connect(a)
}
}(addr, numConns)
}
c.hostMu.RUnlock()
//Wait until we're finished connecting to each host before returning
wg.Wait()
}
// Should only be called if c.mu is locked
func (c *SimplePool) removeConnLocked(conn *Conn) {
conn.Close()
connPool := c.connPool[conn.addr]
if connPool == nil {
return
}
connPool.RemoveNode(conn)
if connPool.Size() == 0 {
c.hostPool.RemoveNode(connPool)
delete(c.connPool, conn.addr)
}
delete(c.conns, conn)
}
func (c *SimplePool) removeConn(conn *Conn) {
c.mu.Lock()
defer c.mu.Unlock()
c.removeConnLocked(conn)
}
//HandleError is called by a Connection object to report to the pool an error has occured.
//Logic is then executed within the pool to clean up the erroroneous connection and try to
//top off the pool.
func (c *SimplePool) HandleError(conn *Conn, err error, closed bool) {
if !closed {
// ignore all non-fatal errors
return
}
c.removeConn(conn)
c.mu.Lock()
poolClosed := c.quit
c.mu.Unlock()
if !poolClosed {
go c.fillPool() // top off pool.
}
}
//Pick selects a connection to be used by the query.
func (c *SimplePool) Pick(qry *Query) *Conn {
//Check if connections are available
c.mu.Lock()
conns := len(c.conns)
c.mu.Unlock()
if conns == 0 {
//try to populate the pool before returning.
c.fillPool()
}
return c.hostPool.Pick(qry)
}
//Size returns the number of connections currently active in the pool
func (p *SimplePool) Size() int {
p.mu.Lock()
conns := len(p.conns)
p.mu.Unlock()
return conns
}
//Close kills the pool and all associated connections.
func (c *SimplePool) Close() {
c.quitOnce.Do(func() {
c.mu.Lock()
defer c.mu.Unlock()
c.quit = true
close(c.quitWait)
for conn := range c.conns {
c.removeConnLocked(conn)
}
})
}
func (c *SimplePool) SetHosts(hosts []HostInfo) {
c.hostMu.Lock()
toRemove := make(map[string]struct{})
for k := range c.hosts {
toRemove[k] = struct{}{}
}
for _, host := range hosts {
host := host
delete(toRemove, host.Peer)
// we already have it
if _, ok := c.hosts[host.Peer]; ok {
// TODO: Check rack, dc, token range is consistent, trigger topology change
// update stored host
continue
}
c.hosts[host.Peer] = &host
}
// can we hold c.mu whilst iterating this loop?
for addr := range toRemove {
c.removeHostLocked(addr)
}
c.hostMu.Unlock()
c.fillPool()
}
func (c *SimplePool) removeHostLocked(addr string) {
if _, ok := c.hosts[addr]; !ok {
return
}
delete(c.hosts, addr)
c.mu.Lock()
defer c.mu.Unlock()
if _, ok := c.connPool[addr]; !ok {
return
}
for conn := range c.conns {
if conn.Address() == addr {
c.removeConnLocked(conn)
}
}
}
//NewRoundRobinConnPool creates a connection pool which selects hosts by
//round-robin, and then selects a connection for that host by round-robin.
func NewRoundRobinConnPool(cfg *ClusterConfig) (ConnectionPool, error) {
return NewPolicyConnPool(
cfg,
NewRoundRobinHostPolicy(),
NewRoundRobinConnPolicy,
)
}
//NewTokenAwareConnPool creates a connection pool which selects hosts by
//a token aware policy, and then selects a connection for that host by
//round-robin.
func NewTokenAwareConnPool(cfg *ClusterConfig) (ConnectionPool, error) {
return NewPolicyConnPool(
cfg,
NewTokenAwareHostPolicy(NewRoundRobinHostPolicy()),
NewRoundRobinConnPolicy,
)
}
type policyConnPool struct {
port int
numConns int
connCfg ConnConfig
connCfg *ConnConfig
keyspace string
mu sync.RWMutex
@ -484,18 +69,13 @@ type policyConnPool struct {
hostConnPools map[string]*hostConnPool
}
//Creates a policy based connection pool. This func isn't meant to be directly
//used as a NewPoolFunc in ClusterConfig, instead a func should be created
//which satisfies the NewPoolFunc type, which calls this func with the desired
//hostPolicy and connPolicy; see NewRoundRobinConnPool or NewTokenAwareConnPool
//for examples.
func NewPolicyConnPool(
cfg *ClusterConfig,
hostPolicy HostSelectionPolicy,
connPolicy func() ConnSelectionPolicy,
) (ConnectionPool, error) {
var err error
var tlsConfig *tls.Config
func newPolicyConnPool(cfg *ClusterConfig, hostPolicy HostSelectionPolicy,
connPolicy func() ConnSelectionPolicy) (*policyConnPool, error) {
var (
err error
tlsConfig *tls.Config
)
if cfg.SslOpts != nil {
tlsConfig, err = setupTLSConfig(cfg.SslOpts)
@ -508,7 +88,7 @@ func NewPolicyConnPool(
pool := &policyConnPool{
port: cfg.Port,
numConns: cfg.NumConns,
connCfg: ConnConfig{
connCfg: &ConnConfig{
ProtoVersion: cfg.ProtoVersion,
CQLVersion: cfg.CQLVersion,
Timeout: cfg.Timeout,
@ -594,9 +174,12 @@ func (p *policyConnPool) Size() int {
func (p *policyConnPool) Pick(qry *Query) *Conn {
nextHost := p.hostPolicy.Pick(qry)
var (
host *HostInfo
conn *Conn
)
p.mu.RLock()
var host *HostInfo
var conn *Conn
for conn == nil {
host = nextHost()
if host == nil {
@ -629,7 +212,7 @@ type hostConnPool struct {
port int
addr string
size int
connCfg ConnConfig
connCfg *ConnConfig
keyspace string
policy ConnSelectionPolicy
// protection for conns, closed, filling
@ -639,14 +222,8 @@ type hostConnPool struct {
filling bool
}
func newHostConnPool(
host string,
port int,
size int,
connCfg ConnConfig,
keyspace string,
policy ConnSelectionPolicy,
) *hostConnPool {
func newHostConnPool(host string, port int, size int, connCfg *ConnConfig,
keyspace string, policy ConnSelectionPolicy) *hostConnPool {
pool := &hostConnPool{
host: host,

220
Godeps/_workspace/src/github.com/gocql/gocql/control.go generated vendored Normal file
View File

@ -0,0 +1,220 @@
package gocql
import (
"errors"
"fmt"
"sync/atomic"
"time"
)
type controlConn struct {
session *Session
conn atomic.Value
connecting uint64
retry RetryPolicy
quit chan struct{}
}
func createControlConn(session *Session) *controlConn {
control := &controlConn{
session: session,
quit: make(chan struct{}),
retry: &SimpleRetryPolicy{NumRetries: 3},
}
control.conn.Store((*Conn)(nil))
control.reconnect()
go control.heartBeat()
return control
}
func (c *controlConn) heartBeat() {
for {
select {
case <-c.quit:
return
case <-time.After(5 * time.Second):
}
resp, err := c.writeFrame(&writeOptionsFrame{})
if err != nil {
goto reconn
}
switch resp.(type) {
case *supportedFrame:
continue
case error:
goto reconn
default:
panic(fmt.Sprintf("gocql: unknown frame in response to options: %T", resp))
}
reconn:
c.reconnect()
time.Sleep(5 * time.Second)
continue
}
}
func (c *controlConn) reconnect() {
if !atomic.CompareAndSwapUint64(&c.connecting, 0, 1) {
return
}
success := false
defer func() {
// debounce reconnect a little
if success {
go func() {
time.Sleep(500 * time.Millisecond)
atomic.StoreUint64(&c.connecting, 0)
}()
} else {
atomic.StoreUint64(&c.connecting, 0)
}
}()
oldConn := c.conn.Load().(*Conn)
// TODO: should have our own roundrobbin for hosts so that we can try each
// in succession and guantee that we get a different host each time.
conn := c.session.pool.Pick(nil)
if conn == nil {
return
}
newConn, err := Connect(conn.addr, conn.cfg, c)
if err != nil {
// TODO: add log handler for things like this
return
}
c.conn.Store(newConn)
success = true
if oldConn != nil {
oldConn.Close()
}
}
func (c *controlConn) HandleError(conn *Conn, err error, closed bool) {
if !closed {
return
}
oldConn := c.conn.Load().(*Conn)
if oldConn != conn {
return
}
c.reconnect()
}
func (c *controlConn) writeFrame(w frameWriter) (frame, error) {
conn := c.conn.Load().(*Conn)
if conn == nil {
return nil, errNoControl
}
framer, err := conn.exec(w, nil)
if err != nil {
return nil, err
}
return framer.parseFrame()
}
// query will return nil if the connection is closed or nil
func (c *controlConn) query(statement string, values ...interface{}) (iter *Iter) {
q := c.session.Query(statement, values...).Consistency(One)
const maxConnectAttempts = 5
connectAttempts := 0
for {
conn := c.conn.Load().(*Conn)
if conn == nil {
if connectAttempts > maxConnectAttempts {
return &Iter{err: errNoControl}
}
connectAttempts++
c.reconnect()
continue
}
iter = conn.executeQuery(q)
q.attempts++
if iter.err == nil || !c.retry.Attempt(q) {
break
}
}
return
}
func (c *controlConn) awaitSchemaAgreement() (err error) {
const (
// TODO(zariel): if we export this make this configurable
maxWaitTime = 60 * time.Second
peerSchemas = "SELECT schema_version FROM system.peers"
localSchemas = "SELECT schema_version FROM system.local WHERE key='local'"
)
endDeadline := time.Now().Add(maxWaitTime)
for time.Now().Before(endDeadline) {
iter := c.query(peerSchemas)
versions := make(map[string]struct{})
var schemaVersion string
for iter.Scan(&schemaVersion) {
versions[schemaVersion] = struct{}{}
schemaVersion = ""
}
if err = iter.Close(); err != nil {
goto cont
}
iter = c.query(localSchemas)
for iter.Scan(&schemaVersion) {
versions[schemaVersion] = struct{}{}
schemaVersion = ""
}
if err = iter.Close(); err != nil {
goto cont
}
if len(versions) <= 1 {
return nil
}
cont:
time.Sleep(200 * time.Millisecond)
}
if err != nil {
return
}
// not exported
return errors.New("gocql: cluster schema versions not consistent")
}
func (c *controlConn) close() {
// TODO: handle more gracefully
close(c.quit)
}
var errNoControl = errors.New("gocql: no controll connection available")

View File

@ -12,6 +12,7 @@ import (
"log"
"net"
"runtime"
"strings"
"sync"
"time"
)
@ -179,6 +180,31 @@ func (c Consistency) String() string {
}
}
func ParseConsistency(s string) Consistency {
switch strings.ToUpper(s) {
case "ANY":
return Any
case "ONE":
return One
case "TWO":
return Two
case "THREE":
return Three
case "QUORUM":
return Quorum
case "ALL":
return All
case "LOCAL_QUORUM":
return LocalQuorum
case "EACH_QUORUM":
return EachQuorum
case "LOCAL_ONE":
return LocalOne
default:
panic("invalid consistency: " + s)
}
}
type SerialConsistency uint16
const (
@ -500,7 +526,7 @@ func (f *framer) parseErrorFrame() frame {
stmtId := f.readShortBytes()
return &RequestErrUnprepared{
errorFrame: errD,
StatementId: stmtId,
StatementId: copyBytes(stmtId), // defensivly copy
}
case errReadFailure:
res := &RequestErrReadFailure{
@ -1371,6 +1397,17 @@ func (f *framer) writeBatchFrame(streamID int, w *writeBatchFrame) error {
return f.finishWrite()
}
type writeOptionsFrame struct{}
func (w *writeOptionsFrame) writeFrame(framer *framer, streamID int) error {
return framer.writeOptionsFrame(streamID, w)
}
func (f *framer) writeOptionsFrame(stream int, _ *writeOptionsFrame) error {
f.writeHeader(f.flags, opOptions, stream)
return f.finishWrite()
}
func (f *framer) readByte() byte {
if len(f.rbuf) < 1 {
panic(fmt.Errorf("not enough bytes in buffer to read byte require 1 got: %d", len(f.rbuf)))
@ -1466,13 +1503,7 @@ func (f *framer) readBytes() []byte {
panic(fmt.Errorf("not enough bytes in buffer to read bytes require %d got: %d", size, len(f.rbuf)))
}
// we cant make assumptions about the length of the life of the supplied byte
// slice so we defensivly copy it out of the underlying buffer. This has the
// downside of increasing allocs per read but will provide much greater memory
// safety. The allocs can hopefully be improved in the future.
// TODO: dont copy into a new slice
l := make([]byte, size)
copy(l, f.rbuf[:size])
l := f.rbuf[:size]
f.rbuf = f.rbuf[size:]
return l
@ -1484,8 +1515,7 @@ func (f *framer) readShortBytes() []byte {
panic(fmt.Errorf("not enough bytes in buffer to read short bytes: require %d got %d", size, len(f.rbuf)))
}
l := make([]byte, size)
copy(l, f.rbuf[:size])
l := f.rbuf[:size]
f.rbuf = f.rbuf[size:]
return l

View File

@ -180,3 +180,9 @@ func (iter *Iter) MapScan(m map[string]interface{}) bool {
}
return false
}
func copyBytes(p []byte) []byte {
b := make([]byte, len(p))
copy(b, p)
return b
}

View File

@ -24,20 +24,19 @@ type ringDescriber struct {
closeChan chan bool
}
func (r *ringDescriber) GetHosts() (
hosts []HostInfo,
partitioner string,
err error,
) {
func (r *ringDescriber) GetHosts() (hosts []HostInfo, partitioner string, err error) {
// we need conn to be the same because we need to query system.peers and system.local
// on the same node to get the whole cluster
conn := r.session.Pool.Pick(nil)
if conn == nil {
iter := r.session.control.query("SELECT data_center, rack, host_id, tokens, partitioner FROM system.local")
if iter == nil {
return r.prevHosts, r.prevPartitioner, nil
}
query := r.session.Query("SELECT data_center, rack, host_id, tokens, partitioner FROM system.local")
iter := conn.executeQuery(query)
conn := r.session.pool.Pick(nil)
if conn == nil {
return r.prevHosts, r.prevPartitioner, nil
}
host := HostInfo{}
iter.Scan(&host.DataCenter, &host.Rack, &host.HostId, &host.Tokens, &partitioner)
@ -57,8 +56,10 @@ func (r *ringDescriber) GetHosts() (
hosts = []HostInfo{host}
query = r.session.Query("SELECT peer, data_center, rack, host_id, tokens FROM system.peers")
iter = conn.executeQuery(query)
iter = r.session.control.query("SELECT peer, data_center, rack, host_id, tokens FROM system.peers")
if iter == nil {
return r.prevHosts, r.prevPartitioner, nil
}
host = HostInfo{}
for iter.Scan(&host.Peer, &host.DataCenter, &host.Rack, &host.HostId, &host.Tokens) {
@ -97,21 +98,21 @@ func (h *ringDescriber) run(sleep time.Duration) {
}
for {
// if we have 0 hosts this will return the previous list of hosts to
// attempt to reconnect to the cluster otherwise we would never find
// downed hosts again, could possibly have an optimisation to only
// try to add new hosts if GetHosts didnt error and the hosts didnt change.
hosts, partitioner, err := h.GetHosts()
if err != nil {
log.Println("RingDescriber: unable to get ring topology:", err)
continue
}
h.session.pool.SetHosts(hosts)
h.session.pool.SetPartitioner(partitioner)
select {
case <-time.After(sleep):
// if we have 0 hosts this will return the previous list of hosts to
// attempt to reconnect to the cluster otherwise we would never find
// downed hosts again, could possibly have an optimisation to only
// try to add new hosts if GetHosts didnt error and the hosts didnt change.
hosts, partitioner, err := h.GetHosts()
if err != nil {
log.Println("RingDescriber: unable to get ring topology:", err)
} else {
h.session.Pool.SetHosts(hosts)
if v, ok := h.session.Pool.(SetPartitioner); ok {
v.SetPartitioner(partitioner)
}
}
case <-h.closeChan:
return
}

View File

@ -40,10 +40,6 @@ function run_tests() {
rm -rf $HOME/.ccm/test/node1/data/system_auth
fi
ccm start -v
ccm status
ccm node1 nodetool status
local proto=2
if [[ $version == 1.2.* ]]; then
proto=1
@ -53,15 +49,20 @@ function run_tests() {
proto=3
elif [[ $version == 2.2.* ]]; then
proto=4
ccm updateconf 'enable_user_defined_functions: true'
fi
ccm start -v
ccm status
ccm node1 nodetool status
if [ "$auth" = true ]
then
sleep 30s
go test -v . -timeout 15s -run=TestAuthentication -tags integration -runssl -runauth -proto=$proto -cluster=$(ccm liveset) -clusterSize=$clusterSize -autowait=1000ms
else
go test -timeout 5m -tags integration -cover -v -runssl -proto=$proto -rf=3 -cluster=$(ccm liveset) -clusterSize=$clusterSize -autowait=2000ms -compressor=snappy ./... | tee results.txt
go test -timeout 5m -tags integration -v -gocql.timeout=10s -runssl -proto=$proto -rf=3 -cluster=$(ccm liveset) -clusterSize=$clusterSize -autowait=2000ms -compressor=snappy ./...
if [ ${PIPESTATUS[0]} -ne 0 ]; then
echo "--- FAIL: ccm status follows:"
@ -72,13 +73,6 @@ function run_tests() {
echo "--- FAIL: Received a non-zero exit code from the go test execution, please investigate this"
exit 1
fi
cover=`cat results.txt | grep coverage: | grep -o "[0-9]\{1,3\}" | head -n 1`
if [[ $cover -lt "55" ]]; then
echo "--- FAIL: expected coverage of at least 60 %, but coverage was $cover %"
exit 1
fi
fi
ccm remove

View File

@ -1356,7 +1356,16 @@ func marshalUDT(info TypeInfo, value interface{}) ([]byte, error) {
if !f.IsValid() {
return nil, marshalErrorf("cannot marshal %T into %s", value, info)
} else if f.Kind() == reflect.Ptr {
f = f.Elem()
if f.IsNil() {
n := -1
buf = append(buf, byte(n>>24),
byte(n>>16),
byte(n>>8),
byte(n))
continue
} else {
f = f.Elem()
}
}
data, err := Marshal(e.Type, f.Interface())

View File

@ -335,30 +335,18 @@ func componentColumnCountOfType(columns map[string]*ColumnMetadata, kind string)
}
// query only for the keyspace metadata for the specified keyspace from system.schema_keyspace
func getKeyspaceMetadata(
session *Session,
keyspaceName string,
) (*KeyspaceMetadata, error) {
query := session.Query(
`
func getKeyspaceMetadata(session *Session, keyspaceName string) (*KeyspaceMetadata, error) {
const stmt = `
SELECT durable_writes, strategy_class, strategy_options
FROM system.schema_keyspaces
WHERE keyspace_name = ?
`,
keyspaceName,
)
// Set a routing key to avoid GetRoutingKey from computing the routing key
// TODO use a separate connection (pool) for system keyspace queries.
query.RoutingKey([]byte{})
WHERE keyspace_name = ?`
keyspace := &KeyspaceMetadata{Name: keyspaceName}
var strategyOptionsJSON []byte
err := query.Scan(
&keyspace.DurableWrites,
&keyspace.StrategyClass,
&strategyOptionsJSON,
)
iter := session.control.query(stmt, keyspaceName)
iter.Scan(&keyspace.DurableWrites, &keyspace.StrategyClass, &strategyOptionsJSON)
err := iter.Close()
if err != nil {
return nil, fmt.Errorf("Error querying keyspace schema: %v", err)
}
@ -431,11 +419,7 @@ func getTableMetadata(session *Session, keyspaceName string) ([]TableMetadata, e
}
}
// Set a routing key to avoid GetRoutingKey from computing the routing key
// TODO use a separate connection (pool) for system keyspace queries.
query := session.Query(stmt, keyspaceName)
query.RoutingKey([]byte{})
iter := query.Iter()
iter := session.control.query(stmt, keyspaceName)
tables := []TableMetadata{}
table := TableMetadata{Keyspace: keyspaceName}
@ -560,11 +544,7 @@ func getColumnMetadata(
var indexOptionsJSON []byte
query := session.Query(stmt, keyspaceName)
// Set a routing key to avoid GetRoutingKey from computing the routing key
// TODO use a separate connection (pool) for system keyspace queries.
query.RoutingKey([]byte{})
iter := query.Iter()
iter := session.control.query(stmt, keyspaceName)
for scan(iter, &column, &indexOptionsJSON) {
var err error

View File

@ -10,8 +10,8 @@ import (
"sync/atomic"
)
//RetryableQuery is an interface that represents a query or batch statement that
//exposes the correct functions for the retry policy logic to evaluate correctly.
// RetryableQuery is an interface that represents a query or batch statement that
// exposes the correct functions for the retry policy logic to evaluate correctly.
type RetryableQuery interface {
Attempts() int
GetConsistency() Consistency
@ -48,8 +48,8 @@ func (s *SimpleRetryPolicy) Attempt(q RetryableQuery) bool {
return q.Attempts() <= s.NumRetries
}
//HostSelectionPolicy is an interface for selecting
//the most appropriate host to execute a given query.
// HostSelectionPolicy is an interface for selecting
// the most appropriate host to execute a given query.
type HostSelectionPolicy interface {
SetHosts
SetPartitioner
@ -57,11 +57,12 @@ type HostSelectionPolicy interface {
Pick(*Query) NextHost
}
//NextHost is an iteration function over picked hosts
// NextHost is an iteration function over picked hosts
type NextHost func() *HostInfo
//NewRoundRobinHostPolicy is a round-robin load balancing policy
func NewRoundRobinHostPolicy() HostSelectionPolicy {
// RoundRobinHostPolicy is a round-robin load balancing policy, where each host
// is tried sequentially for each query.
func RoundRobinHostPolicy() HostSelectionPolicy {
return &roundRobinHostPolicy{hosts: []HostInfo{}}
}
@ -105,8 +106,10 @@ func (r *roundRobinHostPolicy) Pick(qry *Query) NextHost {
}
}
//NewTokenAwareHostPolicy is a token aware host selection policy
func NewTokenAwareHostPolicy(fallback HostSelectionPolicy) HostSelectionPolicy {
// TokenAwareHostPolicy is a token aware host selection policy, where hosts are
// selected based on the partition key, so queries are sent to the host which
// owns the partition. Fallback is used when routing information is not available.
func TokenAwareHostPolicy(fallback HostSelectionPolicy) HostSelectionPolicy {
return &tokenAwareHostPolicy{fallback: fallback, hosts: []HostInfo{}}
}
@ -227,8 +230,10 @@ type roundRobinConnPolicy struct {
mu sync.RWMutex
}
func NewRoundRobinConnPolicy() ConnSelectionPolicy {
return &roundRobinConnPolicy{}
func RoundRobinConnPolicy() func() ConnSelectionPolicy {
return func() ConnSelectionPolicy {
return &roundRobinConnPolicy{}
}
}
func (r *roundRobinConnPolicy) SetConns(conns []*Conn) {

View File

@ -28,7 +28,7 @@ import (
// and automatically sets a default consinstency level on all operations
// that do not have a consistency level set.
type Session struct {
Pool ConnectionPool
pool *policyConnPool
cons Consistency
pageSize int
prefetch float64
@ -38,6 +38,8 @@ type Session struct {
hostSource *ringDescriber
mu sync.RWMutex
control *controlConn
cfg ClusterConfig
closeMu sync.RWMutex
@ -60,47 +62,48 @@ func NewSession(cfg ClusterConfig) (*Session, error) {
cfg.NumStreams = maxStreams
}
pool, err := cfg.ConnPoolType(&cfg)
if err != nil {
return nil, err
}
//Adjust the size of the prepared statements cache to match the latest configuration
stmtsLRU.Lock()
initStmtsLRU(cfg.MaxPreparedStmts)
stmtsLRU.Unlock()
s := &Session{
Pool: pool,
cons: cfg.Consistency,
prefetch: 0.25,
cfg: cfg,
pageSize: cfg.PageSize,
}
pool, err := cfg.PoolConfig.buildPool(&s.cfg)
if err != nil {
return nil, err
}
s.pool = pool
//See if there are any connections in the pool
if pool.Size() > 0 {
s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo)
s.SetConsistency(cfg.Consistency)
s.SetPageSize(cfg.PageSize)
if cfg.DiscoverHosts {
s.hostSource = &ringDescriber{
session: s,
dcFilter: cfg.Discovery.DcFilter,
rackFilter: cfg.Discovery.RackFilter,
closeChan: make(chan bool),
}
go s.hostSource.run(cfg.Discovery.Sleep)
}
return s, nil
if pool.Size() == 0 {
s.Close()
return nil, ErrNoConnectionsStarted
}
s.Close()
s.routingKeyInfoCache.lru = lru.New(cfg.MaxRoutingKeyInfo)
return nil, ErrNoConnectionsStarted
if !cfg.disableControlConn {
s.control = createControlConn(s)
}
if cfg.DiscoverHosts {
s.hostSource = &ringDescriber{
session: s,
dcFilter: cfg.Discovery.DcFilter,
rackFilter: cfg.Discovery.RackFilter,
closeChan: make(chan bool),
}
go s.hostSource.run(cfg.Discovery.Sleep)
}
return s, nil
}
// SetConsistency sets the default consistency level for this session. This
@ -154,9 +157,10 @@ func (s *Session) Query(stmt string, values ...interface{}) *Query {
}
type QueryInfo struct {
Id []byte
Args []ColumnInfo
Rval []ColumnInfo
Id []byte
Args []ColumnInfo
Rval []ColumnInfo
PKeyColumns []int
}
// Bind generates a new query object based on the query statement passed in.
@ -185,11 +189,15 @@ func (s *Session) Close() {
}
s.isClosed = true
s.Pool.Close()
s.pool.Close()
if s.hostSource != nil {
close(s.hostSource.closeChan)
}
if s.control != nil {
s.control.close()
}
}
func (s *Session) Closed() bool {
@ -210,12 +218,16 @@ func (s *Session) executeQuery(qry *Query) *Iter {
qry.attempts = 0
qry.totalLatency = 0
for {
conn := s.Pool.Pick(qry)
conn := s.pool.Pick(qry)
//Assign the error unavailable to the iterator
if conn == nil {
iter = &Iter{err: ErrNoConnections}
break
if qry.rt == nil || !qry.rt.Attempt(qry) {
iter = &Iter{err: ErrNoConnections}
break
}
continue
}
t := time.Now()
@ -289,12 +301,12 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) {
s.routingKeyInfoCache.mu.Unlock()
var (
prepared *resultPreparedFrame
info *QueryInfo
partitionKey []*ColumnMetadata
)
// get the query info for the statement
conn := s.Pool.Pick(nil)
conn := s.pool.Pick(nil)
if conn == nil {
// no connections
inflight.err = ErrNoConnections
@ -303,20 +315,20 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) {
return nil, inflight.err
}
prepared, inflight.err = conn.prepareStatement(stmt, nil)
info, inflight.err = conn.prepareStatement(stmt, nil)
if inflight.err != nil {
// don't cache this error
s.routingKeyInfoCache.Remove(stmt)
return nil, inflight.err
}
if len(prepared.reqMeta.columns) == 0 {
if len(info.Args) == 0 {
// no arguments, no routing key, and no error
return nil, nil
}
// get the table metadata
table := prepared.reqMeta.columns[0].Table
table := info.Args[0].Table
var keyspaceMetadata *KeyspaceMetadata
keyspaceMetadata, inflight.err = s.KeyspaceMetadata(s.cfg.Keyspace)
@ -349,7 +361,7 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) {
routingKeyInfo.indexes[keyIndex] = -1
// find the column in the query info
for argIndex, boundColumn := range prepared.reqMeta.columns {
for argIndex, boundColumn := range info.Args {
if keyColumn.Name == boundColumn.Name {
// there may be many such bound columns, pick the first
routingKeyInfo.indexes[keyIndex] = argIndex
@ -371,26 +383,25 @@ func (s *Session) routingKeyInfo(stmt string) (*routingKeyInfo, error) {
return routingKeyInfo, nil
}
// ExecuteBatch executes a batch operation and returns nil if successful
// otherwise an error is returned describing the failure.
func (s *Session) ExecuteBatch(batch *Batch) error {
func (s *Session) executeBatch(batch *Batch) (*Iter, error) {
// fail fast
if s.Closed() {
return ErrSessionClosed
return nil, ErrSessionClosed
}
// Prevent the execution of the batch if greater than the limit
// Currently batches have a limit of 65536 queries.
// https://datastax-oss.atlassian.net/browse/JAVA-229
if batch.Size() > BatchSizeMaximum {
return ErrTooManyStmts
return nil, ErrTooManyStmts
}
var err error
var iter *Iter
batch.attempts = 0
batch.totalLatency = 0
for {
conn := s.Pool.Pick(nil)
conn := s.pool.Pick(nil)
//Assign the error unavailable and break loop
if conn == nil {
@ -398,12 +409,12 @@ func (s *Session) ExecuteBatch(batch *Batch) error {
break
}
t := time.Now()
err = conn.executeBatch(batch)
iter, err = conn.executeBatch(batch)
batch.totalLatency += time.Now().Sub(t).Nanoseconds()
batch.attempts++
//Exit loop if operation executed correctly
if err == nil {
return nil
return iter, err
}
if batch.rt == nil || !batch.rt.Attempt(batch) {
@ -411,9 +422,59 @@ func (s *Session) ExecuteBatch(batch *Batch) error {
}
}
return nil, err
}
// ExecuteBatch executes a batch operation and returns nil if successful
// otherwise an error is returned describing the failure.
func (s *Session) ExecuteBatch(batch *Batch) error {
_, err := s.executeBatch(batch)
return err
}
// ExecuteBatchCAS executes a batch operation and returns nil if successful and
// an iterator (to scan aditional rows if more than one conditional statement)
// was sent, otherwise an error is returned describing the failure.
// Further scans on the interator must also remember to include
// the applied boolean as the first argument to *Iter.Scan
func (s *Session) ExecuteBatchCAS(batch *Batch, dest ...interface{}) (applied bool, iter *Iter, err error) {
if iter, err := s.executeBatch(batch); err == nil {
if err := iter.checkErrAndNotFound(); err != nil {
return false, nil, err
}
if len(iter.Columns()) > 1 {
dest = append([]interface{}{&applied}, dest...)
iter.Scan(dest...)
} else {
iter.Scan(&applied)
}
return applied, iter, nil
} else {
return false, nil, err
}
}
// MapExecuteBatchCAS executes a batch operation much like ExecuteBatchCAS,
// however it accepts a map rather than a list of arguments for the initial
// scan.
func (s *Session) MapExecuteBatchCAS(batch *Batch, dest map[string]interface{}) (applied bool, iter *Iter, err error) {
if iter, err := s.executeBatch(batch); err == nil {
if err := iter.checkErrAndNotFound(); err != nil {
return false, nil, err
}
iter.MapScan(dest)
applied = dest["[applied]"].(bool)
delete(dest, "[applied]")
// we usually close here, but instead of closing, just returin an error
// if MapScan failed. Although Close just returns err, using Close
// here might be confusing as we are not actually closing the iter
return applied, iter, iter.err
} else {
return false, nil, err
}
}
// Query represents a CQL statement that can be executed.
type Query struct {
stmt string
@ -717,6 +778,9 @@ type Iter struct {
rows [][][]byte
meta resultMetadata
next *nextIter
framer *framer
once sync.Once
}
// Columns returns the name and type of the selected columns.
@ -790,6 +854,13 @@ func (iter *Iter) Scan(dest ...interface{}) bool {
// Close closes the iterator and returns any errors that happened during
// the query or the iteration.
func (iter *Iter) Close() error {
iter.once.Do(func() {
if iter.framer != nil {
framerPool.Put(iter.framer)
iter.framer = nil
}
})
return iter.err
}
@ -998,29 +1069,40 @@ func (t *traceWriter) Trace(traceId []byte) {
coordinator string
duration int
)
t.session.Query(`SELECT coordinator, duration
iter := t.session.control.query(`SELECT coordinator, duration
FROM system_traces.sessions
WHERE session_id = ?`, traceId).
Consistency(One).Scan(&coordinator, &duration)
WHERE session_id = ?`, traceId)
iter.Scan(&coordinator, &duration)
if err := iter.Close(); err != nil {
t.mu.Lock()
fmt.Fprintln(t.w, "Error:", err)
t.mu.Unlock()
return
}
iter := t.session.Query(`SELECT event_id, activity, source, source_elapsed
FROM system_traces.events
WHERE session_id = ?`, traceId).
Consistency(One).Iter()
var (
timestamp time.Time
activity string
source string
elapsed int
)
t.mu.Lock()
defer t.mu.Unlock()
fmt.Fprintf(t.w, "Tracing session %016x (coordinator: %s, duration: %v):\n",
traceId, coordinator, time.Duration(duration)*time.Microsecond)
t.mu.Lock()
defer t.mu.Unlock()
iter = t.session.control.query(`SELECT event_id, activity, source, source_elapsed
FROM system_traces.events
WHERE session_id = ?`, traceId)
for iter.Scan(&timestamp, &activity, &source, &elapsed) {
fmt.Fprintf(t.w, "%s: %s (source: %s, elapsed: %d)\n",
timestamp.Format("2006/01/02 15:04:05.999999"), activity, source, elapsed)
}
if err := iter.Close(); err != nil {
fmt.Fprintln(t.w, "Error:", err)
}

View File

@ -8,6 +8,7 @@ package github
import (
"errors"
"fmt"
"io"
"mime"
"os"
"path/filepath"
@ -211,6 +212,29 @@ func (s *RepositoriesService) GetReleaseAsset(owner, repo string, id int) (*Rele
return asset, resp, err
}
// DownloadReleaseAsset downloads a release asset.
//
// DownloadReleaseAsset returns an io.ReadCloser that reads the contents of the
// specified release asset. It is the caller's responsibility to close the ReadCloser.
//
// GitHub API docs : http://developer.github.com/v3/repos/releases/#get-a-single-release-asset
func (s *RepositoriesService) DownloadReleaseAsset(owner, repo string, id int) (io.ReadCloser, error) {
u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", defaultMediaType)
resp, err := s.client.client.Do(req)
if err != nil {
return nil, err
}
return resp.Body, nil
}
// EditReleaseAsset edits a repository release asset.
//
// GitHub API docs : http://developer.github.com/v3/repos/releases/#edit-a-release-asset

View File

@ -14,6 +14,8 @@ import (
"strconv"
"strings"
"time"
"github.com/hashicorp/go-cleanhttp"
)
// QueryOptions are used to parameterize a query
@ -119,7 +121,7 @@ func DefaultConfig() *Config {
config := &Config{
Address: "127.0.0.1:8500",
Scheme: "http",
HttpClient: &http.Client{},
HttpClient: cleanhttp.DefaultClient(),
}
if addr := os.Getenv("CONSUL_HTTP_ADDR"); addr != "" {
@ -198,12 +200,12 @@ func NewClient(config *Config) (*Client, error) {
}
if parts := strings.SplitN(config.Address, "unix://", 2); len(parts) == 2 {
trans := cleanhttp.DefaultTransport()
trans.Dial = func(_, _ string) (net.Conn, error) {
return net.Dial("unix", parts[1])
}
config.HttpClient = &http.Client{
Transport: &http.Transport{
Dial: func(_, _ string) (net.Conn, error) {
return net.Dial("unix", parts[1])
},
},
Transport: trans,
}
config.Address = parts[1]
}

View File

@ -0,0 +1,363 @@
Mozilla Public License, version 2.0
1. Definitions
1.1. "Contributor"
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached the
notice in Exhibit A, the Executable Form of such Source Code Form, and
Modifications of such Source Code Form, in each case including portions
thereof.
1.5. "Incompatible With Secondary Licenses"
means
a. that the initial Contributor has attached the notice described in
Exhibit B to the Covered Software; or
b. that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the terms of
a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in a
separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible, whether
at the time of the initial grant or subsequently, any and all of the
rights conveyed by this License.
1.10. "Modifications"
means any of the following:
a. any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered Software; or
b. any new file in Source Code Form that contains any Covered Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the License,
by the making, using, selling, offering for sale, having made, import,
or transfer of either its Contributions or its Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public
License, Version 3.0, or any later versions of those licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that controls, is
controlled by, or is under common control with You. For purposes of this
definition, "control" means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by contract or
otherwise, or (b) ownership of more than fifty percent (50%) of the
outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
a. under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
b. under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
a. for any code that a Contributor has removed from Covered Software; or
b. for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
c. under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights to
grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
3. Responsibilities
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
a. such Covered Software must also be made available in Source Code Form,
as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost
of distribution to the recipient; and
b. You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter the
recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty, or
limitations of liability) contained within the Source Code Form of the
Covered Software, except that You may alter any license notices to the
extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute,
judicial order, or regulation then You must: (a) comply with the terms of
this License to the maximum extent possible; and (b) describe the
limitations and the code they affect. Such description must be placed in a
text file included with all distributions of the Covered Software under
this License. Except to the extent prohibited by statute or regulation,
such description must be sufficiently detailed for a recipient of ordinary
skill to be able to understand it.
5. Termination
5.1. The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor
are reinstated (a) provisionally, unless and until such Contributor
explicitly and finally terminates Your grants, and (b) on an ongoing
basis, if such Contributor fails to notify You of the non-compliance by
some reasonable means prior to 60 days after You have come back into
compliance. Moreover, Your grants from a particular Contributor are
reinstated on an ongoing basis if such Contributor notifies You of the
non-compliance by some reasonable means, this is the first time You have
received notice of non-compliance with this License from such
Contributor, and You become compliant prior to 30 days after Your receipt
of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
6. Disclaimer of Warranty
Covered Software is provided under this License on an "as is" basis,
without warranty of any kind, either expressed, implied, or statutory,
including, without limitation, warranties that the Covered Software is free
of defects, merchantable, fit for a particular purpose or non-infringing.
The entire risk as to the quality and performance of the Covered Software
is with You. Should any Covered Software prove defective in any respect,
You (not any Contributor) assume the cost of any necessary servicing,
repair, or correction. This disclaimer of warranty constitutes an essential
part of this License. No use of any Covered Software is authorized under
this License except under this disclaimer.
7. Limitation of Liability
Under no circumstances and under no legal theory, whether tort (including
negligence), contract, or otherwise, shall any Contributor, or anyone who
distributes Covered Software as permitted above, be liable to You for any
direct, indirect, special, incidental, or consequential damages of any
character including, without limitation, damages for lost profits, loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses, even if such party shall have been
informed of the possibility of such damages. This limitation of liability
shall not apply to liability for death or personal injury resulting from
such party's negligence to the extent applicable law prohibits such
limitation. Some jurisdictions do not allow the exclusion or limitation of
incidental or consequential damages, so this exclusion and limitation may
not apply to You.
8. Litigation
Any litigation relating to this License may be brought only in the courts
of a jurisdiction where the defendant maintains its principal place of
business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions. Nothing
in this Section shall prevent a party's ability to bring cross-claims or
counter-claims.
9. Miscellaneous
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides that
the language of a contract shall be construed against the drafter shall not
be used to construe this License against a Contributor.
10. Versions of the License
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses If You choose to distribute Source Code Form that is
Incompatible With Secondary Licenses under the terms of this version of
the License, the notice described in Exhibit B of this License must be
attached.
Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file,
then You may include the notice in a location (such as a LICENSE file in a
relevant directory) where a recipient would be likely to look for such a
notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
This Source Code Form is "Incompatible
With Secondary Licenses", as defined by
the Mozilla Public License, v. 2.0.

View File

@ -0,0 +1,30 @@
# cleanhttp
Functions for accessing "clean" Go http.Client values
-------------
The Go standard library contains a default `http.Client` called
`http.DefaultClient`. It is a common idiom in Go code to start with
`http.DefaultClient` and tweak it as necessary, and in fact, this is
encouraged; from the `http` package documentation:
> The Client's Transport typically has internal state (cached TCP connections),
so Clients should be reused instead of created as needed. Clients are safe for
concurrent use by multiple goroutines.
Unfortunately, this is a shared value, and it is not uncommon for libraries to
assume that they are free to modify it at will. With enough dependencies, it
can be very easy to encounter strange problems and race conditions due to
manipulation of this shared value across libraries and goroutines (clients are
safe for concurrent use, but writing values to the client struct itself is not
protected).
Making things worse is the fact that a bare `http.Client` will use a default
`http.Transport` called `http.DefaultTransport`, which is another global value
that behaves the same way. So it is not simply enough to replace
`http.DefaultClient` with `&http.Client{}`.
This repository provides some simple functions to get a "clean" `http.Client`
-- one that uses the same default values as the Go standard library, but
returns a client that does not share any state with other clients.

View File

@ -0,0 +1,28 @@
package cleanhttp
import (
"net"
"net/http"
"time"
)
// DefaultTransport returns a new http.Transport with the same default values
// as http.DefaultTransport
func DefaultTransport() *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
}
}
// DefaultClient returns a new http.Client with the same default values as
// http.Client, but with a non-shared Transport
func DefaultClient() *http.Client {
return &http.Client{
Transport: DefaultTransport(),
}
}

View File

@ -215,9 +215,7 @@ func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) {
}
if len(v) == 0 {
err = ci.Close()
ci.closed = true
return nil, err
return nil, ci.Close()
}
numValues := len(v)
@ -240,9 +238,10 @@ func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) {
}
func (ci *copyin) Close() (err error) {
if ci.closed {
return errCopyInClosed
if ci.closed { // Don't do anything, we're already closed
return nil
}
ci.closed = true
if ci.cn.bad {
return driver.ErrBadConn

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// 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.

View File

@ -1,4 +1,4 @@
// Copyright 2015 The oauth2 Authors. All rights reserved.
// 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.