diff options
34 files changed, 480 insertions, 400 deletions
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.lock b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.lock index ca6a7c0559e..926ba4778fb 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.lock +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.lock @@ -117,8 +117,7 @@ version = "v0.0.4" [[projects]] - branch = "master" - digest = "1:f58ef310a536f99b5233fc3a66f9c9a5cc29737c1413e0c3909f5dbc5bee858d" + digest = "1:2d2c593e72230cae2b6c251a27dc0c77f0429a748a658b4e718c1bfaaad49dfc" name = "github.com/mongodb/mongo-tools-common" packages = [ "archive", @@ -140,7 +139,8 @@ "util", ] pruneopts = "T" - revision = "2b6170aab3e61d522c060a1f2a319e8b105bf78c" + revision = "df8a7a8c229da4ceb91bdcb448b93cb08b02d479" + version = "v1.0.2" [[projects]] digest = "1:f363c75e8cac5653bc5c0c2b90cbd8a522fdc48c13a5f8d85078750f82d1a009" @@ -202,7 +202,7 @@ revision = "73f8eece6fdcd902c185bf651de50f3828bed5ed" [[projects]] - digest = "1:282674c4b65c1ca536e1f097449fe5e4b6fbaadc5aaaa1d81328b91aefc0da6e" + digest = "1:0a52cfa03e3941ae528e91266bf3e2c25ea39363d5c71adb85efadbfe80d1e42" name = "go.mongodb.org/mongo-driver" packages = [ "bson", @@ -236,8 +236,8 @@ "x/mongo/driver/wiremessage", ] pruneopts = "T" - revision = "c520d023af0a89aec8b7f97717b52da270df2c38" - version = "v1.1.1" + revision = "1261197350f3ad46a907489aee7ecc49b39efb82" + version = "v1.1.2" [[projects]] digest = "1:0f2b2cb9f84318c0f71fed3087ff9ac370370f842469b71b00348c3d72a19b44" diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.toml b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.toml index ed25a6f7dc1..c56fd7e523d 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.toml +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.toml @@ -29,11 +29,11 @@ required = ["github.com/3rf/mongo-lint"] [[constraint]] name = "github.com/mongodb/mongo-tools-common" - branch = "master" + version = "^v1.0.2" [[constraint]] name = "go.mongodb.org/mongo-driver" - version = "v1.1" + version = "^v1.1.2" [[constraint]] name = "github.com/10gen/escaper" diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/import.data b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/import.data index 7b7a7abf2f4..8932d7112e3 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/import.data +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/import.data @@ -1,5 +1,5 @@ { - "commit": "22a650479aafb32c0f164625c825c43a8b96e914", + "commit": "976b41822808521389218141029f3cf786cdefc9", "github": "mongodb/mongo-tools.git", "vendor": "tools", "branch": "v4.2" diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongostat/main/mongostat.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongostat/main/mongostat.go index c3f4e257d02..1684dec9113 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongostat/main/mongostat.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongostat/main/mongostat.go @@ -150,7 +150,12 @@ func main() { // we have to check this here, otherwise the user will be prompted // for a password for each discovered node if opts.Auth.ShouldAskForPassword() { - opts.Auth.Password = password.Prompt() + pass, err := password.Prompt() + if err != nil { + log.Logvf(log.Always, "Failed: %v", err) + os.Exit(util.ExitFailure) + } + opts.Auth.Password = pass } var factory stat_consumer.FormatterConstructor diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.lock b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.lock index 957c66ead31..c6ddd00f958 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.lock +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.lock @@ -26,13 +26,6 @@ revision = "3e4dfb77656c424b6d1196a4d5fed0fcf63677cc" [[projects]] - digest = "1:8e9ae4fedb2abb5267f2cd69f8d3010e6c464a9c51d1fa1f9d192c0757ac691a" - name = "github.com/howeyc/gopass" - packages = ["."] - pruneopts = "UT" - revision = "44476384cd4721b68705e72f19e95d1a3a504370" - -[[projects]] digest = "1:fb26351f6c6501b149453ecc70fdb5ffeb08191bf4aa3e32dd5cd1e78336df23" name = "github.com/jessevdk/go-flags" packages = ["."] @@ -88,7 +81,7 @@ revision = "73f8eece6fdcd902c185bf651de50f3828bed5ed" [[projects]] - digest = "1:c540afe732e96088051488bc827eadfba64b90a0e803ea61e7ec80907887362e" + digest = "1:27e22fe552475e0b843c0bffe24e6bc5c55cb4c5d68d119b8c79af08b1903bb4" name = "go.mongodb.org/mongo-driver" packages = [ "bson", @@ -121,8 +114,8 @@ "x/mongo/driver/wiremessage", ] pruneopts = "UT" - revision = "d42ea7239f0db8a61e77191b9f2730a922459042" - version = "v1.1.0" + revision = "1261197350f3ad46a907489aee7ecc49b39efb82" + version = "v1.1.2" [[projects]] digest = "1:79784b4d6789bbd40f17a9d204051bdd887d889acbbdc24ed8263b3dca28dfbf" @@ -161,13 +154,13 @@ analyzer-name = "dep" analyzer-version = 1 input-imports = [ - "github.com/howeyc/gopass", "github.com/jessevdk/go-flags", "github.com/smartystreets/goconvey/convey", "go.mongodb.org/mongo-driver/bson", "go.mongodb.org/mongo-driver/bson/primitive", "go.mongodb.org/mongo-driver/mongo", "go.mongodb.org/mongo-driver/mongo/options", + "go.mongodb.org/mongo-driver/mongo/readconcern", "go.mongodb.org/mongo-driver/mongo/readpref", "go.mongodb.org/mongo-driver/mongo/writeconcern", "go.mongodb.org/mongo-driver/tag", diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.toml b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.toml index aaa46c59df8..7aa792cb814 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.toml +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/Gopkg.toml @@ -26,11 +26,7 @@ [[constraint]] name = "go.mongodb.org/mongo-driver" - version = "v1.1" - -[[constraint]] - name = "github.com/howeyc/gopass" - revision = "44476384cd4721b68705e72f19e95d1a3a504370" + version = "^v1.1.2" [[constraint]] name = "github.com/jessevdk/go-flags" diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/bson_stream.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/bson_stream.go index b5d25021d4f..e1579da6028 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/bson_stream.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/bson_stream.go @@ -8,8 +8,9 @@ package db import ( "fmt" - "go.mongodb.org/mongo-driver/bson" "io" + + "go.mongodb.org/mongo-driver/bson" ) // BSONSource reads documents from the underlying io.ReadCloser, Stream which @@ -18,6 +19,7 @@ type BSONSource struct { reusableBuf []byte Stream io.ReadCloser err error + MaxBSONSize int32 } // DecodedBSONSource reads documents from the underlying io.ReadCloser, Stream which @@ -36,12 +38,12 @@ type RawDocSource interface { // NewBSONSource creates a BSONSource with a reusable I/O buffer func NewBSONSource(in io.ReadCloser) *BSONSource { - return &BSONSource{make([]byte, MaxBSONSize), in, nil} + return &BSONSource{make([]byte, MaxBSONSize), in, nil, MaxBSONSize} } // NewBufferlessBSONSource creates a BSONSource without a reusable I/O buffer func NewBufferlessBSONSource(in io.ReadCloser) *BSONSource { - return &BSONSource{nil, in, nil} + return &BSONSource{nil, in, nil, MaxBSONSize} } // Close closes the BSONSource, rendering it unusable for I/O. @@ -112,7 +114,7 @@ func (bs *BSONSource) LoadNext() []byte { // actually fit into the buffer that was provided. If not, either the BSON is // invalid, or the buffer passed in is too small. // Verify that we do not have an invalid BSON document with size < 5. - if bsonSize > MaxBSONSize || bsonSize < 5 { + if bsonSize > bs.MaxBSONSize || bsonSize < 5 { bs.err = fmt.Errorf("invalid BSONSize: %v bytes", bsonSize) return nil } @@ -144,3 +146,7 @@ func (bs *BSONSource) LoadNext() []byte { func (bs *BSONSource) Err() error { return bs.err } + +func (bs *BSONSource) SetMaxBSONSize(size int32) { + bs.MaxBSONSize = size +} diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/buffered_bulk.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/buffered_bulk.go index 4abfdadcce0..6204597e39a 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/buffered_bulk.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/buffered_bulk.go @@ -98,6 +98,12 @@ func (bb *BufferedBulkInserter) InsertRaw(rawBytes []byte) (*mongo.BulkWriteResu return bb.addModel(mongo.NewInsertOneModel().SetDocument(rawBytes)) } +// Delete adds a document to the buffer for bulk removal. If the buffer becomes full, the bulk delete is performed, returning +// any error that occurs. +func (bb *BufferedBulkInserter) Delete(selector, replacement bson.D) (*mongo.BulkWriteResult, error) { + return bb.addModel(mongo.NewDeleteOneModel().SetFilter(selector)) +} + // addModel adds a WriteModel to the buffer. If the buffer becomes full, the bulk write is performed, returning any error // that occurs. func (bb *BufferedBulkInserter) addModel(model mongo.WriteModel) (*mongo.BulkWriteResult, error) { diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/db.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/db.go index 1fc4d95a516..4e4d1839832 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/db.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/db.go @@ -24,8 +24,6 @@ import ( "github.com/mongodb/mongo-tools-common/log" "github.com/mongodb/mongo-tools-common/options" "github.com/mongodb/mongo-tools-common/password" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" mopt "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/writeconcern" @@ -52,9 +50,6 @@ const ( DefaultTestPort = "33333" ) -// Hard coded socket timeout in seconds -const SocketTimeout = 600 - const ( ErrLostConnection = "lost connection to server" ErrNoReachableServers = "no reachable servers" @@ -89,27 +84,6 @@ type SessionProvider struct { client *mongo.Client } -// ApplyOpsResponse represents the response from an 'applyOps' command. -type ApplyOpsResponse struct { - Ok bool `bson:"ok"` - ErrMsg string `bson:"errmsg"` -} - -// Oplog represents a MongoDB oplog document. -type Oplog struct { - Timestamp primitive.Timestamp `bson:"ts"` - HistoryID int64 `bson:"h"` - Version int `bson:"v"` - Operation string `bson:"op"` - Namespace string `bson:"ns"` - Object bson.D `bson:"o"` - Query bson.D `bson:"o2,omitempty"` - UI *primitive.Binary `bson:"ui,omitempty"` - LSID bson.Raw `bson:"lsid,omitempty"` - TxnNumber *int64 `bson:"txnNumber,omitempty"` - PrevOpTime bson.Raw `bson:"prevOpTime,omitempty"` -} - // Returns a mongo.Client connected to the database server for which the // session provider is configured. func (sp *SessionProvider) GetSession() (*mongo.Client, error) { @@ -142,7 +116,11 @@ func (sp *SessionProvider) DB(name string) *mongo.Database { func NewSessionProvider(opts options.ToolOptions) (*SessionProvider, error) { // finalize auth options, filling in missing passwords if opts.Auth.ShouldAskForPassword() { - opts.Auth.Password = password.Prompt() + pass, err := password.Prompt() + if err != nil { + return nil, fmt.Errorf("error reading password: %v", err) + } + opts.Auth.Password = pass } client, err := configureClient(opts) @@ -301,10 +279,12 @@ func configureClient(opts options.ToolOptions) (*mongo.Client, error) { if err := uriOpts.Validate(); err != nil { return nil, fmt.Errorf("error parsing options from URI: %v", err) } - timeout := time.Duration(opts.Timeout) * time.Second - clientopt.SetConnectTimeout(timeout) - clientopt.SetSocketTimeout(SocketTimeout * time.Second) + clientopt.SetConnectTimeout(time.Duration(opts.Timeout) * time.Second) + clientopt.SetSocketTimeout(time.Duration(opts.SocketTimeout) * time.Second) + if opts.Connection.ServerSelectionTimeout > 0 { + clientopt.SetServerSelectionTimeout(time.Duration(opts.Connection.ServerSelectionTimeout) * time.Second) + } clientopt.SetReplicaSet(opts.ReplicaSetName) clientopt.SetAppName(opts.AppName) diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/oplog.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/oplog.go new file mode 100644 index 00000000000..d119dc300ad --- /dev/null +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/oplog.go @@ -0,0 +1,147 @@ +package db + +import ( + "context" + "fmt" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" + mopts "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/mongo/readconcern" +) + +// ApplyOpsResponse represents the response from an 'applyOps' command. +type ApplyOpsResponse struct { + Ok bool `bson:"ok"` + ErrMsg string `bson:"errmsg"` +} + +// Oplog represents a MongoDB oplog document. +type Oplog struct { + Timestamp primitive.Timestamp `bson:"ts"` + HistoryID int64 `bson:"h"` + Version int `bson:"v"` + Operation string `bson:"op"` + Namespace string `bson:"ns"` + Object bson.D `bson:"o"` + Query bson.D `bson:"o2,omitempty"` + UI *primitive.Binary `bson:"ui,omitempty"` + LSID bson.Raw `bson:"lsid,omitempty"` + TxnNumber *int64 `bson:"txnNumber,omitempty"` + PrevOpTime bson.Raw `bson:"prevOpTime,omitempty"` +} + +// OplogTailTime represents two ways of describing the "end" of the oplog at a +// point in time. The Latest field represents the last visible (storage +// committed) timestamp. The Restart field represents a (possibly older) +// timestamp that can be used to start tailing or copying the oplog without +// losing parts of transactions in progress. +type OplogTailTime struct { + Latest primitive.Timestamp + Restart primitive.Timestamp +} + +var zeroTimestamp = primitive.Timestamp{} + +// GetOplogTailTime constructs an OplogTailTime +func GetOplogTailTime(client *mongo.Client) (OplogTailTime, error) { + // Check oldest active first to be sure it is less-than-or-equal to the + // latest visible. + oldestActive, err := GetOldestActiveTransactionTimestamp(client) + if err != nil { + return OplogTailTime{}, err + } + latestVisible, err := GetLatestVisibleOplogTimestamp(client) + if err != nil { + return OplogTailTime{}, err + } + // No oldest active means the latest visible is the restart time as well. + if oldestActive == zeroTimestamp { + return OplogTailTime{Latest: latestVisible, Restart: latestVisible}, nil + } + return OplogTailTime{Latest: latestVisible, Restart: oldestActive}, nil +} + +// GetOldestActiveTransactionTimestamp returns the oldest active transaction +// timestamp from the config.transactions table or else a zero-value +// primitive.Timestamp. +func GetOldestActiveTransactionTimestamp(client *mongo.Client) (primitive.Timestamp, error) { + coll := client.Database("config").Collection("transactions", mopts.Collection().SetReadConcern(readconcern.Local())) + filter := bson.D{{"state", bson.D{{"$in", bson.A{"prepared", "inProgress"}}}}} + opts := mopts.FindOne().SetSort(bson.D{{"startOpTime", 1}}) + + result, err := coll.FindOne(context.Background(), filter, opts).DecodeBytes() + if err != nil { + if err == mongo.ErrNoDocuments { + return primitive.Timestamp{}, nil + } + return primitive.Timestamp{}, fmt.Errorf("config.transactions.findOne error: %v", err) + } + + rawTS, err := result.LookupErr("startOpTime", "ts") + if err != nil { + return primitive.Timestamp{}, fmt.Errorf("config.transactions row had no startOpTime.ts field") + } + + t, i, ok := rawTS.TimestampOK() + if !ok { + return primitive.Timestamp{}, fmt.Errorf("config.transactions startOpTime.ts was not a BSON timestamp") + } + + return primitive.Timestamp{T: t, I: i}, nil +} + +// GetLatestVisibleOplogTimestamp returns the timestamp of the most recent +// "visible" oplog record. By "visible", we mean that all prior oplog entries +// have been storage-committed. See SERVER-30724 for a more detailed +// description. +func GetLatestVisibleOplogTimestamp(client *mongo.Client) (primitive.Timestamp, error) { + latestOpTime, err := GetLatestOplogTimestamp(client, bson.D{}) + if err != nil { + return primitive.Timestamp{}, err + } + // Do a forward scan starting at the last op fetched to ensure that + // all operations with earlier oplog times have been storage-committed. + var confirmOp Oplog + opts := mopts.FindOne().SetOplogReplay(true) + coll := client.Database("local").Collection("oplog.rs") + res := coll.FindOne(context.Background(), bson.M{"ts": bson.M{"$gte": latestOpTime}}, opts) + if err := res.Err(); err != nil { + return primitive.Timestamp{}, err + } + + err = res.Decode(&confirmOp) + if err == mongo.ErrNoDocuments { + return primitive.Timestamp{}, fmt.Errorf("Last op was not confirmed. last op time: %v. confirmation time was not found.", + latestOpTime) + } + if err != nil { + return primitive.Timestamp{}, err + } + + if !confirmOp.Timestamp.Equal(latestOpTime) { + return primitive.Timestamp{}, fmt.Errorf("Last op was not confirmed. last op time: %v. confirmation time: %v", + latestOpTime, confirmOp.Timestamp) + } + return latestOpTime, nil +} + +// GetLatestOplogTimestamp returns the timestamp of the most recent oplog +// record satisfying the given `query` or a zero-value primitive.Timestamp if +// no oplog record matches. This method does not ensure that all prior oplog +// entries are visible (i.e. have been storage-committed). +func GetLatestOplogTimestamp(client *mongo.Client, query interface{}) (primitive.Timestamp, error) { + var record Oplog + opts := mopts.FindOne().SetProjection(bson.M{"ts": 1}).SetSort(bson.D{{"$natural", -1}}) + coll := client.Database("local").Collection("oplog.rs") + res := coll.FindOne(context.Background(), query, opts) + if err := res.Err(); err != nil { + return primitive.Timestamp{}, err + } + + if err := res.Decode(&record); err != nil { + return primitive.Timestamp{}, err + } + return record.Timestamp, nil +} diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/options/options.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/options/options.go index 0c9901fa8f3..5b40470cc60 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/options/options.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/options/options.go @@ -139,8 +139,10 @@ type Connection struct { Host string `short:"h" long:"host" value-name:"<hostname>" description:"mongodb host to connect to (setname/host1,host2 for replica sets)"` Port string `long:"port" value-name:"<port>" description:"server port (can also use --host hostname:port)"` - Timeout int `long:"dialTimeout" default:"3" hidden:"true" description:"dial timeout in seconds"` - TCPKeepAliveSeconds int `long:"TCPKeepAliveSeconds" default:"30" hidden:"true" description:"seconds between TCP keep alives"` + Timeout int `long:"dialTimeout" default:"3" hidden:"true" description:"dial timeout in seconds"` + SocketTimeout int `long:"socketTimeout" default:"0" hidden:"true" description:"socket timeout in seconds (0 for no timeout)"` + TCPKeepAliveSeconds int `long:"TCPKeepAliveSeconds" default:"30" hidden:"true" description:"seconds between TCP keep alives"` + ServerSelectionTimeout int `long:"serverSelectionTimeout" hidden:"true" description:"seconds to wait for server selection; 0 means driver default"` } // Struct holding ssl-related options @@ -509,8 +511,11 @@ func (opts *ToolOptions) setOptionsFromURI(cs connstring.ConnString) error { return fmt.Errorf(IncompatibleArgsErrorFormat, "--port") case opts.Connection.Timeout != 3: return fmt.Errorf(IncompatibleArgsErrorFormat, "--dialTimeout") + case opts.Connection.SocketTimeout != 0: + return fmt.Errorf(IncompatibleArgsErrorFormat, "--socketTimeout") } opts.Connection.Timeout = int(cs.ConnectTimeout / time.Millisecond) + opts.Connection.SocketTimeout = int(cs.SocketTimeout / time.Millisecond) } if opts.enabledOptions.Auth { diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/pass_util.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/pass_util.go index 4d55a1453de..2da2ccafd81 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/pass_util.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/pass_util.go @@ -9,9 +9,11 @@ package password import ( - "github.com/howeyc/gopass" - "golang.org/x/crypto/ssh/terminal" + "io" + "os" "syscall" + + "golang.org/x/crypto/ssh/terminal" ) // This file contains all the calls needed to properly @@ -22,7 +24,22 @@ func IsTerminal() bool { return terminal.IsTerminal(int(syscall.Stdin)) } -func GetPass() string { - pass, _ := gopass.GetPasswd() - return string(pass) +func GetPass() (string, error) { + oldState, err := terminal.MakeRaw(0) + if err != nil { + return "", err + } + defer terminal.Restore(0, oldState) + + screen := struct { + io.Reader + io.Writer + }{os.Stdin, os.Stderr} + + t := terminal.NewTerminal(screen, "") + pass, err := t.ReadPassword("") + if err != nil { + return "", err + } + return string(pass), nil } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/pass_util_solaris.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/pass_util_solaris.go deleted file mode 100644 index 58ad45c0b76..00000000000 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/pass_util_solaris.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2014-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package password - -import ( - "os" - "syscall" - "unsafe" -) - -// This file is a mess based primarily on -// "github.com/howeyc/gopass" -// "golang.org/x/crypto/ssh/terminal" -// with extra unistd.h ripped from solaris on amd64 -// -// TODO: get some of these changes merged into the above two packages - -// ioctl constants -- not defined in solaris syscall pkg -const ( - SYS_IOCTL = 54 - TCGETS = 21517 - TCSETS = 21518 - ttyfd = 0 //STDIN -) - -// getTermios reads the current termios settings into the -// given termios struct. -func getTermios(term *syscall.Termios) error { - _, _, errno := syscall.Syscall(SYS_IOCTL, - uintptr(ttyfd), uintptr(TCGETS), - uintptr(unsafe.Pointer(term))) - if errno != 0 { - return os.NewSyscallError("SYS_IOCTL", errno) - } - return nil -} - -// setTermios applies the supplied termios settings -func setTermios(term *syscall.Termios) error { - _, _, errno := syscall.Syscall(SYS_IOCTL, - uintptr(ttyfd), uintptr(TCSETS), - uintptr(unsafe.Pointer(term))) - if errno != 0 { - return os.NewSyscallError("SYS_IOCTL", errno) - } - return nil -} - -// setRaw puts the terminal into "raw" mode, which takes -// in all key presses and does not echo them. -func setRaw(term syscall.Termios) error { - termCopy := term - termCopy.Iflag &^= syscall.ISTRIP | syscall.INLCR | - syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF - termCopy.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG - return setTermios(&termCopy) -} - -// isTerminal checks if we are reading from a terminal (instead of a pipe). -func IsTerminal() bool { - var termios syscall.Termios - _, _, errno := syscall.Syscall(SYS_IOCTL, - uintptr(ttyfd), TCGETS, - uintptr(unsafe.Pointer(&termios))) - return errno == 0 -} - -// readChar safely gets one byte from stdin -func readChar() byte { - var originalTerm syscall.Termios - if err := getTermios(&originalTerm); err != nil { - panic(err) // should not happen on amd64 solaris (untested on sparc) - } - if err := setRaw(originalTerm); err != nil { - panic(err) - } - defer func() { - // make sure we return the termios back to normal - if err := setTermios(&originalTerm); err != nil { - panic(err) - } - }() - - // read a single byte then reset the terminal state - var singleChar [1]byte - if n, err := syscall.Read(ttyfd, singleChar[:]); n == 0 || err != nil { - panic(err) - } - return singleChar[0] -} - -// get password from terminal -func GetPass() string { - // keep reading in characters until we hit a stopping point - pass := []byte{} - for { - ch := readChar() - if ch == backspaceKey || ch == deleteKey { - if len(pass) > 0 { - pass = pass[:len(pass)-1] - } - } else if ch == carriageReturnKey || ch == newLineKey || ch == eotKey || ch == eofKey { - break - } else if ch != 0 { - pass = append(pass, ch) - } - } - return string(pass) -} diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/password.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/password.go index 290f1849d71..3905cce93e3 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/password.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/password/password.go @@ -27,30 +27,34 @@ const ( // Prompt displays a prompt asking for the password and returns the // password the user enters as a string. -func Prompt() string { +func Prompt() (string, error) { var pass string + var err error if IsTerminal() { log.Logv(log.DebugLow, "standard input is a terminal; reading password from terminal") fmt.Fprintf(os.Stderr, "Enter password:") - pass = GetPass() + pass, err = GetPass() } else { log.Logv(log.Always, "reading password from standard input") fmt.Fprintf(os.Stderr, "Enter password:") - pass = readPassFromStdin() + pass, err = readPassFromStdin() + } + if err != nil { + return "", err } fmt.Fprintln(os.Stderr) - return pass + return pass, nil } // readPassFromStdin pipes in a password from stdin if // we aren't using a terminal for standard input -func readPassFromStdin() string { +func readPassFromStdin() (string, error) { pass := []byte{} for { var chBuf [1]byte n, err := os.Stdin.Read(chBuf[:]) if err != nil { - panic(err) + return "", err } if n == 0 { break @@ -66,5 +70,5 @@ func readPassFromStdin() string { pass = append(pass, ch) } } - return string(pass) + return string(pass), nil } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/buffer.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/buffer.go index 2add53b5f9b..76a77a6ca0c 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/buffer.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/buffer.go @@ -15,6 +15,7 @@ import ( "github.com/mongodb/mongo-tools-common/bsonutil" "github.com/mongodb/mongo-tools-common/db" + "github.com/mongodb/mongo-tools-common/util" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) @@ -23,6 +24,8 @@ var ErrBufferClosed = errors.New("transaction buffer already closed") var ErrTxnAborted = errors.New("transaction aborted") var ErrNotTransaction = errors.New("oplog entry is not a transaction") +var zeroTimestamp = primitive.Timestamp{} + type txnTask struct { meta Meta op db.Oplog @@ -37,15 +40,17 @@ type txnState struct { ingestDone chan struct{} ingestErr error stopChan chan struct{} + startTime primitive.Timestamp wg sync.WaitGroup } -func newTxnState() *txnState { +func newTxnState(op db.Oplog) *txnState { return &txnState{ ingestChan: make(chan txnTask), ingestDone: make(chan struct{}), stopChan: make(chan struct{}), buffer: make([]db.Oplog, 0), + startTime: op.Timestamp, } } @@ -107,7 +112,7 @@ func (b *Buffer) AddOp(m Meta, op db.Oplog) error { // Get or initialize transaction state state, ok := b.txns[m.id] if !ok { - state = newTxnState() + state = newTxnState(op) b.txns[m.id] = state b.wg.Add(1) state.wg.Add(1) @@ -211,6 +216,21 @@ LOOP: b.wg.Done() } +// OldestTimestamp returns the timestamp of the oldest buffered transaction, or +// a zero-value timestamp if no transactions are buffered. This will include +// committed transactions until they are purged. +func (b *Buffer) OldestTimestamp() primitive.Timestamp { + b.Lock() + defer b.Unlock() + oldest := zeroTimestamp + for _, v := range b.txns { + if oldest == zeroTimestamp || util.TimestampLessThan(v.startTime, oldest) { + oldest = v.startTime + } + } + return oldest +} + // PurgeTxn closes any transaction streams in progress and deletes all oplog // entries associated with a transaction. // diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/README.md b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/README.md index 379a5a999c3..0d2e92a5591 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/README.md +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/README.md @@ -31,7 +31,7 @@ The MongoDB supported driver for Go. The recommended way to get started using the MongoDB Go driver is by using `dep` to install the dependency in your project. ```bash -dep ensure -add "go.mongodb.org/mongo-driver/mongo@~1.1.1" +dep ensure -add "go.mongodb.org/mongo-driver/mongo@~1.1.2" ``` ------------------------- diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/client.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/client.go index fd53f15b117..af25b00e9cf 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/client.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/client.go @@ -498,10 +498,11 @@ func (c *Client) ListDatabases(ctx context.Context, filter interface{}, opts ... return ListDatabasesResult{}, err } - selector := makePinnedSelector(sess, description.CompositeSelector([]description.ServerSelector{ + selector := description.CompositeSelector([]description.ServerSelector{ description.ReadPrefSelector(readpref.Primary()), description.LatencySelector(c.localThreshold), - })) + }) + selector = makeReadPrefSelector(sess, selector, c.localThreshold) ldo := options.MergeListDatabasesOptions(opts...) op := operation.NewListDatabases(filterDoc). diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/collection.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/collection.go index 4bc9b5405de..b356cb6e5ae 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/collection.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/collection.go @@ -654,11 +654,10 @@ func aggregate(a aggregateParams) (*Cursor, error) { sess = nil } - defaultSelector := a.readSelector - if hasOutputStage { - defaultSelector = a.writeSelector + selector := makePinnedSelector(sess, a.writeSelector) + if !hasOutputStage { + selector = makeReadPrefSelector(sess, a.readSelector, a.client.localThreshold) } - selector := makePinnedSelector(sess, defaultSelector) ao := options.MergeAggregateOptions(a.opts...) cursorOpts := driver.CursorOptions{ @@ -756,8 +755,7 @@ func (coll *Collection) CountDocuments(ctx context.Context, filter interface{}, rc = nil } - selector := makePinnedSelector(sess, coll.readSelector) - + selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) op := operation.NewAggregate(pipelineArr).Session(sess).ReadConcern(rc).ReadPreference(coll.readPreference). CommandMonitor(coll.client.monitor).ServerSelector(selector).ClusterClock(coll.client.clock).Database(coll.db.name). Collection(coll.name).Deployment(coll.client.topology) @@ -832,8 +830,7 @@ func (coll *Collection) EstimatedDocumentCount(ctx context.Context, rc = nil } - selector := makePinnedSelector(sess, coll.readSelector) - + selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) op := operation.NewCount().Session(sess).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor). Deployment(coll.client.topology).ReadConcern(rc).ReadPreference(coll.readPreference). @@ -888,8 +885,7 @@ func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter i rc = nil } - selector := makePinnedSelector(sess, coll.readSelector) - + selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) option := options.MergeDistinctOptions(opts...) op := operation.NewDistinct(fieldName, bsoncore.Document(f)). @@ -971,8 +967,7 @@ func (coll *Collection) Find(ctx context.Context, filter interface{}, rc = nil } - selector := makePinnedSelector(sess, coll.readSelector) - + selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) op := operation.NewFind(f). Session(sess).ReadConcern(rc).ReadPreference(coll.readPreference). CommandMonitor(coll.client.monitor).ServerSelector(selector). @@ -1421,3 +1416,14 @@ func makePinnedSelector(sess *session.Client, defaultSelector description.Server return defaultSelector.SelectServer(t, svrs) } } + +func makeReadPrefSelector(sess *session.Client, selector description.ServerSelector, localThreshold time.Duration) description.ServerSelectorFunc { + if sess != nil && sess.TransactionRunning() { + selector = description.CompositeSelector([]description.ServerSelector{ + description.ReadPrefSelector(sess.CurrentRp), + description.LatencySelector(localThreshold), + }) + } + + return makePinnedSelector(sess, selector) +} diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/database.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/database.go index 46900ba5af1..9ee642e4798 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/database.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/database.go @@ -58,13 +58,18 @@ func newDatabase(client *Client, name string, opts ...*options.DatabaseOptions) wc = dbOpt.WriteConcern } + reg := client.registry + if dbOpt.Registry != nil { + reg = dbOpt.Registry + } + db := &Database{ client: client, name: name, readPreference: rp, readConcern: rc, writeConcern: wc, - registry: client.registry, + registry: reg, } db.readSelector = description.CompositeSelector([]description.ServerSelector{ @@ -273,7 +278,11 @@ func (db *Database) ListCollections(ctx context.Context, filter interface{}, opt return nil, err } - selector := makePinnedSelector(sess, db.readSelector) + selector := description.CompositeSelector([]description.ServerSelector{ + description.ReadPrefSelector(readpref.Primary()), + description.LatencySelector(db.client.localThreshold), + }) + selector = makeReadPrefSelector(sess, selector, db.client.localThreshold) lco := options.MergeListCollectionsOptions(opts...) op := operation.NewListCollections(filterDoc). @@ -313,6 +322,8 @@ func (db *Database) ListCollectionNames(ctx context.Context, filter interface{}, return nil, err } + defer res.Close(ctx) + names := make([]string, 0) for res.Next(ctx) { next := &bsonx.Doc{} @@ -334,6 +345,7 @@ func (db *Database) ListCollectionNames(ctx context.Context, filter interface{}, names = append(names, elemName) } + res.Close(ctx) return names, nil } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go index df6bae198ea..e21e9b045f6 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go @@ -75,13 +75,14 @@ func (iv IndexView) List(ctx context.Context, opts ...*options.ListIndexesOption return nil, err } - readSelector := description.CompositeSelector([]description.ServerSelector{ + selector := description.CompositeSelector([]description.ServerSelector{ description.ReadPrefSelector(readpref.Primary()), description.LatencySelector(iv.coll.client.localThreshold), }) + selector = makeReadPrefSelector(sess, selector, iv.coll.client.localThreshold) op := operation.NewListIndexes(). Session(sess).CommandMonitor(iv.coll.client.monitor). - ServerSelector(readSelector).ClusterClock(iv.coll.client.clock). + ServerSelector(selector).ClusterClock(iv.coll.client.clock). Database(iv.coll.db.name).Collection(iv.coll.name). Deployment(iv.coll.client.topology) @@ -197,10 +198,7 @@ func (iv IndexView) CreateMany(ctx context.Context, models []IndexModel, opts .. return nil, err } - selector := iv.coll.writeSelector - if sess != nil && sess.PinnedServer != nil { - selector = sess.PinnedServer - } + selector := makePinnedSelector(sess, iv.coll.writeSelector) option := options.MergeCreateIndexesOptions(opts...) @@ -332,10 +330,7 @@ func (iv IndexView) drop(ctx context.Context, name string, opts ...*options.Drop sess = nil } - selector := iv.coll.writeSelector - if sess != nil && sess.PinnedServer != nil { - selector = sess.PinnedServer - } + selector := makePinnedSelector(sess, iv.coll.writeSelector) dio := options.MergeDropIndexesOptions(opts...) op := operation.NewDropIndexes(name). diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/options/indexoptions.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/options/indexoptions.go index a49e6ee9635..791d521c175 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/options/indexoptions.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/options/indexoptions.go @@ -105,6 +105,9 @@ func MergeListIndexesOptions(opts ...*ListIndexesOptions) *ListIndexesOptions { if opt == nil { continue } + if opt.BatchSize != nil { + c.BatchSize = opt.BatchSize + } if opt.MaxTime != nil { c.MaxTime = opt.MaxTime } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/session.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/session.go index 889a54dbe7f..a84a33bad13 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/session.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/mongo/session.go @@ -185,14 +185,14 @@ func (s *sessionImpl) AbortTransaction(ctx context.Context) error { selector := makePinnedSelector(s.clientSession, description.WriteSelector()) s.clientSession.Aborting = true - err = operation.NewAbortTransaction().Session(s.clientSession).ClusterClock(s.client.clock).Database("admin"). + _ = operation.NewAbortTransaction().Session(s.clientSession).ClusterClock(s.client.clock).Database("admin"). Deployment(s.topo).WriteConcern(s.clientSession.CurrentWc).ServerSelector(selector). Retry(driver.RetryOncePerCommand).CommandMonitor(s.client.monitor).RecoveryToken(bsoncore.Document(s.clientSession.RecoveryToken)).Execute(ctx) s.clientSession.Aborting = false _ = s.clientSession.AbortTransaction() - return replaceErrors(err) + return nil } // CommitTransaction commits the sesson's transaction. diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/version/version.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/version/version.go index 90a2c80c96c..93790e8d79d 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/version/version.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/version/version.go @@ -7,4 +7,4 @@ package version // import "go.mongodb.org/mongo-driver/version" // Driver is the current version of the driver. -var Driver = "v1.1.1" +var Driver = "v1.1.2" diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go index 0774f6acd8c..78af1331c2c 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go @@ -56,40 +56,59 @@ type HandshakeOptions struct { PerformAuthentication func(description.Server) bool } -// Handshaker creates a connection handshaker for the given authenticator. -func Handshaker(h driver.Handshaker, options *HandshakeOptions) driver.Handshaker { - return driver.HandshakerFunc(func(ctx context.Context, addr address.Address, conn driver.Connection) (description.Server, error) { - desc, err := operation.NewIsMaster(). - AppName(options.AppName). - Compressors(options.Compressors). - SASLSupportedMechs(options.DBUser). - Handshake(ctx, addr, conn) +type authHandshaker struct { + wrapped driver.Handshaker + options *HandshakeOptions +} - if err != nil { - return description.Server{}, newAuthError("handshake failure", err) - } +// GetDescription performs an isMaster to retrieve the initial description for conn. +func (ah *authHandshaker) GetDescription(ctx context.Context, addr address.Address, conn driver.Connection) (description.Server, error) { + if ah.wrapped != nil { + return ah.wrapped.GetDescription(ctx, addr, conn) + } - performAuth := options.PerformAuthentication - if performAuth == nil { - performAuth = func(serv description.Server) bool { - return serv.Kind == description.RSPrimary || - serv.Kind == description.RSSecondary || - serv.Kind == description.Mongos || - serv.Kind == description.Standalone - } - } - if performAuth(desc) && options.Authenticator != nil { - err = options.Authenticator.Auth(ctx, desc, conn) - if err != nil { - return description.Server{}, newAuthError("auth error", err) - } + desc, err := operation.NewIsMaster(). + AppName(ah.options.AppName). + Compressors(ah.options.Compressors). + SASLSupportedMechs(ah.options.DBUser). + GetDescription(ctx, addr, conn) + if err != nil { + return description.Server{}, newAuthError("handshake failure", err) + } + return desc, nil +} +// FinishHandshake performs authentication for conn if necessary. +func (ah *authHandshaker) FinishHandshake(ctx context.Context, conn driver.Connection) error { + performAuth := ah.options.PerformAuthentication + if performAuth == nil { + performAuth = func(serv description.Server) bool { + return serv.Kind == description.RSPrimary || + serv.Kind == description.RSSecondary || + serv.Kind == description.Mongos || + serv.Kind == description.Standalone } - if h == nil { - return desc, nil + } + desc := conn.Description() + if performAuth(desc) && ah.options.Authenticator != nil { + err := ah.options.Authenticator.Auth(ctx, desc, conn) + if err != nil { + return newAuthError("auth error", err) } - return h.Handshake(ctx, addr, conn) - }) + } + + if ah.wrapped == nil { + return nil + } + return ah.wrapped.FinishHandshake(ctx, conn) +} + +// Handshaker creates a connection handshaker for the given authenticator. +func Handshaker(h driver.Handshaker, options *HandshakeOptions) driver.Handshaker { + return &authHandshaker{ + wrapped: h, + options: options, + } } // Authenticator handles authenticating a connection. diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batches.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batches.go index f99a6a4cc71..346921671e8 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batches.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batches.go @@ -39,16 +39,13 @@ func (b *Batches) AdvanceBatch(maxCount, targetBatchSize int) error { if len(b.Current) > 0 { return nil } - if targetBatchSize > reservedCommandBufferBytes { - targetBatchSize -= reservedCommandBufferBytes - } if maxCount <= 0 { maxCount = 1 } splitAfter := 0 - size := 1 + size := 0 for i, doc := range b.Documents { if i == maxCount { break diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/description/topology.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/description/topology.go index 07454711511..b6f4e3ea31d 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/description/topology.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/description/topology.go @@ -7,9 +7,6 @@ package description import ( - "sort" - "strings" - "go.mongodb.org/mongo-driver/x/mongo/driver/address" ) @@ -41,39 +38,24 @@ type TopologyDiff struct { func DiffTopology(old, new Topology) TopologyDiff { var diff TopologyDiff - // TODO: do this without sorting... - oldServers := serverSorter(old.Servers) - newServers := serverSorter(new.Servers) - - sort.Sort(oldServers) - sort.Sort(newServers) - - i := 0 - j := 0 - for { - if i < len(oldServers) && j < len(newServers) { - comp := strings.Compare(oldServers[i].Addr.String(), newServers[j].Addr.String()) - switch comp { - case 1: - //left is bigger than - diff.Added = append(diff.Added, newServers[j]) - j++ - case -1: - // right is bigger - diff.Removed = append(diff.Removed, oldServers[i]) - i++ - case 0: - i++ - j++ - } - } else if i < len(oldServers) { - diff.Removed = append(diff.Removed, oldServers[i]) - i++ - } else if j < len(newServers) { - diff.Added = append(diff.Added, newServers[j]) - j++ + oldServers := make(map[string]bool) + for _, s := range old.Servers { + oldServers[s.Addr.String()] = true + } + + for _, s := range new.Servers { + addr := s.Addr.String() + if oldServers[addr] { + delete(oldServers, addr) } else { - break + diff.Added = append(diff.Added, s) + } + } + + for _, s := range old.Servers { + addr := s.Addr.String() + if oldServers[addr] { + diff.Removed = append(diff.Removed, s) } } @@ -90,47 +72,22 @@ type HostlistDiff struct { func (t Topology) DiffHostlist(hostlist []string) HostlistDiff { var diff HostlistDiff - oldServers := serverSorter(t.Servers) - sort.Sort(oldServers) - sort.Strings(hostlist) - - i := 0 - j := 0 - for { - if i < len(oldServers) && j < len(hostlist) { - oldServer := oldServers[i].Addr.String() - comp := strings.Compare(oldServer, hostlist[j]) - switch comp { - case 1: - // oldServers[i] is bigger - diff.Added = append(diff.Added, hostlist[j]) - j++ - case -1: - // hostlist[j] is bigger - diff.Removed = append(diff.Removed, oldServer) - i++ - case 0: - i++ - j++ - } - } else if i < len(oldServers) { - diff.Removed = append(diff.Removed, oldServers[i].Addr.String()) - i++ - } else if j < len(hostlist) { - diff.Added = append(diff.Added, hostlist[j]) - j++ + oldServers := make(map[string]bool) + for _, s := range t.Servers { + oldServers[s.Addr.String()] = true + } + + for _, addr := range hostlist { + if oldServers[addr] { + delete(oldServers, addr) } else { - break + diff.Added = append(diff.Added, addr) } } - return diff -} - -type serverSorter []Server + for addr := range oldServers { + diff.Removed = append(diff.Removed, addr) + } -func (ss serverSorter) Len() int { return len(ss) } -func (ss serverSorter) Swap(i, j int) { ss[i], ss[j] = ss[j], ss[i] } -func (ss serverSorter) Less(i, j int) bool { - return strings.Compare(ss[i].Addr.String(), ss[j].Addr.String()) < 0 + return diff } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go index 4ff81a8ae12..870657f5d5e 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go @@ -59,16 +59,8 @@ type ErrorProcessor interface { // handshake over a provided driver.Connection. This is used during connection // initialization. Implementations must be goroutine safe. type Handshaker interface { - Handshake(context.Context, address.Address, Connection) (description.Server, error) -} - -// HandshakerFunc is an adapter to allow the use of ordinary functions as -// connection handshakers. -type HandshakerFunc func(context.Context, address.Address, Connection) (description.Server, error) - -// Handshake implements the Handshaker interface. -func (hf HandshakerFunc) Handshake(ctx context.Context, addr address.Address, conn Connection) (description.Server, error) { - return hf(ctx, addr, conn) + GetDescription(context.Context, address.Address, Connection) (description.Server, error) + FinishHandshake(context.Context, Connection) error } // SingleServerDeployment is an implementation of Deployment that always returns a single server. diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/ismaster.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/ismaster.go index 97d2858ed8a..e894fcd8db1 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/ismaster.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/ismaster.go @@ -28,6 +28,8 @@ type IsMaster struct { res bsoncore.Document } +var _ driver.Handshaker = (*IsMaster)(nil) + // NewIsMaster constructs an IsMaster. func NewIsMaster() *IsMaster { return &IsMaster{} } @@ -401,8 +403,9 @@ func (im *IsMaster) Execute(ctx context.Context) error { }.Execute(ctx, nil) } -// Handshake implements the Handshaker interface. -func (im *IsMaster) Handshake(ctx context.Context, _ address.Address, c driver.Connection) (description.Server, error) { +// GetDescription retrieves the server description for the given connection. This function implements the Handshaker +// interface. +func (im *IsMaster) GetDescription(ctx context.Context, _ address.Address, c driver.Connection) (description.Server, error) { err := driver.Operation{ Clock: im.clock, CommandFn: im.handshakeCommand, @@ -418,3 +421,9 @@ func (im *IsMaster) Handshake(ctx context.Context, _ address.Address, c driver.C } return im.Result(c.Address()), nil } + +// FinishHandshake implements the Handshaker interface. This is a no-op function because a non-authenticated connection +// does not do anything besides the initial isMaster for a handshake. +func (im *IsMaster) FinishHandshake(context.Context, driver.Connection) error { + return nil +} diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation_legacy.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation_legacy.go index 5f128a14137..dd69aaed5ea 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation_legacy.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation_legacy.go @@ -107,8 +107,6 @@ func (op Operation) createLegacyFindWireMessage(dst []byte, desc description.Sel optsElems = bsoncore.AppendValueElement(optsElems, "$hint", elem.Value()) case "comment": optsElems = bsoncore.AppendValueElement(optsElems, "$comment", elem.Value()) - case "maxScan": - optsElems = bsoncore.AppendValueElement(optsElems, "$maxScan", elem.Value()) case "max": optsElems = bsoncore.AppendValueElement(optsElems, "$max", elem.Value()) case "min": @@ -141,7 +139,7 @@ func (op Operation) createLegacyFindWireMessage(dst []byte, desc description.Sel flags |= wiremessage.TailableCursor case "awaitData": flags |= wiremessage.AwaitData - case "oplogReply": + case "oplogReplay": flags |= wiremessage.OplogReplay case "noCursorTimeout": flags |= wiremessage.NoCursorTimeout @@ -560,8 +558,12 @@ func (op Operation) createLegacyListIndexesWiremessage(dst []byte, desc descript switch elem.Key() { case "listIndexes": filterCollName = elem.Value().StringValue() - case "batchSize": - batchSize = elem.Value().Int32() + case "cursor": + // the batchSize option is embedded in a cursor subdocument + cursorDoc := elem.Value().Document() + if val, err := cursorDoc.LookupErr("batchSize"); err == nil { + batchSize = val.Int32() + } case "maxTimeMS": optsElems = bsoncore.AppendValueElement(optsElems, "$maxTimeMS", elem.Value()) } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go index fd227fca7d9..db1a2ab514a 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go @@ -37,7 +37,7 @@ type connection struct { nc net.Conn // When nil, the connection is closed. addr address.Address idleTimeout time.Duration - idleDeadline time.Time + idleDeadline atomic.Value // Stores a time.Time lifetimeDeadline time.Time readTimeout time.Duration writeTimeout time.Duration @@ -87,6 +87,7 @@ func newConnection(ctx context.Context, addr address.Address, opts ...Connection // connect handles the I/O for a connection. It will dial, configure TLS, and perform // initialization handshakes. func (c *connection) connect(ctx context.Context) { + if !atomic.CompareAndSwapInt32(&c.connected, initialized, connected) { return } @@ -113,46 +114,56 @@ func (c *connection) connect(ctx context.Context) { c.bumpIdleDeadline() // running isMaster and authentication is handled by a handshaker on the configuration instance. - if c.config.handshaker != nil { - c.desc, err = c.config.handshaker.Handshake(ctx, c.addr, initConnection{c}) - if err != nil { - if c.nc != nil { - _ = c.nc.Close() - } - atomic.StoreInt32(&c.connected, disconnected) - c.connectErr = ConnectionError{Wrapped: err, init: true} - return - } - if c.config.descCallback != nil { - c.config.descCallback(c.desc) + handshaker := c.config.handshaker + if handshaker == nil { + return + } + + handshakeConn := initConnection{c} + c.desc, err = handshaker.GetDescription(ctx, c.addr, handshakeConn) + if err == nil { + err = handshaker.FinishHandshake(ctx, handshakeConn) + } + if err != nil { + if c.nc != nil { + _ = c.nc.Close() } - if len(c.desc.Compression) > 0 { - clientMethodLoop: - for _, method := range c.config.compressors { - for _, serverMethod := range c.desc.Compression { - if method != serverMethod { - continue - } + atomic.StoreInt32(&c.connected, disconnected) + c.connectErr = ConnectionError{Wrapped: err, init: true} + return + } - switch strings.ToLower(method) { - case "snappy": - c.compressor = wiremessage.CompressorSnappy - case "zlib": - c.compressor = wiremessage.CompressorZLib - c.zliblevel = wiremessage.DefaultZlibLevel - if c.config.zlibLevel != nil { - c.zliblevel = *c.config.zlibLevel - } + if c.config.descCallback != nil { + c.config.descCallback(c.desc) + } + if len(c.desc.Compression) > 0 { + clientMethodLoop: + for _, method := range c.config.compressors { + for _, serverMethod := range c.desc.Compression { + if method != serverMethod { + continue + } + + switch strings.ToLower(method) { + case "snappy": + c.compressor = wiremessage.CompressorSnappy + case "zlib": + c.compressor = wiremessage.CompressorZLib + c.zliblevel = wiremessage.DefaultZlibLevel + if c.config.zlibLevel != nil { + c.zliblevel = *c.config.zlibLevel } - break clientMethodLoop } + break clientMethodLoop } } } } -func (c *connection) connectWait() error { - <-c.connectDone +func (c *connection) wait() error { + if c.connectDone != nil { + <-c.connectDone + } return c.connectErr } @@ -259,7 +270,11 @@ func (c *connection) close() error { return nil } if c.pool == nil { - err := c.nc.Close() + var err error + + if c.nc != nil { + err = c.nc.Close() + } atomic.StoreInt32(&c.connected, disconnected) return err } @@ -268,7 +283,8 @@ func (c *connection) close() error { func (c *connection) expired() bool { now := time.Now() - if !c.idleDeadline.IsZero() && now.After(c.idleDeadline) { + idleDeadline, ok := c.idleDeadline.Load().(time.Time) + if ok && now.After(idleDeadline) { return true } @@ -281,7 +297,7 @@ func (c *connection) expired() bool { func (c *connection) bumpIdleDeadline() { if c.idleTimeout > 0 { - c.idleDeadline = time.Now().Add(c.idleTimeout) + c.idleDeadline.Store(time.Now().Add(c.idleTimeout)) } } @@ -292,10 +308,15 @@ type initConnection struct{ *connection } var _ driver.Connection = initConnection{} -func (c initConnection) Description() description.Server { return description.Server{} } -func (c initConnection) Close() error { return nil } -func (c initConnection) ID() string { return c.id } -func (c initConnection) Address() address.Address { return c.addr } +func (c initConnection) Description() description.Server { + if c.connection == nil { + return description.Server{} + } + return c.connection.desc +} +func (c initConnection) Close() error { return nil } +func (c initConnection) ID() string { return c.id } +func (c initConnection) Address() address.Address { return c.addr } func (c initConnection) LocalAddress() address.Address { if c.connection == nil || c.nc == nil { return address.Address("0.0.0.0") @@ -410,11 +431,8 @@ func (c *Connection) Close() error { defer c.s.sem.Release(1) } err := c.pool.put(c.connection) - if err != nil { - return err - } c.connection = nil - return nil + return err } // Expire closes this connection and will closeConnection the underlying socket. @@ -428,11 +446,8 @@ func (c *Connection) Expire() error { c.s.sem.Release(1) } err := c.close() - if err != nil { - return err - } c.connection = nil - return nil + return err } // Alive returns if the connection is still alive. diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection_options.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection_options.go index 9462fc85ded..fe60359999e 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection_options.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection_options.go @@ -35,10 +35,6 @@ var DefaultDialer Dialer = &net.Dialer{} // initialization. Implementations must be goroutine safe. type Handshaker = driver.Handshaker -// HandshakerFunc is an adapter to allow the use of ordinary functions as -// connection handshakers. -type HandshakerFunc = driver.HandshakerFunc - type connectionConfig struct { appName string connectTimeout time.Duration diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go index 6a9cc634c3b..ee986838100 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go @@ -116,7 +116,11 @@ func connectionCloseFunc(v interface{}) { return } - go func() { _ = c.pool.closeConnection(c) }() + go func() { + // wait for connection to finish trying to connect + _ = c.wait() + _ = c.pool.closeConnection(c) + }() } // connectionInitFunc returns an init function for the resource pool that will make new connections for this pool @@ -329,7 +333,7 @@ func (p *pool) get(ctx context.Context) (*connection, error) { c.connect(ctx) } - err := c.connectWait() + err := c.wait() if err != nil { if p.monitor != nil { p.monitor.Event(&event.PoolEvent{ @@ -377,7 +381,7 @@ func (p *pool) get(ctx context.Context) (*connection, error) { c.connect(ctx) // wait for conn to be connected - err = c.connectWait() + err = c.wait() if err != nil { if p.monitor != nil { p.monitor.Event(&event.PoolEvent{ @@ -413,10 +417,14 @@ func (p *pool) closeConnection(c *connection) error { if !atomic.CompareAndSwapInt32(&c.connected, connected, disconnected) { return nil // We're closing an already closed connection } - err := c.nc.Close() - if err != nil { - return ConnectionError{ConnectionID: c.id, Wrapped: err, message: "failed to closeConnection net.Conn"} + + if c.nc != nil { + err := c.nc.Close() + if err != nil { + return ConnectionError{ConnectionID: c.id, Wrapped: err, message: "failed to close net.Conn"} + } } + return nil } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go index d1cc331b282..79c6931b743 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go @@ -499,7 +499,7 @@ func (s *Server) heartbeat(conn *connection) (description.Server, *connection) { conn.connect(ctx) - err := conn.connectWait() + err := conn.wait() if err == nil { descPtr = &conn.desc } diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology.go index 97cedeb47a6..340b64cc7cf 100644 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology.go +++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology.go @@ -591,6 +591,8 @@ func (t *Topology) addServer(addr address.Address) error { func (t *Topology) String() string { desc := t.Description() str := fmt.Sprintf("Type: %s\nServers:\n", desc.Kind) + t.serversLock.Lock() + defer t.serversLock.Unlock() for _, s := range t.servers { str += s.String() + "\n" } |