summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Golden <xdg@xdg.me>2019-06-26 15:52:26 -0400
committerDavid Golden <xdg@xdg.me>2019-06-26 16:59:48 -0400
commit6cb22a4feef4e5eb03412e392d2274707965f9b9 (patch)
tree61219f9a7117fba82ae5715addbfebb062211e48
parent42c1fa4f55a55fd9cc98a57f691160152acacf7e (diff)
downloadmongo-6cb22a4feef4e5eb03412e392d2274707965f9b9.tar.gz
Import tools: d7cc167b3f43f7264b6e4350a1632dd730793d6b from branch v4.1
ref: 25f23659be..d7cc167b3f for: 4.3.1 TOOLS-1801 text index collation creation may require explicit 'simple' locale
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/Gopkg.lock4
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/binaryurl.py5
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/common.yml417
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/import.data2
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/fixtures_test.go167
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata.go8
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata_test.go51
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/oplog.go11
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/restore.go12
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/bsonutil/bsonutil.go36
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/db/db.go19
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/testutil/testutil.go30
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/buffer.go354
-rw-r--r--src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/meta.go115
14 files changed, 1091 insertions, 140 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 b8e973ece01..63bbe06b62a 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
@@ -104,7 +104,7 @@
[[projects]]
branch = "master"
- digest = "1:d60f927aee2981fec0cc764cc118f202964b6023ada356e532b6c708e489ec26"
+ digest = "1:65929a60fecb8d113b86f4a83d447f28f97a72bf0eafc760a6a41c287f08e362"
name = "github.com/mongodb/mongo-tools-common"
packages = [
"archive",
@@ -125,7 +125,7 @@
"util",
]
pruneopts = "T"
- revision = "4316ec1965c626bbe74458444880c40950565e64"
+ revision = "947545918a26ddef9a4fa2ab3043b0d85071cb81"
[[projects]]
digest = "1:f363c75e8cac5653bc5c0c2b90cbd8a522fdc48c13a5f8d85078750f82d1a009"
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/binaryurl.py b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/binaryurl.py
index df18a8146f1..41cfad63455 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/binaryurl.py
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/binaryurl.py
@@ -48,10 +48,9 @@ if opts.version == "latest" or isVersionGreaterOrEqual(opts.version,"4.1.0"):
opts.target = 'windows_x86_64-2012plus'
def isCorrectVersion(version):
+ # for approximate match, ignore '-rcX' part, but due to json file ordering
+ # x.y.z will always be before x.y.z-rcX, which is what we want
parts = version["version"].split("-")
- # always skip '-rcX' versions
- if len(parts) > 1:
- return False
actual = parts[0].split(".")
desired = opts.version.split(".")
for i in range(len(desired)):
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/common.yml b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/common.yml
index 51b7f5734b2..55957624a17 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/common.yml
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/common.yml
@@ -13,37 +13,43 @@ mongo_tools_variables:
mongo_tools_task_lists:
mac_task_list: &macos_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: qa-tests-3.2
- name: qa-tests-3.4
- name: qa-tests-3.6
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: qa-dump-restore-gzip
+ - name: qa-dump-restore-gzip-4.2
- name: qa-dump-restore-gzip-3.2
- - name: qa-dump-restore-archiving
+ - name: qa-dump-restore-archiving-4.2
- name: qa-dump-restore-archiving-3.2
- name: unit
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2107
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
macos_ssl_task_list: &macos_ssl_tasks
- name: dist
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: unit
- name: replay-dist
rhel_x86_64_task_list: &rhel_x86_64_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: legacy30
- name: lint-go
- name: format-go
@@ -52,50 +58,59 @@ mongo_tools_variables:
- name: qa-tests-3.4
- name: qa-tests-3.6
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: qa-dump-restore-gzip
+ - name: qa-dump-restore-gzip-4.2
- name: qa-dump-restore-gzip-3.2
- - name: qa-dump-restore-archiving
+ - name: qa-dump-restore-archiving-4.2
- name: qa-dump-restore-archiving-3.2
- name: unit
- name: vet
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2116
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
rhel_x86_64_ssl_task_list: &rhel_x86_64_ssl_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: replay-dist
rhel_x86_64_enterprise_task_list: &rhel_x86_64_enterprise_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
# Disabled due to TOOLS-2119
# - name: kerberos
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2116
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
ubuntu_x86_64_task_list: &ubuntu_x86_64_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: lint-go
- name: format-go
- name: lint-js
@@ -103,63 +118,75 @@ mongo_tools_variables:
- name: qa-tests-3.4
- name: qa-tests-3.6
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: qa-dump-restore-gzip
+ - name: qa-dump-restore-gzip-4.2
- name: qa-dump-restore-gzip-3.2
- - name: qa-dump-restore-archiving
+ - name: qa-dump-restore-archiving-4.2
- name: qa-dump-restore-archiving-3.2
- name: unit
- name: vet
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2108
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
ubuntu_x86_64_ssl_task_list: &ubuntu_x86_64_ssl_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: replay-dist
ubuntu_x86_64_enterprise_task_list: &ubuntu_x86_64_enterprise_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: kerberos
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2108
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
ubuntu_x86_64_race_task_list: &ubuntu_x86_64_race_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: unit
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2108
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
windows_64_task_list: &windows_64_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
distros:
- windows-64-vs2013-test
- name: qa-tests-3.2
@@ -174,13 +201,16 @@ mongo_tools_variables:
- name: qa-tests-4.0
distros:
- windows-64-vs2013-test
- - name: qa-dump-restore-archiving
+ - name: qa-tests-4.2
+ distros:
+ - windows-64-vs2013-test
+ - name: qa-dump-restore-archiving-4.2
distros:
- windows-64-vs2013-test
- name: qa-dump-restore-archiving-3.2
distros:
- windows-64-vs2013-test
- - name: qa-dump-restore-gzip
+ - name: qa-dump-restore-gzip-4.2
distros:
- windows-64-vs2013-test
- name: qa-dump-restore-gzip-3.2
@@ -190,16 +220,21 @@ mongo_tools_variables:
- name: unit
windows_64_ssl_task_list: &windows_64_ssl_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: unit
windows_64_enterprise_task_list: &windows_64_enterprise_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
- name: kerberos
distros:
- windows-64-vs2013-test
@@ -215,63 +250,78 @@ mongo_tools_variables:
- name: qa-tests-4.0
distros:
- windows-64-vs2013-test
+ - name: qa-tests-4.2
+ distros:
+ - windows-64-vs2013-test
- name: qa-tests-unstable
distros:
- windows-64-vs2013-test
- name: unit
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
rhel71_ppc64le_enterprise_task_list: &rhel71_ppc64le_enterprise_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
#- name: kerberos
- - name: qa-dump-restore-archiving
- - name: qa-dump-restore-gzip
+ - name: qa-dump-restore-archiving-4.2
+ - name: qa-dump-restore-gzip-4.2
- name: qa-tests-3.4
- name: qa-tests-3.6
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2108
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
rhel67_s390x_enterprise_task_list: &rhel67_s390x_enterprise_tasks
- name: dist
- - name: integration
- - name: integration-auth
+ - name: integration-4.0
+ - name: integration-4.0-auth
+ - name: integration-4.2
+ - name: integration-4.2-auth
# Disabled due to TOOLS-2119
# - name: kerberos
- - name: qa-dump-restore-archiving
- - name: qa-dump-restore-gzip
+ - name: qa-dump-restore-archiving-4.2
+ - name: qa-dump-restore-gzip-4.2
- name: qa-tests-3.4
- name: qa-tests-3.6
- name: qa-tests-4.0
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: replay-dist
- - name: replay-sanity_check
- - name: replay-go_test
- - name: replay-auth_test
- - name: replay-sharded_test
- - name: replay-repl_test
+ - name: replay-sanity_check-4.2
+ - name: replay-go_test-4.2
+ - name: replay-auth_test-4.2
+ - name: replay-sharded_test-4.2
+ - name: replay-repl_test-4.2
# Disabled due to TOOLS-2108
- # - name: replay-replay_test
+ # - name: replay-replay_test-4.2
ubuntu1604_arm64_ssl_task_list: &ubuntu1604_arm64_ssl_tasks
- name: dist
- - name: integration
- - name: integration-auth
- - name: qa-dump-restore-archiving
- - name: qa-dump-restore-gzip
+ - name: integration-4.0
+ - name: integration-4.0-auth
- name: qa-tests-3.4
- name: qa-tests-3.6
- name: qa-tests-4.0
+ - name: replay-dist
+ ubuntu1804_arm64_ssl_task_list: &ubuntu1804_arm64_ssl_tasks
+ - name: dist
+ - name: integration-4.2
+ - name: integration-4.2-auth
+ - name: qa-dump-restore-archiving-4.2
+ - name: qa-dump-restore-gzip-4.2
+ - name: qa-tests-4.2
- name: qa-tests-unstable
- - name: native-cert-ssl
+ - name: native-cert-ssl-4.2
- name: replay-dist
@@ -938,7 +988,7 @@ tasks:
vars:
tool: mongotop
-- name: integration
+- name: integration-4.0
commands:
- func: "fetch source"
- command: expansions.update
@@ -951,7 +1001,7 @@ tasks:
vars:
INT_TEST: "true"
-- name: integration-auth
+- name: integration-4.0-auth
commands:
- func: "fetch source"
# Concat auth args
@@ -976,6 +1026,44 @@ tasks:
INT_TEST: "true"
AUTH_TEST: "true"
+- name: integration-4.2
+ commands:
+ - func: "fetch source"
+ - command: expansions.update
+ - func: "download mongod"
+ vars:
+ mongo_version: "4.2"
+ - func: "start mongod"
+ - func: "wait for mongod to be ready"
+ - func: "run tool integration tests"
+ vars:
+ INT_TEST: "true"
+
+- name: integration-4.2-auth
+ commands:
+ - func: "fetch source"
+ # Concat auth args
+ - command: expansions.update
+ params:
+ updates:
+ - key: "mongod_args"
+ concat: " --auth"
+ - key: "auth_username"
+ value: "passwordIsTaco"
+ - key: "auth_password"
+ value: "Taco"
+ - key: "create_mongod_users_command"
+ value: "db.createUser({ user: '${auth_username}', pwd: '${auth_password}', roles: [{ role: '__system', db: 'admin' }] });"
+ - func: "download mongod"
+ vars:
+ mongo_version: "4.2"
+ - func: "start mongod"
+ - func: "wait for mongod to be ready"
+ - func: "run tool integration tests"
+ vars:
+ INT_TEST: "true"
+ AUTH_TEST: "true"
+
- name: kerberos
commands:
- func: "fetch source"
@@ -1110,6 +1198,45 @@ tasks:
resmoke_suite: "core${resmoke_use_ssl}"
excludes: "requires_mongo_26,${excludes}"
+- name: qa-tests-4.2
+ depends_on:
+ - name: dist
+ commands:
+ - func: "fetch source"
+ - func: "get buildnumber"
+ - func: "setup credentials"
+ - func: "download mongod"
+ vars:
+ mongo_version: "4.2"
+ - func: "fetch tool"
+ vars:
+ tool: mongoimport
+ - func: "fetch tool"
+ vars:
+ tool: mongoexport
+ - func: "fetch tool"
+ vars:
+ tool: mongodump
+ - func: "fetch tool"
+ vars:
+ tool: mongorestore
+ - func: "fetch tool"
+ vars:
+ tool: mongostat
+ - func: "fetch tool"
+ vars:
+ tool: mongotop
+ - func: "fetch tool"
+ vars:
+ tool: mongofiles
+ - func: "fetch tool"
+ vars:
+ tool: bsondump
+ - func: "run qa-tests"
+ vars:
+ resmoke_suite: "core${resmoke_use_ssl}"
+ excludes: "requires_mongo_26,requires_unstable,${excludes}"
+
- name: qa-tests-4.0
depends_on:
- name: dist
@@ -1266,7 +1393,7 @@ tasks:
resmoke_suite: "core${resmoke_use_ssl}"
excludes: "requires_mongo_26,requires_mongo_34,requires_mongo_36,requires_mongo_40,requires_unstable,,${excludes}"
-- name: native-cert-ssl
+- name: native-cert-ssl-4.2
depends_on:
- name: dist
commands:
@@ -1275,7 +1402,7 @@ tasks:
- func: "setup credentials"
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "fetch tool"
vars:
tool: mongoimport
@@ -1313,7 +1440,7 @@ tasks:
chmod 400 jstests/libs/key*
python buildscripts/resmoke.py --suite=native_cert_ssl --continueOnFailure --log=buildlogger --reportFile=../../report.json ${resmoke_args} --excludeWithAnyTags="${excludes}"
-- name: qa-dump-restore-archiving
+- name: qa-dump-restore-archiving-4.2
depends_on:
- name: dist
commands:
@@ -1322,7 +1449,7 @@ tasks:
- func: "setup credentials"
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "fetch tool"
vars:
tool: mongodump
@@ -1355,7 +1482,7 @@ tasks:
resmoke_suite: "restore_archive"
excludes: "requires_mongo_26,requires_mongo_34,requires_mongo_36,requires_mongo_40,requires_unstable,${excludes}"
-- name: qa-dump-restore-gzip
+- name: qa-dump-restore-gzip-4.2
depends_on:
- name: dist
commands:
@@ -1364,7 +1491,7 @@ tasks:
- func: "setup credentials"
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "fetch tool"
vars:
tool: mongodump
@@ -1466,7 +1593,7 @@ tasks:
tool: mongoreplay
- func: "build tool"
-- name: replay-sanity_check
+- name: replay-sanity_check-4.2
depends_on:
- name: replay-dist
commands:
@@ -1476,7 +1603,7 @@ tasks:
tool: mongoreplay
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "start mongod"
- func: "wait for mongod to be ready"
- command: shell.exec
@@ -1490,7 +1617,7 @@ tasks:
echo "Running sanity check"
PATH=$PATH:$PWD/bin ./mongoreplay/sanity_check.sh -p ${mongod_port}
-- name: replay-go_test
+- name: replay-go_test-4.2
depends_on:
- name: replay-dist
commands:
@@ -1506,7 +1633,7 @@ tasks:
pcapFname: getmore_single_channel.pcap
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "start mongod"
- func: "wait for mongod to be ready"
- func: "run replay go_test"
@@ -1516,7 +1643,7 @@ tasks:
additional_args: github.com/mongodb/mongo-tools/mongoreplay
TESTING_REPLAY: true
-- name: replay-sharded_test
+- name: replay-sharded_test-4.2
depends_on:
- name: replay-dist
commands:
@@ -1532,7 +1659,7 @@ tasks:
pcapFname: getmore_single_channel.pcap
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "create sharded_cluster"
- func: "run replay go_test"
vars:
@@ -1541,7 +1668,7 @@ tasks:
additional_args: github.com/mongodb/mongo-tools/mongoreplay --run "LiveDB"
TESTING_REPLAY: true
-- name: replay-auth_test
+- name: replay-auth_test-4.2
depends_on:
- name: replay-dist
commands:
@@ -1557,7 +1684,7 @@ tasks:
pcapFname: getmore_single_channel.pcap
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "start mongod"
vars:
additional_args: --auth
@@ -1572,7 +1699,7 @@ tasks:
additional_args: github.com/mongodb/mongo-tools/mongoreplay --run "(LiveDB)|(Authed)"
TESTING_REPLAY: true
-- name: replay-repl_test
+- name: replay-repl_test-4.2
depends_on:
- name: replay-dist
commands:
@@ -1588,7 +1715,7 @@ tasks:
pcapFname: getmore_single_channel.pcap
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "create repl_set"
vars:
mongod_port: ${mongod_port}
@@ -1599,7 +1726,7 @@ tasks:
additional_args: github.com/mongodb/mongo-tools/mongoreplay --run "LiveDB"
TESTING_REPLAY: true
-- name: replay-replay_test
+- name: replay-replay_test-4.2
depends_on:
- name: replay-dist
commands:
@@ -1609,7 +1736,7 @@ tasks:
tool: mongoreplay
- func: "download mongod"
vars:
- mongo_version: "4.0"
+ mongo_version: "4.2"
- func: "fetch ftdc"
- command: shell.exec
params:
@@ -2024,6 +2151,7 @@ buildvariants:
# ARM Buildvariants #
#######################################
+# MongoDB 3.4 - 4.0
- name: ubuntu1604-arm64-ssl
display_name: ZAP ARM64 Ubuntu 16.04 SSL
run_on:
@@ -2046,6 +2174,29 @@ buildvariants:
USE_SSL: "true"
tasks: *ubuntu1604_arm64_ssl_tasks
+# MongoDB 4.2+
+- name: ubuntu1804-arm64-ssl
+ display_name: ZAP ARM64 Ubuntu 18.04 SSL
+ run_on:
+ - ubuntu1804-arm64-test
+ stepback: false
+ batchtime: 10080 # weekly
+ expansions:
+ <<: *mongod_default_startup_args
+ <<: *mongo_default_startup_args
+ mongo_os: "ubuntu1804"
+ mongo_edition: "targeted"
+ mongo_arch: "aarch64"
+ build_tags: "ssl"
+ resmoke_use_ssl: _ssl
+ excludes: requires_mmap_available,requires_large_ram,requires_mongo_24,requires_mongo_26,requires_mongo_30
+ resmoke_args: -j 2
+ arch: "linux/arm64"
+ edition: ssl
+ integration_test_args: integration
+ USE_SSL: "true"
+ tasks: *ubuntu1804_arm64_ssl_tasks
+
#######################################
# Power Buildvariants #
#######################################
@@ -2072,6 +2223,7 @@ buildvariants:
integration_test_args: integration
tasks: *rhel71_ppc64le_enterprise_tasks
+# MongoDB 3.4 - 4.0
- name: ubuntu1604-ppc64le-enterprise
display_name: ZAP PPC64LE Ubuntu 16.04 Enterprise
run_on:
@@ -2084,6 +2236,19 @@ buildvariants:
- name: dist
- name: replay-dist
+# MongoDB 4.2+
+- name: ubuntu1804-ppc64le-enterprise
+ display_name: ZAP PPC64LE Ubuntu 18.04 Enterprise
+ run_on:
+ - ubuntu1804-power8-test
+ stepback: false
+ batchtime: 10080 # weekly
+ expansions:
+ build_tags: 'ssl sasl gssapi'
+ tasks:
+ - name: dist
+ - name: replay-dist
+
#######################################
# Z (s390x) Buildvariants #
#######################################
@@ -2122,6 +2287,18 @@ buildvariants:
- name: dist
- name: replay-dist
+- name: ubuntu1804-s390x-enterprise
+ display_name: ZAP s390x Ubuntu 18.04 Enterprise
+ run_on:
+ - ubuntu1804-zseries-test
+ stepback: false
+ batchtime: 10080 # weekly
+ expansions:
+ build_tags: "sasl gssapi ssl"
+ tasks:
+ - name: dist
+ - name: replay-dist
+
#######################################
# Experimental Buildvariants #
#######################################
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 e3a82705d12..24abf8f7dec 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": "25f23659be74d2f882ead1a9882b66872214f369",
+ "commit": "d7cc167b3f43f7264b6e4350a1632dd730793d6b",
"github": "mongodb/mongo-tools.git",
"vendor": "tools",
"branch": "v4.1"
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/fixtures_test.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/fixtures_test.go
new file mode 100644
index 00000000000..d04b61ff2d9
--- /dev/null
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/fixtures_test.go
@@ -0,0 +1,167 @@
+// Copyright (C) MongoDB, Inc. 2019-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 mongorestore
+
+import (
+ "fmt"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+
+ "github.com/mongodb/mongo-tools-common/db"
+ "github.com/mongodb/mongo-tools/legacy/util"
+ "go.mongodb.org/mongo-driver/bson"
+)
+
+type testCollData struct {
+ ns string
+ docs []bson.D
+ metadata bson.D
+}
+
+func (tcd testCollData) SplitNS() (string, string) {
+ ns := strings.SplitN(tcd.ns, ".", 2)
+ if len(ns) != 2 {
+ panic(fmt.Sprintf("invalid namespace '%s'", tcd.ns))
+ }
+ return ns[0], util.EscapeCollectionName(ns[1])
+}
+
+func (tcd testCollData) Mkdir(basePath string) error {
+ db, _ := tcd.SplitNS()
+ dbDir := path.Join(basePath, db)
+ err := os.MkdirAll(dbDir, 0755)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (tcd testCollData) WriteData(basePath string) error {
+ db, coll := tcd.SplitNS()
+ file, err := os.Create(path.Join(basePath, db, coll+".bson"))
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ for _, doc := range tcd.docs {
+ raw, err := bson.Marshal(doc)
+ if err != nil {
+ return err
+ }
+ _, err = file.Write(raw)
+ if err != nil {
+ return err
+ }
+ }
+
+ return file.Sync()
+}
+
+func (tcd testCollData) WriteMetadata(basePath string) error {
+ if tcd.metadata == nil {
+ return nil
+ }
+
+ db, coll := tcd.SplitNS()
+ file, err := os.Create(path.Join(basePath, db, coll+".metadata.json"))
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ raw, err := bson.MarshalExtJSON(tcd.metadata, true, false)
+ if err != nil {
+ return err
+ }
+ _, err = file.Write(raw)
+ if err != nil {
+ return err
+ }
+
+ return file.Sync()
+}
+
+type testDumpDir struct {
+ dirName string
+ oplog []db.Oplog
+ collections []testCollData
+}
+
+func (tdd *testDumpDir) Create() error {
+
+ err := tdd.Cleanup()
+ if err != nil {
+ return err
+ }
+
+ err = os.MkdirAll(tdd.Path(), 0755)
+ if err != nil {
+ return err
+ }
+
+ for _, coll := range tdd.collections {
+ err := coll.Mkdir(tdd.Path())
+ if err != nil {
+ return err
+ }
+ err = coll.WriteData(tdd.Path())
+ if err != nil {
+ return err
+ }
+ err = coll.WriteMetadata(tdd.Path())
+ if err != nil {
+ return err
+ }
+ }
+
+ err = tdd.WriteOplog()
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Cleanup removes the test directory unless "NO_CLEANUP" is set in the environment.
+func (tdd *testDumpDir) Cleanup() error {
+ noCleanup := os.Getenv("NO_CLEANUP")
+ if noCleanup == "0" {
+ return nil
+ }
+ return os.RemoveAll(tdd.Path())
+}
+
+func (tdd *testDumpDir) WriteOplog() error {
+ if tdd.oplog == nil {
+ return nil
+ }
+ file, err := os.Create(path.Join(tdd.Path(), "oplog.bson"))
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ for _, op := range tdd.oplog {
+ raw, err := bson.Marshal(op)
+ if err != nil {
+ return err
+ }
+ _, err = file.Write(raw)
+ if err != nil {
+ return err
+ }
+ }
+
+ return file.Sync()
+}
+
+func (tdd *testDumpDir) Path() string {
+ return filepath.Join("testdata", tdd.dirName)
+}
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata.go
index b2555c64d6e..dd3c657e687 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata.go
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata.go
@@ -146,7 +146,7 @@ func (restore *MongoRestore) CollectionExists(intent *intents.Intent) (bool, err
// CreateIndexes takes in an intent and an array of index documents and
// attempts to create them using the createIndexes command. If that command
// fails, we fall back to individual index creation.
-func (restore *MongoRestore) CreateIndexes(intent *intents.Intent, indexes []IndexDocument) error {
+func (restore *MongoRestore) CreateIndexes(intent *intents.Intent, indexes []IndexDocument, hasNonSimpleCollation bool) error {
// first, sanitize the indexes
for _, index := range indexes {
// update the namespace of the index before inserting
@@ -165,6 +165,12 @@ func (restore *MongoRestore) CreateIndexes(intent *intents.Intent, indexes []Ind
if !restore.OutputOptions.KeepIndexVersion {
delete(index.Options, "v")
}
+
+ // for non-simple default collation on the collection, indexes without
+ // a collation option need to add "collation:{locale:"simple"}}
+ if _, ok := index.Options["collation"]; hasNonSimpleCollation && !ok {
+ index.Options["collation"] = bson.D{{"locale", "simple"}}
+ }
}
session, err := restore.SessionProvider.GetSession()
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata_test.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata_test.go
index a5670174d59..f11a842e944 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata_test.go
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/metadata_test.go
@@ -7,6 +7,8 @@
package mongorestore
import (
+ "fmt"
+ "io/ioutil"
"testing"
"github.com/mongodb/mongo-tools-common/intents"
@@ -179,3 +181,52 @@ func TestGetDumpAuthVersion(t *testing.T) {
})
}
+
+const indexCollationTestDataFile = "testdata/index_collation.json"
+
+func TestIndexGetsSimpleCollation(t *testing.T) {
+ testtype.SkipUnlessTestType(t, testtype.IntegrationTestType)
+
+ metadata, err := readCollationTestData(indexCollationTestDataFile)
+ if err != nil {
+ t.Fatalf("Error reading data file: %v", err)
+ }
+
+ dumpDir := testDumpDir{
+ dirName: "index_collation",
+ collections: []testCollData{{
+ ns: "test.foo",
+ metadata: metadata,
+ }},
+ }
+
+ err = dumpDir.Create()
+ if err != nil {
+ t.Fatalf("Error reading data file: %v", err)
+ }
+
+ Convey("With a test MongoRestore", t, func() {
+ args := []string{
+ DropOption,
+ dumpDir.Path(),
+ }
+ restore, err := getRestoreWithArgs(args...)
+ So(err, ShouldBeNil)
+
+ result := restore.Restore()
+ So(result.Err, ShouldBeNil)
+ })
+}
+
+func readCollationTestData(filename string) (bson.D, error) {
+ b, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, fmt.Errorf("couldn't load %s: %v", filename, err)
+ }
+ var data bson.D
+ err = bson.UnmarshalExtJSON(b, false, &data)
+ if err != nil {
+ return nil, fmt.Errorf("couldn't decode JSON: %v", err)
+ }
+ return data, nil
+}
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/oplog.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/oplog.go
index 4d76079d290..a24f316bf38 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/oplog.go
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/oplog.go
@@ -178,11 +178,16 @@ func (restore *MongoRestore) filterUUIDs(op db.Oplog) (db.Oplog, error) {
if !restore.OutputOptions.PreserveUUID {
op.UI = nil
+ // TODO TOOLS-2308: the following workaround is no longer allowed since
+ // 4.1.3 and no longer needed since 3.6.9/4.0.3. We're commenting it
+ // out to get our CI to green, but need a longer-term fix for users on
+ // 3.0.0-3.0.8/4.0.0-4.0.2.
+
// new createIndexes oplog command requires 'ui', so if we aren't
// preserving UUIDs, we must convert it to an old style index insert
- if op.Operation == "c" && op.Object[0].Key == "createIndexes" {
- return convertCreateIndexToIndexInsert(op)
- }
+ // if op.Operation == "c" && op.Object[0].Key == "createIndexes" {
+ // return convertCreateIndexToIndexInsert(op)
+ // }
}
// Check for and filter nested applyOps ops
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/restore.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/restore.go
index fb28c144485..1ddc7b639f0 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/restore.go
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/mongorestore/restore.go
@@ -12,6 +12,7 @@ import (
"strings"
"time"
+ "github.com/mongodb/mongo-tools-common/bsonutil"
"github.com/mongodb/mongo-tools-common/db"
"github.com/mongodb/mongo-tools-common/intents"
"github.com/mongodb/mongo-tools-common/log"
@@ -184,6 +185,7 @@ func (restore *MongoRestore) RestoreIntent(intent *intents.Intent) Result {
}
logMessageSuffix := "with no metadata"
+ var hasNonSimpleCollation bool
// first create the collection with options from the metadata file
if intent.MetadataFile != nil {
logMessageSuffix = "using options from metadata"
@@ -211,6 +213,14 @@ func (restore *MongoRestore) RestoreIntent(intent *intents.Intent) Result {
}
uuid = metadata.UUID
}
+
+ collation, err := bsonutil.FindSubdocumentByKey("collation", &options)
+ if err == nil {
+ localeValue, err := bsonutil.FindValueByKey("locale", &collation)
+ if err == nil {
+ hasNonSimpleCollation = localeValue != "simple"
+ }
+ }
}
// The only way to specify options on the idIndex is at collection creation time.
@@ -279,7 +289,7 @@ func (restore *MongoRestore) RestoreIntent(intent *intents.Intent) Result {
// finally, add indexes
if len(indexes) > 0 && !restore.OutputOptions.NoIndexRestore {
log.Logvf(log.Always, "restoring indexes for collection %v from metadata", intent.Namespace())
- err = restore.CreateIndexes(intent, indexes)
+ err = restore.CreateIndexes(intent, indexes, hasNonSimpleCollation)
if err != nil {
result.Err = fmt.Errorf("error creating indexes for %v: %v", intent.Namespace(), err)
return result
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/bsonutil/bsonutil.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/bsonutil/bsonutil.go
index ab7f28313bf..020fa9a78b1 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/bsonutil/bsonutil.go
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/bsonutil/bsonutil.go
@@ -63,7 +63,7 @@ func GetExtendedBsonD(doc bson.D) (bson.D, error) {
return nil, err
}
bsonDoc = append(bsonDoc, bson.E{
- Key: docElem.Key,
+ Key: docElem.Key,
Value: bsonValue,
})
}
@@ -81,6 +81,40 @@ func FindValueByKey(keyName string, document *bson.D) (interface{}, error) {
return nil, ErrNoSuchField
}
+// FindIntByKey returns the value of keyName in the document as an int for
+// either int32 or int64 underlying type.
+func FindIntByKey(keyName string, document *bson.D) (int, error) {
+ raw, err := FindValueByKey(keyName, document)
+ if err != nil {
+ return 0, err
+ }
+ switch x := raw.(type) {
+ case int32:
+ return int(x), nil
+ case int64:
+ return int(x), nil
+ case int:
+ return x, nil
+ default:
+ return 0, fmt.Errorf("field '%s' is not an integer type", keyName)
+ }
+}
+
+// FindSubdocumentByKey returns the value of keyName in document as a document.
+// Returns an error if keyName is not found in the top-level of the document,
+// or if it is found but its value is not a document.
+func FindSubdocumentByKey(keyName string, document *bson.D) (bson.D, error) {
+ value, err := FindValueByKey(keyName, document)
+ if err != nil {
+ return bson.D{}, err
+ }
+ doc, ok := value.(bson.D)
+ if !ok {
+ return bson.D{}, fmt.Errorf("field '%s' is not a document", keyName)
+ }
+ return doc, nil
+}
+
// ParseSpecialKeys takes a JSON document and inspects it for any extended JSON
// type (e.g $numberLong) and replaces any such values with the corresponding
// BSON type. (uses legacy extJSON parser)
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 dde6bf2cc63..7537a48ef5b 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
@@ -92,14 +92,17 @@ type ApplyOpsResponse struct {
// 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"`
- UI *primitive.Binary `bson:"ui,omitempty"`
+ 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
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/testutil/testutil.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/testutil/testutil.go
index 342876520cb..561858044a6 100644
--- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/testutil/testutil.go
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/testutil/testutil.go
@@ -8,6 +8,7 @@
package testutil
import (
+ "math/rand"
"os"
"strconv"
"strings"
@@ -137,3 +138,32 @@ func dottedStringToSlice(s string) ([]int, error) {
}
return parts, nil
}
+
+// MergeOplogStreams combines oplog arrays such that the order of entries is
+// random, but order-preserving with respect to each initial stream.
+func MergeOplogStreams(input [][]db.Oplog) []db.Oplog {
+ // Copy input op arrays so we can destructively shuffle them together
+ streams := make([][]db.Oplog, len(input))
+ opCount := 0
+ for i, v := range input {
+ streams[i] = make([]db.Oplog, len(v))
+ copy(streams[i], v)
+ opCount += len(v)
+ }
+
+ ops := make([]db.Oplog, 0, opCount)
+ for len(streams) != 0 {
+ // randomly pick a stream to add an op
+ rand.Shuffle(len(streams), func(i, j int) {
+ streams[i], streams[j] = streams[j], streams[i]
+ })
+ ops = append(ops, streams[0][0])
+ // remove the op and its stream if empty
+ streams[0] = streams[0][1:]
+ if len(streams[0]) == 0 {
+ streams = streams[1:]
+ }
+ }
+
+ return ops
+}
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
new file mode 100644
index 00000000000..2add53b5f9b
--- /dev/null
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/buffer.go
@@ -0,0 +1,354 @@
+// Copyright (C) MongoDB, Inc. 2019-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 txn implements functions for examining and processing transaction
+// oplog entries.
+package txn
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+
+ "github.com/mongodb/mongo-tools-common/bsonutil"
+ "github.com/mongodb/mongo-tools-common/db"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+var ErrBufferClosed = errors.New("transaction buffer already closed")
+var ErrTxnAborted = errors.New("transaction aborted")
+var ErrNotTransaction = errors.New("oplog entry is not a transaction")
+
+type txnTask struct {
+ meta Meta
+ op db.Oplog
+}
+
+// txnState tracks an individual transaction, including storage of related ops
+// and communication channels. It includes a WaitGroup for waiting on
+// transaction-related goroutines.
+type txnState struct {
+ buffer []db.Oplog
+ ingestChan chan txnTask
+ ingestDone chan struct{}
+ ingestErr error
+ stopChan chan struct{}
+ wg sync.WaitGroup
+}
+
+func newTxnState() *txnState {
+ return &txnState{
+ ingestChan: make(chan txnTask),
+ ingestDone: make(chan struct{}),
+ stopChan: make(chan struct{}),
+ buffer: make([]db.Oplog, 0),
+ }
+}
+
+// Because state is currently kept in memory, purge merely drops the reference
+// so the GC will eventually clean up. Eventually, this might clean up a file
+// on disk.
+func (ts *txnState) purge() error {
+ ts.buffer = nil
+ return nil
+}
+
+// Buffer stores transaction oplog entries until they are needed
+// to commit them to a desination. It includes a WaitGroup for tracking
+// all goroutines across all transactions for use in global shutdown.
+type Buffer struct {
+ sync.Mutex
+ stopped bool
+ txns map[ID]*txnState
+ wg sync.WaitGroup
+}
+
+// NewBuffer initializes a transaction oplog buffer.
+func NewBuffer() *Buffer {
+ return &Buffer{
+ txns: make(map[ID]*txnState),
+ }
+}
+
+// Concurrency notes:
+//
+// We require that AddOp, GetTxnStream and PurgeTxn be called serially as part
+// of orchestrating replay of oplog entries. The only method that could run
+// concurrently is Stop. If Stop is called, we're in some sort of global
+// shutdown, so we don't care how other methods and goroutines resolve, only
+// that they do so without panicking.
+//
+
+// AddOp sends a transaction oplog entry to a background goroutine (starting
+// one for a new transaction ID) for asynchronous pre-processing and storage.
+// If the oplog entry is not a transaction, an error will be returned. Any
+// errors during processing can be discovered later via the error channel from
+// `GetTxnStream`.
+//
+// Must not be called concurrently with other transaction-related operations.
+// Must not be called for a given transaction after starting to stream that
+// transaction.
+func (b *Buffer) AddOp(m Meta, op db.Oplog) error {
+ b.Lock()
+ defer b.Unlock()
+
+ if b.stopped {
+ return ErrBufferClosed
+ }
+
+ if !m.IsTxn() {
+ return ErrNotTransaction
+ }
+
+ // Get or initialize transaction state
+ state, ok := b.txns[m.id]
+ if !ok {
+ state = newTxnState()
+ b.txns[m.id] = state
+ b.wg.Add(1)
+ state.wg.Add(1)
+ go b.ingester(state)
+ }
+
+ // Send unless the ingester has shut down, e.g. on error
+ select {
+ case <-state.ingestDone:
+ case state.ingestChan <- txnTask{meta: m, op: op}:
+ }
+
+ return nil
+}
+
+func (b *Buffer) ingester(state *txnState) {
+LOOP:
+ for {
+ select {
+ case t := <-state.ingestChan:
+ if t.meta.IsData() {
+ // process it
+ innerOps, err := extractInnerOps(t.op.Object)
+ if err != nil {
+ state.ingestErr = err
+ break LOOP
+ }
+ // store it
+ for _, op := range innerOps {
+ state.buffer = append(state.buffer, op)
+ }
+ }
+ if t.meta.IsFinal() {
+ break LOOP
+ }
+ case <-state.stopChan:
+ break LOOP
+ }
+ }
+ close(state.ingestDone)
+ state.wg.Done()
+ b.wg.Done()
+}
+
+// GetTxnStream returns a channel of Oplog entries in a transaction and a
+// channel for errors. If the buffer has been stopped, the returned op channel
+// will be closed and the error channel will have an error on it.
+//
+// Must not be called concurrently with other transaction-related operations.
+// For a given transaction, it must not be called until after a final oplog
+// entry has been passed to AddOp and it must not be called more than once.
+func (b *Buffer) GetTxnStream(m Meta) (<-chan db.Oplog, <-chan error) {
+ b.Lock()
+ defer b.Unlock()
+
+ opChan := make(chan db.Oplog)
+ errChan := make(chan error, 1)
+
+ if b.stopped {
+ return sendErrAndClose(opChan, errChan, ErrBufferClosed)
+ }
+
+ if !m.IsTxn() {
+ return sendErrAndClose(opChan, errChan, ErrNotTransaction)
+ }
+
+ state := b.txns[m.id]
+ if state == nil {
+ return sendErrAndClose(opChan, errChan, fmt.Errorf("GetTxnStream found no state for %v", m.id))
+ }
+
+ // The final oplog entry must have been passed to AddOp before calling this
+ // method, so we know this will be able to make progress.
+ <-state.ingestDone
+
+ if state.ingestErr != nil {
+ return sendErrAndClose(opChan, errChan, state.ingestErr)
+ }
+
+ // Launch streaming goroutine
+ b.wg.Add(1)
+ state.wg.Add(1)
+ go b.streamer(state, opChan, errChan)
+
+ return opChan, errChan
+}
+
+func (b *Buffer) streamer(state *txnState, opChan chan<- db.Oplog, errChan chan<- error) {
+LOOP:
+ for _, op := range state.buffer {
+ select {
+ case opChan <- op:
+ case <-state.stopChan:
+ errChan <- ErrTxnAborted
+ break LOOP
+ }
+ }
+ close(opChan)
+ close(errChan)
+ state.wg.Done()
+ b.wg.Done()
+}
+
+// PurgeTxn closes any transaction streams in progress and deletes all oplog
+// entries associated with a transaction.
+//
+// Must not be called concurrently with other transaction-related operations.
+// For a given transaction, it must not be called until after a final oplog
+// entry has been passed to AddOp and it must not be called more than once.
+func (b *Buffer) PurgeTxn(m Meta) error {
+ b.Lock()
+ defer b.Unlock()
+ if b.stopped {
+ return ErrBufferClosed
+ }
+ state := b.txns[m.id]
+ if state == nil {
+ return fmt.Errorf("PurgeTxn found no state for %v", m.id)
+ }
+
+ // When the lock is dropped, we don't want Stop to find this transaction and
+ // double-close it.
+ delete(b.txns, m.id)
+ close(state.stopChan)
+
+ // Wait for goroutines to terminate, then clean up.
+ state.wg.Wait()
+ state.purge()
+
+ return nil
+}
+
+// Stop shuts down processing and cleans up. Subsequent calls to Stop() will return nil.
+// All other methods error after this is called.
+func (b *Buffer) Stop() error {
+ b.Lock()
+ if b.stopped {
+ b.Unlock()
+ return nil
+ }
+
+ b.stopped = true
+ for _, state := range b.txns {
+ close(state.stopChan)
+ }
+
+ b.Unlock()
+
+ // At this point we know any subsequent public method will see the buffer
+ // is stopped, no new goroutines will be launched, and existing goroutines
+ // have been signaled to close. Next, wait for goroutines to stop, then
+ // clean up.
+
+ b.wg.Wait()
+ var firstErr error
+ for _, state := range b.txns {
+ err := state.purge()
+ if err != nil && firstErr == nil {
+ firstErr = err
+ }
+ }
+
+ return firstErr
+}
+
+// sendErrAndClose is a utility for putting an error on a channel before closing.
+func sendErrAndClose(o chan db.Oplog, e chan error, err error) (chan db.Oplog, chan error) {
+ e <- err
+ close(o)
+ close(e)
+ return o, e
+}
+
+const extractErrorFmt = "error extracting transaction ops: %s: %v"
+
+func extractInnerOps(doc bson.D) ([]db.Oplog, error) {
+ rawAO, err := bsonutil.FindValueByKey("applyOps", &doc)
+ if err != nil {
+ return nil, fmt.Errorf(extractErrorFmt, "applyOps field", err)
+ }
+
+ ao, ok := rawAO.(bson.A)
+ if !ok {
+ return nil, fmt.Errorf(extractErrorFmt, "applyOps field", "not a BSON array")
+ }
+
+ ops := make([]db.Oplog, len(ao))
+ for i, v := range ao {
+ opDoc, ok := v.(bson.D)
+ if !ok {
+ return nil, fmt.Errorf(extractErrorFmt, "applyOps op", "not a BSON document")
+ }
+ op, err := bsonDocToOplog(opDoc)
+ if err != nil {
+ return nil, fmt.Errorf(extractErrorFmt, "applyOps op", err)
+ }
+ ops[i] = *op
+ }
+
+ return ops, nil
+}
+
+const opConvertErrorFmt = "error converting bson.D to op: %s: %v"
+
+func bsonDocToOplog(doc bson.D) (*db.Oplog, error) {
+ op := db.Oplog{}
+
+ for _, v := range doc {
+ switch v.Key {
+ case "op":
+ s, ok := v.Value.(string)
+ if !ok {
+ return nil, fmt.Errorf(opConvertErrorFmt, "op field", "not a string")
+ }
+ op.Operation = s
+ case "ns":
+ s, ok := v.Value.(string)
+ if !ok {
+ return nil, fmt.Errorf(opConvertErrorFmt, "ns field", "not a string")
+ }
+ op.Namespace = s
+ case "o":
+ d, ok := v.Value.(bson.D)
+ if !ok {
+ return nil, fmt.Errorf(opConvertErrorFmt, "o field", "not a BSON Document")
+ }
+ op.Object = d
+ case "o2":
+ d, ok := v.Value.(bson.D)
+ if !ok {
+ return nil, fmt.Errorf(opConvertErrorFmt, "o2 field", "not a BSON Document")
+ }
+ op.Query = d
+ case "ui":
+ u, ok := v.Value.(primitive.Binary)
+ if !ok {
+ return nil, fmt.Errorf(opConvertErrorFmt, "ui field", "not binary data")
+ }
+ op.UI = &u
+ }
+ }
+
+ return &op, nil
+}
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/meta.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/meta.go
new file mode 100644
index 00000000000..549872010b1
--- /dev/null
+++ b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/mongodb/mongo-tools-common/txn/meta.go
@@ -0,0 +1,115 @@
+// Copyright (C) MongoDB, Inc. 2019-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 txn
+
+import (
+ "encoding/base64"
+ "fmt"
+
+ "github.com/mongodb/mongo-tools-common/db"
+)
+
+// "empty" prevOpTime is {ts: Timestamp(0, 0), t: NumberLong(-1)} as BSON.
+var emptyPrev = string([]byte{
+ 28, 0, 0, 0, 17, 116, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 18, 116, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0,
+})
+
+// ID wraps fields needed to uniquely identify a transaction for use as a map
+// key. The 'lsid' is a string rather than bson.Raw or []byte so that this
+// type is a valid map key.
+type ID struct {
+ lsid string
+ txnNumber int64
+}
+
+func (id ID) String() string {
+ return fmt.Sprintf("%s-%d", base64.RawStdEncoding.EncodeToString([]byte(id.lsid)), id.txnNumber)
+}
+
+// Meta holds information extracted from an oplog entry for later routing
+// logic. Zero value means 'not a transaction'. We store 'prevOpTime' as
+// string so the struct is comparable.
+type Meta struct {
+ id ID
+ commit bool
+ abort bool
+ partial bool
+ prepare bool
+ prevOpTime string
+}
+
+// NewMeta extracts transaction metadata from an oplog entry. A
+// non-transaction will return a zero-value Meta struct, not an error.
+//
+// Currently there is no way for this to error, but that may change in the
+// future if we change the db.Oplog.Object to bson.Raw, so the API is designed
+// with failure as a possibility.
+func NewMeta(op db.Oplog) (Meta, error) {
+ if op.LSID == nil {
+ return Meta{}, nil
+ }
+
+ // Default prevOpTime to empty to "upgrade" 4.0 transactions without it.
+ m := Meta{
+ id: ID{lsid: string(op.LSID), txnNumber: *op.TxnNumber},
+ prevOpTime: emptyPrev,
+ }
+
+ if op.PrevOpTime != nil {
+ m.prevOpTime = string(op.PrevOpTime)
+ }
+
+ for _, e := range op.Object {
+ switch e.Key {
+ case "commitTransaction":
+ m.commit = true
+ case "abortTransaction":
+ m.abort = true
+ case "partialTxn":
+ m.partial = true
+ case "prepare":
+ m.prepare = true
+ }
+ }
+
+ return m, nil
+}
+
+// IsAbort is true if the oplog entry had the abort command.
+func (m Meta) IsAbort() bool {
+ return m.abort
+}
+
+// IsData is true if the oplog entry contains transaction data
+func (m Meta) IsData() bool {
+ return !m.commit && !m.abort
+}
+
+// IsCommit is true if the oplog entry was an abort command or was the
+// final entry of an unprepared transaction.
+func (m Meta) IsCommit() bool {
+ return m.commit || (m.IsTxn() && !m.prepare && !m.partial)
+}
+
+// IsFinal is true if the oplog entry is the closing entry of a transaction,
+// i.e. if IsAbort or IsCommit is true.
+func (m Meta) IsFinal() bool {
+ return m.IsCommit() || m.IsAbort()
+}
+
+// IsMultiOp is true if the oplog entry is part of a prepared and/or large
+// transaction.
+func (m Meta) IsMultiOp() bool {
+ return m.partial || m.prepare || (m.IsTxn() && m.prevOpTime != emptyPrev)
+}
+
+// IsTxn is true if the oplog entry is part of any transaction, i.e. the lsid field
+// exists.
+func (m Meta) IsTxn() bool {
+ return m != Meta{}
+}