From 8de8b81bfd518a9c4143cb8a6561946d9d8ebdde Mon Sep 17 00:00:00 2001 From: Dom Dwyer Date: Tue, 18 Apr 2017 11:22:12 +0100 Subject: [PATCH 1/2] Add read concern configuration to Safe{} --- .travis.yml | 2 +- README.md | 2 +- auth.go | 4 ++-- auth_test.go | 2 +- bson/bson_corpus_spec_test.go | 2 +- bson/bson_corpus_spec_test_generator.go | 4 ++-- bson/bson_test.go | 2 +- bson/decimal_test.go | 2 +- bson/json.go | 2 +- bson/json_test.go | 2 +- bulk.go | 2 +- bulk_test.go | 2 +- cluster.go | 2 +- cluster_test.go | 4 ++-- dbtest/dbserver.go | 2 +- dbtest/dbserver_test.go | 4 ++-- gridfs.go | 2 +- gridfs_test.go | 4 ++-- internal/scram/scram_test.go | 2 +- saslimpl.go | 2 +- server.go | 2 +- session.go | 22 ++++++++++++++++++++-- session_test.go | 24 ++++++++++++++++++++++-- socket.go | 25 +++++++++++++------------ suite_test.go | 4 ++-- txn/debug.go | 2 +- txn/flusher.go | 4 ++-- txn/sim_test.go | 8 ++++---- txn/tarjan.go | 2 +- txn/tarjan_test.go | 2 +- txn/txn.go | 4 ++-- txn/txn_test.go | 8 ++++---- 32 files changed, 98 insertions(+), 59 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5f0127d41..f5c0c33a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: go -go_import_path: github.com/domodwyer/mgo +go_import_path: github.com/globalsign/mgo addons: apt: diff --git a/README.md b/README.md index 28192f0c7..7d16e8ff5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/domodwyer/mgo.svg?branch=master)](https://travis-ci.org/domodwyer/mgo) [![GoDoc](https://godoc.org/github.com/domodwyer/mgo?status.svg)](https://godoc.org/github.com/domodwyer/mgo) +[![Build Status](https://travis-ci.org/domodwyer/mgo.svg?branch=master)](https://travis-ci.org/domodwyer/mgo) [![GoDoc](https://godoc.org/github.com/globalsign/mgo?status.svg)](https://godoc.org/github.com/globalsign/mgo) The MongoDB driver for Go ------------------------- diff --git a/auth.go b/auth.go index df76edb85..388e62105 100644 --- a/auth.go +++ b/auth.go @@ -34,8 +34,8 @@ import ( "fmt" "sync" - "github.com/domodwyer/mgo/bson" - "github.com/domodwyer/mgo/internal/scram" + "github.com/globalsign/mgo/bson" + "github.com/globalsign/mgo/internal/scram" ) type authCmd struct { diff --git a/auth_test.go b/auth_test.go index 7b9a83502..9f04b2246 100644 --- a/auth_test.go +++ b/auth_test.go @@ -38,7 +38,7 @@ import ( "sync" "time" - mgo "github.com/domodwyer/mgo" + mgo "github.com/globalsign/mgo" . "gopkg.in/check.v1" ) diff --git a/bson/bson_corpus_spec_test.go b/bson/bson_corpus_spec_test.go index 6c92f165f..3cff72440 100644 --- a/bson/bson_corpus_spec_test.go +++ b/bson/bson_corpus_spec_test.go @@ -6,7 +6,7 @@ import ( "encoding/hex" "time" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) diff --git a/bson/bson_corpus_spec_test_generator.go b/bson/bson_corpus_spec_test_generator.go index 14a4bdc9b..3525a004b 100644 --- a/bson/bson_corpus_spec_test_generator.go +++ b/bson/bson_corpus_spec_test_generator.go @@ -12,7 +12,7 @@ import ( "path/filepath" "strings" - "github.com/domodwyer/mgo/internal/json" + "github.com/globalsign/mgo/internal/json" ) func main() { @@ -162,7 +162,7 @@ import ( "time" . "gopkg.in/check.v1" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) func testValid(c *C, in []byte, expected []byte, result interface{}) { diff --git a/bson/bson_test.go b/bson/bson_test.go index d770e5132..35bcc52f0 100644 --- a/bson/bson_test.go +++ b/bson/bson_test.go @@ -37,7 +37,7 @@ import ( "testing" "time" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) diff --git a/bson/decimal_test.go b/bson/decimal_test.go index 577b77102..2cc510cca 100644 --- a/bson/decimal_test.go +++ b/bson/decimal_test.go @@ -33,7 +33,7 @@ import ( "regexp" "strings" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) diff --git a/bson/json.go b/bson/json.go index 181542ba3..3cfa102c4 100644 --- a/bson/json.go +++ b/bson/json.go @@ -7,7 +7,7 @@ import ( "strconv" "time" - "github.com/domodwyer/mgo/internal/json" + "github.com/globalsign/mgo/internal/json" ) // UnmarshalJSON unmarshals a JSON value that may hold non-standard diff --git a/bson/json_test.go b/bson/json_test.go index 3a93b2c93..d8ce798f9 100644 --- a/bson/json_test.go +++ b/bson/json_test.go @@ -1,7 +1,7 @@ package bson_test import ( - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" "reflect" "strings" diff --git a/bulk.go b/bulk.go index 1ece3e0e5..d6925fba4 100644 --- a/bulk.go +++ b/bulk.go @@ -4,7 +4,7 @@ import ( "bytes" "sort" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) // Bulk represents an operation that can be prepared with several diff --git a/bulk_test.go b/bulk_test.go index 60084ccca..b1a5fbb3c 100644 --- a/bulk_test.go +++ b/bulk_test.go @@ -27,7 +27,7 @@ package mgo_test import ( - mgo "github.com/domodwyer/mgo" + mgo "github.com/globalsign/mgo" . "gopkg.in/check.v1" ) diff --git a/cluster.go b/cluster.go index 76ceba6a6..97e7e9641 100644 --- a/cluster.go +++ b/cluster.go @@ -35,7 +35,7 @@ import ( "sync" "time" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) // --------------------------------------------------------------------------- diff --git a/cluster_test.go b/cluster_test.go index ded0b9e68..c2ec24919 100644 --- a/cluster_test.go +++ b/cluster_test.go @@ -34,8 +34,8 @@ import ( "sync" "time" - mgo "github.com/domodwyer/mgo" - "github.com/domodwyer/mgo/bson" + mgo "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) diff --git a/dbtest/dbserver.go b/dbtest/dbserver.go index 39cdbce56..4fe530c90 100644 --- a/dbtest/dbserver.go +++ b/dbtest/dbserver.go @@ -9,7 +9,7 @@ import ( "strconv" "time" - mgo "github.com/domodwyer/mgo" + mgo "github.com/globalsign/mgo" "gopkg.in/tomb.v2" ) diff --git a/dbtest/dbserver_test.go b/dbtest/dbserver_test.go index 0dfcced84..f0576c25c 100644 --- a/dbtest/dbserver_test.go +++ b/dbtest/dbserver_test.go @@ -5,10 +5,10 @@ import ( "testing" "time" - mgo "github.com/domodwyer/mgo" + mgo "github.com/globalsign/mgo" . "gopkg.in/check.v1" - "github.com/domodwyer/mgo/dbtest" + "github.com/globalsign/mgo/dbtest" ) type M map[string]interface{} diff --git a/gridfs.go b/gridfs.go index 9a3d4c224..71ca609fa 100644 --- a/gridfs.go +++ b/gridfs.go @@ -36,7 +36,7 @@ import ( "sync" "time" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) type GridFS struct { diff --git a/gridfs_test.go b/gridfs_test.go index 0e06fea00..9fdd0a26f 100644 --- a/gridfs_test.go +++ b/gridfs_test.go @@ -31,8 +31,8 @@ import ( "os" "time" - mgo "github.com/domodwyer/mgo" - "github.com/domodwyer/mgo/bson" + mgo "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) diff --git a/internal/scram/scram_test.go b/internal/scram/scram_test.go index dcfdf1af8..a54a56b7b 100644 --- a/internal/scram/scram_test.go +++ b/internal/scram/scram_test.go @@ -6,7 +6,7 @@ import ( "strings" - "github.com/domodwyer/mgo/internal/scram" + "github.com/globalsign/mgo/internal/scram" . "gopkg.in/check.v1" ) diff --git a/saslimpl.go b/saslimpl.go index 996fa8f5e..088270ccf 100644 --- a/saslimpl.go +++ b/saslimpl.go @@ -3,7 +3,7 @@ package mgo import ( - "github.com/domodwyer/mgo/internal/sasl" + "github.com/globalsign/mgo/internal/sasl" ) func saslNew(cred Credential, host string) (saslStepper, error) { diff --git a/server.go b/server.go index f42290559..6a9fffe65 100644 --- a/server.go +++ b/server.go @@ -33,7 +33,7 @@ import ( "sync" "time" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) // --------------------------------------------------------------------------- diff --git a/session.go b/session.go index 95f6557c1..79fa01520 100644 --- a/session.go +++ b/session.go @@ -41,7 +41,7 @@ import ( "sync" "time" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) type Mode int @@ -1889,6 +1889,7 @@ func (s *Session) SetPrefetch(p float64) { type Safe struct { W int // Min # of servers to ack before success WMode string // Write mode for MongoDB 2.0+ (e.g. "majority") + RMode string // Read mode for MonogDB 3.2+ ("majority", "local", "linearizable") WTimeout int // Milliseconds to wait for W before timing out FSync bool // Sync via the journal if present, or via data files sync otherwise J bool // Sync via the journal if present @@ -1980,6 +1981,7 @@ func (s *Session) Safe() (safe *Safe) { // // Relevant documentation: // +// https://docs.mongodb.com/manual/reference/read-concern/ // http://www.mongodb.org/display/DOCS/getLastError+Command // http://www.mongodb.org/display/DOCS/Verifying+Propagation+of+Writes+with+getLastError // http://www.mongodb.org/display/DOCS/Data+Center+Awareness @@ -1998,6 +2000,7 @@ func (s *Session) SetSafe(safe *Safe) { // That is: // // - safe.WMode is always used if set. +// - safe.RMode is always used if set. // - safe.W is used if larger than the current W and WMode is empty. // - safe.FSync is always used if true. // - safe.J is used if FSync is false. @@ -2036,6 +2039,13 @@ func (s *Session) ensureSafe(safe *Safe) { w = safe.W } + // Set the read concern + switch safe.RMode { + case "majority", "local", "linearizable": + s.queryConfig.op.readConcern = safe.RMode + default: + } + var cmd getLastError if s.safeOp == nil { cmd = getLastError{1, w, safe.WTimeout, safe.FSync, safe.J} @@ -3284,7 +3294,9 @@ func prepareFindOp(socket *mongoSocket, op *queryOp, limit int32) bool { Snapshot: op.options.Snapshot, OplogReplay: op.flags&flagLogReplay != 0, Collation: op.options.Collation, + ReadConcern: readLevel{level: op.readConcern}, } + if op.limit < 0 { find.BatchSize = -op.limit find.SingleBatch = true @@ -3334,7 +3346,7 @@ type findCmd struct { Comment string `bson:"comment,omitempty"` MaxScan int `bson:"maxScan,omitempty"` MaxTimeMS int `bson:"maxTimeMS,omitempty"` - ReadConcern interface{} `bson:"readConcern,omitempty"` + ReadConcern readLevel `bson:"readConcern,omitempty"` Max interface{} `bson:"max,omitempty"` Min interface{} `bson:"min,omitempty"` ReturnKey bool `bson:"returnKey,omitempty"` @@ -3348,6 +3360,12 @@ type findCmd struct { Collation *Collation `bson:"collation,omitempty"` } +// readLevel provides the nested "level: majority" serialisation needed for the +// query read concern. +type readLevel struct { + level string `bson:"level,omitempty"` +} + // getMoreCmd holds the command used for requesting more query results on MongoDB 3.2+. // // Relevant documentation: diff --git a/session_test.go b/session_test.go index 38470fe95..a4ce5482a 100644 --- a/session_test.go +++ b/session_test.go @@ -38,8 +38,8 @@ import ( "testing" "time" - mgo "github.com/domodwyer/mgo" - "github.com/domodwyer/mgo/bson" + mgo "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) @@ -2781,6 +2781,7 @@ func (s *S) TestSafeSetting(c *C) { safe := session.Safe() c.Assert(safe.W, Equals, 0) c.Assert(safe.WMode, Equals, "") + c.Assert(safe.RMode, Equals, "") c.Assert(safe.WTimeout, Equals, 0) c.Assert(safe.FSync, Equals, false) c.Assert(safe.J, Equals, false) @@ -2790,6 +2791,7 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 1) c.Assert(safe.WMode, Equals, "") + c.Assert(safe.RMode, Equals, "") c.Assert(safe.WTimeout, Equals, 2) c.Assert(safe.FSync, Equals, true) c.Assert(safe.J, Equals, false) @@ -2799,6 +2801,7 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 0) c.Assert(safe.WMode, Equals, "") + c.Assert(safe.RMode, Equals, "") c.Assert(safe.WTimeout, Equals, 0) c.Assert(safe.FSync, Equals, false) c.Assert(safe.J, Equals, false) @@ -2808,6 +2811,7 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 5) c.Assert(safe.WMode, Equals, "") + c.Assert(safe.RMode, Equals, "") c.Assert(safe.WTimeout, Equals, 6) c.Assert(safe.FSync, Equals, false) c.Assert(safe.J, Equals, true) @@ -2817,6 +2821,7 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 5) c.Assert(safe.WMode, Equals, "") + c.Assert(safe.RMode, Equals, "") c.Assert(safe.WTimeout, Equals, 6) c.Assert(safe.FSync, Equals, false) c.Assert(safe.J, Equals, true) @@ -2826,6 +2831,7 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 6) c.Assert(safe.WMode, Equals, "") + c.Assert(safe.RMode, Equals, "") c.Assert(safe.WTimeout, Equals, 4) c.Assert(safe.FSync, Equals, true) c.Assert(safe.J, Equals, false) @@ -2835,6 +2841,17 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 0) c.Assert(safe.WMode, Equals, "majority") + c.Assert(safe.RMode, Equals, "") + c.Assert(safe.WTimeout, Equals, 2) + c.Assert(safe.FSync, Equals, true) + c.Assert(safe.J, Equals, false) + + // Read concern + session.EnsureSafe(&mgo.Safe{RMode: "majority"}) + safe = session.Safe() + c.Assert(safe.W, Equals, 0) + c.Assert(safe.WMode, Equals, "majority") + c.Assert(safe.RMode, Equals, "majority") c.Assert(safe.WTimeout, Equals, 2) c.Assert(safe.FSync, Equals, true) c.Assert(safe.J, Equals, false) @@ -2844,6 +2861,7 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 0) c.Assert(safe.WMode, Equals, "something") + c.Assert(safe.RMode, Equals, "majority") c.Assert(safe.WTimeout, Equals, 2) c.Assert(safe.FSync, Equals, true) c.Assert(safe.J, Equals, false) @@ -2853,6 +2871,7 @@ func (s *S) TestSafeSetting(c *C) { safe = session.Safe() c.Assert(safe.W, Equals, 0) c.Assert(safe.WMode, Equals, "something") + c.Assert(safe.RMode, Equals, "majority") c.Assert(safe.WTimeout, Equals, 2) c.Assert(safe.FSync, Equals, true) c.Assert(safe.J, Equals, false) @@ -2863,6 +2882,7 @@ func (s *S) TestSafeSetting(c *C) { clone.EnsureSafe(&mgo.Safe{WMode: "foo"}) safe = session.Safe() c.Assert(safe.WMode, Equals, "something") + c.Assert(safe.RMode, Equals, "majority") } func (s *S) TestSafeInsert(c *C) { diff --git a/socket.go b/socket.go index 5c7ca22ec..66e511ec7 100644 --- a/socket.go +++ b/socket.go @@ -33,7 +33,7 @@ import ( "sync" "time" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) type replyFunc func(err error, reply *replyOp, docNum int, docData []byte) @@ -67,17 +67,18 @@ const ( ) type queryOp struct { - query interface{} - collection string - serverTags []bson.D - selector interface{} - replyFunc replyFunc - mode Mode - skip int32 - limit int32 - options queryWrapper - hasOptions bool - flags queryOpFlags + query interface{} + collection string + serverTags []bson.D + selector interface{} + replyFunc replyFunc + mode Mode + skip int32 + limit int32 + options queryWrapper + hasOptions bool + flags queryOpFlags + readConcern string } type queryWrapper struct { diff --git a/suite_test.go b/suite_test.go index e1c43711a..624d5a543 100644 --- a/suite_test.go +++ b/suite_test.go @@ -38,8 +38,8 @@ import ( "testing" "time" - mgo "github.com/domodwyer/mgo" - "github.com/domodwyer/mgo/bson" + mgo "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) diff --git a/txn/debug.go b/txn/debug.go index 8da7f33be..e23d277af 100644 --- a/txn/debug.go +++ b/txn/debug.go @@ -6,7 +6,7 @@ import ( "sort" "sync/atomic" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) var ( diff --git a/txn/flusher.go b/txn/flusher.go index 64548a789..b1ead31d9 100644 --- a/txn/flusher.go +++ b/txn/flusher.go @@ -3,9 +3,9 @@ package txn import ( "fmt" - mgo "github.com/domodwyer/mgo" + mgo "github.com/globalsign/mgo" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) func flush(r *Runner, t *transaction) error { diff --git a/txn/sim_test.go b/txn/sim_test.go index f7b0f7cc6..65183c8ab 100644 --- a/txn/sim_test.go +++ b/txn/sim_test.go @@ -5,10 +5,10 @@ import ( "math/rand" "time" - mgo "github.com/domodwyer/mgo" - "github.com/domodwyer/mgo/bson" - "github.com/domodwyer/mgo/dbtest" - "github.com/domodwyer/mgo/txn" + mgo "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" + "github.com/globalsign/mgo/dbtest" + "github.com/globalsign/mgo/txn" . "gopkg.in/check.v1" ) diff --git a/txn/tarjan.go b/txn/tarjan.go index 7e9ad6e1e..66dc1898f 100644 --- a/txn/tarjan.go +++ b/txn/tarjan.go @@ -3,7 +3,7 @@ package txn import ( "sort" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" ) func tarjanSort(successors map[bson.ObjectId][]bson.ObjectId) [][]bson.ObjectId { diff --git a/txn/tarjan_test.go b/txn/tarjan_test.go index 4632aad0d..42a721bc4 100644 --- a/txn/tarjan_test.go +++ b/txn/tarjan_test.go @@ -3,7 +3,7 @@ package txn import ( "fmt" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" . "gopkg.in/check.v1" ) diff --git a/txn/txn.go b/txn/txn.go index 5a25a05bd..d9a9f9657 100644 --- a/txn/txn.go +++ b/txn/txn.go @@ -14,9 +14,9 @@ import ( "strings" "sync" - mgo "github.com/domodwyer/mgo" + mgo "github.com/globalsign/mgo" - "github.com/domodwyer/mgo/bson" + "github.com/globalsign/mgo/bson" crand "crypto/rand" mrand "math/rand" diff --git a/txn/txn_test.go b/txn/txn_test.go index da54c96fe..ce9d138e2 100644 --- a/txn/txn_test.go +++ b/txn/txn_test.go @@ -7,10 +7,10 @@ import ( "testing" "time" - mgo "github.com/domodwyer/mgo" - "github.com/domodwyer/mgo/bson" - "github.com/domodwyer/mgo/dbtest" - "github.com/domodwyer/mgo/txn" + mgo "github.com/globalsign/mgo" + "github.com/globalsign/mgo/bson" + "github.com/globalsign/mgo/dbtest" + "github.com/globalsign/mgo/txn" . "gopkg.in/check.v1" ) From d3cd25b4d59c9f596c00f747871d547b2c17a158 Mon Sep 17 00:00:00 2001 From: Dom Dwyer Date: Tue, 18 Apr 2017 11:46:19 +0100 Subject: [PATCH 2/2] Fix tests --- session.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.go b/session.go index 79fa01520..829aba443 100644 --- a/session.go +++ b/session.go @@ -1901,7 +1901,7 @@ func (s *Session) Safe() (safe *Safe) { defer s.m.Unlock() if s.safeOp != nil { cmd := s.safeOp.query.(*getLastError) - safe = &Safe{WTimeout: cmd.WTimeout, FSync: cmd.FSync, J: cmd.J} + safe = &Safe{WTimeout: cmd.WTimeout, FSync: cmd.FSync, J: cmd.J, RMode: s.queryConfig.op.readConcern} switch w := cmd.W.(type) { case string: safe.WMode = w