Compare commits
82 Commits
master
...
SERVER-728
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f6d2a91a6 | ||
|
|
198c1c465d | ||
|
|
233d39b231 | ||
|
|
cb81f98b45 | ||
|
|
62488ce919 | ||
|
|
ea7276ff7a | ||
|
|
ed293ecd07 | ||
|
|
0f6baedfbb | ||
|
|
eb49b1fea5 | ||
|
|
988151ae97 | ||
|
|
5215370322 | ||
|
|
4e4823e6df | ||
|
|
0c6cc27734 | ||
|
|
38bf4fb1db | ||
|
|
877bb0f2a6 | ||
|
|
00988012c4 | ||
|
|
91958f623b | ||
|
|
2c684d00b9 | ||
|
|
f9a0cd79be | ||
|
|
46bb04d7fd | ||
|
|
ca939e3cc8 | ||
|
|
fb56c5b9a1 | ||
|
|
28aaaddf78 | ||
|
|
e1e07f94db | ||
|
|
bf4b3ae9b3 | ||
|
|
f9e2d80228 | ||
|
|
f8765617a6 | ||
|
|
25184c1132 | ||
|
|
5a27856c9c | ||
|
|
96763fa1fe | ||
|
|
a687e8ade1 | ||
|
|
550b1584bc | ||
|
|
c7bd639a41 | ||
|
|
962a7f752a | ||
|
|
96b382d296 | ||
|
|
d08a11d306 | ||
|
|
e29864141f | ||
|
|
48a5a5e48a | ||
|
|
7e54d2db73 | ||
|
|
8f3946c68a | ||
|
|
1330f5552e | ||
|
|
8bb4e5e521 | ||
|
|
e58010bf6a | ||
|
|
bdacd70b1c | ||
|
|
b5ff7228cb | ||
|
|
3dfde12941 | ||
|
|
1494cea315 | ||
|
|
314825e8df | ||
|
|
89b0377ea5 | ||
|
|
19ec50e155 | ||
|
|
9af849e64e | ||
|
|
b52f0ba969 | ||
|
|
c73aa5a010 | ||
|
|
8e9fb6aecf | ||
|
|
855410a37a | ||
|
|
3e35e9121f | ||
|
|
e033be9f8c | ||
|
|
5a8a7076ad | ||
|
|
a0ee5a1e6c | ||
|
|
099b1a174e | ||
|
|
8b06b20e74 | ||
|
|
f876854381 | ||
|
|
d3b2ad3244 | ||
|
|
ae13a0375b | ||
|
|
a748104759 | ||
|
|
37f6d07553 | ||
|
|
09cb75d4c6 | ||
|
|
f4b99751fb | ||
|
|
b5f7f35d46 | ||
|
|
96399bf635 | ||
|
|
ced7b06862 | ||
|
|
619ab6338d | ||
|
|
6a050da034 | ||
|
|
5927f2e811 | ||
|
|
239040917d | ||
|
|
de755012e0 | ||
|
|
e72d191a30 | ||
|
|
2b1a5b3ccc | ||
|
|
180639fd33 | ||
|
|
2e15f33879 | ||
|
|
4d1c6a2b36 | ||
|
|
3419f8de5e |
@ -1,6 +1,6 @@
|
||||
#  MongoDB README
|
||||
|
||||
Welcome to MongoDB!
|
||||
Welcome to MongoDB 6.3!
|
||||
|
||||
## Components
|
||||
|
||||
@ -92,4 +92,3 @@ Welcome to MongoDB!
|
||||
October 16, 2018, including patch fixes for prior versions, are published
|
||||
under the [Server Side Public License (SSPL) v1](LICENSE-Community.txt).
|
||||
See individual files for details.
|
||||
|
||||
|
||||
@ -28,20 +28,21 @@ DEFAULT_TIMEOUT_OVERRIDES = "etc/evergreen_timeouts.yml"
|
||||
DEFAULT_EVERGREEN_CONFIG = "etc/evergreen.yml"
|
||||
DEFAULT_EVERGREEN_AUTH_CONFIG = "~/.evergreen.yml"
|
||||
COMMIT_QUEUE_ALIAS = "__commit_queue"
|
||||
UNITTEST_TASK = "run_unittests"
|
||||
IGNORED_SUITES = {
|
||||
"integration_tests_replset", "integration_tests_replset_ssl_auth", "integration_tests_sharded",
|
||||
"integration_tests_standalone", "integration_tests_standalone_audit", "mongos_test",
|
||||
"server_selection_json_test"
|
||||
"integration_tests_replset",
|
||||
"integration_tests_replset_ssl_auth",
|
||||
"integration_tests_sharded",
|
||||
"integration_tests_standalone",
|
||||
"integration_tests_standalone_audit",
|
||||
"mongos_test",
|
||||
"server_selection_json_test",
|
||||
"sdam_json_test",
|
||||
}
|
||||
HISTORY_LOOKBACK = timedelta(weeks=2)
|
||||
|
||||
COMMIT_QUEUE_TIMEOUT = timedelta(minutes=40)
|
||||
COMMIT_QUEUE_TIMEOUT = timedelta(minutes=20)
|
||||
DEFAULT_REQUIRED_BUILD_TIMEOUT = timedelta(hours=1, minutes=20)
|
||||
DEFAULT_NON_REQUIRED_BUILD_TIMEOUT = timedelta(hours=2)
|
||||
# 2x the longest "run tests" phase for unittests as of c9bf1dbc9cc46e497b2f12b2d6685ef7348b0726,
|
||||
# which is 5 mins 47 secs, excluding outliers below
|
||||
UNITTESTS_TIMEOUT = timedelta(minutes=12)
|
||||
|
||||
|
||||
class TimeoutOverride(BaseModel):
|
||||
@ -225,11 +226,6 @@ class TaskTimeoutOrchestrator:
|
||||
LOGGER.info("Overriding configured timeout", exec_timeout_secs=override.total_seconds())
|
||||
determined_timeout = override
|
||||
|
||||
elif task_name == UNITTEST_TASK and override is None:
|
||||
LOGGER.info("Overriding unittest timeout",
|
||||
exec_timeout_secs=UNITTESTS_TIMEOUT.total_seconds())
|
||||
determined_timeout = UNITTESTS_TIMEOUT
|
||||
|
||||
elif _is_required_build_variant(
|
||||
variant) and determined_timeout > DEFAULT_REQUIRED_BUILD_TIMEOUT:
|
||||
LOGGER.info("Overriding required-builder timeout",
|
||||
|
||||
@ -61,8 +61,8 @@ def generate_version_expansions():
|
||||
raise ValueError("Unable to parse version from stdin and no version.json provided")
|
||||
|
||||
if version_parts[0]:
|
||||
expansions["suffix"] = "latest"
|
||||
expansions["src_suffix"] = "latest"
|
||||
expansions["suffix"] = "v6.3-latest"
|
||||
expansions["src_suffix"] = "v6.3-latest"
|
||||
expansions["is_release"] = "false"
|
||||
else:
|
||||
expansions["suffix"] = version_line
|
||||
|
||||
@ -7,6 +7,8 @@ selector:
|
||||
##
|
||||
# TODO SERVER-68341: Implement enable/disable command for mongoQ in the serverless.
|
||||
- jstests/change_streams/projection_fakes_internal_event.js
|
||||
# TODO SERVER-69959: Implement a majority-committed insert listener.
|
||||
- jstests/change_streams/only_wake_getmore_for_relevant_changes.js
|
||||
|
||||
##
|
||||
# TODO SERVER-70760: This test creates its own sharded cluster and uses transaction. The support
|
||||
|
||||
@ -4,6 +4,8 @@ selector:
|
||||
roots:
|
||||
- jstests/change_streams/**/*.js
|
||||
exclude_files:
|
||||
# TODO SERVER-69959: Implement a majority-committed insert listener.
|
||||
- jstests/change_streams/only_wake_getmore_for_relevant_changes.js
|
||||
# TODO SERVER-68341: Implement enable/disable command for mongoQ in the serverless.
|
||||
- jstests/change_streams/projection_fakes_internal_event.js
|
||||
# TODO SERVER-68557 This test list databases that does not work in the sharded-cluster. This test
|
||||
|
||||
@ -25,5 +25,3 @@ executor:
|
||||
mongod_options:
|
||||
set_parameters:
|
||||
enableTestCommands: 1
|
||||
# Fully enable column scan for CSI tests. This can't be done at runtime because it interferes with other tests.
|
||||
internalQueryColumnScanMinNumColumnFilters: 0
|
||||
|
||||
@ -5,8 +5,7 @@ import inject
|
||||
import structlog
|
||||
from buildscripts.resmoke_proxy.resmoke_proxy import ResmokeProxyService
|
||||
from buildscripts.timeouts.timeout import TimeoutEstimate
|
||||
from buildscripts.util.teststats import HistoricTaskData
|
||||
from evergreen import EvergreenApi
|
||||
from buildscripts.util.teststats import HistoricTaskData, normalize_test_name
|
||||
|
||||
LOGGER = structlog.get_logger(__name__)
|
||||
CLEAN_EVERY_N_HOOK = "CleanEveryN"
|
||||
@ -53,7 +52,10 @@ class TimeoutService:
|
||||
if not historic_stats:
|
||||
return TimeoutEstimate.no_timeouts()
|
||||
|
||||
test_set = set(self.resmoke_proxy.list_tests(timeout_params.suite_name))
|
||||
test_set = {
|
||||
normalize_test_name(test)
|
||||
for test in self.resmoke_proxy.list_tests(timeout_params.suite_name)
|
||||
}
|
||||
test_runtimes = [
|
||||
stat for stat in historic_stats.get_tests_runtimes() if stat.test_name in test_set
|
||||
]
|
||||
|
||||
@ -30,6 +30,8 @@ last-continuous:
|
||||
ticket: SERVER-53335
|
||||
- test_file: jstests/replsets/replSetGetStatus_member_wall_times.js
|
||||
ticket: SERVER-54909
|
||||
- test_file: jstests/sharding/migration_server_status.js
|
||||
ticket: SERVER-56186
|
||||
- test_file: jstests/sharding/cwwc_conflict_add_shard.js
|
||||
ticket: SERVER-56800
|
||||
- test_file: jstests/sharding/reconfig_fails_no_cwwc_set_sharding.js
|
||||
@ -254,12 +256,16 @@ last-continuous:
|
||||
ticket: SERVER-67723
|
||||
- test_file: jstests/sharding/collection_uuid_shard_capped_collection.js
|
||||
ticket: SERVER-67885
|
||||
- test_file: jstests/sharding/prepare_transaction_then_migrate.js
|
||||
ticket: SERVER-68361
|
||||
- test_file: jstests/core/txns/txn_ops_allowed_on_buckets_coll.js
|
||||
ticket: SERVER-68556
|
||||
- test_file: jstests/core/txns/no_writes_to_system_collections_in_txn.js
|
||||
ticket: SERVER-68556
|
||||
- test_file: jstests/sharding/resharding_temp_ns_routing_info_unsharded.js
|
||||
ticket: SERVER-68628
|
||||
- test_file: jstests/sharding/move_chunk_concurrent_cloning.js
|
||||
ticket: SERVER-68648
|
||||
- test_file: jstests/sharding/move_chunk_interrupt_postimage.js
|
||||
ticket: SERVER-68728
|
||||
- test_file: jstests/sharding/resharding_critical_section_metrics.js
|
||||
@ -272,26 +278,22 @@ last-continuous:
|
||||
ticket: SERVER-69861
|
||||
- test_file: jstests/aggregation/expressions/switch_errors.js
|
||||
ticket: SERVER-70190
|
||||
- test_file: jstests/core/cover_null_queries.js
|
||||
ticket: SERVER-70436
|
||||
- test_file: jstests/sharding/prepare_transaction_then_migrate.js
|
||||
ticket: SERVER-68361
|
||||
- test_file: jstests/sharding/migration_server_status.js
|
||||
ticket: SERVER-56186
|
||||
- test_file: jstests/replsets/apply_ops_strips_hash.js
|
||||
ticket: SERVER-70841
|
||||
- test_file: jstests/replsets/wtimeout_too_large.js
|
||||
ticket: SERVER-70360
|
||||
- test_file: jstests/sharding/all_collection_stats.js
|
||||
ticket: SERVER-71477
|
||||
- test_file: jstests/core/cover_null_queries.js
|
||||
ticket: SERVER-70436
|
||||
- test_file: jstests/sharding/timeseries_sharding_admin_commands.js
|
||||
ticket: SERVER-70790
|
||||
- test_file: jstests/replsets/apply_ops_strips_hash.js
|
||||
ticket: SERVER-70841
|
||||
- test_file: jstests/sharding/all_collection_stats.js
|
||||
ticket: SERVER-71477
|
||||
- test_file: jstests/sharding/hidden_index.js
|
||||
ticket: SERVER-71638
|
||||
- test_file: jstests/sharding/invalid_system_views_sharded_collection.js
|
||||
ticket: SERVER-71667
|
||||
- test_file: jstests/sharding/drop_collection.js
|
||||
ticket: SERVER-71689
|
||||
- test_file: jstests/sharding/hidden_index.js
|
||||
ticket: SERVER-71638
|
||||
- test_file: jstests/core/query/project/project_with_collation.js
|
||||
ticket: SERVER-72416
|
||||
- test_file: jstests/core/collation.js
|
||||
@ -300,12 +302,30 @@ last-continuous:
|
||||
ticket: SERVER-72416
|
||||
- test_file: src/mongo/db/modules/enterprise/jstests/fcbis/oplog_rollover.js
|
||||
ticket: SERVER-72422
|
||||
- test_file: jstests/sharding/move_chunk_concurrent_cloning.js
|
||||
ticket: SERVER-68648
|
||||
- test_file: jstests/sharding/timeseries_cluster_indexstats.js
|
||||
ticket: SERVER-72620
|
||||
- test_file: jstests/core/timeseries/bucket_unpacking_with_sort_extended_range.js
|
||||
ticket: SERVER-73110
|
||||
- test_file: jstests/core/doc_validation_with_now_variable.js
|
||||
ticket: SERVER-73125
|
||||
- test_file: jstests/core/timeseries/timeseries_groupby_reorder.js
|
||||
ticket: SERVER-73822
|
||||
- test_file: jstests/sharding/internal_txns/incomplete_transaction_history_during_migration.js
|
||||
ticket: SERVER-73938
|
||||
- test_file: jstests/sharding/shard_keys_with_dollar_sign.js
|
||||
ticket: SERVER-74124
|
||||
- test_file: jstests/core/query/sbe_plan_cache_autoparameterize_ixscan.js
|
||||
ticket: SERVER-74262
|
||||
- test_file: jstests/replsets/log_ddl_ops.js
|
||||
ticket: SERVER-73601
|
||||
- test_file: jstests/core/clustered/clustered_collection_collation.js
|
||||
ticket: SERVER-67105
|
||||
- test_file: src/mongo/db/modules/enterprise/jstests/fle2/collection_coll_stats.js
|
||||
ticket: SERVER-74461
|
||||
- test_file: src/mongo/db/modules/enterprise/jstests/fle2/top_command.js
|
||||
ticket: SERVER-74460
|
||||
- test_file: jstests/sharding/query/group_plan_cache_sharded.js
|
||||
ticket: SERVER-74245
|
||||
suites: null
|
||||
last-lts:
|
||||
all:
|
||||
@ -405,6 +425,8 @@ last-lts:
|
||||
ticket: SERVER-55305
|
||||
- test_file: jstests/replsets/rollback_with_coalesced_txn_table_updates_from_vectored_inserts.js
|
||||
ticket: SERVER-55305
|
||||
- test_file: jstests/sharding/migration_server_status.js
|
||||
ticket: SERVER-56186
|
||||
- test_file: jstests/sharding/time_zone_info_mongos.js
|
||||
ticket: SERVER-56371
|
||||
- test_file: jstests/concurrency/fsm_workloads/findAndModify_flip_location.js
|
||||
@ -637,12 +659,16 @@ last-lts:
|
||||
ticket: SERVER-67723
|
||||
- test_file: jstests/sharding/collection_uuid_shard_capped_collection.js
|
||||
ticket: SERVER-67885
|
||||
- test_file: jstests/sharding/prepare_transaction_then_migrate.js
|
||||
ticket: SERVER-68361
|
||||
- test_file: jstests/core/txns/txn_ops_allowed_on_buckets_coll.js
|
||||
ticket: SERVER-68556
|
||||
- test_file: jstests/core/txns/no_writes_to_system_collections_in_txn.js
|
||||
ticket: SERVER-68556
|
||||
- test_file: jstests/sharding/resharding_temp_ns_routing_info_unsharded.js
|
||||
ticket: SERVER-68628
|
||||
- test_file: jstests/sharding/move_chunk_concurrent_cloning.js
|
||||
ticket: SERVER-68648
|
||||
- test_file: jstests/sharding/move_chunk_interrupt_postimage.js
|
||||
ticket: SERVER-68728
|
||||
- test_file: jstests/replsets/tenant_migration_recipient_forget_migration.js
|
||||
@ -653,26 +679,22 @@ last-lts:
|
||||
ticket: SERVER-69861
|
||||
- test_file: jstests/aggregation/expressions/switch_errors.js
|
||||
ticket: SERVER-70190
|
||||
- test_file: jstests/core/cover_null_queries.js
|
||||
ticket: SERVER-70436
|
||||
- test_file: jstests/sharding/prepare_transaction_then_migrate.js
|
||||
ticket: SERVER-68361
|
||||
- test_file: jstests/sharding/migration_server_status.js
|
||||
ticket: SERVER-56186
|
||||
- test_file: jstests/replsets/apply_ops_strips_hash.js
|
||||
ticket: SERVER-70841
|
||||
- test_file: jstests/replsets/wtimeout_too_large.js
|
||||
ticket: SERVER-70360
|
||||
- test_file: jstests/sharding/all_collection_stats.js
|
||||
ticket: SERVER-71477
|
||||
- test_file: jstests/core/cover_null_queries.js
|
||||
ticket: SERVER-70436
|
||||
- test_file: jstests/sharding/timeseries_sharding_admin_commands.js
|
||||
ticket: SERVER-70790
|
||||
- test_file: jstests/replsets/apply_ops_strips_hash.js
|
||||
ticket: SERVER-70841
|
||||
- test_file: jstests/sharding/all_collection_stats.js
|
||||
ticket: SERVER-71477
|
||||
- test_file: jstests/sharding/hidden_index.js
|
||||
ticket: SERVER-71638
|
||||
- test_file: jstests/sharding/invalid_system_views_sharded_collection.js
|
||||
ticket: SERVER-71667
|
||||
- test_file: jstests/sharding/drop_collection.js
|
||||
ticket: SERVER-71689
|
||||
- test_file: jstests/sharding/hidden_index.js
|
||||
ticket: SERVER-71638
|
||||
- test_file: jstests/core/query/project/project_with_collation.js
|
||||
ticket: SERVER-72416
|
||||
- test_file: jstests/core/collation.js
|
||||
@ -681,10 +703,16 @@ last-lts:
|
||||
ticket: SERVER-72416
|
||||
- test_file: src/mongo/db/modules/enterprise/jstests/fcbis/oplog_rollover.js
|
||||
ticket: SERVER-72422
|
||||
- test_file: jstests/sharding/move_chunk_concurrent_cloning.js
|
||||
ticket: SERVER-68648
|
||||
- test_file: jstests/sharding/timeseries_cluster_indexstats.js
|
||||
ticket: SERVER-72620
|
||||
- test_file: jstests/core/timeseries/bucket_unpacking_with_sort_extended_range.js
|
||||
ticket: SERVER-73110
|
||||
- test_file: jstests/core/doc_validation_with_now_variable.js
|
||||
ticket: SERVER-73125
|
||||
- test_file: jstests/core/timeseries/timeseries_groupby_reorder.js
|
||||
ticket: SERVER-73822
|
||||
- test_file: jstests/sharding/internal_txns/incomplete_transaction_history_during_migration.js
|
||||
ticket: SERVER-73938
|
||||
- test_file: jstests/sharding/shard_keys_with_dollar_sign.js
|
||||
ticket: SERVER-74124
|
||||
suites: null
|
||||
|
||||
@ -190,12 +190,12 @@ variables:
|
||||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: burn_in_tests_gen
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: buildscripts_test
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.aggregation !.gcm
|
||||
- name: .encrypt !.aggregation !.gcm !.feature_flag_guarded
|
||||
- name: external_auth
|
||||
- name: external_auth_aws
|
||||
- name: external_auth_windows
|
||||
@ -251,7 +251,7 @@ variables:
|
||||
- name: compile_build_tools_next_TG
|
||||
distros:
|
||||
- rhel70
|
||||
- name: .aggfuzzer
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: auth_gen
|
||||
@ -316,7 +316,7 @@ buildvariants:
|
||||
large_distro_name: rhel80-medium
|
||||
compile_variant: *linux_x86_dynamic_debug_compile_variant_name
|
||||
tasks:
|
||||
- name: .aggregation !.encrypt
|
||||
- name: .aggregation !.encrypt !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: .causally_consistent !.wo_snapshot
|
||||
- name: .change_streams !.secondary_reads
|
||||
@ -346,40 +346,6 @@ buildvariants:
|
||||
- name: sharding_gen
|
||||
- name: sharding_opportunistic_secondary_targeting_gen
|
||||
|
||||
- <<: *linux-64-debug-required-template
|
||||
name: &linux-64-debug-wtdevelop linux-64-debug-wtdevelop
|
||||
display_name: "~ Linux DEBUG WiredTiger develop"
|
||||
cron: "0 */4 * * *" # From the ${project_required_suggested_cron} parameter
|
||||
modules:
|
||||
- wtdevelop
|
||||
depends_on:
|
||||
- name: archive_dist_test_debug
|
||||
variant: &linux_x86_dynamic_debug_wtdevelop_compile_variant_name linux-x86-dynamic-debug-wtdevelop-compile
|
||||
- name: version_gen
|
||||
variant: generate-tasks-for-version
|
||||
# This is added because of EVG-18211.
|
||||
# Without this we are adding extra dependencies on evergreen and it is causing strain
|
||||
omit_generated_tasks: true
|
||||
expansions:
|
||||
use_wt_develop: true
|
||||
resmoke_jobs_factor: 0.5 # Avoid starting too many mongod's
|
||||
large_distro_name: rhel80-medium
|
||||
max_sub_suites: "5"
|
||||
target_resmoke_time: "15"
|
||||
compile_flags: >-
|
||||
--dbg=on
|
||||
--opt=on
|
||||
-j$(grep -c ^processor /proc/cpuinfo)
|
||||
--variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars
|
||||
--enable-free-mon=on
|
||||
--enable-http-client=on
|
||||
--link-model=dynamic
|
||||
scons_cache_mode: all
|
||||
scons_cache_scope: shared
|
||||
num_scons_link_jobs_available: 0.99
|
||||
test_flags: --excludeWithAnyTags=requires_http_client
|
||||
compile_variant: *linux_x86_dynamic_debug_wtdevelop_compile_variant_name
|
||||
|
||||
- name: &tla-plus tla-plus
|
||||
display_name: "TLA+"
|
||||
run_on:
|
||||
@ -430,8 +396,8 @@ buildvariants:
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: test_api_version_compatibility
|
||||
- name: .aggfuzzer !.multiversion
|
||||
- name: .aggregation !.multiversion
|
||||
- name: .aggfuzzer !.multiversion !.feature_flag_guarded
|
||||
- name: .aggregation !.multiversion !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth !.multiversion
|
||||
- name: .causally_consistent !.sharding
|
||||
@ -658,8 +624,8 @@ buildvariants:
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: test_api_version_compatibility
|
||||
- name: .aggfuzzer !.multiversion
|
||||
- name: .aggregation !.multiversion
|
||||
- name: .aggfuzzer !.multiversion !.feature_flag_guarded
|
||||
- name: .aggregation !.multiversion !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth !.multiversion
|
||||
- name: .causally_consistent !.sharding
|
||||
@ -805,7 +771,7 @@ buildvariants:
|
||||
- name: compile_build_tools_next_TG
|
||||
distros:
|
||||
- windows-vsCurrent-xlarge
|
||||
- name: .aggregation !.auth !.encrypt
|
||||
- name: .aggregation !.auth !.encrypt !.feature_flag_guarded
|
||||
- name: aggregation_expression_multiversion_fuzzer_gen
|
||||
- name: aggregation_expression_optimization_fuzzer_gen
|
||||
- name: auth_gen
|
||||
@ -1022,8 +988,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: .aggfuzzer
|
||||
- name: .aggregation !.auth !.encrypt !.unwind
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.auth !.encrypt !.unwind !.feature_flag_guarded
|
||||
- name: auth_gen
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -1116,7 +1082,7 @@ buildvariants:
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: compile_build_tools_next_TG
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: auth_gen
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: disk_wiredtiger
|
||||
@ -1329,8 +1295,8 @@ buildvariants:
|
||||
variant: generate-tasks-for-version
|
||||
tasks:
|
||||
- name: burn_in_tests_gen
|
||||
- name: .aggfuzzer
|
||||
- name: .aggregation
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth
|
||||
- name: unittest_shell_hang_analyzer_gen
|
||||
@ -1432,8 +1398,8 @@ buildvariants:
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: test_api_version_compatibility
|
||||
- name: .aggfuzzer !.no_debug_mode
|
||||
- name: .aggregation !.no_debug_mode
|
||||
- name: .aggfuzzer !.feature_flag_guarded !.no_debug_mode
|
||||
- name: .aggregation !.feature_flag_guarded !.no_debug_mode
|
||||
- name: audit
|
||||
- name: .auth !.no_debug_mode
|
||||
- name: .causally_consistent !.sharding
|
||||
@ -1902,7 +1868,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: .aggfuzzer
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: auth_gen
|
||||
@ -2751,8 +2717,8 @@ buildvariants:
|
||||
# - name: test_api_version_compatibility # Not relevant for TSAN
|
||||
# - name: burn_in_tests_gen # No burn in tests needed
|
||||
- name: check_feature_flag_tags
|
||||
# - name: .aggfuzzer # Not passing
|
||||
# - name: .aggregation # Not passing
|
||||
# - name: .aggfuzzer !.feature_flag_guarded # Not passing
|
||||
# - name: .aggregation !.feature_flag_guarded # Not passing
|
||||
- name: audit
|
||||
# - name: .auth # Not passing
|
||||
# - name: burn_in_tags_gen # No burn in tests needed
|
||||
@ -2859,8 +2825,8 @@ buildvariants:
|
||||
compile_variant: *enterprise-rhel80-debug-complete-tsan
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: .aggfuzzer
|
||||
- name: .aggregation
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: .auth
|
||||
- name: resmoke_end2end_tests
|
||||
- name: unittest_shell_hang_analyzer_gen
|
||||
@ -3006,7 +2972,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_parallel_dbtest_stream_TG
|
||||
distros:
|
||||
- rhel80-build
|
||||
- name: .aggregation !.no_async
|
||||
- name: .aggregation !.no_async !.feature_flag_guarded
|
||||
- name: .sharding .auth
|
||||
- name: .sharding .causally_consistent !.wo_snapshot
|
||||
- name: .concurrency .common !.kill_terminate
|
||||
@ -3048,7 +3014,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_parallel_dbtest_stream_TG
|
||||
distros:
|
||||
- rhel80-build
|
||||
- name: .aggregation !.no_async
|
||||
- name: .aggregation !.no_async !.feature_flag_guarded
|
||||
- name: .sharding .auth
|
||||
- name: .sharding .causally_consistent !.wo_snapshot
|
||||
- name: .concurrency .common !.kill_terminate
|
||||
@ -3087,7 +3053,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_parallel_dbtest_stream_TG
|
||||
distros:
|
||||
- rhel80-build
|
||||
- name: .aggregation !.no_async
|
||||
- name: .aggregation !.no_async !.feature_flag_guarded
|
||||
- name: .sharding .auth
|
||||
- name: .sharding .causally_consistent !.wo_snapshot
|
||||
- name: .concurrency .common !.kill_terminate
|
||||
@ -3131,7 +3097,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_parallel_dbtest_stream_TG
|
||||
distros:
|
||||
- rhel80-build
|
||||
- name: .aggregation !.no_async
|
||||
- name: .aggregation !.no_async !.feature_flag_guarded
|
||||
- name: .sharding .auth
|
||||
- name: .sharding .causally_consistent !.wo_snapshot
|
||||
- name: .concurrency .common !.kill_terminate
|
||||
@ -3175,7 +3141,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_parallel_dbtest_stream_TG
|
||||
distros:
|
||||
- rhel80-build
|
||||
- name: .aggregation !.no_async
|
||||
- name: .aggregation !.no_async !.feature_flag_guarded
|
||||
- name: .sharding .auth
|
||||
- name: .sharding .causally_consistent !.wo_snapshot
|
||||
- name: .concurrency .common !.kill_terminate
|
||||
@ -3212,7 +3178,7 @@ buildvariants:
|
||||
distros:
|
||||
- rhel80-build
|
||||
patch_only: true
|
||||
- name: .aggregation !.no_async
|
||||
- name: .aggregation !.no_async !.feature_flag_guarded
|
||||
patch_only: true
|
||||
- name: .sharding .auth
|
||||
patch_only: true
|
||||
@ -3439,18 +3405,6 @@ buildvariants:
|
||||
- windows-vsCurrent-large
|
||||
- name: .benchmarks !benchmarks_orphaned
|
||||
|
||||
- <<: *enterprise-windows-nopush-template
|
||||
name: &enterprise-windows-wtdevelop enterprise-windows-wtdevelop
|
||||
display_name: "~ Enterprise Windows WiredTiger develop"
|
||||
cron: "0 */4 * * *" # From the ${project_required_suggested_cron} parameter
|
||||
modules:
|
||||
- enterprise
|
||||
- wtdevelop
|
||||
expansions:
|
||||
<<: *enterprise-windows-nopush-expansions-template
|
||||
use_wt_develop: true
|
||||
compile_variant: *enterprise-windows-wtdevelop
|
||||
|
||||
### QO & QE Patch-Specific Build Variants ###
|
||||
- <<: *enterprise-windows-nopush-template
|
||||
name: &windows-compile-query-patch-only windows-compile-query-patch-only
|
||||
|
||||
@ -6,16 +6,358 @@ include:
|
||||
- filename: etc/evergreen_yml_components/variants/atlas.yml
|
||||
- filename: etc/evergreen_yml_components/variants/misc_release.yml
|
||||
### Comment out when using this file for a LTS or Rapid release branch. ###
|
||||
- filename: etc/evergreen_yml_components/variants/ibm.yml
|
||||
# - filename: etc/evergreen_yml_components/variants/ibm.yml
|
||||
### Uncomment when using this file for a LTS release branch. ###
|
||||
# - filename: etc/evergreen_yml_components/variants/in_memory.yml
|
||||
### Uncomment when using this file for a LTS or Rapid release branch. ###
|
||||
# - filename: etc/evergreen_yml_components/variants/sanitizer.yml
|
||||
- filename: etc/evergreen_yml_components/variants/sanitizer.yml
|
||||
### Uncomment when using this file for a LTS or Rapid release branch. ###
|
||||
# - filename: etc/evergreen_yml_components/variants/ninja.yml
|
||||
- filename: etc/evergreen_yml_components/variants/ninja.yml
|
||||
- filename: etc/evergreen_yml_components/variants/compile_static_analysis.yml
|
||||
|
||||
|
||||
parameters:
|
||||
- key: evergreen_config_file_path
|
||||
value: "etc/evergreen_nightly.yml"
|
||||
description: "path to this file"
|
||||
|
||||
|
||||
variables:
|
||||
|
||||
# Common compile variant dependency specifications.
|
||||
- &linux_x86_dynamic_compile_variant_dependency
|
||||
depends_on:
|
||||
- name: archive_dist_test_debug
|
||||
variant: &linux_x86_dynamic_compile_variant_name linux-x86-dynamic-compile-required
|
||||
- name: version_gen
|
||||
variant: generate-tasks-for-version
|
||||
# This is added because of EVG-18211.
|
||||
# Without this we are adding extra dependencies on evergreen and it is causing strain
|
||||
omit_generated_tasks: true
|
||||
|
||||
- &linux_x86_dynamic_debug_compile_variant_dependency
|
||||
depends_on:
|
||||
- name: archive_dist_test_debug
|
||||
variant: &linux_x86_dynamic_debug_compile_variant_name linux-x86-dynamic-debug-compile-required
|
||||
- name: version_gen
|
||||
variant: generate-tasks-for-version
|
||||
# This is added because of EVG-18211.
|
||||
# Without this we are adding extra dependencies on evergreen and it is causing strain
|
||||
omit_generated_tasks: true
|
||||
|
||||
- &linux_debug_aubsan_compile_variant_dependency
|
||||
depends_on:
|
||||
- name: archive_dist_test_debug
|
||||
variant: &linux_debug_aubsan_compile_variant_name linux-debug-aubsan-compile-required
|
||||
- name: version_gen
|
||||
variant: generate-tasks-for-version
|
||||
# This is added because of EVG-18211.
|
||||
# Without this we are adding extra dependencies on evergreen and it is causing strain
|
||||
omit_generated_tasks: true
|
||||
|
||||
- &windows_compile_variant_dependency
|
||||
depends_on:
|
||||
- name: archive_dist_test_debug
|
||||
variant: &windows_compile_variant_name windows-compile-required
|
||||
- name: version_gen
|
||||
variant: generate-tasks-for-version
|
||||
# This is added because of EVG-18211.
|
||||
# Without this we are adding extra dependencies on evergreen and it is causing strain
|
||||
omit_generated_tasks: true
|
||||
- name: version_burn_in_gen
|
||||
variant: generate-tasks-for-version
|
||||
|
||||
- &linux_x86_generic_expansions
|
||||
multiversion_platform: rhel80
|
||||
multiversion_edition: enterprise
|
||||
repo_edition: enterprise
|
||||
large_distro_name: rhel80-medium
|
||||
num_scons_link_jobs_available: 0.99
|
||||
compile_variant: *linux_x86_dynamic_compile_variant_name
|
||||
|
||||
# If you add anything to san_options, make sure the appropriate changes are
|
||||
# also made to SConstruct.
|
||||
# and also to the san_options in compile_static_analysis.yml
|
||||
- aubsan_options: &aubsan_options
|
||||
>-
|
||||
UBSAN_OPTIONS="print_stacktrace=1:external_symbolizer_path=/opt/mongodbtoolchain/v4/bin/llvm-symbolizer"
|
||||
LSAN_OPTIONS="suppressions=etc/lsan.suppressions:report_objects=1"
|
||||
ASAN_OPTIONS="detect_leaks=1:check_initialization_order=true:strict_init_order=true:abort_on_error=1:disable_coredump=0:handle_abort=1:strict_string_checks=true:detect_invalid_pointer_pairs=1:external_symbolizer_path=/opt/mongodbtoolchain/v4/bin/llvm-symbolizer"
|
||||
|
||||
|
||||
buildvariants:
|
||||
|
||||
- &linux-64-debug-required-template
|
||||
<<: *linux_x86_dynamic_debug_compile_variant_dependency
|
||||
name: &linux-64-debug-required linux-64-debug-required
|
||||
display_name: "! Linux x86 Shared Library DEBUG"
|
||||
cron: "0 */4 * * *" # From the ${project_required_suggested_cron} parameter
|
||||
run_on:
|
||||
- rhel80-medium
|
||||
expansions:
|
||||
resmoke_jobs_factor: 0.5 # Avoid starting too many mongod's
|
||||
test_flags: --excludeWithAnyTags=requires_http_client
|
||||
target_resmoke_time: 15
|
||||
max_sub_suites: 5
|
||||
large_distro_name: rhel80-medium
|
||||
compile_variant: *linux_x86_dynamic_debug_compile_variant_name
|
||||
tasks:
|
||||
- name: .aggregation !.encrypt !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: .causally_consistent !.wo_snapshot
|
||||
- name: .change_streams !.secondary_reads
|
||||
- name: .clustered_collections
|
||||
- name: .misc_js
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: json_schema
|
||||
- name: query_golden_classic
|
||||
- name: libunwind_tests
|
||||
- name: .multi_shard
|
||||
- name: multi_stmt_txn_jscore_passthrough_with_migration_gen
|
||||
- name: .ocsp
|
||||
- name: .read_write_concern
|
||||
- name: .replica_sets !.encrypt !.ignore_non_generated_replica_sets_jscore_passthrough !.fcbis
|
||||
- name: replica_sets_jscore_passthrough_gen
|
||||
- name: replica_sets_reconfig_jscore_passthrough_gen
|
||||
- name: replica_sets_reconfig_jscore_stepdown_passthrough_gen
|
||||
- name: replica_sets_max_mirroring_large_txns_format_gen
|
||||
- name: .retry
|
||||
- name: .read_only
|
||||
- name: session_jscore_passthrough
|
||||
- name: sharded_multi_stmt_txn_jscore_passthrough
|
||||
- name: .sharding .jscore !.wo_snapshot
|
||||
- name: sharding_gen
|
||||
- name: sharding_opportunistic_secondary_targeting_gen
|
||||
|
||||
- &enterprise-windows-template
|
||||
<<: *windows_compile_variant_dependency
|
||||
name: &enterprise-windows-required enterprise-windows-required
|
||||
display_name: "! Enterprise Windows"
|
||||
cron: "0 */4 * * *" # From the ${project_required_suggested_cron} parameter
|
||||
modules:
|
||||
- enterprise
|
||||
run_on:
|
||||
- windows-vsCurrent-small
|
||||
expansions: &windows_required_expansions
|
||||
compile_variant: *windows_compile_variant_name
|
||||
exe: ".exe"
|
||||
content_type: application/zip
|
||||
python: '/cygdrive/c/python/python37/python.exe'
|
||||
ext: zip
|
||||
multiversion_platform: windows
|
||||
multiversion_edition: enterprise
|
||||
jstestfuzz_num_generated_files: 35
|
||||
target_resmoke_time: 20
|
||||
max_sub_suites: 5
|
||||
large_distro_name: windows-vsCurrent-large
|
||||
push_path: windows
|
||||
push_bucket: downloads.10gen.com
|
||||
push_name: windows
|
||||
push_arch: x86_64-enterprise
|
||||
test_flags: &windows_common_test_excludes --excludeWithAnyTags=incompatible_with_windows_tls
|
||||
external_auth_jobs_max: 1
|
||||
tasks:
|
||||
#- name: burn_in_tests_gen
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: .encrypt !.aggregation !.replica_sets !.sharding !.jscore
|
||||
- name: external_auth
|
||||
- name: external_auth_aws
|
||||
- name: external_auth_windows
|
||||
distros:
|
||||
- windows-2016-dc
|
||||
- name: .jscore .common !.sharding
|
||||
- name: jsCore_auth
|
||||
- name: jsCore_ese
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: .jstestfuzz .common
|
||||
- name: mqlrun
|
||||
- name: noPassthrough_gen
|
||||
- name: noPassthroughWithMongod_gen
|
||||
- name: .replica_sets .common !.ignore_non_generated_replica_sets_jscore_passthrough
|
||||
- name: .replica_sets .multi_oplog !.ignore_non_generated_replica_sets_jscore_passthrough !.gcm
|
||||
- name: replica_sets_jscore_passthrough_gen
|
||||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: sasl
|
||||
- name: .sharding .txns
|
||||
- name: sharding_auth_gen
|
||||
- name: sharding_auth_audit_gen
|
||||
- name: sharding_ese_gen
|
||||
|
||||
- &enterprise-rhel-80-64-bit-dynamic-template
|
||||
<<: *linux_x86_dynamic_compile_variant_dependency
|
||||
name: &enterprise-rhel-80-64-bit-dynamic-required enterprise-rhel-80-64-bit-dynamic-required
|
||||
display_name: "! Shared Library Enterprise RHEL 8.0"
|
||||
cron: "0 */4 * * *" # From the ${project_required_suggested_cron} parameter
|
||||
modules:
|
||||
- enterprise
|
||||
run_on:
|
||||
- rhel80-small
|
||||
expansions: &enterprise-rhel-80-64-bit-dynamic-expansions
|
||||
<<: *linux_x86_generic_expansions
|
||||
scons_cache_scope: shared
|
||||
scons_cache_mode: all
|
||||
has_packages: false
|
||||
jstestfuzz_num_generated_files: 40
|
||||
jstestfuzz_concurrent_num_files: 10
|
||||
target_resmoke_time: 10
|
||||
max_sub_suites: 5
|
||||
idle_timeout_factor: 1.5
|
||||
exec_timeout_factor: 1.5
|
||||
large_distro_name: rhel80-medium
|
||||
depends_on:
|
||||
- name: archive_dist_test_debug
|
||||
variant: *linux_x86_dynamic_compile_variant_name
|
||||
- name: version_gen
|
||||
variant: generate-tasks-for-version
|
||||
# This is added because of EVG-18211.
|
||||
# Without this we are adding extra dependencies on evergreen and it is causing strain
|
||||
omit_generated_tasks: true
|
||||
- name: version_burn_in_gen
|
||||
variant: generate-tasks-for-version
|
||||
tasks:
|
||||
#- name: burn_in_tests_gen
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth
|
||||
- name: unittest_shell_hang_analyzer_gen
|
||||
- name: .causally_consistent !.sharding
|
||||
- name: .change_streams
|
||||
- name: .change_stream_fuzzer
|
||||
- name: .misc_js
|
||||
- name: .concurrency !.large !.ubsan !.no_txns !.debug_only
|
||||
- name: .concurrency .large !.ubsan !.no_txns !.debug_only
|
||||
distros:
|
||||
- rhel80-medium
|
||||
- name: .config_fuzzer !.large
|
||||
- name: .config_fuzzer .large
|
||||
distros:
|
||||
- rhel80-medium
|
||||
- name: disk_wiredtiger
|
||||
- name: .encrypt
|
||||
- name: idl_tests
|
||||
- name: initial_sync_fuzzer_gen
|
||||
- name: jsCore
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: .jscore .common !jsCore
|
||||
- name: jsCore_min_batch_repeat_queries_ese_gsm
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: json_schema
|
||||
- name: .jstestfuzz !.flow_control # Flow control jstestfuzz take longer.
|
||||
- name: libunwind_tests
|
||||
- name: mqlrun
|
||||
- name: .multi_shard
|
||||
- name: multi_stmt_txn_jscore_passthrough_with_migration_gen
|
||||
- name: multiversion_gen
|
||||
- name: .query_fuzzer
|
||||
- name: .random_multiversion_ds
|
||||
- name: .read_write_concern .large
|
||||
distros:
|
||||
- rhel80-medium
|
||||
- name: .read_write_concern !.large
|
||||
- name: .replica_sets !.encrypt !.auth
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: replica_sets_api_version_jscore_passthrough_gen
|
||||
- name: replica_sets_reconfig_jscore_passthrough_gen
|
||||
- name: replica_sets_reconfig_jscore_stepdown_passthrough_gen
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: replica_sets_reconfig_kill_primary_jscore_passthrough_gen
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: retryable_writes_jscore_passthrough_gen
|
||||
- name: retryable_writes_jscore_stepdown_passthrough_gen
|
||||
distros:
|
||||
- rhel80-medium
|
||||
- name: .read_only
|
||||
- name: .rollbackfuzzer
|
||||
- name: sasl
|
||||
- name: search
|
||||
- name: search_auth
|
||||
- name: search_ssl
|
||||
- name: session_jscore_passthrough
|
||||
- name: .sharding .jscore !.wo_snapshot !.multi_stmt
|
||||
- name: sharding_api_version_jscore_passthrough_gen
|
||||
- name: .sharding .txns
|
||||
- name: .sharding .common
|
||||
- name: .updatefuzzer
|
||||
- name: secondary_reads_passthrough_gen
|
||||
- name: .serverless
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
|
||||
- &rhel80-debug-aubsan-lite-template
|
||||
<<: *linux_debug_aubsan_compile_variant_dependency
|
||||
name: &rhel80-debug-aubsan-lite-required rhel80-debug-aubsan-lite-required
|
||||
display_name: "! Shared Library {A,UB}SAN Enterprise RHEL 8.0 DEBUG"
|
||||
cron: "0 */4 * * *" # From the ${project_required_suggested_cron} parameter
|
||||
modules:
|
||||
- enterprise
|
||||
run_on:
|
||||
- rhel80-build
|
||||
expansions: &aubsan-lite-required-expansions
|
||||
compile_variant: *linux_debug_aubsan_compile_variant_name
|
||||
lang_environment: LANG=C
|
||||
san_options: *aubsan_options
|
||||
test_flags: --excludeWithAnyTags=requires_ocsp_stapling
|
||||
resmoke_jobs_factor: 0.3 # Avoid starting too many mongod's under {A,UB}SAN build.
|
||||
hang_analyzer_dump_core: false
|
||||
max_sub_suites: 3
|
||||
num_scons_link_jobs_available: 0.99
|
||||
large_distro_name: rhel80-build
|
||||
tasks:
|
||||
- name: jsCore
|
||||
- name: jsCore_txns
|
||||
|
||||
- <<: *enterprise-rhel-80-64-bit-dynamic-template
|
||||
name: &commit-queue commit-queue
|
||||
display_name: "~ Commit Queue"
|
||||
cron: "0 4 * * 0" # From the ${project_weekly_cron} parameter
|
||||
stepback: false
|
||||
expansions:
|
||||
<<: *linux_x86_generic_expansions
|
||||
scons_cache_scope: shared
|
||||
scons_cache_mode: all
|
||||
has_packages: false
|
||||
compile_flags: >-
|
||||
--ssl
|
||||
MONGO_DISTMOD=rhel80
|
||||
-j$(grep -c ^processor /proc/cpuinfo)
|
||||
--variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars
|
||||
--link-model=dynamic
|
||||
crypt_task_compile_flags: >-
|
||||
SHLINKFLAGS_EXTRA="-Wl,-Bsymbolic
|
||||
-Wl,--no-gnu-unique"
|
||||
CCFLAGS="-fno-gnu-unique"
|
||||
clang_tidy_toolchain: v4
|
||||
num_scons_unit_cc_jobs_available: 0.2
|
||||
compile_variant: *commit-queue
|
||||
depends_on: []
|
||||
tasks:
|
||||
- name: compile_test_and_package_parallel_core_stream_TG
|
||||
distros:
|
||||
- rhel80-xlarge-commitqueue
|
||||
- name: compile_test_and_package_parallel_unittest_stream_TG
|
||||
distros:
|
||||
- rhel80-xlarge-commitqueue
|
||||
- name: compile_test_and_package_parallel_dbtest_stream_TG
|
||||
distros:
|
||||
- rhel80-xlarge-commitqueue
|
||||
- name: jsCore
|
||||
distros:
|
||||
- rhel80-xlarge-commitqueue
|
||||
- name: .lint
|
||||
- name: test_api_version_compatibility
|
||||
- name: validate_commit_message
|
||||
- name: check_feature_flag_tags
|
||||
- name: compile_venv_deps_check
|
||||
|
||||
@ -10,131 +10,28 @@
|
||||
# in alphabetical order.
|
||||
|
||||
overrides:
|
||||
amazon-linux2-arm64-compile:
|
||||
- task: server_discovery_and_monitoring_json_test
|
||||
exec_timeout: 30 # 30 min.
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
enterprise-amazon2-arm64:
|
||||
- task: config_fuzzer_replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours.
|
||||
|
||||
enterprise-amazon2022:
|
||||
- task: config_fuzzer_replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours.
|
||||
|
||||
enterprise-amazon2022-arm64:
|
||||
- task: config_fuzzer_replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours.
|
||||
|
||||
enterprise-rhel-70-64-bit:
|
||||
- task: config_fuzzer_replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours.
|
||||
|
||||
enterprise-macos:
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours
|
||||
- task: run_unittests
|
||||
exec_timeout: 60
|
||||
|
||||
enterprise-macos-arm64:
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours
|
||||
- task: run_unittests
|
||||
exec_timeout: 60
|
||||
|
||||
enterprise-macos-cxx20:
|
||||
- task: run_unittests
|
||||
exec_timeout: 60
|
||||
|
||||
enterprise-macos-rosetta-2:
|
||||
- task: run_unittests
|
||||
exec_timeout: 60
|
||||
|
||||
enterprise-rhel-80-64-bit-coverage:
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours.
|
||||
|
||||
enterprise-rhel-80-64-bit-dynamic:
|
||||
- task: replica_sets_large_txns_format
|
||||
exec_timeout: 120 # 2 hours.
|
||||
- task: config_fuzzer_replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours.
|
||||
|
||||
enterprise-rhel80-debug-tsan:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
enterprise-rhel80-debug-complete-tsan:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
enterprise-rhel80-debug-complete-v4tsan-experimental:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
enterprise-rhel80-debug-v4tsan-experimental:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
enterprise-windows:
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 180 # 3 hours.
|
||||
|
||||
enterprise-windows-all-feature-flags-suggested:
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 180 # 3 hours.
|
||||
|
||||
linux-64-debug:
|
||||
- task: auth
|
||||
exec_timeout: 60 # 1 hour.
|
||||
|
||||
linux-x86-dynamic-compile-required:
|
||||
- task: server_discovery_and_monitoring_json_test
|
||||
exec_timeout: 30 # 30 min.
|
||||
|
||||
linux-64-debug-repeated-execution:
|
||||
- task: run_unittests
|
||||
exec_timeout: 120 # 2 hours.
|
||||
|
||||
macos:
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours
|
||||
- task: run_unittests
|
||||
exec_timeout: 60
|
||||
- task: sharded_collections_jscore_passthrough
|
||||
exec_timeout: 300 # 5 hours
|
||||
|
||||
macos-debug-suggested:
|
||||
- task: run_unittests
|
||||
exec_timeout: 60
|
||||
|
||||
macos-arm64:
|
||||
- task: run_unittests
|
||||
exec_timeout: 60
|
||||
- task: sharding_update_v1_oplog_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours
|
||||
- task: sharded_collections_jscore_passthrough
|
||||
exec_timeout: 300 # 5 hours
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours
|
||||
|
||||
rhel80-asan:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
rhel80-debug-asan:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
rhel80-debug-aubsan-lite:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
rhel80-debug-ubsan:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
- task: update_timeseries_fuzzer
|
||||
exec_timeout: 150 # 2.5 hours
|
||||
|
||||
@ -142,22 +39,6 @@ overrides:
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 180 # 3 hours.
|
||||
|
||||
rhel80-ubsan:
|
||||
- task: run_unittests
|
||||
exec_timeout: 24
|
||||
|
||||
windows:
|
||||
- task: replica_sets
|
||||
exec_timeout: 180 # 3 hours.
|
||||
|
||||
windows-debug-suggested:
|
||||
- task: replica_sets_initsync_jscore_passthrough
|
||||
exec_timeout: 150 # 2.5 hours.
|
||||
- task: replica_sets_jscore_passthrough
|
||||
exec_timeout: 180 # 3 hours.
|
||||
- task: run_unittests
|
||||
exec_timeout: 30 # 30 minutes.
|
||||
|
||||
rhel80-debug-ubsan-all-feature-flags:
|
||||
- task: update_timeseries_fuzzer
|
||||
exec_timeout: 150 # 2.5 hours
|
||||
|
||||
@ -66,7 +66,7 @@ modules:
|
||||
- name: enterprise
|
||||
repo: git@github.com:10gen/mongo-enterprise-modules.git
|
||||
prefix: src/mongo/db/modules
|
||||
branch: master
|
||||
branch: v6.3
|
||||
|
||||
- name: wtdevelop
|
||||
repo: git@github.com:wiredtiger/wiredtiger.git
|
||||
@ -616,7 +616,7 @@ functions:
|
||||
"get buildnumber": &get_buildnumber
|
||||
command: keyval.inc
|
||||
params:
|
||||
key: "${build_variant}_master"
|
||||
key: "${build_variant}_v6.3"
|
||||
destination: "builder_num"
|
||||
|
||||
"run diskstats": &run_diskstats
|
||||
@ -3876,7 +3876,7 @@ tasks:
|
||||
## Standalone fuzzer for checking columnstore index correctness ##
|
||||
- <<: *jstestfuzz_template
|
||||
name: aggregation_columnstore_fuzzer_gen
|
||||
tags: ["aggfuzzer", "common", "columnstore", "require_npm", "random_name", "sbe_only"]
|
||||
tags: ["aggfuzzer", "common", "columnstore", "require_npm", "random_name", "sbe_only", "feature_flag_guarded"]
|
||||
commands:
|
||||
- func: "generate resmoke tasks"
|
||||
vars:
|
||||
@ -4691,7 +4691,9 @@ tasks:
|
||||
|
||||
- <<: *task_template
|
||||
name: aggregation_column_store_index_passthrough
|
||||
tags: ["aggregation", "sbe_only"]
|
||||
# TODO SERVER-75026 Remove the 'feature_flag_guarded' tag and ensure this suite is run on all
|
||||
# variants.
|
||||
tags: ["aggregation", "sbe_only", "feature_flag_guarded"]
|
||||
depends_on:
|
||||
- name: aggregation
|
||||
commands:
|
||||
@ -5515,9 +5517,11 @@ tasks:
|
||||
|
||||
- <<: *task_template
|
||||
name: jsCore_column_store_indexes
|
||||
# TODO SERVER-75026 Remove the 'feature_flag_guarded' tag and ensure this suite is run on all
|
||||
# variants.
|
||||
tags: ["jscore", "sbe_only", "feature_flag_guarded"]
|
||||
depends_on:
|
||||
- name: jsCore
|
||||
tags: ["jscore", "sbe_only"]
|
||||
commands:
|
||||
- func: "do setup"
|
||||
- func: "run tests"
|
||||
|
||||
@ -41,7 +41,7 @@ buildvariants:
|
||||
- name: compile_build_tools_next_TG
|
||||
distros:
|
||||
- rhel70
|
||||
- name: .aggfuzzer
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: auth_gen
|
||||
@ -50,7 +50,7 @@ buildvariants:
|
||||
- name: .encrypt !.sharding !.replica_sets !.aggregation !.jscore
|
||||
- name: external_auth
|
||||
- name: external_auth_aws
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
|
||||
@ -29,8 +29,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel80-xlarge
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggregation !.unwind !.encrypt
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: .aggregation !.unwind !.encrypt !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth !.multiversion
|
||||
- name: .causally_consistent !.wo_snapshot !.durable_history
|
||||
@ -108,7 +108,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
|
||||
@ -32,8 +32,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- amazon2-build
|
||||
- name: .aggfuzzer .common
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -98,8 +98,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- amazon2-build
|
||||
- name: .aggfuzzer .common
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
@ -153,7 +153,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- amazon2-arm64-large
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -220,8 +220,8 @@ buildvariants:
|
||||
distros:
|
||||
- amazon2-arm64-large
|
||||
- name: test_api_version_compatibility
|
||||
- name: .aggfuzzer
|
||||
- name: .aggregation
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth
|
||||
- name: .causally_consistent !.sharding
|
||||
@ -246,7 +246,7 @@ buildvariants:
|
||||
- name: jsCore
|
||||
distros:
|
||||
- amazon2-arm64-large
|
||||
- name: .jscore .common !jsCore
|
||||
- name: .jscore .common !jsCore !.feature_flag_guarded
|
||||
- name: jsCore_min_batch_repeat_queries_ese_gsm
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: json_schema
|
||||
@ -386,8 +386,8 @@ buildvariants:
|
||||
distros:
|
||||
- amazon2022-large
|
||||
- name: test_api_version_compatibility
|
||||
- name: .aggfuzzer !.multiversion
|
||||
- name: .aggregation
|
||||
- name: .aggfuzzer !.multiversion !.feature_flag_guarded
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth !.multiversion
|
||||
- name: .causally_consistent !.sharding
|
||||
@ -448,8 +448,6 @@ buildvariants:
|
||||
distros:
|
||||
- amazon2022-large
|
||||
- name: .publish_crypt
|
||||
distros:
|
||||
- amazon2022-large
|
||||
- name: secondary_reads_passthrough_gen
|
||||
- name: server_discovery_and_monitoring_json_test_TG
|
||||
- name: .serverless
|
||||
@ -488,7 +486,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- amazon2022-arm64-large
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -551,8 +549,8 @@ buildvariants:
|
||||
distros:
|
||||
- amazon2022-arm64-large
|
||||
- name: test_api_version_compatibility
|
||||
- name: .aggfuzzer !.multiversion
|
||||
- name: .aggregation
|
||||
- name: .aggfuzzer !.feature_flag_guarded !.multiversion
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth !.multiversion
|
||||
- name: .causally_consistent !.sharding
|
||||
@ -577,7 +575,7 @@ buildvariants:
|
||||
- name: jsCore
|
||||
distros:
|
||||
- amazon2022-arm64-large
|
||||
- name: .jscore .common !jsCore
|
||||
- name: .jscore .common !jsCore !.feature_flag_guarded
|
||||
- name: jsCore_min_batch_repeat_queries_ese_gsm
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: json_schema
|
||||
@ -659,8 +657,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- debian10-build
|
||||
- name: .aggfuzzer .common
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: aggregation_auth
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
@ -669,7 +667,7 @@ buildvariants:
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jscore .common !.decimal !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: multiversion_gen
|
||||
@ -725,14 +723,14 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- debian10-build
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.replica_sets !.aggregation !.sharding !.jscore
|
||||
- name: .jepsen_docker
|
||||
distros:
|
||||
- debian10-large
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: replica_sets_auth_gen
|
||||
@ -777,8 +775,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- debian11-large
|
||||
- name: .aggfuzzer .common
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: aggregation_auth
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
@ -787,7 +785,7 @@ buildvariants:
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jscore .common !.decimal !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: multiversion_gen
|
||||
@ -841,14 +839,14 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- debian11-large
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.replica_sets !.aggregation !.sharding !.jscore
|
||||
- name: .jepsen_docker
|
||||
distros:
|
||||
- debian11-large
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: replica_sets_auth_gen
|
||||
@ -892,7 +890,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel70
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -993,7 +991,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel80-build
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -1061,8 +1059,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel80-large
|
||||
- name: .aggfuzzer
|
||||
- name: .aggregation
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: .auth
|
||||
- name: unittest_shell_hang_analyzer_gen
|
||||
@ -1170,7 +1168,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel82-arm64-large
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -1231,7 +1229,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel82-arm64-large
|
||||
- name: .aggfuzzer !.multiversion
|
||||
- name: .aggfuzzer !.multiversion !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: auth_gen
|
||||
@ -1239,7 +1237,7 @@ buildvariants:
|
||||
- name: .encrypt !.sharding !.replica_sets !.aggregation !.jscore
|
||||
- name: external_auth
|
||||
- name: external_auth_aws
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
@ -1288,7 +1286,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel90-build
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -1345,7 +1343,7 @@ buildvariants:
|
||||
- name: compile_build_tools_next_TG
|
||||
distros:
|
||||
- rhel90-large
|
||||
- name: .aggfuzzer !.multiversion
|
||||
- name: .aggfuzzer !.feature_flag_guarded !.multiversion
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: auth_gen
|
||||
@ -1434,8 +1432,6 @@ buildvariants:
|
||||
distros:
|
||||
- ubuntu2204-arm64-small
|
||||
- name: .publish
|
||||
distros:
|
||||
- rhel80-small
|
||||
- name: generate_buildid_to_debug_symbols_mapping
|
||||
|
||||
- name: enterprise-rhel90-arm64
|
||||
@ -1475,7 +1471,7 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- rhel90-arm64-large
|
||||
- name: .aggfuzzer !.multiversion
|
||||
- name: .aggfuzzer !.multiversion !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: auth_audit_gen
|
||||
- name: auth_gen
|
||||
@ -1505,8 +1501,6 @@ buildvariants:
|
||||
distros:
|
||||
- ubuntu2204-arm64-small
|
||||
- name: .publish
|
||||
distros:
|
||||
- rhel80-small
|
||||
- name: generate_buildid_to_debug_symbols_mapping
|
||||
|
||||
- name: suse12
|
||||
@ -1542,8 +1536,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- suse12-sp5-large
|
||||
- name: .aggfuzzer .common
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -1554,7 +1548,7 @@ buildvariants:
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jscore .common !.decimal !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: multiversion_gen
|
||||
- name: .logical_session_cache .one_sec
|
||||
@ -1610,11 +1604,11 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- suse12-sp5-large
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.replica_sets !.aggregation !.sharding !.jscore
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: replica_sets_auth_gen
|
||||
@ -1666,11 +1660,11 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- suse15-build
|
||||
- name: .aggfuzzer .common !.multiversion
|
||||
- name: .aggfuzzer .common !.multiversion !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.replica_sets !.aggregation !.sharding !.jscore
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: replica_sets_auth_gen
|
||||
@ -1715,8 +1709,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- suse15-build
|
||||
- name: .aggfuzzer .common !.multiversion
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.multiversion !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -1724,7 +1718,7 @@ buildvariants:
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jscore .common !.decimal !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: multiversion_gen
|
||||
@ -1772,8 +1766,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- ubuntu1804-build
|
||||
- name: .aggfuzzer .common
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: .misc_js
|
||||
- name: .concurrency .common
|
||||
@ -1856,7 +1850,7 @@ buildvariants:
|
||||
- ubuntu1804-build
|
||||
- name: .crypt
|
||||
- name: .publish_crypt
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.aggregation !.replica_sets !.sharding !.jscore
|
||||
@ -1865,7 +1859,7 @@ buildvariants:
|
||||
- name: .jepsen
|
||||
distros:
|
||||
- ubuntu1804-build
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: jsCore_auth
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
@ -1924,7 +1918,7 @@ buildvariants:
|
||||
compile_variant: enterprise-ubuntu1804-arm64
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: aggregation_wildcard_fuzzer_gen
|
||||
- name: .auth !.audit !.multiversion !.jscore
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
@ -1932,7 +1926,7 @@ buildvariants:
|
||||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: fle
|
||||
- name: .jscore .common !.auth
|
||||
- name: .jscore .common !.auth !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: replica_sets_gen
|
||||
@ -2018,8 +2012,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- ubuntu2204-large
|
||||
- name: .aggfuzzer .common !.multiversion
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.multiversion !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: .misc_js
|
||||
- name: .concurrency .common
|
||||
@ -2073,8 +2067,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- ubuntu2004-large
|
||||
- name: .aggfuzzer .common !.multiversion
|
||||
- name: aggregation
|
||||
- name: .aggfuzzer .common !.multiversion !.feature_flag_guarded
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: .auth !.audit !.multiversion
|
||||
- name: .misc_js
|
||||
- name: .concurrency .common
|
||||
@ -2142,13 +2136,13 @@ buildvariants:
|
||||
- ubuntu2004-large
|
||||
- name: .crypt
|
||||
- name: .publish_crypt
|
||||
- name: .aggfuzzer .common !.multiversion
|
||||
- name: .aggfuzzer .common !.multiversion !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.aggregation !.replica_sets !.sharding !.jscore
|
||||
- name: external_auth
|
||||
- name: external_auth_aws
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: jsCore_auth
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
@ -2208,13 +2202,13 @@ buildvariants:
|
||||
- ubuntu2204-large
|
||||
- name: .crypt
|
||||
- name: .publish_crypt
|
||||
- name: .aggfuzzer .common !.multiversion
|
||||
- name: .aggfuzzer .common !.multiversion !.feature_flag_guarded
|
||||
- name: audit
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.aggregation !.replica_sets !.sharding !.jscore
|
||||
- name: external_auth
|
||||
- name: external_auth_aws
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: jsCore_auth
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
@ -2268,7 +2262,7 @@ buildvariants:
|
||||
compile_variant: enterprise-ubuntu2004-arm64
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: aggregation_wildcard_fuzzer_gen
|
||||
- name: .auth !.audit !.multiversion !.jscore
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
@ -2276,7 +2270,7 @@ buildvariants:
|
||||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: fle
|
||||
- name: .jscore .common !.auth
|
||||
- name: .jscore .common !.auth !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: replica_sets_gen
|
||||
@ -2360,7 +2354,7 @@ buildvariants:
|
||||
compile_variant: enterprise-ubuntu2204-arm64
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
- name: aggregation
|
||||
- name: aggregation !.feature_flag_guarded
|
||||
- name: aggregation_wildcard_fuzzer_gen
|
||||
- name: .auth !.audit !.multiversion !.jscore
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
@ -2368,7 +2362,7 @@ buildvariants:
|
||||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: fle
|
||||
- name: .jscore .common !.auth
|
||||
- name: .jscore .common !.auth !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: replica_sets_gen
|
||||
@ -2455,8 +2449,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_no_unittests_TG
|
||||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: .aggfuzzer
|
||||
- name: .aggregation !.auth !.encrypt !.unwind
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.auth !.encrypt !.unwind !.feature_flag_guarded
|
||||
- name: auth_gen
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -2468,7 +2462,7 @@ buildvariants:
|
||||
- name: .concurrency .common
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.auth
|
||||
- name: .jscore .common !.auth !.feature_flag_guarded
|
||||
- name: json_schema
|
||||
- name: .jstestfuzz !.initsync !.flow_control !.stepdowns
|
||||
- name: multiversion_gen
|
||||
@ -2529,8 +2523,8 @@ buildvariants:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: .aggfuzzer
|
||||
- name: .aggregation !.auth !.encrypt !.unwind
|
||||
- name: .aggfuzzer !.feature_flag_guarded
|
||||
- name: .aggregation !.auth !.encrypt !.unwind !.feature_flag_guarded
|
||||
- name: auth_gen
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .misc_js
|
||||
@ -2545,7 +2539,7 @@ buildvariants:
|
||||
- windows-vsCurrent-large
|
||||
- name: .publish_crypt
|
||||
- name: disk_wiredtiger
|
||||
- name: .jscore .common !.auth
|
||||
- name: .jscore .common !.auth !.feature_flag_guarded
|
||||
- name: json_schema
|
||||
- name: .jstestfuzz !.initsync !.flow_control !.stepdowns
|
||||
- name: multiversion_gen
|
||||
@ -2588,7 +2582,7 @@ buildvariants:
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: compile_build_tools_next_TG
|
||||
- name: .aggregation !.auth !.encrypt !.unwind
|
||||
- name: .aggregation !.auth !.encrypt !.unwind !.feature_flag_guarded
|
||||
- name: auth_gen
|
||||
- name: .causally_consistent !.sharding
|
||||
- name: .change_streams !.secondary_reads
|
||||
@ -2597,7 +2591,7 @@ buildvariants:
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: initial_sync_fuzzer_gen
|
||||
- name: .jscore .common !.auth
|
||||
- name: .jscore .common !.auth !.feature_flag_guarded
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: .jstestfuzz .causal
|
||||
- name: .jstestfuzz .interrupt
|
||||
@ -2642,7 +2636,7 @@ buildvariants:
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: compile_build_tools_next_TG
|
||||
- name: .aggregation !.auth !.encrypt !.unwind
|
||||
- name: .aggregation !.auth !.encrypt !.unwind !.feature_flag_guarded
|
||||
- name: auth_gen
|
||||
- name: .causally_consistent !.sharding
|
||||
- name: .change_streams !.secondary_reads
|
||||
@ -2651,7 +2645,7 @@ buildvariants:
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: initial_sync_fuzzer_gen
|
||||
- name: .jscore .common !.auth
|
||||
- name: .jscore .common !.auth !.feature_flag_guarded
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: .jstestfuzz .causal
|
||||
- name: .jstestfuzz .interrupt
|
||||
@ -2708,7 +2702,7 @@ buildvariants:
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
# TODO: SERVER-66945 Re-enable ESE on enterprise macos
|
||||
# - name: .encrypt !.replica_sets !.sharding !.aggregation !.jscore
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: mqlrun
|
||||
@ -2752,7 +2746,7 @@ buildvariants:
|
||||
- name: auth_audit_gen
|
||||
- name: causally_consistent_jscore_txns_passthrough
|
||||
- name: .encrypt !.replica_sets !.sharding !.aggregation !.jscore
|
||||
- name: .jscore .common !.decimal !.sharding
|
||||
- name: .jscore .common !.decimal !.sharding !.feature_flag_guarded
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
- name: mqlrun
|
||||
|
||||
@ -32,7 +32,7 @@ buildvariants:
|
||||
compile_variant: rhel80-asan
|
||||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: .aggfuzzer .common
|
||||
- name: .aggfuzzer .common !.feature_flag_guarded
|
||||
- name: free_monitoring
|
||||
- name: .jstestfuzz !.initsync
|
||||
|
||||
@ -76,7 +76,7 @@ buildvariants:
|
||||
compile_variant: rhel80-debug-asan
|
||||
tasks:
|
||||
- name: compile_test_benchmark_and_package_serial_TG
|
||||
- name: .aggregation
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: .auth
|
||||
- name: audit
|
||||
- name: .benchmarks
|
||||
@ -158,7 +158,7 @@ buildvariants:
|
||||
compile_variant: rhel80-debug-ubsan
|
||||
tasks:
|
||||
- name: compile_test_benchmark_and_package_serial_TG
|
||||
- name: .aggregation
|
||||
- name: .aggregation !.feature_flag_guarded
|
||||
- name: .auth
|
||||
- name: audit
|
||||
- name: .benchmarks
|
||||
|
||||
10
etc/perf.yml
10
etc/perf.yml
@ -99,7 +99,7 @@ modules:
|
||||
- name: enterprise
|
||||
repo: git@github.com:10gen/mongo-enterprise-modules.git
|
||||
prefix: src/mongo/db/modules
|
||||
branch: master
|
||||
branch: v6.3
|
||||
- name: mongo-tools
|
||||
repo: git@github.com:mongodb/mongo-tools.git
|
||||
prefix: mongo-tools/src/github.com/mongodb
|
||||
@ -770,7 +770,7 @@ microbenchmark-buildvariants:
|
||||
display_name: Standalone Linux inMemory
|
||||
cron: "0 */4 * * *" # Every 4 hours starting at midnight
|
||||
modules: *modules
|
||||
expansions:
|
||||
expansions: &linux-standalone-expansions
|
||||
# We are explicitly tracking the rhel62 variant compile options from evergreen.yml for
|
||||
# microbenchmarks, since they run on the centos6 boxes. If we can get proper artifacts directly
|
||||
# from that project, we should do that and remove the compile tasks.
|
||||
@ -826,7 +826,7 @@ microbenchmark-buildvariants:
|
||||
display_name: 1-Node ReplSet Linux inMemory
|
||||
cron: "0 */4 * * *" # Every 4 hours starting at midnight
|
||||
modules: *modules
|
||||
expansions:
|
||||
expansions: &linux-repl-expansions
|
||||
mongod_exec_wrapper: *exec_wrapper
|
||||
perf_exec_wrapper: *perf_wrapper
|
||||
platform: linux
|
||||
@ -856,6 +856,7 @@ buildvariants:
|
||||
display_name: Standalone Linux inMemory (all feature flags)
|
||||
cron: "0 0 * * *" # Every day starting at 00:00
|
||||
expansions:
|
||||
<<: *linux-standalone-expansions
|
||||
mongodb_setup: microbenchmarks_standalone-all-feature-flags
|
||||
|
||||
- <<: *linux-wt-standalone
|
||||
@ -864,6 +865,7 @@ buildvariants:
|
||||
# Will make it less frequent when the current SBE perf improvement is finished (SERVER-69799).
|
||||
cron: "0 0 * * 0,2,3,4,5" # Run it every day except Saturday and Monday.
|
||||
expansions:
|
||||
<<: *linux-standalone-expansions
|
||||
mongodb_setup: microbenchmarks_standalone-classic-query-engine
|
||||
|
||||
- <<: *linux-wt-standalone
|
||||
@ -872,6 +874,7 @@ buildvariants:
|
||||
# Will make it less frequent when the current SBE perf improvement is finished (SERVER-69799).
|
||||
cron: "0 0 * * 0,2,3,4,5" # Run it every day except Saturday and Monday.
|
||||
expansions:
|
||||
<<: *linux-standalone-expansions
|
||||
mongodb_setup: microbenchmarks_standalone-sbe
|
||||
|
||||
- <<: *linux-wt-repl
|
||||
@ -879,4 +882,5 @@ buildvariants:
|
||||
display_name: 1-Node ReplSet Linux inMemory (all feature flags)
|
||||
cron: "0 0 * * *" # Every day starting at 00:00
|
||||
expansions:
|
||||
<<: *linux-repl-expansions
|
||||
mongodb_setup: microbenchmarks_replica-all-feature-flags
|
||||
|
||||
2263
etc/system_perf.yml
2263
etc/system_perf.yml
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,12 @@ if [[ -n "${burn_in_bypass}" ]]; then
|
||||
build_variant_for_timeout=${burn_in_bypass}
|
||||
fi
|
||||
|
||||
if [[ -n "${alias}" ]]; then
|
||||
evg_alias=${alias}
|
||||
else
|
||||
evg_alias="evg-alias-absent"
|
||||
fi
|
||||
|
||||
activate_venv
|
||||
PATH=$PATH:$HOME:/ $python buildscripts/evergreen_task_timeout.py $timeout_factor \
|
||||
--install-dir "${install_dir}" \
|
||||
@ -32,7 +38,7 @@ PATH=$PATH:$HOME:/ $python buildscripts/evergreen_task_timeout.py $timeout_facto
|
||||
--suite-name ${suite_name} \
|
||||
--project ${project} \
|
||||
--build-variant $build_variant_for_timeout \
|
||||
--evg-alias '${alias}' \
|
||||
--evg-alias $evg_alias \
|
||||
--timeout ${timeout_secs} \
|
||||
--exec-timeout ${exec_timeout_secs} \
|
||||
--evg-api-config ./.evergreen.yml \
|
||||
|
||||
@ -8,9 +8,8 @@ function testMongod(mongod, systemuserpwd = undefined) {
|
||||
const admin = mongod.getDB('admin');
|
||||
admin.createUser({user: 'admin', pwd: 'admin', roles: ['root']});
|
||||
|
||||
function assertUnauthorized(cmd, msg) {
|
||||
const errmsg =
|
||||
assert.commandFailedWithCode(admin.runCommand(cmd), ErrorCodes.Unauthorized).errmsg;
|
||||
function assertError(cmd, msg, code) {
|
||||
const errmsg = assert.commandFailedWithCode(admin.runCommand(cmd), code).errmsg;
|
||||
assert(errmsg.includes(msg), "Error message is missing '" + msg + "': " + errmsg);
|
||||
}
|
||||
|
||||
@ -18,7 +17,8 @@ function testMongod(mongod, systemuserpwd = undefined) {
|
||||
|
||||
// Localhost authbypass is disabled, and we haven't logged in,
|
||||
// so normal auth-required commands should fail.
|
||||
assertUnauthorized({usersInfo: 1}, 'Command usersInfo requires authentication');
|
||||
assertError(
|
||||
{usersInfo: 1}, 'Command usersInfo requires authentication', ErrorCodes.Unauthorized);
|
||||
|
||||
// Hello command requires no auth, so it works fine.
|
||||
assert.commandWorked(admin.runCommand({hello: 1}));
|
||||
@ -33,7 +33,8 @@ function testMongod(mongod, systemuserpwd = undefined) {
|
||||
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
|
||||
}
|
||||
};
|
||||
assertUnauthorized(kImpersonatedHello, 'Unauthorized use of impersonation metadata');
|
||||
assertError(
|
||||
kImpersonatedHello, 'Unauthorized use of impersonation metadata', ErrorCodes.Unauthorized);
|
||||
|
||||
// TODO SERVER-72448: Remove
|
||||
const kImpersonatedHelloLegacy = {
|
||||
@ -43,11 +44,41 @@ function testMongod(mongod, systemuserpwd = undefined) {
|
||||
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
|
||||
}
|
||||
};
|
||||
assertUnauthorized(kImpersonatedHelloLegacy, 'Unauthorized use of impersonation metadata');
|
||||
assertError(kImpersonatedHelloLegacy,
|
||||
'Unauthorized use of impersonation metadata',
|
||||
ErrorCodes.Unauthorized);
|
||||
|
||||
// TODO SERVER-72448: Remove, checks that both legacy and new impersonation metadata fields
|
||||
// cannot be set simultaneously.
|
||||
const kImpersonatedHelloBoth = {
|
||||
hello: 1,
|
||||
"$audit": {
|
||||
"$impersonatedUser": {user: 'admin', db: 'admin'},
|
||||
"$impersonatedUsers": [{user: 'admin', db: 'admin'}],
|
||||
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
|
||||
}
|
||||
};
|
||||
assertError(kImpersonatedHelloBoth,
|
||||
'Cannot specify both $impersonatedUser and $impersonatedUsers',
|
||||
ErrorCodes.BadValue);
|
||||
|
||||
// TODO SERVER-72448: Remove, checks that the legacy impersonation metadata field can only
|
||||
// contain at most 1 field if specified.
|
||||
const kImpersonatedHelloLegacyMultiple = {
|
||||
hello: 1,
|
||||
"$audit": {
|
||||
"$impersonatedUsers": [{user: 'admin', db: 'admin'}, {user: 'test', db: 'pwd'}],
|
||||
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
|
||||
}
|
||||
};
|
||||
assertError(kImpersonatedHelloLegacyMultiple,
|
||||
'Can only impersonate up to one user per connection',
|
||||
ErrorCodes.BadValue);
|
||||
|
||||
// Try as admin (root role), should still fail.
|
||||
admin.auth('admin', 'admin');
|
||||
assertUnauthorized(kImpersonatedHello, 'Unauthorized use of impersonation metadata');
|
||||
assertError(
|
||||
kImpersonatedHello, 'Unauthorized use of impersonation metadata', ErrorCodes.Unauthorized);
|
||||
admin.logout();
|
||||
|
||||
if (systemuserpwd !== undefined) {
|
||||
|
||||
56
jstests/auth/sbe_plan_cache_user_roles.js
Normal file
56
jstests/auth/sbe_plan_cache_user_roles.js
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Test $$USER_ROLES works correctly with the SBE plan cache. The same query should return the
|
||||
* updated user role info when a different user logs in.
|
||||
* @tags: [
|
||||
* featureFlagUserRoles,
|
||||
* # Multiple servers can mess up the plan cache list.
|
||||
* assumes_standalone_mongod,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
|
||||
|
||||
const mongod = MongoRunner.runMongod();
|
||||
const dbName = "test";
|
||||
const db = mongod.getDB(dbName);
|
||||
|
||||
// Create two users, each with different roles.
|
||||
assert.commandWorked(
|
||||
db.runCommand({createUser: "user1", pwd: "pwd", roles: [{role: "read", db: dbName}]}));
|
||||
assert.commandWorked(
|
||||
db.runCommand({createUser: "user2", pwd: "pwd", roles: [{role: "readWrite", db: dbName}]}));
|
||||
|
||||
const coll = db.sbe_plan_cache_user_roles;
|
||||
coll.drop();
|
||||
|
||||
const verifyPlanCache = function(role) {
|
||||
if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
|
||||
const caches = coll.getPlanCache().list();
|
||||
assert.eq(1, caches.length, caches);
|
||||
assert.eq(caches[0].cachedPlan.stages.includes(role), false, caches);
|
||||
}
|
||||
};
|
||||
|
||||
assert.commandWorked(coll.insert({_id: 1}));
|
||||
|
||||
// While logged in as user1, we should see user1's roles.
|
||||
db.auth("user1", "pwd");
|
||||
let results = coll.find({}, {roles: "$$USER_ROLES"}).toArray();
|
||||
assert.eq(results.length, 1);
|
||||
assert.eq(results[0].roles, [{_id: "test.read", role: "read", db: "test"}]);
|
||||
// It can take two executions of a query for a plan to get cached.
|
||||
coll.find({}, {roles: "$$USER_ROLES"}).toArray();
|
||||
verifyPlanCache("test.read");
|
||||
db.logout();
|
||||
|
||||
// While logged in as user2, we should see user2's roles.
|
||||
db.auth("user2", "pwd");
|
||||
results = coll.find({}, {roles: "$$USER_ROLES"}).toArray();
|
||||
assert.eq(results.length, 1);
|
||||
assert.eq(results[0].roles, [{_id: "test.readWrite", role: "readWrite", db: "test"}]);
|
||||
verifyPlanCache("test.readWrite");
|
||||
db.logout();
|
||||
|
||||
MongoRunner.stopMongod(mongod);
|
||||
})();
|
||||
@ -10,6 +10,8 @@
|
||||
* ]
|
||||
*/
|
||||
|
||||
load('jstests/libs/feature_flag_util.js');
|
||||
|
||||
const dbPrefix = jsTestName() + '_DB_';
|
||||
const dbCount = 2;
|
||||
const collPrefix = 'sharded_coll_';
|
||||
@ -62,6 +64,10 @@ var $config = (function() {
|
||||
]);
|
||||
},
|
||||
movePrimary: function(db, collName, connCache) {
|
||||
if (this.skipMovePrimary) {
|
||||
return;
|
||||
}
|
||||
|
||||
db = getRandomDb(db);
|
||||
const shardId = getRandomShard(connCache);
|
||||
|
||||
@ -91,6 +97,10 @@ var $config = (function() {
|
||||
};
|
||||
|
||||
let setup = function(db, collName, connCache) {
|
||||
// TODO (SERVER-71309): Remove once 7.0 becomes last LTS. Prevent non-resilient movePrimary
|
||||
// operations from being executed in multiversion suites.
|
||||
this.skipMovePrimary = !FeatureFlagUtil.isEnabled(db.getMongo(), 'ResilientMovePrimary');
|
||||
|
||||
for (var i = 0; i < dbCount; i++) {
|
||||
const dbName = dbPrefix + i;
|
||||
const newDb = db.getSiblingDB(dbName);
|
||||
@ -116,7 +126,6 @@ var $config = (function() {
|
||||
startState: 'create',
|
||||
states: states,
|
||||
transitions: transitions,
|
||||
data: {},
|
||||
setup: setup,
|
||||
teardown: teardown,
|
||||
passConnectionCache: true
|
||||
|
||||
@ -16,10 +16,6 @@
|
||||
* does_not_support_add_remove_shards,
|
||||
* # This test just performs rename operations that can't be executed in transactions
|
||||
* does_not_support_transactions,
|
||||
* # Can be removed once PM-1965-Milestone-1 is completed.
|
||||
*
|
||||
* # TODO SERVER-73385 reenable when fixed.
|
||||
* assumes_balancer_off,
|
||||
* ]
|
||||
*/
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
// does_not_support_stepdowns,
|
||||
// requires_non_retryable_writes,
|
||||
// requires_profiling,
|
||||
// # Uses $where operator
|
||||
// requires_scripting,
|
||||
// ]
|
||||
|
||||
// Confirms that profiled delete execution contains all expected metrics with proper values.
|
||||
|
||||
@ -3,6 +3,9 @@
|
||||
* above a columnscan stage.
|
||||
*
|
||||
* @tags: [
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* # explain is not supported in transactions
|
||||
* does_not_support_transactions,
|
||||
* requires_pipeline_optimization,
|
||||
@ -10,8 +13,6 @@
|
||||
* assumes_read_concern_unchanged,
|
||||
* # explain will be different in a sharded collection
|
||||
* assumes_unsharded_collection,
|
||||
* # column store row store expression skipping is new in 6.2.
|
||||
* requires_fcv_62,
|
||||
* # Columnstore tests set server parameters to disable columnstore query planning heuristics -
|
||||
* # 1) server parameters are stored in-memory only so are not transferred onto the recipient,
|
||||
* # 2) server parameters may not be set in stepdown passthroughs because it is a command that may
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
* requires_collstats,
|
||||
*
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* uses_column_store_index,
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
*
|
||||
* # In passthrough suites, this test makes direct connections to mongod instances that compose
|
||||
* # the passthrough fixture in order to perform additional validation. Tenant migration,
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
* Test column stores indexes that use a "columnstoreProjection" or "prefix.$**" notation to limit
|
||||
* indexed data to a subset of the document namespace.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* # Runs explain on an aggregate command which is only compatible with readConcern local.
|
||||
* assumes_read_concern_unchanged,
|
||||
* # Columnstore tests set server parameters to disable columnstore query planning heuristics -
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
/**
|
||||
* Tests the eligibility of certain queries to use a columnstore index.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* # Refusing to run a test that issues an aggregation command with explain because it may return
|
||||
* # incomplete results if interrupted by a stepdown.
|
||||
* does_not_support_stepdowns,
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
/**
|
||||
* Tests some basic use cases and functionality of a columnstore index.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
*
|
||||
* # Uses $indexStats which is not supported inside a transaction.
|
||||
* does_not_support_transactions,
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
/**
|
||||
* Testing of just the query layer's integration for columnar index.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* # Runs explain on an aggregate command which is only compatible with readConcern local.
|
||||
* assumes_read_concern_unchanged,
|
||||
* # Columnstore tests set server parameters to disable columnstore query planning heuristics -
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
* might be pushed down into the column scan stage.
|
||||
*
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* # Runs explain on an aggregate command which is only compatible with readConcern local.
|
||||
* assumes_read_concern_unchanged,
|
||||
* # Columnstore tests set server parameters to disable columnstore query planning heuristics -
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Testing of just the query layer's integration for columnar indexes that encode large arrays.
|
||||
* @tags: [
|
||||
* # Column store indexes are still under a feature flag and require full SBE.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* # Columnstore tests set server parameters to disable columnstore query planning heuristics -
|
||||
* # 1) server parameters are stored in-memory only so are not transferred onto the recipient,
|
||||
* # 2) server parameters may not be set in stepdown passthroughs because it is a command that may
|
||||
@ -8,8 +11,6 @@
|
||||
* tenant_migration_incompatible,
|
||||
* does_not_support_stepdowns,
|
||||
* not_allowed_with_security_token,
|
||||
|
||||
* requires_fcv_63,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Tests parsing and validation of columnstore indexes.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* # Uses index building in background.
|
||||
* requires_background_index,
|
||||
* # Columnstore tests set server parameters to disable columnstore query planning heuristics -
|
||||
|
||||
20
jstests/core/doc_validation_with_now_variable.js
Normal file
20
jstests/core/doc_validation_with_now_variable.js
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Tests that insertion with a $$NOW Validator works properly.
|
||||
*
|
||||
* @tags: [assumes_no_implicit_collection_creation_after_drop]
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
const coll = db.coll_doc_validation_with_now_variable;
|
||||
coll.drop();
|
||||
// assert.commandWorked(db.createCollection("coll_doc_validation_with_now_variable",
|
||||
// {validator: {"$expr": {$gt: ["$ts", "$$NOW"]}}}));
|
||||
|
||||
assert.commandWorked(db.createCollection("coll_doc_validation_with_now_variable",
|
||||
{validator: {"$expr": {$lt: ["$ts", "$$NOW"]}}}));
|
||||
|
||||
assert.commandWorked(coll.insert({"ts": new Date(1589617694938)}));
|
||||
|
||||
const result = coll.insert({"ts": new Date(2708791380000)});
|
||||
assert.commandFailedWithCode(result, ErrorCodes.DocumentValidationFailure, tojson(result));
|
||||
})();
|
||||
@ -3,6 +3,8 @@
|
||||
// not_allowed_with_security_token,
|
||||
// does_not_support_stepdowns,
|
||||
// uses_map_reduce_with_temp_collections,
|
||||
// # Uses $where operator
|
||||
// requires_scripting,
|
||||
// ]
|
||||
|
||||
/**
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
// Check that count returns 0 in some exception cases.
|
||||
//
|
||||
// @tags: [requires_fastcount]
|
||||
// @tags: [
|
||||
// requires_fastcount
|
||||
// ]
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
// @tags: [requires_non_retryable_writes]
|
||||
// @tags: [
|
||||
// requires_non_retryable_writes
|
||||
//]
|
||||
|
||||
t = db.jstests_js2;
|
||||
t.remove({});
|
||||
|
||||
91
jstests/core/query/sbe_plan_cache_autoparameterize_ixscan.js
Normal file
91
jstests/core/query/sbe_plan_cache_autoparameterize_ixscan.js
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Tests that auto-parameterized index scan plans are correctly stored in the SBE plan cache, and
|
||||
* that they can be correctly recovered from the cache with new parameter values.
|
||||
*
|
||||
* @tags: [
|
||||
* not_allowed_with_security_token,
|
||||
* assumes_read_concern_unchanged,
|
||||
* assumes_read_preference_unchanged,
|
||||
* assumes_unsharded_collection,
|
||||
* does_not_support_stepdowns,
|
||||
* # The SBE plan cache was enabled by default in 6.3.
|
||||
* requires_fcv_63,
|
||||
* # Plan cache state is node-local and will not get migrated alongside tenant data.
|
||||
* tenant_migration_incompatible,
|
||||
* cqf_incompatible,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled'.
|
||||
load("jstests/libs/analyze_plan.js"); // For 'getQueryHashFromExplain'.
|
||||
|
||||
// This test is specifically verifying the behavior of the SBE plan cache, which is only enabled
|
||||
// when SBE is enabled.
|
||||
if (!checkSBEEnabled(db)) {
|
||||
jsTestLog("Skipping test because SBE is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
const coll = db[jsTestName()];
|
||||
coll.drop();
|
||||
|
||||
// Set up the collection with an index and a set of documents.
|
||||
assert.commandWorked(coll.createIndex({a: 1}));
|
||||
assert.commandWorked(coll.insertMany([{_id: 1, a: 1}, {_id: 2, a: 2}, {_id: 3, a: 3}]));
|
||||
const filter1 = {
|
||||
a: {$gte: 2, $lte: 2}
|
||||
};
|
||||
const filter2 = {
|
||||
a: {$gte: 1, $lte: 2}
|
||||
};
|
||||
const sortPattern = {
|
||||
a: -1
|
||||
};
|
||||
|
||||
// Create a cache entry using 'filter1'.
|
||||
assert.eq(0, coll.getPlanCache().list().length, "Expected 0 cache entries");
|
||||
const filter1Result = coll.find(filter1).sort(sortPattern).toArray();
|
||||
const expectedFilter1Result = [{_id: 2, a: 2}];
|
||||
assert.eq(expectedFilter1Result, filter1Result);
|
||||
const cacheEntries = coll.getPlanCache().list();
|
||||
assert.eq(1, cacheEntries.length, cacheEntries);
|
||||
const cacheEntry = cacheEntries[0];
|
||||
|
||||
// Verify that our cache entry is pinned and active.
|
||||
assert(cacheEntry.isPinned, cacheEntry);
|
||||
assert(cacheEntry.isActive, cacheEntry);
|
||||
|
||||
// Capture the results for 'filter2' and verify that it used the same plan cache entry as 'filter1'.
|
||||
const cacheResults = coll.find(filter2).sort(sortPattern).toArray();
|
||||
const expectedFilter2Result = [{_id: 2, a: 2}, {_id: 1, a: 1}];
|
||||
assert.eq(cacheResults, expectedFilter2Result);
|
||||
|
||||
// There should still be exactly one plan cache entry.
|
||||
assert.eq(1, coll.getPlanCache().list().length, cacheEntries);
|
||||
|
||||
// The plan cache key and the query hashes of both queries should match.
|
||||
const explain = coll.find(filter2).sort(sortPattern).explain();
|
||||
const planCacheKey = cacheEntry.planCacheKey;
|
||||
assert.neq(null, planCacheKey, cacheEntry);
|
||||
assert.eq(planCacheKey, getPlanCacheKeyFromExplain(explain, db), explain);
|
||||
|
||||
const queryHash = cacheEntry.queryHash;
|
||||
assert.neq(null, queryHash, cacheEntry);
|
||||
assert.eq(queryHash, getQueryHashFromExplain(explain, db), explain);
|
||||
|
||||
// Clear the plan cache, and run 'filter2' again. This time, verify that we create a cache entry
|
||||
// with the same planCacheKey and queryHash as before.
|
||||
coll.getPlanCache().clear();
|
||||
assert.eq(0, coll.getPlanCache().list().length, "Expected 0 cache entries");
|
||||
const results = coll.find(filter2).sort(sortPattern).toArray();
|
||||
const newCacheEntries = coll.getPlanCache().list();
|
||||
assert.eq(1, newCacheEntries.length, "Expected 1 cache entry");
|
||||
const newCacheEntry = newCacheEntries[0];
|
||||
assert.eq(newCacheEntry.planCacheKey, planCacheKey, newCacheEntry);
|
||||
assert.eq(newCacheEntry.queryHash, queryHash, newCacheEntry);
|
||||
|
||||
// The query should also return the same results as before.
|
||||
assert.eq(results, cacheResults);
|
||||
}());
|
||||
@ -211,5 +211,8 @@ if (TimeseriesTest.timeseriesScalabilityImprovementsEnabled(db.getMongo())) {
|
||||
"timeseries":
|
||||
{"bucketMaxSpanSeconds": bucketingValueMax, "bucketRoundingSeconds": bucketingValueMax}
|
||||
}));
|
||||
|
||||
// No-op command should succeed with empty time-series options.
|
||||
assert.commandWorked(db.runCommand({"collMod": collName, "timeseries": {}}));
|
||||
}
|
||||
})();
|
||||
|
||||
@ -38,7 +38,18 @@ if (!isMongos(db)) {
|
||||
res.stages[1]);
|
||||
}
|
||||
|
||||
const res = coll.aggregate([{$group: {_id: '$meta', accmin: {$min: '$b'}, accmax: {$max: '$c'}}}])
|
||||
.toArray();
|
||||
let res = coll.aggregate([{$group: {_id: '$meta', accmin: {$min: '$b'}, accmax: {$max: '$c'}}}])
|
||||
.toArray();
|
||||
assert.docEq([{"_id": null, "accmin": 1, "accmax": 3}], res);
|
||||
|
||||
// Test SERVER-73822 fix: complex $min and $max (i.e. not just straight field refs) work correctly.
|
||||
res = coll.aggregate([{
|
||||
$group: {
|
||||
_id: '$meta',
|
||||
accmin: {$min: {$add: ["$b", "$c"]}},
|
||||
accmax: {$max: {$add: ["$b", "$c"]}}
|
||||
}
|
||||
}])
|
||||
.toArray();
|
||||
assert.docEq([{"_id": null, "accmin": 2, "accmax": 6}], res);
|
||||
})();
|
||||
|
||||
@ -19,7 +19,7 @@ const tsColl = db.timeseries_predicates_timeseries;
|
||||
coll.drop();
|
||||
tsColl.drop();
|
||||
assert.commandWorked(
|
||||
db.createCollection(tsColl.getName(), {timeseries: {timeField: 'time', metaField: 'meta'}}));
|
||||
db.createCollection(tsColl.getName(), {timeseries: {timeField: 'time', metaField: 'mt'}}));
|
||||
const bucketsColl = db.getCollection('system.buckets.' + tsColl.getName());
|
||||
|
||||
// Test that 'predicate' behaves correctly on the example documents,
|
||||
@ -88,18 +88,18 @@ checkAllBucketings({x: {$exists: true}}, [
|
||||
|
||||
// Test $or...
|
||||
{
|
||||
// ... on metric + meta.
|
||||
// ... on metric + mt.
|
||||
checkAllBucketings({
|
||||
$or: [
|
||||
{x: {$lt: 0}},
|
||||
{'meta.y': {$gt: 0}},
|
||||
{'mt.y': {$gt: 0}},
|
||||
]
|
||||
},
|
||||
[
|
||||
{x: +1, meta: {y: -1}},
|
||||
{x: +1, meta: {y: +1}},
|
||||
{x: -1, meta: {y: -1}},
|
||||
{x: -1, meta: {y: +1}},
|
||||
{x: +1, mt: {y: -1}},
|
||||
{x: +1, mt: {y: +1}},
|
||||
{x: -1, mt: {y: -1}},
|
||||
{x: -1, mt: {y: +1}},
|
||||
]);
|
||||
|
||||
// ... when one argument can't be pushed down.
|
||||
@ -133,18 +133,18 @@ checkAllBucketings({x: {$exists: true}}, [
|
||||
|
||||
// Test $and...
|
||||
{
|
||||
// ... on metric + meta.
|
||||
// ... on metric + mt.
|
||||
checkAllBucketings({
|
||||
$and: [
|
||||
{x: {$lt: 0}},
|
||||
{'meta.y': {$gt: 0}},
|
||||
{'mt.y': {$gt: 0}},
|
||||
]
|
||||
},
|
||||
[
|
||||
{x: +1, meta: {y: -1}},
|
||||
{x: +1, meta: {y: +1}},
|
||||
{x: -1, meta: {y: -1}},
|
||||
{x: -1, meta: {y: +1}},
|
||||
{x: +1, mt: {y: -1}},
|
||||
{x: +1, mt: {y: +1}},
|
||||
{x: -1, mt: {y: -1}},
|
||||
{x: -1, mt: {y: +1}},
|
||||
]);
|
||||
|
||||
// ... when one argument can't be pushed down.
|
||||
@ -182,28 +182,28 @@ checkAllBucketings({
|
||||
$or: [
|
||||
{
|
||||
$and: [
|
||||
{'meta.a': {$gt: 0}},
|
||||
{'mt.a': {$gt: 0}},
|
||||
{'x': {$lt: 0}},
|
||||
]
|
||||
},
|
||||
{
|
||||
$and: [
|
||||
{'meta.b': {$gte: 0}},
|
||||
{'mt.b': {$gte: 0}},
|
||||
{time: {$gt: ISODate('2020-01-01')}},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
[
|
||||
{meta: {a: -1, b: -1}, x: -1, time: ISODate('2020-02-01')},
|
||||
{meta: {a: -1, b: -1}, x: -1, time: ISODate('2019-12-31')},
|
||||
{meta: {a: -1, b: -1}, x: +1, time: ISODate('2020-02-01')},
|
||||
{meta: {a: -1, b: -1}, x: +1, time: ISODate('2019-12-31')},
|
||||
{mt: {a: -1, b: -1}, x: -1, time: ISODate('2020-02-01')},
|
||||
{mt: {a: -1, b: -1}, x: -1, time: ISODate('2019-12-31')},
|
||||
{mt: {a: -1, b: -1}, x: +1, time: ISODate('2020-02-01')},
|
||||
{mt: {a: -1, b: -1}, x: +1, time: ISODate('2019-12-31')},
|
||||
|
||||
{meta: {a: +1, b: -1}, x: -1, time: ISODate('2020-02-01')},
|
||||
{meta: {a: +1, b: -1}, x: -1, time: ISODate('2019-12-31')},
|
||||
{meta: {a: +1, b: -1}, x: +1, time: ISODate('2020-02-01')},
|
||||
{meta: {a: +1, b: -1}, x: +1, time: ISODate('2019-12-31')},
|
||||
{mt: {a: +1, b: -1}, x: -1, time: ISODate('2020-02-01')},
|
||||
{mt: {a: +1, b: -1}, x: -1, time: ISODate('2019-12-31')},
|
||||
{mt: {a: +1, b: -1}, x: +1, time: ISODate('2020-02-01')},
|
||||
{mt: {a: +1, b: -1}, x: +1, time: ISODate('2019-12-31')},
|
||||
]);
|
||||
|
||||
// Test nested $and / $or where some leaf predicates cannot be pushed down.
|
||||
@ -211,72 +211,72 @@ checkAllBucketings({
|
||||
$or: [
|
||||
{
|
||||
$and: [
|
||||
{'meta.a': {$gt: 0}},
|
||||
{'mt.a': {$gt: 0}},
|
||||
{'x': {$exists: false}},
|
||||
]
|
||||
},
|
||||
{
|
||||
$and: [
|
||||
{'meta.b': {$gte: 0}},
|
||||
{'mt.b': {$gte: 0}},
|
||||
{time: {$gt: ISODate('2020-01-01')}},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
[
|
||||
{meta: {a: -1, b: -1}, time: ISODate('2020-02-01')},
|
||||
{meta: {a: -1, b: -1}, time: ISODate('2019-12-31')},
|
||||
{meta: {a: -1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
|
||||
{meta: {a: -1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
|
||||
{mt: {a: -1, b: -1}, time: ISODate('2020-02-01')},
|
||||
{mt: {a: -1, b: -1}, time: ISODate('2019-12-31')},
|
||||
{mt: {a: -1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
|
||||
{mt: {a: -1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
|
||||
|
||||
{meta: {a: +1, b: -1}, time: ISODate('2020-02-01')},
|
||||
{meta: {a: +1, b: -1}, time: ISODate('2019-12-31')},
|
||||
{meta: {a: +1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
|
||||
{meta: {a: +1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
|
||||
{mt: {a: +1, b: -1}, time: ISODate('2020-02-01')},
|
||||
{mt: {a: +1, b: -1}, time: ISODate('2019-12-31')},
|
||||
{mt: {a: +1, b: -1}, x: 'asdf', time: ISODate('2020-02-01')},
|
||||
{mt: {a: +1, b: -1}, x: 'asdf', time: ISODate('2019-12-31')},
|
||||
]);
|
||||
|
||||
// Test $exists on meta, inside $or.
|
||||
// Test $exists on mt, inside $or.
|
||||
checkAllBucketings({
|
||||
$or: [
|
||||
{"meta.a": {$exists: true}},
|
||||
{"mt.a": {$exists: true}},
|
||||
{"x": {$gt: 2}},
|
||||
]
|
||||
},
|
||||
[
|
||||
{meta: {a: 1}, x: 1},
|
||||
{meta: {a: 2}, x: 2},
|
||||
{meta: {a: 3}, x: 3},
|
||||
{meta: {a: 4}, x: 4},
|
||||
{meta: {}, x: 1},
|
||||
{meta: {}, x: 2},
|
||||
{meta: {}, x: 3},
|
||||
{meta: {}, x: 4},
|
||||
{mt: {a: 1}, x: 1},
|
||||
{mt: {a: 2}, x: 2},
|
||||
{mt: {a: 3}, x: 3},
|
||||
{mt: {a: 4}, x: 4},
|
||||
{mt: {}, x: 1},
|
||||
{mt: {}, x: 2},
|
||||
{mt: {}, x: 3},
|
||||
{mt: {}, x: 4},
|
||||
]);
|
||||
|
||||
// Test $in on meta, inside $or.
|
||||
// Test $in on mt, inside $or.
|
||||
checkAllBucketings({
|
||||
$or: [
|
||||
{"meta.a": {$in: [1, 3]}},
|
||||
{"mt.a": {$in: [1, 3]}},
|
||||
{"x": {$gt: 2}},
|
||||
]
|
||||
},
|
||||
[
|
||||
{meta: {a: 1}, x: 1},
|
||||
{meta: {a: 2}, x: 2},
|
||||
{meta: {a: 3}, x: 3},
|
||||
{meta: {a: 4}, x: 4},
|
||||
{meta: {}, x: 1},
|
||||
{meta: {}, x: 2},
|
||||
{meta: {}, x: 3},
|
||||
{meta: {}, x: 4},
|
||||
{mt: {a: 1}, x: 1},
|
||||
{mt: {a: 2}, x: 2},
|
||||
{mt: {a: 3}, x: 3},
|
||||
{mt: {a: 4}, x: 4},
|
||||
{mt: {}, x: 1},
|
||||
{mt: {}, x: 2},
|
||||
{mt: {}, x: 3},
|
||||
{mt: {}, x: 4},
|
||||
]);
|
||||
|
||||
// Test geo predicates on meta, inside $or.
|
||||
// Test geo predicates on mt, inside $or.
|
||||
for (const pred of ['$geoWithin', '$geoIntersects']) {
|
||||
checkAllBucketings({
|
||||
$or: [
|
||||
{
|
||||
"meta.location": {
|
||||
"mt.location": {
|
||||
[pred]: {
|
||||
$geometry: {
|
||||
type: "Polygon",
|
||||
@ -295,66 +295,90 @@ for (const pred of ['$geoWithin', '$geoIntersects']) {
|
||||
]
|
||||
},
|
||||
[
|
||||
{meta: {location: [1, 1]}, x: 1},
|
||||
{meta: {location: [1, 1]}, x: 2},
|
||||
{meta: {location: [1, 1]}, x: 3},
|
||||
{meta: {location: [1, 1]}, x: 4},
|
||||
{meta: {location: [5, 5]}, x: 1},
|
||||
{meta: {location: [5, 5]}, x: 2},
|
||||
{meta: {location: [5, 5]}, x: 3},
|
||||
{meta: {location: [5, 5]}, x: 4},
|
||||
{mt: {location: [1, 1]}, x: 1},
|
||||
{mt: {location: [1, 1]}, x: 2},
|
||||
{mt: {location: [1, 1]}, x: 3},
|
||||
{mt: {location: [1, 1]}, x: 4},
|
||||
{mt: {location: [5, 5]}, x: 1},
|
||||
{mt: {location: [5, 5]}, x: 2},
|
||||
{mt: {location: [5, 5]}, x: 3},
|
||||
{mt: {location: [5, 5]}, x: 4},
|
||||
]);
|
||||
}
|
||||
|
||||
// Test $mod on meta, inside $or.
|
||||
// Test $mod on mt, inside $or.
|
||||
// $mod is an example of a predicate that we don't handle specially in time-series optimizations:
|
||||
// it can be pushed down if and only if it's on a metadata field.
|
||||
checkAllBucketings({
|
||||
$or: [
|
||||
{"meta.a": {$mod: [2, 0]}},
|
||||
{"mt.a": {$mod: [2, 0]}},
|
||||
{"x": {$gt: 4}},
|
||||
]
|
||||
},
|
||||
[
|
||||
{meta: {a: 1}, x: 1},
|
||||
{meta: {a: 2}, x: 2},
|
||||
{meta: {a: 3}, x: 3},
|
||||
{meta: {a: 4}, x: 4},
|
||||
{meta: {a: 5}, x: 5},
|
||||
{meta: {a: 6}, x: 6},
|
||||
{meta: {a: 7}, x: 7},
|
||||
{meta: {a: 8}, x: 8},
|
||||
{mt: {a: 1}, x: 1},
|
||||
{mt: {a: 2}, x: 2},
|
||||
{mt: {a: 3}, x: 3},
|
||||
{mt: {a: 4}, x: 4},
|
||||
{mt: {a: 5}, x: 5},
|
||||
{mt: {a: 6}, x: 6},
|
||||
{mt: {a: 7}, x: 7},
|
||||
{mt: {a: 8}, x: 8},
|
||||
]);
|
||||
|
||||
// Test $elemMatch on meta, inside $or.
|
||||
// Test $elemMatch on mt, inside $or.
|
||||
checkAllBucketings({
|
||||
$or: [
|
||||
{"meta.a": {$elemMatch: {b: 3}}},
|
||||
{"mt.a": {$elemMatch: {b: 3}}},
|
||||
{"x": {$gt: 4}},
|
||||
]
|
||||
},
|
||||
[
|
||||
{x: 1, meta: {a: []}},
|
||||
{x: 2, meta: {a: [{b: 2}]}},
|
||||
{x: 3, meta: {a: [{b: 3}]}},
|
||||
{x: 4, meta: {a: [{b: 2}, {b: 3}]}},
|
||||
{x: 5, meta: {a: []}},
|
||||
{x: 6, meta: {a: [{b: 2}]}},
|
||||
{x: 7, meta: {a: [{b: 3}]}},
|
||||
{x: 8, meta: {a: [{b: 2}, {b: 3}]}},
|
||||
{x: 1, mt: {a: []}},
|
||||
{x: 2, mt: {a: [{b: 2}]}},
|
||||
{x: 3, mt: {a: [{b: 3}]}},
|
||||
{x: 4, mt: {a: [{b: 2}, {b: 3}]}},
|
||||
{x: 5, mt: {a: []}},
|
||||
{x: 6, mt: {a: [{b: 2}]}},
|
||||
{x: 7, mt: {a: [{b: 3}]}},
|
||||
{x: 8, mt: {a: [{b: 2}, {b: 3}]}},
|
||||
]);
|
||||
checkAllBucketings({
|
||||
$or: [
|
||||
{"meta.a": {$elemMatch: {b: 2, c: 3}}},
|
||||
{"mt.a": {$elemMatch: {b: 2, c: 3}}},
|
||||
{"x": {$gt: 3}},
|
||||
]
|
||||
},
|
||||
[
|
||||
{x: 1, meta: {a: []}},
|
||||
{x: 2, meta: {a: [{b: 2, c: 3}]}},
|
||||
{x: 3, meta: {a: [{b: 2}, {c: 3}]}},
|
||||
{x: 4, meta: {a: []}},
|
||||
{x: 5, meta: {a: [{b: 2, c: 3}]}},
|
||||
{x: 6, meta: {a: [{b: 2}, {c: 3}]}},
|
||||
{x: 1, mt: {a: []}},
|
||||
{x: 2, mt: {a: [{b: 2, c: 3}]}},
|
||||
{x: 3, mt: {a: [{b: 2}, {c: 3}]}},
|
||||
{x: 4, mt: {a: []}},
|
||||
{x: 5, mt: {a: [{b: 2, c: 3}]}},
|
||||
{x: 6, mt: {a: [{b: 2}, {c: 3}]}},
|
||||
]);
|
||||
|
||||
// Test a standalone $elemMatch on mt.
|
||||
checkAllBucketings({"mt.a": {$elemMatch: {b: 3}}}, [
|
||||
{mt: {a: []}},
|
||||
{mt: {a: [{b: 2}]}},
|
||||
{mt: {a: [{b: 3}]}},
|
||||
{mt: {a: [{b: 2}, {b: 3}]}},
|
||||
{mt: {a: []}},
|
||||
{mt: {a: [{b: 2}]}},
|
||||
{mt: {a: [{b: 3}]}},
|
||||
{mt: {a: [{b: 2}, {b: 3}]}},
|
||||
]);
|
||||
|
||||
// Test a standalone $size on mt.
|
||||
checkAllBucketings({"mt.a": {$size: 1}}, [
|
||||
{mt: {a: []}},
|
||||
{mt: {a: [{b: 2}]}},
|
||||
{mt: {a: [{b: 3}]}},
|
||||
{mt: {a: [{b: 2}, {b: 3}]}},
|
||||
{mt: {a: []}},
|
||||
{mt: {a: [{b: 2}]}},
|
||||
{mt: {a: [{b: 3}]}},
|
||||
{mt: {a: [{b: 2}, {b: 3}]}},
|
||||
]);
|
||||
})();
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
// requires_non_retryable_writes,
|
||||
// # TODO SERVER-30466
|
||||
// does_not_support_causal_consistency,
|
||||
// # Uses $where operator
|
||||
// requires_scripting,
|
||||
// ]
|
||||
|
||||
// Tests for the arrayFilters option to update and findAndModify.
|
||||
|
||||
@ -8,15 +8,21 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
load("jstests/libs/columnstore_util.js"); // For setUpServerForColumnStoreIndexTest.
|
||||
|
||||
let conn = MongoRunner.runMongod();
|
||||
|
||||
const dbpath = conn.dbpath;
|
||||
const dbName = jsTestName();
|
||||
const collName = 'coll';
|
||||
|
||||
const csiEnabled = setUpServerForColumnStoreIndexTest(conn.getDB(dbName));
|
||||
|
||||
const create = function(conn) {
|
||||
assert.commandWorked(conn.getDB(dbName).createCollection(collName));
|
||||
assert.commandWorked(conn.getDB(dbName)[collName].createIndex({'$**': "columnstore"}));
|
||||
if (csiEnabled) {
|
||||
assert.commandWorked(conn.getDB(dbName)[collName].createIndex({'$**': "columnstore"}));
|
||||
}
|
||||
};
|
||||
|
||||
const collUri = function(conn) {
|
||||
@ -55,14 +61,16 @@ const primary = replTest.getPrimary();
|
||||
// Run validate as a replica set, which will expect the tables to not be logged.
|
||||
let res = assert.commandWorked(primary.getDB(dbName).runCommand({validate: collName}));
|
||||
assert(!res.valid);
|
||||
assert.eq(res.errors.length, 3);
|
||||
assert.eq(res.errors.length, csiEnabled ? 3 : 2);
|
||||
checkLog.containsJson(primary, 6898101, {uri: collUri(primary), expected: false});
|
||||
checkLog.containsJson(
|
||||
primary, 6898101, {index: '_id_', uri: indexUri(primary, '_id_'), expected: false});
|
||||
checkLog.containsJson(
|
||||
primary,
|
||||
6898101,
|
||||
{index: '$**_columnstore', uri: indexUri(primary, '$**_columnstore'), expected: false});
|
||||
if (csiEnabled) {
|
||||
checkLog.containsJson(
|
||||
primary,
|
||||
6898101,
|
||||
{index: '$**_columnstore', uri: indexUri(primary, '$**_columnstore'), expected: false});
|
||||
}
|
||||
|
||||
// Create the collection and indexes as a replica set, which will cause the tables to not be logged.
|
||||
assert.commandWorked(primary.getDB(dbName).runCommand({drop: collName}));
|
||||
@ -74,13 +82,15 @@ conn = MongoRunner.runMongod(nodeOptions);
|
||||
// Run validate as a standalone, which will expect the tables to be logged.
|
||||
res = assert.commandWorked(conn.getDB(dbName).runCommand({validate: collName}));
|
||||
assert(!res.valid);
|
||||
assert.eq(res.errors.length, 3);
|
||||
assert.eq(res.errors.length, csiEnabled ? 3 : 2);
|
||||
checkLog.containsJson(conn, 6898101, {uri: collUri(conn), expected: true});
|
||||
checkLog.containsJson(conn, 6898101, {index: '_id_', uri: indexUri(conn, '_id_'), expected: true});
|
||||
checkLog.containsJson(
|
||||
conn,
|
||||
6898101,
|
||||
{index: '$**_columnstore', uri: indexUri(conn, '$**_columnstore'), expected: true});
|
||||
if (csiEnabled) {
|
||||
checkLog.containsJson(
|
||||
conn,
|
||||
6898101,
|
||||
{index: '$**_columnstore', uri: indexUri(conn, '$**_columnstore'), expected: true});
|
||||
}
|
||||
|
||||
MongoRunner.stopMongod(conn, null, {skipValidation: true});
|
||||
}());
|
||||
|
||||
@ -524,17 +524,36 @@ function assertStagesForExplainOfCommand({coll, cmdObj, expectedStages, stagesNo
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "planCacheKey" from the explain result.
|
||||
* Utility to obtain a value from 'explainRes' using 'getValueCallback'.
|
||||
*/
|
||||
function getFieldValueFromExplain(explainRes, getValueCallback) {
|
||||
assert(explainRes.hasOwnProperty("queryPlanner"), explainRes);
|
||||
const plannerOutput = explainRes.queryPlanner;
|
||||
const fieldValue = getValueCallback(plannerOutput);
|
||||
assert.eq(typeof fieldValue, "string");
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the 'planCacheKey' from 'explainRes'.
|
||||
*/
|
||||
function getPlanCacheKeyFromExplain(explainRes, db) {
|
||||
const hash = FixtureHelpers.isMongos(db) &&
|
||||
explainRes.queryPlanner.hasOwnProperty("winningPlan") &&
|
||||
explainRes.queryPlanner.winningPlan.hasOwnProperty("shards")
|
||||
? explainRes.queryPlanner.winningPlan.shards[0].planCacheKey
|
||||
: explainRes.queryPlanner.planCacheKey;
|
||||
assert.eq(typeof hash, "string");
|
||||
return getFieldValueFromExplain(explainRes, function(plannerOutput) {
|
||||
return FixtureHelpers.isMongos(db) && plannerOutput.hasOwnProperty("winningPlan") &&
|
||||
plannerOutput.winningPlan.hasOwnProperty("shards")
|
||||
? plannerOutput.winningPlan.shards[0].planCacheKey
|
||||
: plannerOutput.planCacheKey;
|
||||
});
|
||||
}
|
||||
|
||||
return hash;
|
||||
/**
|
||||
* Get the 'queryHash' from 'explainRes'.
|
||||
*/
|
||||
function getQueryHashFromExplain(explainRes, db) {
|
||||
return getFieldValueFromExplain(explainRes, function(plannerOutput) {
|
||||
return FixtureHelpers.isMongos(db) ? plannerOutput.winningPlan.shards[0].queryHash
|
||||
: plannerOutput.queryHash;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -87,12 +87,10 @@ var CheckShardFilteringMetadataHelpers = (function() {
|
||||
const configDB = mongosConn.getDB('config');
|
||||
|
||||
// Check shards know correct database versions.
|
||||
// Note: We can only check the dbVersion on the primary shards because non-primary shards
|
||||
// can have stale dbVersions cached (for versions on which they were not primary.). TODO:
|
||||
// Once shards became authoritative for their dbVersions, we can check all shards.
|
||||
configDB.databases.find({primary: shardId}).forEach(configDatabasesEntry => {
|
||||
checkDatabase(configDatabasesEntry);
|
||||
});
|
||||
// TODO: SERVER-73991 Reenable this check.
|
||||
// configDB.databases.find({primary: shardId}).forEach(configDatabasesEntry => {
|
||||
// checkDatabase(configDatabasesEntry);
|
||||
// });
|
||||
|
||||
// Check that shards have correct filtering metadata for sharded collections.
|
||||
if (!skipCheckShardedCollections) {
|
||||
|
||||
@ -58,7 +58,14 @@ function safeToCreateColumnStoreIndexInCluster(nodes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
const getParamFeatureFlagRes = assert.commandWorked(
|
||||
conn.adminCommand({getParameter: 1, featureFlagColumnstoreIndexes: 1}));
|
||||
if (!getParamFeatureFlagRes.featureFlagColumnstoreIndexes ||
|
||||
!getParamFeatureFlagRes.featureFlagColumnstoreIndexes["value"]) {
|
||||
jsTestLog("Note: declining to create column store index, because " +
|
||||
"featureFlagColumnstoreIndexes is disabled");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -81,9 +88,13 @@ function setUpServerForColumnStoreIndexTest(db) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parallel tests cannot set these server parameters during execution due to the side effect of
|
||||
// clearing the SBE plan cache, so the parallel test suite overrides this for us up front.
|
||||
if (!(TestData || {}).isParallelTest) {
|
||||
// TODO SERVER-75026: Re-enable CSI in parallel tests.
|
||||
// Note that we should not fully enable columnscans during the parallel tests due to the side
|
||||
// effect of clearing the SBE plan cache. Fully enabling column scans should only be done
|
||||
// in non-parallel environments.
|
||||
if ((TestData || {}).isParallelTest) {
|
||||
return false;
|
||||
} else {
|
||||
fullyEnableColumnScan(nodes);
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,13 @@ var FeatureFlagUtil = class {
|
||||
} catch (err) {
|
||||
// Some db-like objects (e.g. ShardingTest.shard0) aren't supported by FixtureHelpers,
|
||||
// but we can replace it with an object that should work and try again.
|
||||
setConn(db.getDB(db.defaultDB));
|
||||
if (typeof db.getDB === typeof Function) {
|
||||
setConn(db.getDB(db.defaultDB));
|
||||
} else {
|
||||
// Some db-like objects (e.g ShardedClusterFixture) have a getSiblingDB method
|
||||
// instead of getDB, use that here to avoid an undefined error.
|
||||
setConn(db.getSiblingDB(db.defaultDB));
|
||||
}
|
||||
}
|
||||
|
||||
if (user) {
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Verifies that the server ignores collection option "recordPreImages" on binary upgrade from the
|
||||
* last LTS version to the current, as well as removes the option from collection attributes on
|
||||
* FCV upgrade.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
load('jstests/multiVersion/libs/multi_rs.js');
|
||||
|
||||
const lastLTSVersion = "last-lts";
|
||||
const latestVersion = "latest";
|
||||
|
||||
// Setup a two-node replica set with last LTS binaries, so it is possible to create a collection
|
||||
// with "recordPreImages" option.
|
||||
const rst = new ReplSetTest(
|
||||
{name: jsTestName(), nodes: [{binVersion: lastLTSVersion}, {binVersion: lastLTSVersion}]});
|
||||
rst.startSet();
|
||||
rst.initiate();
|
||||
const testDB = rst.getPrimary().getDB("test");
|
||||
const primaryNode = rst.getPrimary();
|
||||
const secondaryNode = rst.getSecondary();
|
||||
|
||||
// Create the collection.
|
||||
const collectionName = "coll";
|
||||
assert.commandWorked(testDB.createCollection(collectionName, {recordPreImages: true}));
|
||||
let coll = testDB[collectionName];
|
||||
|
||||
// Insert a test document which will be updated to trigger recording of change stream pre-images.
|
||||
assert.commandWorked(coll.insert({_id: 1, a: 1}));
|
||||
assert.commandWorked(coll.updateOne({_id: 1}, {$inc: {a: 1}}));
|
||||
rst.awaitReplication();
|
||||
|
||||
// Upgrade the binary of the secondary node to the current version to setup a mixed binary cluster.
|
||||
rst.upgradeMembers([secondaryNode], {binVersion: latestVersion});
|
||||
|
||||
// Make sure the primary node did not change.
|
||||
rst.stepUp(primaryNode);
|
||||
|
||||
// Verify that recording of change stream pre-images succeeds.
|
||||
assert.commandWorked(coll.updateOne({_id: 1}, {$inc: {a: 1}}));
|
||||
rst.awaitReplication();
|
||||
|
||||
// Finally upgrade the binary of the primary node to the current version.
|
||||
rst.upgradePrimary(rst.getPrimary(), {binVersion: latestVersion});
|
||||
|
||||
// Update a document on the collection with inactive "recordPreImages" collection option.
|
||||
coll = rst.getPrimary().getDB("test")[collectionName];
|
||||
assert.commandWorked(coll.updateOne({_id: 1}, {$inc: {a: 1}}));
|
||||
rst.awaitReplication();
|
||||
|
||||
// Upgrade the FCV to the latest to trigger removal of "recordPreImages" collection option from
|
||||
// persistent catalog entries.
|
||||
assert.commandWorked(rst.getPrimary().adminCommand({setFeatureCompatibilityVersion: latestFCV}));
|
||||
|
||||
// To check the collection options, downgrade FCV to later replace the binary of the server with
|
||||
// the last LTS binary version.
|
||||
assert.commandWorked(rst.getPrimary().adminCommand({setFeatureCompatibilityVersion: lastLTSFCV}));
|
||||
rst.upgradeSet({binVersion: lastLTSVersion});
|
||||
|
||||
// Verify that collection option "recordPreImages" was removed.
|
||||
const result =
|
||||
assert.commandWorked(rst.getPrimary().getDB("test").runCommand({listCollections: 1}));
|
||||
assert.eq(result.cursor.firstBatch[0].name, collectionName);
|
||||
assert.docEq(
|
||||
{},
|
||||
result.cursor.firstBatch[0].options,
|
||||
`Collection option "recordPreImages" was not removed. Got response: ${tojson(result)}`);
|
||||
rst.stopSet();
|
||||
})();
|
||||
@ -2,7 +2,8 @@
|
||||
* Tests to ensure that COLUMN_SCAN plan and scanned columns appear in slow query log lines when
|
||||
* the columstore index is the winning plan.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
|
||||
@ -4,10 +4,11 @@
|
||||
* Indexes are validated by comparing query results that use the index with results from a control
|
||||
* query that uses a collection scan.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* # We could potentially need to resume an index build in the event of a stepdown, which is not
|
||||
* # yet implemented.
|
||||
* does_not_support_stepdowns,
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
|
||||
@ -4,9 +4,11 @@
|
||||
* as well as the createIndex response when a columnstore index is created.
|
||||
*
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* requires_persistence,
|
||||
* requires_replication,
|
||||
* # column store indexes are still under a feature flag and require full sbe
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* ]
|
||||
*/
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ const dbname = "foo";
|
||||
const isDirectoryPerDBSupported =
|
||||
jsTest.options().storageEngine == "wiredTiger" || !jsTest.options().storageEngine;
|
||||
|
||||
const m = MongoRunner.runMongod({dbpath: dbpath, directoryperdb: ''});
|
||||
const m = MongoRunner.runMongod({dbpath: dbpath, directoryperdb: '', syncdelay: 1});
|
||||
|
||||
if (!isDirectoryPerDBSupported) {
|
||||
assert.isnull(m, 'storage engine without directoryperdb support should fail to start up');
|
||||
|
||||
@ -30,12 +30,40 @@ assert.commandWorked(coll.createIndex({a: 1, b: 1}));
|
||||
// entry (thanks to the "skipUnindexingDocumentWhenDeleted" failpoint).
|
||||
function createDanglingIndexEntry(doc) {
|
||||
assert.commandWorked(coll.insert(doc));
|
||||
const docId = coll.findOne(doc)._id;
|
||||
assert.commandWorked(coll.remove(doc));
|
||||
|
||||
// Validation should now fail.
|
||||
const validateRes = assert.commandWorked(coll.validate());
|
||||
assert.eq(false, validateRes.valid);
|
||||
|
||||
// Server logs for failed validation command should contain oplog entries related to corrupted
|
||||
// index entry.
|
||||
let foundInsert = false;
|
||||
let foundDelete = false;
|
||||
// Look for log message "Oplog entry found for corrupted collection and index entry" (msg id
|
||||
// 7462402).
|
||||
checkLog.containsJson(db.getMongo(), 7464202, {
|
||||
oplogEntryDoc: (oplogDoc) => {
|
||||
let oplogDocId;
|
||||
try {
|
||||
oplogDocId = ObjectId(oplogDoc.o._id.$oid);
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
if (!oplogDocId.equals(docId)) {
|
||||
return false;
|
||||
}
|
||||
jsTestLog('Found oplog entry for corrupted index entry: ' + tojson(oplogDoc));
|
||||
if (oplogDoc.op === 'd') {
|
||||
foundDelete = true;
|
||||
} else if (oplogDoc.op === 'i') {
|
||||
foundInsert = true;
|
||||
}
|
||||
return foundDelete && foundInsert;
|
||||
}
|
||||
});
|
||||
|
||||
// A query that accesses the now dangling index entry should fail with a
|
||||
// "DataCorruptionDetected" error. Most reads will not detect this problem because they ignore
|
||||
// prepare conflicts by default and that exempts them from checking this assertion. Only writes
|
||||
|
||||
221
jstests/noPassthrough/read_ticket_exhaustion_with_stepdown.js
Normal file
221
jstests/noPassthrough/read_ticket_exhaustion_with_stepdown.js
Normal file
@ -0,0 +1,221 @@
|
||||
/**
|
||||
* Tests exhaustion of read tickets, trying to force a deadlock reproduction
|
||||
* after yield restores lock state. See SERVER-75205 for more information.
|
||||
*
|
||||
* Deadlock:
|
||||
* The deadlock in question involves readers acquiring the RSTL lock, which no longer
|
||||
* happens in 5.0+ due to lock-free reads. Therefore, this test doesn't exercise the
|
||||
* deadlock behavior on 5.0+. 4.4 is the primary target of this test, but there isn't
|
||||
* much test coverage of ticket exhaustion, so this test may provide other benefits on
|
||||
* 5.0+.
|
||||
*
|
||||
* Parallel Shell Coordination:
|
||||
* The 'jsTestName().timing_coordination' collection is used to coordinate timing
|
||||
* between the main thread of the test and all the readers via writes to specific
|
||||
* documents. One side will wait until the document appears.
|
||||
*
|
||||
* Two types of Parallel Shells:
|
||||
* There are two sets of readers - queued and new - meant to saturate the ticketing
|
||||
* system before and after the sleep operation that holds the global X lock. This
|
||||
* dual system of readers ensures that enqueued/blocked readers as well as newly
|
||||
* arriving reads are serviced without deadlocking.
|
||||
* queuedLongReadsFunc - Issues long read commands until told to stop.
|
||||
* newLongReadsFunc - When told to begin, issues long read commands until told
|
||||
* to stop.
|
||||
*
|
||||
* Test Steps:
|
||||
* 0) Start ReplSet with special params:
|
||||
* - lower read ticket concurrency
|
||||
* - increase yielding
|
||||
* 1) Insert 1000 documents.
|
||||
* 2) Kick off parallel readers that perform long collection scans, subject to yields.
|
||||
* 3) Sleep with global X Lock (including RSTL), thus queuing up reads.
|
||||
* 4) Signal new readers that will be received after the global lock is released.
|
||||
* 5) Initiate step down while queue is working its way down to ensure there is a mix of
|
||||
* enqueued readers from the global X lock and new readers initiated afterwards.
|
||||
* <<Should have deadlocked by now for this scenario>>
|
||||
* 6) Stop Readers.
|
||||
*
|
||||
* @tags: [
|
||||
* multiversion_incompatible,
|
||||
* requires_replication,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/parallel_shell_helpers.js");
|
||||
|
||||
const kNumReadTickets = 5;
|
||||
const replTest = new ReplSetTest({
|
||||
name: jsTestName(),
|
||||
nodes: 1,
|
||||
nodeOptions: {
|
||||
setParameter: {
|
||||
// This test seeks the minimum amount of concurrency to force ticket exhaustion.
|
||||
storageEngineConcurrencyAdjustmentAlgorithm: "",
|
||||
storageEngineConcurrentReadTransactions: kNumReadTickets,
|
||||
// Make yielding more common.
|
||||
internalQueryExecYieldPeriodMS: 1,
|
||||
internalQueryExecYieldIterations: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const dbName = jsTestName();
|
||||
const collName = "testcoll";
|
||||
let nQueuedReaders = 20;
|
||||
let nNewReaders = 10;
|
||||
TestData.dbName = dbName;
|
||||
TestData.collName = collName;
|
||||
|
||||
// Issues long read commands until told to stop.
|
||||
// Should be run in a parallel shell via startParallelShell() with a unique id.
|
||||
function queuedLongReadsFunc(id) {
|
||||
jsTestLog("Starting Queued Reader [" + id + "]");
|
||||
|
||||
try {
|
||||
for (let i = 0;
|
||||
db.getSiblingDB(TestData.dbName).timing_coordination.findOne({_id: "stop reading"}) ==
|
||||
null;
|
||||
i++) {
|
||||
jsTestLog("queuedLongReadsFunc on " + TestData.dbName + "." + TestData.collName +
|
||||
" read (" + i + ") beg. Reader id:" + id);
|
||||
try {
|
||||
db.getSiblingDB(TestData.dbName)[TestData.collName].aggregate([{"$count": "x"}]);
|
||||
} catch (e) {
|
||||
jsTestLog("ignoring failed read, possible due to stepdown", e);
|
||||
}
|
||||
jsTestLog("queuedLongReadsFunc read (" + i + ") end. Reader id:" + id);
|
||||
}
|
||||
} catch (e) {
|
||||
jsTestLog("Exiting reader [" + id + "] early due to:" + e);
|
||||
}
|
||||
jsTestLog("Queued Reader complete [" + id + "]");
|
||||
}
|
||||
|
||||
// When told to begin, issues long read commands until told to stop.
|
||||
// Should be run in a parallel shell via startParallelShell() with a unique id.
|
||||
function newLongReadsFunc(id) {
|
||||
jsTestLog("Starting New Reader [" + id + "]");
|
||||
|
||||
// Coordinate all readers to begin at the same time.
|
||||
assert.soon(() => db.getSiblingDB(TestData.dbName).timing_coordination.findOne({
|
||||
_id: "begin new readers"
|
||||
}) !== null,
|
||||
"Expected main test thread to insert a document.");
|
||||
|
||||
try {
|
||||
for (let i = 0;
|
||||
db.getSiblingDB(TestData.dbName).timing_coordination.findOne({_id: "stop reading"}) ==
|
||||
null;
|
||||
i++) {
|
||||
jsTestLog("newLongReadsFunc on " + TestData.dbName + "." + TestData.collName +
|
||||
" read (" + i + ") beg. Reader id:" + id);
|
||||
try {
|
||||
db.getSiblingDB(TestData.dbName)[TestData.collName].aggregate([{"$count": "x"}]);
|
||||
} catch (e) {
|
||||
jsTestLog("ignoring failed read, possible due to stepdown", e);
|
||||
}
|
||||
jsTestLog("newLongReadsFunc read (" + i + ") end. Reader id:" + id);
|
||||
}
|
||||
} catch (e) {
|
||||
jsTestLog("Exiting reader [" + id + "] early due to:" + e);
|
||||
}
|
||||
jsTestLog("New Reader complete [" + id + "]");
|
||||
}
|
||||
|
||||
function runStepDown() {
|
||||
jsTestLog("Making primary step down.");
|
||||
let stats = db.runCommand({serverStatus: 1});
|
||||
jsTestLog(stats.locks);
|
||||
jsTestLog(stats.wiredTiger.concurrentTransactions);
|
||||
const stepDownSecs = 5;
|
||||
assert.commandWorked(primaryAdmin.runCommand({"replSetStepDown": stepDownSecs, "force": true}));
|
||||
|
||||
// Wait until the primary transitioned to SECONDARY state.
|
||||
replTest.waitForState(primary, ReplSetTest.State.SECONDARY);
|
||||
|
||||
// Enforce the replSetStepDown timer.
|
||||
sleep(stepDownSecs * 1000);
|
||||
|
||||
replTest.waitForState(primary, ReplSetTest.State.PRIMARY);
|
||||
replTest.getPrimary();
|
||||
}
|
||||
|
||||
/****************************************************/
|
||||
|
||||
// 0) Start ReplSet with special params:
|
||||
// - lower read ticket concurrency
|
||||
// - increase yielding
|
||||
replTest.startSet();
|
||||
replTest.initiate();
|
||||
let primary = replTest.getPrimary();
|
||||
let db = primary.getDB(dbName);
|
||||
let primaryAdmin = primary.getDB("admin");
|
||||
let primaryColl = db[collName];
|
||||
let queuedReaders = [];
|
||||
let newReaders = [];
|
||||
|
||||
// 1) Insert 1000 documents.
|
||||
jsTestLog("Fill collection [" + dbName + "." + collName + "] with 1000 docs");
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
assert.commandWorked(primaryColl.insert({"x": i}));
|
||||
}
|
||||
jsTestLog("1000 inserts done");
|
||||
|
||||
// 2) Kick off parallel readers that perform long collection scans, subject to yields.
|
||||
for (let i = 0; i < nQueuedReaders; i++) {
|
||||
queuedReaders.push(startParallelShell(funWithArgs(queuedLongReadsFunc, i), primary.port));
|
||||
jsTestLog("queued reader " + queuedReaders.length + " initiated");
|
||||
}
|
||||
|
||||
for (let i = 0; i < newReaders; i++) {
|
||||
newReaders.push(startParallelShell(funWithArgs(newLongReadsFunc, i), primary.port));
|
||||
jsTestLog("new reader " + newReaders.length + " initiated");
|
||||
}
|
||||
|
||||
// 3) Sleep with global X Lock (including RSTL), thus queuing up reads.
|
||||
let ns = dbName + "." + collName;
|
||||
jsTestLog("Sleeping with Global X Lock on " + ns);
|
||||
db.adminCommand({
|
||||
sleep: 1,
|
||||
secs: 5,
|
||||
lock: "w", // MODE_X lock.
|
||||
$comment: "Global lock sleep"
|
||||
});
|
||||
jsTestLog("Done sleeping with Global X Lock on " + ns);
|
||||
|
||||
// 4) Signal new readers that will be received after the global lock is released.
|
||||
assert.commandWorked(
|
||||
db.getSiblingDB(dbName).timing_coordination.insertOne({_id: "begin new readers"}));
|
||||
|
||||
// 5) Initiate step down while queue is working its way down to ensure there is a mix of
|
||||
// enqueued readers from the global X lock and new readers initiated afterwards.
|
||||
assert.soon(
|
||||
() => db.getSiblingDB("admin")
|
||||
.aggregate([{$currentOp: {}}, {$match: {"command.aggregate": TestData.collName}}])
|
||||
.toArray()
|
||||
.length >= kNumReadTickets,
|
||||
"Expected more readers than read tickets.");
|
||||
runStepDown();
|
||||
|
||||
// 6) Stop Readers.
|
||||
jsTestLog("Stopping Readers");
|
||||
assert.commandWorked(db.getSiblingDB(dbName).timing_coordination.insertOne({_id: "stop reading"}));
|
||||
|
||||
for (let i = 0; i < queuedReaders.length; i++) {
|
||||
const awaitQueuedReader = queuedReaders[i];
|
||||
awaitQueuedReader();
|
||||
jsTestLog("queued reader " + i + " done");
|
||||
}
|
||||
for (let i = 0; i < newReaders.length; i++) {
|
||||
const awaitNewReader = newReaders[i];
|
||||
awaitNewReader();
|
||||
jsTestLog("new reader " + i + " done");
|
||||
}
|
||||
queuedReaders = [];
|
||||
newReaders = [];
|
||||
|
||||
replTest.stopSet();
|
||||
})();
|
||||
145
jstests/noPassthrough/sbe_plan_cache_api_version.js
Normal file
145
jstests/noPassthrough/sbe_plan_cache_api_version.js
Normal file
@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Validates the behaviour of the the SBE plan cache when the API version was provided to the
|
||||
* aggregate command.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/analyze_plan.js");
|
||||
load("jstests/libs/sbe_util.js");
|
||||
|
||||
const conn = MongoRunner.runMongod({});
|
||||
assert.neq(conn, null, "mongod failed to start");
|
||||
const db = conn.getDB("plan_cache_api_version");
|
||||
const coll = db.coll;
|
||||
coll.drop();
|
||||
|
||||
const isSBEEnabled = checkSBEEnabled(db);
|
||||
|
||||
assert.commandWorked(coll.insert([{a: 1, b: 1}, {a: 2, b: 2}]));
|
||||
|
||||
// Runs the given pipeline with the specified options and returns its plan cache key.
|
||||
function runPipeline(pipeline, options, explainOptions = {}) {
|
||||
const command = Object.assign({aggregate: coll.getName(), pipeline, cursor: {}}, options);
|
||||
const result = coll.runCommand(command);
|
||||
assert.commandWorked(result);
|
||||
assert.eq(result.cursor.firstBatch.length, 1, result.cursor.firstBatch);
|
||||
|
||||
const explain = coll.runCommand(Object.assign({explain: command}, explainOptions));
|
||||
assert.commandWorked(explain);
|
||||
assert.neq(explain, null);
|
||||
assert.eq(explain.explainVersion, isSBEEnabled ? "2" : "1", explain);
|
||||
assert.neq(explain.queryPlanner.planCacheKey, null, explain);
|
||||
return explain.queryPlanner.planCacheKey;
|
||||
}
|
||||
|
||||
// Runs the given 'pipeline' with the API version and returns its plan cache key.
|
||||
function runPipelineWithApiVersion(pipeline) {
|
||||
const options = {apiVersion: '1'};
|
||||
return runPipeline(pipeline, options, options);
|
||||
}
|
||||
|
||||
// Runs the given 'pipeline' with the API version and 'apiStrict: true' and returns its plan cache
|
||||
// key.
|
||||
function runPipelineWithApiStrict(pipeline) {
|
||||
const options = {apiVersion: '1', apiStrict: true};
|
||||
return runPipeline(pipeline, options, options);
|
||||
}
|
||||
|
||||
// Asserts that a plan cache entry for the given 'cacheKey' exists in the plan cache and has
|
||||
// certain properties set as per provided 'properties' argument.
|
||||
function assertPlanCacheEntryExists(cacheKey, properties = {}) {
|
||||
const entries =
|
||||
coll.aggregate([{$planCacheStats: {}}, {$match: {planCacheKey: cacheKey}}]).toArray();
|
||||
assert.eq(entries.length, 1, entries);
|
||||
const entry = entries[0];
|
||||
|
||||
if (isSBEEnabled) {
|
||||
// The version:"2" field indicates that this is an SBE plan cache entry.
|
||||
assert.eq(entry.version, "2", entry);
|
||||
assert.eq(entry.isActive, properties.isActive, entry);
|
||||
assert.eq(entry.isPinned, properties.isPinned, entry);
|
||||
} else {
|
||||
// The version:"1" field indicates that this is an classic plan cache entry.
|
||||
assert.eq(entry.version, "1", entry);
|
||||
assert.eq(entry.isActive, properties.isActive, entry);
|
||||
}
|
||||
}
|
||||
|
||||
const pipeline = [{$match: {a: 1, b: 1}}];
|
||||
|
||||
// Run a set of testcases where each testcase defines a set of indexes on the collection and
|
||||
// executes the above pipeline with and without the API strict flag. Assert that the plan cache
|
||||
// keys for each of the two queries are different and two different plan cache entries have been
|
||||
// created.
|
||||
|
||||
const sbeEngineTestcases = [
|
||||
{
|
||||
withApiVersion: {isActive: true, isPinned: true},
|
||||
withApiStrict: {isActive: true, isPinned: true},
|
||||
indexSpecs: []
|
||||
},
|
||||
{
|
||||
withApiVersion: {isActive: true, isPinned: true},
|
||||
withApiStrict: {isActive: true, isPinned: true},
|
||||
indexSpecs: [{keyPattern: {a: 1}, options: {name: "a_1"}}]
|
||||
},
|
||||
{
|
||||
withApiVersion: {isActive: false, isPinned: false},
|
||||
withApiStrict: {isActive: true, isPinned: true},
|
||||
indexSpecs: [
|
||||
{keyPattern: {a: 1}, options: {name: "a_1"}},
|
||||
{keyPattern: {a: 1}, options: {name: "a_1_sparse", sparse: true}}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const classicEngineTestcases = [
|
||||
{
|
||||
withApiVersion: {isActive: false},
|
||||
withApiStrict: {isActive: false},
|
||||
indexSpecs: [
|
||||
{keyPattern: {a: 1}, options: {name: "a_1"}},
|
||||
{keyPattern: {b: 1}, options: {name: "b_1"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
withApiVersion: {isActive: false},
|
||||
withApiStrict: {isActive: false},
|
||||
indexSpecs: [
|
||||
{keyPattern: {a: 1}, options: {name: "a_1"}},
|
||||
{keyPattern: {a: 1}, options: {name: "a_1_sparse", sparse: true}},
|
||||
{keyPattern: {b: 1}, options: {name: "b_1"}}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const testcases = isSBEEnabled ? sbeEngineTestcases : classicEngineTestcases;
|
||||
for (const testcase of testcases) {
|
||||
[true, false].forEach((runWithApiStrictFirst) => {
|
||||
assert.commandWorked(coll.dropIndexes());
|
||||
|
||||
for (const indexSpec of testcase.indexSpecs) {
|
||||
assert.commandWorked(coll.createIndex(indexSpec.keyPattern, indexSpec.options));
|
||||
}
|
||||
|
||||
let planCacheKeyWithApiVersion;
|
||||
let planCacheKeyWithApiStrict;
|
||||
|
||||
if (runWithApiStrictFirst) {
|
||||
planCacheKeyWithApiStrict = runPipelineWithApiStrict(pipeline);
|
||||
planCacheKeyWithApiVersion = runPipelineWithApiVersion(pipeline);
|
||||
} else {
|
||||
planCacheKeyWithApiVersion = runPipelineWithApiVersion(pipeline);
|
||||
planCacheKeyWithApiStrict = runPipelineWithApiStrict(pipeline);
|
||||
}
|
||||
|
||||
assert.neq(planCacheKeyWithApiVersion, planCacheKeyWithApiStrict);
|
||||
assertPlanCacheEntryExists(planCacheKeyWithApiVersion, testcase.withApiVersion);
|
||||
assertPlanCacheEntryExists(planCacheKeyWithApiStrict, testcase.withApiStrict);
|
||||
});
|
||||
}
|
||||
|
||||
MongoRunner.stopMongod(conn);
|
||||
}());
|
||||
@ -16,8 +16,8 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
|
||||
load('jstests/libs/fixture_helpers.js'); // For FixtureHelpers.
|
||||
load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled()'.
|
||||
load("jstests/libs/analyze_plan.js"); // For 'getQueryHashFromExplain()'.
|
||||
|
||||
const conn = MongoRunner.runMongod();
|
||||
assert.neq(conn, null, "mongod failed to start");
|
||||
@ -33,14 +33,6 @@ function getCacheEntriesByQueryHashKey(coll, queryHash) {
|
||||
return coll.aggregate([{$planCacheStats: {}}, {$match: {queryHash}}]).toArray();
|
||||
}
|
||||
|
||||
function getQueryHashFromExplain(explainRes) {
|
||||
const hash = FixtureHelpers.isMongos(db)
|
||||
? explainRes.queryPlanner.winningPlan.shards[0].queryHash
|
||||
: explainRes.queryPlanner.queryHash;
|
||||
assert.eq(typeof (hash), "string");
|
||||
return hash;
|
||||
}
|
||||
|
||||
function getPlanCacheSize() {
|
||||
return db.serverStatus().metrics.query.planCacheTotalSizeEstimateBytes;
|
||||
}
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/columnstore_util.js"); // For setUpServerForColumnStoreIndexTest.
|
||||
|
||||
const st = new ShardingTest({shards: 3, rs: {nodes: 1}});
|
||||
const dbName = "test";
|
||||
const collName = "user";
|
||||
@ -48,24 +50,30 @@ for (const catEntry of shardCatalogs) {
|
||||
assert.eq(catEntry.wildcardProjection, kProjectionDoc, shardCatalogs);
|
||||
}
|
||||
|
||||
// Creates a columnstore index with a columnstoreProjection that normalization would change and
|
||||
// verifies the persisted projection doc on each shard matches the original, unnormalized version.
|
||||
const kColumnstoreIndexName = "cs_index";
|
||||
st.s.getCollection(ns).createIndex(
|
||||
{"$**": "columnstore"}, {name: kColumnstoreIndexName, columnstoreProjection: kProjectionDoc});
|
||||
shardCatalogs =
|
||||
st.s.getCollection(ns)
|
||||
.aggregate([
|
||||
{$listCatalog: {}},
|
||||
{$unwind: "$md.indexes"},
|
||||
{$match: {"md.indexes.spec.name": kColumnstoreIndexName}},
|
||||
{$project: {shard: 1, columnstoreProjection: "$md.indexes.spec.columnstoreProjection"}}
|
||||
])
|
||||
.toArray();
|
||||
assert.eq(shardCatalogs.length, 3, shardCatalogs);
|
||||
for (const catEntry of shardCatalogs) {
|
||||
assert.eq(catEntry.columnstoreProjection, kProjectionDoc, shardCatalogs);
|
||||
if (setUpServerForColumnStoreIndexTest(st.s.getDB(dbName))) {
|
||||
// Creates a columnstore index with a columnstoreProjection that normalization would change
|
||||
// and verifies the persisted projection doc on each shard matches the original,
|
||||
// unnormalized version.
|
||||
const kColumnstoreIndexName = "cs_index";
|
||||
st.s.getCollection(ns).createIndex(
|
||||
{"$**": "columnstore"},
|
||||
{name: kColumnstoreIndexName, columnstoreProjection: kProjectionDoc});
|
||||
shardCatalogs =
|
||||
st.s.getCollection(ns)
|
||||
.aggregate([
|
||||
{$listCatalog: {}},
|
||||
{$unwind: "$md.indexes"},
|
||||
{$match: {"md.indexes.spec.name": kColumnstoreIndexName}},
|
||||
{
|
||||
$project:
|
||||
{shard: 1, columnstoreProjection: "$md.indexes.spec.columnstoreProjection"}
|
||||
}
|
||||
])
|
||||
.toArray();
|
||||
assert.eq(shardCatalogs.length, 3, shardCatalogs);
|
||||
for (const catEntry of shardCatalogs) {
|
||||
assert.eq(catEntry.columnstoreProjection, kProjectionDoc, shardCatalogs);
|
||||
}
|
||||
}
|
||||
|
||||
st.stop();
|
||||
})();
|
||||
|
||||
@ -36,6 +36,11 @@ function useBucketingParametersOnLowerFCV() {
|
||||
}
|
||||
}));
|
||||
|
||||
// On the latestFCV, we should not be able to use collMod with incomplete bucketing parameters.
|
||||
assert.commandFailedWithCode(
|
||||
db.runCommand({collMod: collName, timeseries: {bucketMaxSpanSeconds: 3600}}),
|
||||
ErrorCodes.InvalidOptions);
|
||||
|
||||
// We should fail to downgrade if we have a collection with custom bucketing parameters set.
|
||||
assert.commandFailedWithCode(db.adminCommand({setFeatureCompatibilityVersion: lastLTSFCV}),
|
||||
ErrorCodes.CannotDowngrade);
|
||||
@ -66,6 +71,23 @@ function useBucketingParametersOnLowerFCV() {
|
||||
timeseries: {bucketMaxSpanSeconds: 3600, bucketRoundingSeconds: 3600}
|
||||
}),
|
||||
ErrorCodes.InvalidOptions);
|
||||
assert.commandFailedWithCode(
|
||||
db.runCommand({collMod: collName, timeseries: {bucketMaxSpanSeconds: 3600}}),
|
||||
ErrorCodes.InvalidOptions);
|
||||
assert.commandFailedWithCode(
|
||||
db.runCommand({collMod: collName, timeseries: {bucketRoundingSeconds: 3600}}),
|
||||
ErrorCodes.InvalidOptions);
|
||||
|
||||
// Verify the time-series options are valid.
|
||||
let collections = assert.commandWorked(db.runCommand({listCollections: 1})).cursor.firstBatch;
|
||||
let collectionEntry = collections.find(entry => entry.name === 'system.buckets.' + collName);
|
||||
assert(collectionEntry);
|
||||
|
||||
assert.eq(collectionEntry.options.timeseries.granularity, "seconds");
|
||||
// Downgrading does not remove the 'bucketMaxSpanSeconds' parameter. It should correspond with
|
||||
// the "seconds" granularity.
|
||||
assert.eq(collectionEntry.options.timeseries.bucketMaxSpanSeconds, 3600);
|
||||
assert.isnull(collectionEntry.options.timeseries.bucketRoundingSeconds);
|
||||
}
|
||||
|
||||
useBucketingParametersOnLowerFCV();
|
||||
|
||||
@ -72,13 +72,18 @@ function runTest(conn) {
|
||||
"The time reported sending a response didn't include the sleep in the failpoint.");
|
||||
}
|
||||
|
||||
// Test standalone.
|
||||
const m = MongoRunner.runMongod();
|
||||
runTest(m);
|
||||
MongoRunner.stopMongod(m);
|
||||
// TODO(SERVER-63883): re-enable or delete this test depending on resolution
|
||||
const testEnabled = false;
|
||||
|
||||
// Test sharded.
|
||||
const st = new ShardingTest({shards: 1, mongos: 1});
|
||||
runTest(st.s0);
|
||||
st.stop();
|
||||
if (testEnabled) {
|
||||
// Test standalone.
|
||||
const m = MongoRunner.runMongod();
|
||||
runTest(m);
|
||||
MongoRunner.stopMongod(m);
|
||||
|
||||
// Test sharded.
|
||||
const st = new ShardingTest({shards: 1, mongos: 1});
|
||||
runTest(st.s0);
|
||||
st.stop();
|
||||
}
|
||||
})();
|
||||
|
||||
@ -29,6 +29,9 @@ fp.off();
|
||||
let validateRes = assert.commandWorked(db.runCommand({validate: collName}));
|
||||
assert(!validateRes.valid);
|
||||
|
||||
// Ensure that $collStats info gets logged when validation fails.
|
||||
checkLog.containsJson(conn, 7463200);
|
||||
|
||||
// Forces a checkpoint to make the background validation see the data.
|
||||
assert.commandWorked(db.adminCommand({fsync: 1}));
|
||||
validateRes = assert.commandWorked(db.runCommand({validate: collName, background: true}));
|
||||
|
||||
@ -37,6 +37,11 @@ function checkValidate(maxMemoryUsage, {minMissingKeys, maxMissingKeys}) {
|
||||
assert.lte(res.missingIndexEntries.length, maxMissingKeys, tojson(res));
|
||||
}
|
||||
|
||||
function checkValidateLogs() {
|
||||
assert(checkLog.checkContainsWithAtLeastCountJson(
|
||||
conn, 7463100, {"spec": {"v": 2, "key": {"_id": 1}, "name": "_id_"}}, 1));
|
||||
}
|
||||
|
||||
function checkValidateRepair() {
|
||||
const res = coll.validate({repair: true});
|
||||
assert.commandWorked(res);
|
||||
@ -50,6 +55,7 @@ const indexKey = "a".repeat(kIndexKeyLength);
|
||||
assert.commandWorked(coll.insert({_id: indexKey}));
|
||||
corruptIndex();
|
||||
checkValidate(1, {minMissingKeys: 1, maxMissingKeys: 1});
|
||||
checkValidateLogs();
|
||||
|
||||
// Can't repair successfully if there aren't any index inconsistencies reported.
|
||||
checkValidateRepair();
|
||||
@ -69,6 +75,7 @@ corruptIndex();
|
||||
// each key is counted twice, so realistically we only expect to track 2 of them. However, there's
|
||||
// a small chance we could get hash collisions that would lead to us reporting only 1.
|
||||
checkValidate(1, {minMissingKeys: 1, maxMissingKeys: 2});
|
||||
checkValidateLogs();
|
||||
|
||||
// Repair, but incompletely if only some inconsistencies are reported.
|
||||
checkValidateRepair();
|
||||
|
||||
113
jstests/noPassthrough/validate_timeseries_bucket_reopening.js
Normal file
113
jstests/noPassthrough/validate_timeseries_bucket_reopening.js
Normal file
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Validate the state of time-series collections after inserting measurements into reopened buckets.
|
||||
*
|
||||
* We set the 'timeseriesIdleBucketExpiryMemoryUsageThreshold' to a low value and configure the
|
||||
* 'alwaysUseSameBucketCatalogStripe' failpoint to expedite bucket closures and increase the number
|
||||
* of buckets we reopen to insert into.
|
||||
*
|
||||
* @tags: [requires_replication]
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/core/timeseries/libs/timeseries.js"); // For 'TimeseriesTest'.
|
||||
load("jstests/libs/fail_point_util.js");
|
||||
|
||||
const rst = new ReplSetTest({nodes: 1});
|
||||
rst.startSet({setParameter: {timeseriesIdleBucketExpiryMemoryUsageThreshold: 1024}});
|
||||
rst.initiate();
|
||||
|
||||
const db = rst.getPrimary().getDB(jsTestName());
|
||||
assert.commandWorked(db.dropDatabase());
|
||||
|
||||
if (!TimeseriesTest.timeseriesScalabilityImprovementsEnabled(db)) {
|
||||
rst.stopSet();
|
||||
jsTestLog(
|
||||
'Skipping test because the TimeseriesScalabilityImprovements feature flag is disabled.');
|
||||
return;
|
||||
}
|
||||
|
||||
const collNamePrefix = db.validate_timeseries_bucket_reopening_;
|
||||
const timeFieldName = 'time';
|
||||
const metaFieldName1 = 'meta';
|
||||
const metaFieldName2 = 'tag';
|
||||
const valueFieldName = 'value';
|
||||
let testCaseId = 0;
|
||||
|
||||
const validateBucketReopening = function(metaFieldName = null) {
|
||||
// Create collection with metaField passed in.
|
||||
let timeseriesOptions = {timeField: timeFieldName};
|
||||
if (metaFieldName != null) {
|
||||
timeseriesOptions = Object.merge(timeseriesOptions, {metaField: metaFieldName});
|
||||
}
|
||||
jsTestLog("Running validateBucketReopening() with timeseriesOptions = " +
|
||||
tojson(timeseriesOptions));
|
||||
|
||||
const coll = db.getCollection(collNamePrefix + testCaseId++);
|
||||
const bucketsColl = db.getCollection('system.buckets.' + coll.getName());
|
||||
coll.drop();
|
||||
assert.commandWorked(db.createCollection(coll.getName(), {timeseries: timeseriesOptions}));
|
||||
assert.contains(bucketsColl.getName(), db.getCollectionNames());
|
||||
|
||||
// Insert documents with varying metaField values (if the 'metaFieldName' is specified).
|
||||
const distinctMetaValues = 10;
|
||||
const numOfPasses = 100;
|
||||
for (let i = 0; i < numOfPasses; ++i) {
|
||||
for (let j = 0; j < distinctMetaValues; ++j) {
|
||||
if (metaFieldName != null) {
|
||||
assert.commandWorked(coll.insert(
|
||||
{[timeFieldName]: ISODate(), [metaFieldName]: j, [valueFieldName]: "a"}));
|
||||
} else {
|
||||
assert.commandWorked(
|
||||
coll.insert({[timeFieldName]: ISODate(), [valueFieldName]: "a"}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify we inserted measurements into reopened buckets through the time-series stats.
|
||||
const stats = assert.commandWorked(coll.stats());
|
||||
assert(stats.timeseries);
|
||||
if (metaFieldName != null) {
|
||||
// The idea of this test is to insert measurements into reopened buckets so we are looking
|
||||
// to reopen more buckets than we create.
|
||||
assert.lt(stats.timeseries['bucketCount'],
|
||||
stats.timeseries['numBucketsReopened'],
|
||||
"Timeseries stats: " + tojson(stats));
|
||||
assert.lt(stats.timeseries['numBucketsOpenedDueToMetadata'],
|
||||
stats.timeseries['numBucketsReopened'],
|
||||
"Timeseries stats: " + tojson(stats));
|
||||
|
||||
// The number of bucket inserts should be less than the number of bucket updates.
|
||||
assert.lt(stats.timeseries['numBucketInserts'],
|
||||
stats.timeseries['numBucketUpdates'],
|
||||
"Timeseries stats: " + tojson(stats));
|
||||
} else {
|
||||
// When no metaField is specified, all measurements fit in one bucket since there is no need
|
||||
// to close buckets due to metadata.
|
||||
assert.eq(stats.timeseries['bucketCount'], 1, "Timeseries stats: " + tojson(stats));
|
||||
}
|
||||
|
||||
// Finally, validate the collection and ensure there are no inconsistencies.
|
||||
const res = assert.commandWorked(coll.validate());
|
||||
assert.eq(res.valid, true);
|
||||
assert.eq(res.nNonCompliantDocuments, 0);
|
||||
assert.eq(res.nInvalidDocuments, 0);
|
||||
assert.eq(res.errors.length, 0);
|
||||
assert.eq(res.warnings.length, 0);
|
||||
};
|
||||
|
||||
// Activate failpoint to place all buckets in the same stripe in the BucketCatalog.
|
||||
let fpSameStripe = configureFailPoint(db, "alwaysUseSameBucketCatalogStripe");
|
||||
|
||||
// Validate results with no metaField.
|
||||
validateBucketReopening();
|
||||
|
||||
// Validate results with metaField == 'meta'.
|
||||
validateBucketReopening(metaFieldName1);
|
||||
|
||||
// Validate results with metaField == 'tag'.
|
||||
validateBucketReopening(metaFieldName2);
|
||||
|
||||
fpSameStripe.off();
|
||||
rst.stopSet();
|
||||
})();
|
||||
@ -1,7 +1,9 @@
|
||||
/**
|
||||
* Tests the explain support for the COLUMN_SCAN stage.
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* # Column store indexes are still under a feature flag and require full sbe.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
* Testing of the query planner heuristics for determining whether a collection is eligible for
|
||||
* column scan.
|
||||
* @tags: [
|
||||
* # column store indexes are still under a feature flag
|
||||
* featureFlagColumnstoreIndexes
|
||||
* # Column store indexes are still under a feature flag and require full sbe.
|
||||
* featureFlagColumnstoreIndexes,
|
||||
* featureFlagSbeFull,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
|
||||
load("jstests/libs/sbe_assert_error_override.js"); // Override error-code-checking APIs.
|
||||
|
||||
const coll = db[jsTest.name()];
|
||||
@ -39,22 +40,37 @@ assert.commandWorked(db.createView(
|
||||
const viewWithClusterTime = db["viewWithClusterTime"];
|
||||
|
||||
function runTests(query) {
|
||||
const results = query().toArray();
|
||||
assert.eq(results.length, numdocs);
|
||||
const runAndCompare = function() {
|
||||
const results = query().toArray();
|
||||
assert.eq(results.length, numdocs);
|
||||
|
||||
// Make sure the values are the same for all documents
|
||||
for (let i = 0; i < numdocs; ++i) {
|
||||
assert.eq(results[0].timeField, results[i].timeField);
|
||||
}
|
||||
// Make sure the values are the same for all documents
|
||||
for (let i = 0; i < numdocs; ++i) {
|
||||
assert.eq(results[0].timeField, results[i].timeField);
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
const results = runAndCompare();
|
||||
|
||||
// Sleep for a while and then rerun.
|
||||
sleep(3000);
|
||||
|
||||
const resultsLater = query().toArray();
|
||||
assert.eq(resultsLater.length, numdocs);
|
||||
const resultsLater = runAndCompare();
|
||||
|
||||
// Later results should be later in time.
|
||||
assert.lte(results[0].timeField, resultsLater[0].timeField);
|
||||
assert.lt(results[0].timeField, resultsLater[0].timeField);
|
||||
|
||||
// Sleep for a while and then run for the third time.
|
||||
//
|
||||
// Test when the query is cached (it can take two executions of a query for a plan to get
|
||||
// cached).
|
||||
sleep(3000);
|
||||
|
||||
const resultsLast = runAndCompare();
|
||||
|
||||
// 'resultsLast' should be later in time than 'resultsLater'.
|
||||
assert.lt(resultsLater[0].timeField, resultsLast[0].timeField);
|
||||
}
|
||||
|
||||
function runTestsExpectFailure(query) {
|
||||
@ -64,7 +80,7 @@ function runTestsExpectFailure(query) {
|
||||
}
|
||||
|
||||
function baseCollectionNowFind() {
|
||||
return otherColl.find({$expr: {$lte: ["$timeField", "$$NOW"]}});
|
||||
return otherColl.find({$expr: {$lt: ["$timeField", "$$NOW"]}});
|
||||
}
|
||||
|
||||
function baseCollectionClusterTimeFind() {
|
||||
@ -98,6 +114,18 @@ function withExprNow() {
|
||||
return viewWithNow.find({$expr: {$eq: ["$timeField", "$$NOW"]}});
|
||||
}
|
||||
|
||||
function projWithNow() {
|
||||
return coll.find({}, {timeField: "$$NOW"});
|
||||
}
|
||||
|
||||
function aggWithNow() {
|
||||
return coll.aggregate([{$project: {timeField: "$$NOW"}}]);
|
||||
}
|
||||
|
||||
function aggWithNowNotPushedDown() {
|
||||
return coll.aggregate([{$_internalInhibitOptimization: {}}, {$project: {timeField: "$$NOW"}}]);
|
||||
}
|
||||
|
||||
function withExprClusterTime() {
|
||||
return db.runCommand({
|
||||
find: viewWithClusterTime.getName(),
|
||||
@ -106,10 +134,16 @@ function withExprClusterTime() {
|
||||
}
|
||||
|
||||
// Test that $$NOW is usable in all contexts.
|
||||
runTests(baseCollectionNowFind);
|
||||
runTests(baseCollectionNowAgg);
|
||||
//
|
||||
// $$NOW used at insertion time, it is expected values are not changed.
|
||||
assert.eq(baseCollectionNowFind().toArray().length, numdocs);
|
||||
// $$NOW used in the query, it is expected to update its time value for different runs.
|
||||
runTests(fromViewWithNow);
|
||||
runTests(withExprNow);
|
||||
runTests(baseCollectionNowAgg);
|
||||
runTests(projWithNow);
|
||||
runTests(aggWithNow);
|
||||
runTests(aggWithNowNotPushedDown);
|
||||
|
||||
// Test that $$NOW can be used in explain for both find and aggregate.
|
||||
assert.commandWorked(coll.explain().find({$expr: {$lte: ["$timeField", "$$NOW"]}}).finish());
|
||||
@ -121,4 +155,43 @@ runTestsExpectFailure(baseCollectionClusterTimeFind);
|
||||
runTestsExpectFailure(baseCollectionClusterTimeAgg);
|
||||
runTestsExpectFailure(fromViewWithClusterTime);
|
||||
runTestsExpectFailure(withExprClusterTime);
|
||||
|
||||
if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
|
||||
function verifyPlanCacheSize(query) {
|
||||
coll.getPlanCache().clear();
|
||||
|
||||
query().toArray();
|
||||
// It can take two executions of a query for a plan to get cached.
|
||||
query().toArray();
|
||||
|
||||
const caches = coll.getPlanCache().list();
|
||||
assert.eq(caches.length, 1, caches);
|
||||
assert.eq(caches[0].cachedPlan.stages.includes("Date"), false, caches);
|
||||
}
|
||||
|
||||
// Query with $$NOW will be cached.
|
||||
verifyPlanCacheSize(projWithNow);
|
||||
verifyPlanCacheSize(aggWithNow);
|
||||
// $$NOW is not in SBE query.
|
||||
verifyPlanCacheSize(fromViewWithNow);
|
||||
verifyPlanCacheSize(withExprNow);
|
||||
// $$NOW could not be pushed down into SBE.
|
||||
verifyPlanCacheSize(baseCollectionNowAgg);
|
||||
verifyPlanCacheSize(aggWithNowNotPushedDown);
|
||||
}
|
||||
|
||||
// Insert an doc with a future time.
|
||||
const futureColl = db[coll.getName() + "_future"];
|
||||
futureColl.drop();
|
||||
const time = new Date();
|
||||
time.setSeconds(time.getSeconds() + 3);
|
||||
assert.commandWorked(futureColl.insert({timeField: time}));
|
||||
|
||||
// The 'timeField' value is later than '$$NOW' in '$expr'.
|
||||
assert.eq(0, futureColl.find({$expr: {$lt: ["$timeField", "$$NOW"]}}).itcount());
|
||||
// The '$$NOW' in '$expr' should advance its value after sleeping for 3 second, the 'timeField'
|
||||
// value should be earlier than it now.
|
||||
assert.soon(() => {
|
||||
return futureColl.find({$expr: {$lt: ["$timeField", "$$NOW"]}}).itcount() == 1;
|
||||
}, "$$NOW should catch up after 3 seconds");
|
||||
}());
|
||||
|
||||
32
jstests/noPassthroughWithMongod/telemetry_configuration.js
Normal file
32
jstests/noPassthroughWithMongod/telemetry_configuration.js
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Tests that the telemetry store can be resized if it is configured, and cannot be resized if it is
|
||||
* disabled.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/feature_flag_util.js");
|
||||
|
||||
if (FeatureFlagUtil.isEnabled(db, "Telemetry")) {
|
||||
// The feature flag is enabled - make sure the telemetry store can be configured.
|
||||
const original = assert.commandWorked(
|
||||
db.adminCommand({getParameter: 1, internalQueryConfigureTelemetryCacheSize: 1}));
|
||||
assert(original.hasOwnProperty("internalQueryConfigureTelemetryCacheSize"), original);
|
||||
const originalValue = original.internalQueryConfigureTelemetryCacheSize;
|
||||
try {
|
||||
assert.doesNotThrow(
|
||||
() => db.adminCommand(
|
||||
{setParameter: 1, internalQueryConfigureTelemetryCacheSize: '2MB'}));
|
||||
// Other tests verify that resizing actually affects the data structure size.
|
||||
} finally {
|
||||
assert.doesNotThrow(
|
||||
() => db.adminCommand(
|
||||
{setParameter: 1, internalQueryConfigureTelemetryCacheSize: originalValue}));
|
||||
}
|
||||
} else {
|
||||
// The feature flag is disabled - make sure the telemetry store *cannot* be configured.
|
||||
assert.commandFailedWithCode(
|
||||
db.adminCommand({setParameter: 1, internalQueryConfigureTelemetryCacheSize: '2MB'}),
|
||||
7373500);
|
||||
}
|
||||
}());
|
||||
89
jstests/replsets/initial_sync_geo_index_conflict.js
Normal file
89
jstests/replsets/initial_sync_geo_index_conflict.js
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Asserts that applying a single-phase createIndexes oplog entry for a 2d geo index with a
|
||||
* floating point bits field doesn't cause initial-sync to fail if there is an existing index
|
||||
* spec with a rounded bits value.
|
||||
* This may happen if the index was first created on the primary when the collection was empty.
|
||||
* The initial sync node would have to clone the index with the rounded value provided by
|
||||
* listIndexes and subsequently re-apply the single-phase index build entry.
|
||||
*
|
||||
* @tags: [
|
||||
* requires_fcv_63,
|
||||
* ]
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
load('jstests/libs/fail_point_util.js');
|
||||
load('jstests/noPassthrough/libs/index_build.js');
|
||||
|
||||
function runTest(numDocs) {
|
||||
const dbName = 'test';
|
||||
const collectionName = 'coll-' + numDocs;
|
||||
|
||||
// Start one-node repl-set.
|
||||
const rst = new ReplSetTest({nodes: 1});
|
||||
rst.startSet();
|
||||
rst.initiate();
|
||||
const primary = rst.getPrimary();
|
||||
const primaryDB = primary.getDB(dbName);
|
||||
const primaryColl = primaryDB.getCollection(collectionName);
|
||||
|
||||
// Add a secondary.
|
||||
const secondary = rst.add({
|
||||
rsConfig: {votes: 0, priority: 0},
|
||||
setParameter: {
|
||||
numInitialSyncAttempts: 1,
|
||||
// Increase log level to see debug messages for "Ignoring indexing error".
|
||||
logComponentVerbosity: tojsononeline({replication: 1, storage: 1}),
|
||||
},
|
||||
});
|
||||
|
||||
// While the secondary is hung, we create the same index multiple times to
|
||||
// reproduce the interaction between single and two phase index builds on the
|
||||
// same index.
|
||||
const failPoint = configureFailPoint(secondary, 'initialSyncHangBeforeCopyingDatabases');
|
||||
rst.reInitiate();
|
||||
failPoint.wait();
|
||||
|
||||
try {
|
||||
// Create the index using the empty collection fast path. The index build should be
|
||||
// replicated in a single createIndexes oplog entry. A floating point 'bits' option would be
|
||||
// converted to a whole number (12 in this case) when initial sync recreates the indexes on
|
||||
// the collection during the cloning phase. However, the oplog entry generated would still
|
||||
// contain the floating point value 12.345.
|
||||
assert.commandWorked(primaryColl.createIndex({a: '2d'}, {bits: 12.345}));
|
||||
|
||||
for (let i = 0; i < numDocs; i++) {
|
||||
assert.commandWorked(primaryColl.insert({_id: i, a: i}));
|
||||
}
|
||||
} finally {
|
||||
// Resume initial sync. The createIndexes oplog entry will be applied.
|
||||
failPoint.off();
|
||||
}
|
||||
|
||||
// Wait for initial sync to finish.
|
||||
rst.awaitSecondaryNodes();
|
||||
|
||||
// We handle single phase indexing errors in different parts of the oplog application logic
|
||||
// depending on whether the collection is empty at the time. Hence, the different log message
|
||||
// IDs.
|
||||
const expectedLogMsgId = (numDocs === 0 ? 7261800 : 4718200);
|
||||
checkLog.containsJson(secondary, expectedLogMsgId, {
|
||||
namespace: primaryColl.getFullName(),
|
||||
spec: (spec) => {
|
||||
jsTestLog('Checking index spec in oplog application log message: ' + tojson(spec));
|
||||
return spec.name === 'a_2d';
|
||||
}
|
||||
});
|
||||
|
||||
// We rely on the replica set test fixture shutdown to compare the collection contents
|
||||
// (including index specs) between the two nodes in the cluster.
|
||||
rst.stopSet();
|
||||
}
|
||||
|
||||
// We test both empty and non-empty collections because these are handled slightly differently
|
||||
// in the oplog application code.
|
||||
runTest(0);
|
||||
runTest(1);
|
||||
})();
|
||||
@ -12,7 +12,7 @@ const replSet = new ReplSetTest({
|
||||
nodeOptions: {
|
||||
setParameter: {
|
||||
"maxOplogTruncationPointsDuringStartup": 10,
|
||||
logComponentVerbosity: tojson({storage: {verbosity: 2}}),
|
||||
logComponentVerbosity: tojson({storage: {verbosity: 3}}),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -108,14 +108,18 @@
|
||||
checkOptions(c2, Object.keys(coll2Options));
|
||||
checkUUID(c2, coll2uuid);
|
||||
|
||||
function checkIndexes(collName, expectedIndexes) {
|
||||
function checkIndexes(collName, expectedIndexes, shardedColl) {
|
||||
var res = toShard.getDB('test').runCommand({listIndexes: collName});
|
||||
assert.commandWorked(res, 'Failed to get indexes for collection ' + collName);
|
||||
var indexes = res.cursor.firstBatch;
|
||||
indexes.sort(sortByName);
|
||||
|
||||
// There should be 3 indexes on each collection - the _id one, and the 2 we created.
|
||||
assert.eq(indexes.length, 3);
|
||||
// TODO SERVER-74252: once 7.0 becomes LastLTS we can assume that the movePrimary will never
|
||||
// copy indexes of sharded collections.
|
||||
if (shardedColl)
|
||||
assert(indexes.length === 1 || indexes.length === 3);
|
||||
else
|
||||
assert(indexes.length === 3);
|
||||
|
||||
indexes.forEach((index, i) => {
|
||||
var expected;
|
||||
@ -129,8 +133,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
checkIndexes('coll1', coll1Indexes);
|
||||
checkIndexes('coll2', coll2Indexes);
|
||||
checkIndexes('coll1', coll1Indexes, /*shardedColl*/ false);
|
||||
checkIndexes('coll2', coll2Indexes, /*shardedColl*/ true);
|
||||
|
||||
// Verify that the data from the unsharded collections resides on the new primary shard, and was
|
||||
// copied as part of the clone.
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Test that chunk migration can migrate a retryable internal transaction whose oplog entries have
|
||||
* been truncated.
|
||||
*
|
||||
* @tags: [uses_transactions, requires_persistence]
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// This test involves writing directly to the config.transactions collection which is not allowed
|
||||
// in a session.
|
||||
TestData.disableImplicitSessions = true;
|
||||
|
||||
const st = new ShardingTest({shards: 2, rs: {nodes: 1}});
|
||||
|
||||
const dbName = 'testDb';
|
||||
const collName = 'testColl';
|
||||
const ns = dbName + '.' + collName;
|
||||
const testDB = st.s.getDB(dbName);
|
||||
|
||||
assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
|
||||
st.ensurePrimaryShard(dbName, st.shard0.name);
|
||||
|
||||
assert.commandWorked(st.s.getCollection(ns).createIndex({x: 1}));
|
||||
assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {x: 1}}));
|
||||
|
||||
assert.commandWorked(st.s.getDB(dbName).runCommand({insert: collName, documents: [{x: 1}]}));
|
||||
|
||||
const parentLsid = {
|
||||
id: UUID()
|
||||
};
|
||||
const parentTxnNumber = NumberLong(35);
|
||||
|
||||
const originalChildLsid = {
|
||||
id: parentLsid.id,
|
||||
txnNumber: parentTxnNumber,
|
||||
txnUUID: UUID()
|
||||
};
|
||||
const childTxnNumber = NumberLong(1);
|
||||
|
||||
const updateCmdObj = {
|
||||
update: collName,
|
||||
updates: [{q: {x: 1}, u: {$set: {y: 1}}}],
|
||||
stmtId: NumberInt(0),
|
||||
};
|
||||
const res0 = assert.commandWorked(testDB.runCommand(Object.assign({}, updateCmdObj, {
|
||||
lsid: originalChildLsid,
|
||||
txnNumber: childTxnNumber,
|
||||
autocommit: false,
|
||||
startTransaction: true
|
||||
})));
|
||||
assert.eq(res0.nModified, 1, res0);
|
||||
assert.commandWorked(st.s.adminCommand({
|
||||
commitTransaction: 1,
|
||||
lsid: originalChildLsid,
|
||||
txnNumber: childTxnNumber,
|
||||
autocommit: false,
|
||||
}));
|
||||
|
||||
// Manually update the config.transactions document for the retryable internal transaction to point
|
||||
// to an invalid op time.
|
||||
const shard0ConfigTxnsColl = st.rs0.getPrimary().getCollection("config.transactions");
|
||||
const res1 = assert.commandWorked(shard0ConfigTxnsColl.update(
|
||||
{"_id.txnUUID": originalChildLsid.txnUUID},
|
||||
{$set: {lastWriteOpTime: {ts: new Timestamp(100, 1), t: NumberLong(1)}}}));
|
||||
assert.eq(res1.nModified, 1, res1);
|
||||
|
||||
assert.commandWorked(st.s.adminCommand({split: ns, middle: {x: 0}}));
|
||||
assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {x: 0}, to: st.shard1.shardName}));
|
||||
|
||||
assert.commandFailedWithCode(testDB.runCommand(Object.assign(
|
||||
{}, updateCmdObj, {lsid: parentLsid, txnNumber: parentTxnNumber})),
|
||||
ErrorCodes.IncompleteTransactionHistory);
|
||||
|
||||
const retryChildLsid = {
|
||||
id: parentLsid.id,
|
||||
txnNumber: parentTxnNumber,
|
||||
txnUUID: UUID()
|
||||
};
|
||||
assert.commandFailedWithCode(testDB.runCommand(Object.assign({}, updateCmdObj, {
|
||||
lsid: retryChildLsid,
|
||||
txnNumber: childTxnNumber,
|
||||
autocommit: false,
|
||||
startTransaction: true
|
||||
})),
|
||||
ErrorCodes.IncompleteTransactionHistory);
|
||||
|
||||
st.stop();
|
||||
})();
|
||||
@ -106,10 +106,10 @@ const runParallelMoveChunk = (numThreads) => {
|
||||
MongoRunner.stopMongod(staticMongod);
|
||||
};
|
||||
|
||||
// Run test 10 times with random concurrency levels.
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
runParallelMoveChunk(1);
|
||||
|
||||
// Run test a few times with random concurrency levels.
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
runParallelMoveChunk(Math.floor(Math.random() * 31) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
)();
|
||||
})();
|
||||
|
||||
@ -60,7 +60,12 @@ function checkCollectionsCopiedCorrectly(fromShard, toShard, sharded, barUUID, f
|
||||
var indexes = res.cursor.firstBatch;
|
||||
indexes.sort(sortByName);
|
||||
|
||||
assert.eq(indexes.length, 2);
|
||||
// TODO SERVER-74252: once 7.0 becomes LastLTS we can assume that the movePrimary will never
|
||||
// copy indexes of sharded collections.
|
||||
if (sharded)
|
||||
assert(indexes.length == 1 || indexes.length == 2);
|
||||
else
|
||||
assert(indexes.length == 2);
|
||||
|
||||
indexes.forEach((index, i) => {
|
||||
var expected;
|
||||
|
||||
98
jstests/sharding/query/group_plan_cache_sharded.js
Normal file
98
jstests/sharding/query/group_plan_cache_sharded.js
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Test which verifies that the SBE plan cache correctly caches different plans for $group depending
|
||||
* on whether the results will be fed into a merging pipeline or not.
|
||||
*
|
||||
* @tags: [
|
||||
* requires_sharding,
|
||||
* # The SBE plan cache was enabled by default in 6.3.
|
||||
* requires_fcv_63,
|
||||
* # This test uses the _id index
|
||||
* expects_explicit_underscore_id_index,
|
||||
* ]
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
load("jstests/libs/sbe_util.js"); // For 'checkSBEEnabled'.
|
||||
|
||||
const st = new ShardingTest({shards: 2, rs: {nodes: 1}});
|
||||
const mongosDB = st.s.getDB(jsTestName());
|
||||
|
||||
// This test is specifically verifying the behavior of the SBE plan cache, which is only enabled
|
||||
// when SBE is enabled.
|
||||
if (!checkSBEEnabled(mongosDB)) {
|
||||
jsTestLog("Skipping test because SBE is not enabled");
|
||||
st.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
const collName = jsTestName();
|
||||
const coll = mongosDB[collName];
|
||||
|
||||
function runPipeline(predicateValue) {
|
||||
return coll
|
||||
.aggregate([
|
||||
{$match: {_id: {$gte: predicateValue}}},
|
||||
{$group: {_id: null, sumResult: {$sum: "$a"}}}
|
||||
])
|
||||
.toArray();
|
||||
}
|
||||
|
||||
// Shard coll on _id.
|
||||
st.shardColl(
|
||||
coll, {_id: 1} /* key */, {_id: 0} /* split */, {_id: 0} /* move */, mongosDB.getName());
|
||||
const docs = [{_id: -2, a: 1}, {_id: 2, a: 2}];
|
||||
assert.commandWorked(coll.insertMany(docs));
|
||||
|
||||
assert.eq(0, coll.getPlanCache().list().length, "Expected 0 cache entries");
|
||||
|
||||
// Run the first aggregate, which will match the second document and target a single shard.
|
||||
let res = runPipeline(0);
|
||||
assert.eq(res.length, 1);
|
||||
assert.eq(res[0], {_id: null, sumResult: 2}, res);
|
||||
|
||||
let cacheEntries = coll.getPlanCache().list();
|
||||
assert.eq(1, cacheEntries.length, cacheEntries);
|
||||
|
||||
// Capture the plan cache key from our lone cache entry.
|
||||
const nonMergingCacheEntry = cacheEntries[0];
|
||||
assert(nonMergingCacheEntry.hasOwnProperty("planCacheKey"));
|
||||
const nonMergingCacheKey = nonMergingCacheEntry.planCacheKey;
|
||||
|
||||
// Run the second aggregate, which will match both documents and target both shards.
|
||||
res = runPipeline(-2000);
|
||||
assert.eq(res.length, 1);
|
||||
assert.eq(res[0], {_id: null, sumResult: 3}, res);
|
||||
|
||||
// The second aggregate will produce two additional cache entries; one for each shard.
|
||||
cacheEntries = coll.getPlanCache().list();
|
||||
assert.eq(3, cacheEntries.length, cacheEntries);
|
||||
|
||||
// Verify that all three cache entries are pinned and active. Then, verify that exactly one
|
||||
// cache entry has the 'nonMergingCacheKey', while the other two have a different key.
|
||||
let mergingCacheKey = null;
|
||||
let mergingKeyCount = 0;
|
||||
let nonMergingKeyCount = 0;
|
||||
for (const cacheEntry of cacheEntries) {
|
||||
assert(cacheEntry.isPinned, cacheEntry);
|
||||
assert(cacheEntry.isActive, cacheEntry);
|
||||
assert(cacheEntry.hasOwnProperty("planCacheKey"));
|
||||
if (cacheEntry.planCacheKey === nonMergingCacheKey) {
|
||||
nonMergingKeyCount++;
|
||||
} else {
|
||||
mergingKeyCount++;
|
||||
// If we haven't seen the merging cache key before, stash it so that we can verify that the
|
||||
// two merging plans have the exact same cache key.
|
||||
if (mergingCacheKey === null) {
|
||||
mergingCacheKey = cacheEntry.planCacheKey;
|
||||
} else {
|
||||
assert.eq(cacheEntry.planCacheKey, mergingCacheKey, tojson(cacheEntries));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert.eq(nonMergingKeyCount, 1, tojson(cacheEntries));
|
||||
assert.eq(mergingKeyCount, 2, tojson(cacheEntries));
|
||||
|
||||
st.stop();
|
||||
}());
|
||||
57
jstests/sharding/shard_keys_with_dollar_sign.js
Normal file
57
jstests/sharding/shard_keys_with_dollar_sign.js
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Tests that the shardCollection command and reshardCollection command correctly reject a shard key
|
||||
* that has a field name with parts that start with '$'.
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
const st = new ShardingTest({shards: 1});
|
||||
|
||||
const dbName = "testDb";
|
||||
const ns0 = dbName + ".testColl0";
|
||||
const ns1 = dbName + ".testColl1";
|
||||
const ns2 = dbName + ".testColl2";
|
||||
const db = st.s.getDB(dbName);
|
||||
|
||||
function testValidation(key, {isValidIndexKey, isValidShardKey}) {
|
||||
jsTest.log(`Testing ${tojson({key, isValidIndexKey, isValidShardKey})}`);
|
||||
assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
|
||||
st.ensurePrimaryShard(dbName, st.shard0.name);
|
||||
|
||||
const createIndexRes = db.getCollection(ns0).createIndex(key);
|
||||
if (isValidIndexKey) {
|
||||
assert.commandWorked(createIndexRes);
|
||||
} else {
|
||||
assert.commandFailedWithCode(createIndexRes, ErrorCodes.CannotCreateIndex);
|
||||
}
|
||||
|
||||
const shardCollectionRes = st.s.adminCommand({shardCollection: ns1, key});
|
||||
if (isValidShardKey) {
|
||||
assert.commandWorked(shardCollectionRes);
|
||||
} else {
|
||||
assert.commandFailedWithCode(shardCollectionRes, ErrorCodes.BadValue);
|
||||
}
|
||||
|
||||
assert.commandWorked(st.s.adminCommand({shardCollection: ns2, key: {_id: 1}}));
|
||||
const reshardCollectionRes = st.s.adminCommand({reshardCollection: ns2, key});
|
||||
if (isValidShardKey) {
|
||||
assert.commandWorked(reshardCollectionRes);
|
||||
} else {
|
||||
assert.commandFailedWithCode(reshardCollectionRes, ErrorCodes.BadValue);
|
||||
}
|
||||
|
||||
assert.commandWorked(db.dropDatabase());
|
||||
}
|
||||
|
||||
testValidation({"$x": 1}, {isValidIndexKey: false, isValidShardKey: false});
|
||||
testValidation({"x.$y": 1}, {isValidIndexKey: false, isValidShardKey: false});
|
||||
testValidation({"$**": 1}, {isValidIndexKey: true, isValidShardKey: false});
|
||||
testValidation({"x.$**": 1}, {isValidIndexKey: true, isValidShardKey: false});
|
||||
testValidation({"$": 1}, {isValidIndexKey: false, isValidShardKey: false});
|
||||
|
||||
testValidation({"x$": 1}, {isValidIndexKey: true, isValidShardKey: true});
|
||||
testValidation({"x$.y": 1}, {isValidIndexKey: true, isValidShardKey: true});
|
||||
testValidation({"x.y$": 1}, {isValidIndexKey: true, isValidShardKey: true});
|
||||
|
||||
st.stop();
|
||||
})();
|
||||
@ -233,35 +233,40 @@ bool SdamServerSelector::_containsAllTags(ServerDescriptionPtr server, const BSO
|
||||
|
||||
void SdamServerSelector::filterTags(std::vector<ServerDescriptionPtr>* servers,
|
||||
const TagSet& tagSet) {
|
||||
const auto& checkTags = tagSet.getTagBSON();
|
||||
const auto& tagSetList = tagSet.getTagBSON();
|
||||
|
||||
if (checkTags.nFields() == 0)
|
||||
if (tagSetList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto predicate = [&](const ServerDescriptionPtr& s) {
|
||||
auto it = checkTags.begin();
|
||||
while (it != checkTags.end()) {
|
||||
if (it->isABSONObj()) {
|
||||
const BSONObj& tags = it->Obj();
|
||||
if (_containsAllTags(s, tags)) {
|
||||
// found a match -- don't remove the server
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOGV2_WARNING(
|
||||
4671202,
|
||||
"Invalid tags specified for server selection; tags should be specified as "
|
||||
"bson Objects",
|
||||
"tag"_attr = *it);
|
||||
}
|
||||
++it;
|
||||
for (const auto& tagSetElem : tagSetList) {
|
||||
if (tagSetElem.type() != BSONType::Object) {
|
||||
LOGV2_WARNING(4671202,
|
||||
"Invalid tag set specified for server selection; tag sets should be"
|
||||
" specified as a BSON object",
|
||||
"tag"_attr = tagSetElem);
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove the server
|
||||
return true;
|
||||
};
|
||||
const auto predicate = [&](const ServerDescriptionPtr& s) {
|
||||
const bool shouldRemove = !_containsAllTags(s, tagSetElem.embeddedObject());
|
||||
return shouldRemove;
|
||||
};
|
||||
|
||||
servers->erase(std::remove_if(servers->begin(), servers->end(), predicate), servers->end());
|
||||
auto it = std::remove_if(servers->begin(), servers->end(), predicate);
|
||||
// If none of the server descriptions match the tag set, then continue on to check the next
|
||||
// tag set in the list. Otherwise, if at least one of the server descriptions match the tag
|
||||
// set criteria, then we've found our preferred host(s) to read from.
|
||||
if (it != servers->begin()) {
|
||||
servers->erase(it, servers->end());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Getting here means a non-empty tag set list was specified but none of the server descriptions
|
||||
// matched any of the tag sets in the list. We've therefore failed to find any server
|
||||
// description matching the read preference tag criteria.
|
||||
servers->clear();
|
||||
}
|
||||
|
||||
bool SdamServerSelector::recencyFilter(const ReadPreferenceSetting& readPref,
|
||||
|
||||
@ -654,7 +654,9 @@ TEST_F(ServerSelectorTestFixture, ShouldFilterByTags) {
|
||||
tags = TagSets::eastOrWestProductionSet;
|
||||
servers = makeServerDescriptionList();
|
||||
selector.filterTags(&servers, tags);
|
||||
ASSERT_EQ(2, servers.size());
|
||||
ASSERT_EQ(1, servers.size());
|
||||
ASSERT_EQ((std::map<std::string, std::string>{{"dc", "east"}, {"usage", "production"}}),
|
||||
servers[0]->getTags());
|
||||
|
||||
tags = TagSets::testSet;
|
||||
servers = makeServerDescriptionList();
|
||||
|
||||
@ -1475,7 +1475,6 @@ env.Library(
|
||||
'$BUILD_DIR/mongo/db/query/ce/query_ce_histogram',
|
||||
'$BUILD_DIR/mongo/db/query/ce/query_ce_sampling',
|
||||
'$BUILD_DIR/mongo/db/query/optimizer/optimizer',
|
||||
'$BUILD_DIR/mongo/db/repl/wait_for_majority_service',
|
||||
'$BUILD_DIR/mongo/db/session/kill_sessions',
|
||||
'$BUILD_DIR/mongo/db/sorter/sorter_stats',
|
||||
'$BUILD_DIR/mongo/db/stats/resource_consumption_metrics',
|
||||
|
||||
@ -679,6 +679,8 @@ Collection::Validator CollectionImpl::parseValidator(
|
||||
auto expCtx = make_intrusive<ExpressionContext>(
|
||||
opCtx, CollatorInterface::cloneCollator(_shared->_collator.get()), ns());
|
||||
|
||||
expCtx->variables.setDefaultRuntimeConstants(opCtx);
|
||||
|
||||
// The MatchExpression and contained ExpressionContext created as part of the validator are
|
||||
// owned by the Collection and will outlive the OperationContext they were created under.
|
||||
expCtx->opCtx = nullptr;
|
||||
|
||||
@ -174,6 +174,10 @@ StatusWith<CollectionOptions> CollectionOptions::parse(const BSONObj& options, P
|
||||
} else if (fieldName == "flags") {
|
||||
// Ignoring this field as it is deprecated.
|
||||
continue;
|
||||
} else if (fieldName == "recordPreImages") {
|
||||
// Ignoring this field as it is not supported.
|
||||
collectionOptions.recordPreImagesOptionUsed = true;
|
||||
continue;
|
||||
} else if (fieldName == "temp") {
|
||||
collectionOptions.temp = e.trueValue();
|
||||
} else if (fieldName == "changeStreamPreAndPostImages") {
|
||||
|
||||
@ -124,6 +124,12 @@ struct CollectionOptions {
|
||||
|
||||
bool temp = false;
|
||||
|
||||
// Indicates whether "recordPreImages" collection option was used in the collection definition.
|
||||
// This needs to be remembered to make it possible to efficiently remove the option upon FCV
|
||||
// upgrade. Otherwise, this option is not supported.
|
||||
// TODO SERVER-74036: Remove once FCV 7.0 becomes last-LTS.
|
||||
bool recordPreImagesOptionUsed{false};
|
||||
|
||||
// Change stream options define whether or not to store the pre-images of the documents affected
|
||||
// by update and delete operations in a dedicated collection, that will be used for reading data
|
||||
// via changeStreams.
|
||||
|
||||
@ -133,33 +133,6 @@ void _validateIndexes(OperationContext* opCtx,
|
||||
auto& curIndexResults = (results->indexResultsMap)[descriptor->indexName()];
|
||||
curIndexResults.keysTraversed = numTraversedKeys;
|
||||
|
||||
// If we are performing a full index validation, we have information on the number of index
|
||||
// keys validated in _validateIndexesInternalStructure (when we validated the internal
|
||||
// structure of the index). Check if this is consistent with 'numTraversedKeys' from
|
||||
// traverseIndex above.
|
||||
if (validateState->isFullIndexValidation()) {
|
||||
invariant(opCtx->lockState()->isCollectionLockedForMode(validateState->nss(), MODE_X));
|
||||
|
||||
// The number of keys counted in _validateIndexesInternalStructure, when checking the
|
||||
// internal structure of the index.
|
||||
const int64_t numIndexKeys = curIndexResults.keysTraversedFromFullValidate;
|
||||
|
||||
// Check if currIndexResults is valid to ensure that this index is not corrupted or
|
||||
// comprised (which was set in _validateIndexesInternalStructure). If the index is
|
||||
// corrupted, there is no use in checking if the traversal yielded the same key count.
|
||||
if (curIndexResults.valid) {
|
||||
if (numIndexKeys != numTraversedKeys) {
|
||||
curIndexResults.valid = false;
|
||||
string msg = str::stream()
|
||||
<< "number of traversed index entries (" << numTraversedKeys
|
||||
<< ") does not match the number of expected index entries (" << numIndexKeys
|
||||
<< ")";
|
||||
results->errors.push_back(msg);
|
||||
results->valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!curIndexResults.valid) {
|
||||
results->valid = false;
|
||||
}
|
||||
@ -242,6 +215,81 @@ void _validateIndexKeyCount(OperationContext* opCtx,
|
||||
}
|
||||
}
|
||||
|
||||
void _printIndexSpec(const ValidateState* validateState, StringData indexName) {
|
||||
auto& indexes = validateState->getIndexes();
|
||||
auto indexEntry =
|
||||
std::find_if(indexes.begin(),
|
||||
indexes.end(),
|
||||
[&](const std::shared_ptr<const IndexCatalogEntry> indexEntry) -> bool {
|
||||
return indexEntry->descriptor()->indexName() == indexName;
|
||||
});
|
||||
if (indexEntry != indexes.end()) {
|
||||
auto indexSpec = (*indexEntry)->descriptor()->infoObj();
|
||||
LOGV2_ERROR(7463100, "Index failed validation", "spec"_attr = indexSpec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs oplog entries related to corrupted records/indexes in validation results.
|
||||
*/
|
||||
void _logOplogEntriesForInvalidResults(OperationContext* opCtx, ValidateResults* results) {
|
||||
if (results->recordTimestamps.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGV2(
|
||||
7464200,
|
||||
"Validation failed: oplog timestamps referenced by corrupted collection and index entries",
|
||||
"numTimestamps"_attr = results->recordTimestamps.size());
|
||||
|
||||
// Set up read on oplog collection.
|
||||
try {
|
||||
AutoGetOplog oplogRead(opCtx, OplogAccessMode::kRead);
|
||||
const auto& oplogCollection = oplogRead.getCollection();
|
||||
|
||||
// Log oplog entries in reverse from most recent timestamp to oldest.
|
||||
// Due to oplog truncation, if we fail to find any oplog entry for a particular timestamp,
|
||||
// we can stop searching for oplog entries with earlier timestamps.
|
||||
auto recordStore = oplogCollection->getRecordStore();
|
||||
uassert(ErrorCodes::InternalError,
|
||||
"Validation failed: Unable to get oplog record store for corrupted collection and "
|
||||
"index entries",
|
||||
recordStore);
|
||||
|
||||
auto cursor = recordStore->getCursor(opCtx, /*forward=*/false);
|
||||
uassert(ErrorCodes::CursorNotFound,
|
||||
"Validation failed: Unable to get cursor to oplog collection.",
|
||||
cursor);
|
||||
|
||||
for (auto it = results->recordTimestamps.rbegin(); it != results->recordTimestamps.rend();
|
||||
it++) {
|
||||
const auto& timestamp = *it;
|
||||
|
||||
// A record id in the oplog collection is equivalent to the document's timestamp field.
|
||||
RecordId recordId(timestamp.asULL());
|
||||
auto record = cursor->seekExact(recordId);
|
||||
if (!record) {
|
||||
LOGV2(7464201,
|
||||
" Validation failed: Stopping oplog entry search for corrupted collection "
|
||||
"and index entries.",
|
||||
"timestamp"_attr = timestamp);
|
||||
break;
|
||||
}
|
||||
|
||||
LOGV2(
|
||||
7464202,
|
||||
" Validation failed: Oplog entry found for corrupted collection and index entry",
|
||||
"timestamp"_attr = timestamp,
|
||||
"oplogEntryDoc"_attr = redact(record->data.toBson()));
|
||||
}
|
||||
} catch (DBException& ex) {
|
||||
LOGV2_ERROR(7464203,
|
||||
"Validation failed: Unable to fetch entries from oplog collection for "
|
||||
"corrupted collection and index entries",
|
||||
"ex"_attr = ex);
|
||||
}
|
||||
}
|
||||
|
||||
void _reportValidationResults(OperationContext* opCtx,
|
||||
ValidateState* validateState,
|
||||
ValidateResults* results,
|
||||
@ -262,6 +310,7 @@ void _reportValidationResults(OperationContext* opCtx,
|
||||
for (const auto& [indexName, vr] : results->indexResultsMap) {
|
||||
if (!vr.valid) {
|
||||
results->valid = false;
|
||||
_printIndexSpec(validateState, indexName);
|
||||
}
|
||||
|
||||
if (validateState->getSkippedIndexes().contains(indexName)) {
|
||||
@ -300,6 +349,7 @@ void _reportInvalidResults(OperationContext* opCtx,
|
||||
ValidateResults* results,
|
||||
BSONObjBuilder* output) {
|
||||
_reportValidationResults(opCtx, validateState, results, output);
|
||||
_logOplogEntriesForInvalidResults(opCtx, results);
|
||||
LOGV2_OPTIONS(20302,
|
||||
{LogComponent::kIndex},
|
||||
"Validation complete -- Corruption found",
|
||||
@ -459,12 +509,12 @@ Status validate(OperationContext* opCtx,
|
||||
RepairMode repairMode,
|
||||
ValidateResults* results,
|
||||
BSONObjBuilder* output,
|
||||
bool turnOnExtraLoggingForTest) {
|
||||
bool logDiagnostics) {
|
||||
invariant(!opCtx->lockState()->isLocked() || storageGlobalParams.repair);
|
||||
|
||||
// This is deliberately outside of the try-catch block, so that any errors thrown in the
|
||||
// constructor fail the cmd, as opposed to returning OK with valid:false.
|
||||
ValidateState validateState(opCtx, nss, mode, repairMode, turnOnExtraLoggingForTest);
|
||||
ValidateState validateState(opCtx, nss, mode, repairMode, logDiagnostics);
|
||||
|
||||
const auto replCoord = repl::ReplicationCoordinator::get(opCtx);
|
||||
// Check whether we are allowed to read from this node after acquiring our locks. If we are
|
||||
|
||||
@ -106,7 +106,7 @@ Status validate(OperationContext* opCtx,
|
||||
RepairMode repairMode,
|
||||
ValidateResults* results,
|
||||
BSONObjBuilder* output,
|
||||
bool turnOnExtraLoggingForTest = false);
|
||||
bool logDiagnostics);
|
||||
|
||||
/**
|
||||
* Checks whether a failpoint has been hit in the above validate() code..
|
||||
|
||||
@ -91,8 +91,13 @@ std::vector<std::pair<BSONObj, ValidateResults>> foregroundValidate(
|
||||
for (auto mode : modes) {
|
||||
ValidateResults validateResults;
|
||||
BSONObjBuilder output;
|
||||
ASSERT_OK(CollectionValidation::validate(
|
||||
opCtx, nss, mode, repairMode, &validateResults, &output));
|
||||
ASSERT_OK(CollectionValidation::validate(opCtx,
|
||||
nss,
|
||||
mode,
|
||||
repairMode,
|
||||
&validateResults,
|
||||
&output,
|
||||
/*logDiagnostics=*/false));
|
||||
BSONObj obj = output.obj();
|
||||
BSONObjBuilder validateResultsBuilder;
|
||||
validateResults.appendToResultObj(&validateResultsBuilder, true /* debugging */);
|
||||
@ -163,7 +168,8 @@ std::vector<std::pair<BSONObj, ValidateResults>> backgroundValidate(const Namesp
|
||||
CollectionValidation::ValidateMode::kBackground,
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
&validateResults,
|
||||
&output));
|
||||
&output,
|
||||
/*logDiagnostics=*/false));
|
||||
BSONObj obj = output.obj();
|
||||
|
||||
ASSERT_EQ(validateResults.valid, valid);
|
||||
|
||||
@ -61,7 +61,8 @@ protected:
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kForeground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
};
|
||||
|
||||
void tearDown() override {
|
||||
|
||||
@ -831,6 +831,11 @@ Status createCollection(OperationContext* opCtx,
|
||||
}
|
||||
|
||||
if (options.isView()) {
|
||||
// system.profile will have new document inserts due to profiling. Inserts aren't supported
|
||||
// on views.
|
||||
uassert(ErrorCodes::IllegalOperation,
|
||||
"Cannot create system.profile as a view",
|
||||
!ns.isSystemDotProfile());
|
||||
uassert(ErrorCodes::OperationNotSupportedInTransaction,
|
||||
str::stream() << "Cannot create a view in a multi-document "
|
||||
"transaction.",
|
||||
@ -841,6 +846,11 @@ Status createCollection(OperationContext* opCtx,
|
||||
|
||||
return _createView(opCtx, ns, options);
|
||||
} else if (options.timeseries && !ns.isTimeseriesBucketsCollection()) {
|
||||
// system.profile must be a simple collection since new document insertions directly work
|
||||
// against the usual collection API. See introspect.cpp for more details.
|
||||
uassert(ErrorCodes::IllegalOperation,
|
||||
"Cannot create system.profile as a timeseries collection",
|
||||
!ns.isSystemDotProfile());
|
||||
// This helper is designed for user-created time-series collections on primaries. If a
|
||||
// time-series buckets collection is created explicitly or during replication, treat this as
|
||||
// a normal collection creation.
|
||||
|
||||
@ -127,7 +127,7 @@ KeyStringIndexConsistency::KeyStringIndexConsistency(
|
||||
void KeyStringIndexConsistency::addMultikeyMetadataPath(const KeyString::Value& ks,
|
||||
IndexInfo* indexInfo) {
|
||||
auto hash = _hashKeyString(ks, indexInfo->indexNameHash);
|
||||
if (MONGO_unlikely(_validateState->extraLoggingForTest())) {
|
||||
if (MONGO_unlikely(_validateState->logDiagnostics())) {
|
||||
LOGV2(6208500,
|
||||
"[validate](multikeyMetadataPath) Adding with the hash",
|
||||
"hash"_attr = hash,
|
||||
@ -139,7 +139,7 @@ void KeyStringIndexConsistency::addMultikeyMetadataPath(const KeyString::Value&
|
||||
void KeyStringIndexConsistency::removeMultikeyMetadataPath(const KeyString::Value& ks,
|
||||
IndexInfo* indexInfo) {
|
||||
auto hash = _hashKeyString(ks, indexInfo->indexNameHash);
|
||||
if (MONGO_unlikely(_validateState->extraLoggingForTest())) {
|
||||
if (MONGO_unlikely(_validateState->logDiagnostics())) {
|
||||
LOGV2(6208501,
|
||||
"[validate](multikeyMetadataPath) Removing with the hash",
|
||||
"hash"_attr = hash,
|
||||
@ -153,9 +153,26 @@ size_t KeyStringIndexConsistency::getMultikeyMetadataPathCount(IndexInfo* indexI
|
||||
}
|
||||
|
||||
bool KeyStringIndexConsistency::haveEntryMismatch() const {
|
||||
return std::any_of(_indexKeyBuckets.begin(),
|
||||
_indexKeyBuckets.end(),
|
||||
[](const IndexKeyBucket& bucket) -> bool { return bucket.indexKeyCount; });
|
||||
bool haveMismatch =
|
||||
std::any_of(_indexKeyBuckets.begin(),
|
||||
_indexKeyBuckets.end(),
|
||||
[](const IndexKeyBucket& bucket) -> bool { return bucket.indexKeyCount; });
|
||||
|
||||
if (haveMismatch && _validateState->logDiagnostics()) {
|
||||
for (size_t i = 0; i < _indexKeyBuckets.size(); i++) {
|
||||
if (_indexKeyBuckets[i].indexKeyCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGV2(7404500,
|
||||
"[validate](bucket entry mismatch)",
|
||||
"hash"_attr = i,
|
||||
"indexKeyCount"_attr = _indexKeyBuckets[i].indexKeyCount,
|
||||
"bucketBytesSize"_attr = _indexKeyBuckets[i].bucketSizeBytes);
|
||||
}
|
||||
}
|
||||
|
||||
return haveMismatch;
|
||||
}
|
||||
|
||||
void KeyStringIndexConsistency::repairIndexEntries(OperationContext* opCtx,
|
||||
@ -280,9 +297,21 @@ void KeyStringIndexConsistency::addIndexEntryErrors(OperationContext* opCtx,
|
||||
// many as possible within memory limits.
|
||||
using ExtraIt = SimpleBSONObjSet::const_iterator;
|
||||
std::vector<ExtraIt> extraIndexEntriesBySize;
|
||||
// Since the extra entries are stored in a map of sets, we have to iterate the entries in the
|
||||
// map and sum the size of the sets in order to get the total number. Given that we can have at
|
||||
// most 64 indexes per collection, and the total number of entries could potentially be in the
|
||||
// millions, we expect that iterating the map will be much less costly than the additional
|
||||
// allocations and copies that could result from not calling 'reserve' on the vector.
|
||||
size_t totalExtraIndexEntriesCount =
|
||||
std::accumulate(_extraIndexEntries.begin(),
|
||||
_extraIndexEntries.end(),
|
||||
0,
|
||||
[](size_t total, const std::pair<IndexKey, SimpleBSONObjSet>& set) {
|
||||
return total + set.second.size();
|
||||
});
|
||||
extraIndexEntriesBySize.reserve(totalExtraIndexEntriesCount);
|
||||
for (const auto& extraIndexEntry : _extraIndexEntries) {
|
||||
const SimpleBSONObjSet& entries = extraIndexEntry.second;
|
||||
extraIndexEntriesBySize.reserve(extraIndexEntriesBySize.size() + entries.size());
|
||||
for (auto it = entries.begin(); it != entries.end(); ++it) {
|
||||
extraIndexEntriesBySize.push_back(it);
|
||||
}
|
||||
@ -348,7 +377,8 @@ void KeyStringIndexConsistency::addDocumentMultikeyPaths(IndexInfo* indexInfo,
|
||||
void KeyStringIndexConsistency::addDocKey(OperationContext* opCtx,
|
||||
const KeyString::Value& ks,
|
||||
IndexInfo* indexInfo,
|
||||
const RecordId& recordId) {
|
||||
const RecordId& recordId,
|
||||
ValidateResults* results) {
|
||||
auto rawHash = ks.hash(indexInfo->indexNameHash);
|
||||
auto hashLower = rawHash % kNumHashBuckets;
|
||||
auto hashUpper = (rawHash / kNumHashBuckets) % kNumHashBuckets;
|
||||
@ -364,7 +394,7 @@ void KeyStringIndexConsistency::addDocKey(OperationContext* opCtx,
|
||||
upper.bucketSizeBytes += ks.getSize();
|
||||
indexInfo->numRecords++;
|
||||
|
||||
if (MONGO_unlikely(_validateState->extraLoggingForTest())) {
|
||||
if (MONGO_unlikely(_validateState->logDiagnostics())) {
|
||||
LOGV2(4666602,
|
||||
"[validate](record) Adding with hashes",
|
||||
"hashUpper"_attr = hashUpper,
|
||||
@ -396,7 +426,8 @@ void KeyStringIndexConsistency::addDocKey(OperationContext* opCtx,
|
||||
std::make_pair(key, IndexEntryInfo(*indexInfo, recordId, idKeyBuilder.obj(), ks)));
|
||||
|
||||
// Prints the collection document's and index entry's metadata.
|
||||
_validateState->getCollection()->getRecordStore()->printRecordMetadata(opCtx, recordId);
|
||||
_validateState->getCollection()->getRecordStore()->printRecordMetadata(
|
||||
opCtx, recordId, &(results->recordTimestamps));
|
||||
indexInfo->accessMethod->asSortedData()->getSortedDataInterface()->printIndexEntryMetadata(
|
||||
opCtx, ks);
|
||||
}
|
||||
@ -422,7 +453,7 @@ void KeyStringIndexConsistency::addIndexKey(OperationContext* opCtx,
|
||||
upper.bucketSizeBytes += ks.getSize();
|
||||
indexInfo->numKeys++;
|
||||
|
||||
if (MONGO_unlikely(_validateState->extraLoggingForTest())) {
|
||||
if (MONGO_unlikely(_validateState->logDiagnostics())) {
|
||||
LOGV2(4666603,
|
||||
"[validate](index) Adding with hashes",
|
||||
"hashUpper"_attr = hashUpper,
|
||||
@ -473,8 +504,8 @@ void KeyStringIndexConsistency::addIndexKey(OperationContext* opCtx,
|
||||
_extraIndexEntries.insert(std::make_pair(key, infoSet));
|
||||
|
||||
// Prints the collection document's and index entry's metadata.
|
||||
_validateState->getCollection()->getRecordStore()->printRecordMetadata(opCtx,
|
||||
recordId);
|
||||
_validateState->getCollection()->getRecordStore()->printRecordMetadata(
|
||||
opCtx, recordId, &(results->recordTimestamps));
|
||||
indexInfo->accessMethod->asSortedData()
|
||||
->getSortedDataInterface()
|
||||
->printIndexEntryMetadata(opCtx, ks);
|
||||
@ -983,7 +1014,7 @@ void KeyStringIndexConsistency::traverseRecord(OperationContext* opCtx,
|
||||
|
||||
for (const auto& keyString : *documentKeySet) {
|
||||
_totalIndexKeys++;
|
||||
this->addDocKey(opCtx, keyString, &indexInfo, recordId);
|
||||
this->addDocKey(opCtx, keyString, &indexInfo, recordId, results);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -114,8 +114,8 @@ public:
|
||||
|
||||
protected:
|
||||
struct IndexKeyBucket {
|
||||
uint32_t indexKeyCount;
|
||||
uint32_t bucketSizeBytes;
|
||||
uint32_t indexKeyCount = 0;
|
||||
uint32_t bucketSizeBytes = 0;
|
||||
};
|
||||
|
||||
CollectionValidation::ValidateState* _validateState;
|
||||
@ -250,7 +250,8 @@ private:
|
||||
void addDocKey(OperationContext* opCtx,
|
||||
const KeyString::Value& ks,
|
||||
IndexInfo* indexInfo,
|
||||
const RecordId& recordId);
|
||||
const RecordId& recordId,
|
||||
ValidateResults* results);
|
||||
|
||||
/**
|
||||
* During the first phase of validation, given the index entry's KeyString, decrement the
|
||||
|
||||
@ -560,7 +560,7 @@ Status ValidateAdaptor::validateRecord(OperationContext* opCtx,
|
||||
BSONObj recordBson = record.toBson();
|
||||
*dataSize = recordBson.objsize();
|
||||
|
||||
if (MONGO_unlikely(_validateState->extraLoggingForTest())) {
|
||||
if (MONGO_unlikely(_validateState->logDiagnostics())) {
|
||||
LOGV2(4666601, "[validate]", "recordId"_attr = recordId, "recordData"_attr = recordBson);
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -44,7 +45,6 @@ struct IndexValidateResults {
|
||||
std::vector<std::string> errors;
|
||||
std::vector<std::string> warnings;
|
||||
int64_t keysTraversed = 0;
|
||||
int64_t keysTraversedFromFullValidate = 0;
|
||||
int64_t keysRemovedFromRecordStore = 0;
|
||||
};
|
||||
|
||||
@ -60,6 +60,9 @@ struct ValidateResults {
|
||||
std::vector<BSONObj> extraIndexEntries;
|
||||
std::vector<BSONObj> missingIndexEntries;
|
||||
std::vector<RecordId> corruptRecords;
|
||||
// Timestamps (startTs, startDurable, stopTs, stopDurableTs) related to records
|
||||
// with validation errors. See WiredTigerRecordStore::printRecordMetadata().
|
||||
std::set<Timestamp> recordTimestamps;
|
||||
long long numRemovedCorruptRecords = 0;
|
||||
long long numRemovedExtraIndexEntries = 0;
|
||||
long long numInsertedMissingIndexEntries = 0;
|
||||
|
||||
@ -58,12 +58,12 @@ ValidateState::ValidateState(OperationContext* opCtx,
|
||||
const NamespaceString& nss,
|
||||
ValidateMode mode,
|
||||
RepairMode repairMode,
|
||||
bool turnOnExtraLoggingForTest)
|
||||
bool logDiagnostics)
|
||||
: _nss(nss),
|
||||
_mode(mode),
|
||||
_repairMode(repairMode),
|
||||
_dataThrottle(opCtx),
|
||||
_extraLoggingForTest(turnOnExtraLoggingForTest) {
|
||||
_logDiagnostics(logDiagnostics) {
|
||||
|
||||
// Subsequent re-locks will use the UUID when 'background' is true.
|
||||
if (isBackground()) {
|
||||
|
||||
@ -52,15 +52,11 @@ class ValidateState {
|
||||
ValidateState& operator=(const ValidateState&) = delete;
|
||||
|
||||
public:
|
||||
/**
|
||||
* 'turnOnExtraLoggingForTest' turns on extra logging for test debugging. This parameter is for
|
||||
* unit testing only.
|
||||
*/
|
||||
ValidateState(OperationContext* opCtx,
|
||||
const NamespaceString& nss,
|
||||
ValidateMode mode,
|
||||
RepairMode repairMode,
|
||||
bool turnOnExtraLoggingForTest = false);
|
||||
bool logDiagnostics);
|
||||
|
||||
const NamespaceString& nss() const {
|
||||
return _nss;
|
||||
@ -190,11 +186,9 @@ public:
|
||||
|
||||
/**
|
||||
* Indicates whether extra logging should occur during validation.
|
||||
*
|
||||
* This is for unit testing only. Intended to improve diagnosibility.
|
||||
*/
|
||||
bool extraLoggingForTest() {
|
||||
return _extraLoggingForTest;
|
||||
bool logDiagnostics() {
|
||||
return _logDiagnostics;
|
||||
}
|
||||
|
||||
boost::optional<Timestamp> getValidateTimestamp() {
|
||||
@ -278,8 +272,8 @@ private:
|
||||
// Used to detect when the catalog is re-opened while yielding locks.
|
||||
uint64_t _catalogGeneration;
|
||||
|
||||
// Can be set by unit tests to obtain better insight into what validate sees/does.
|
||||
bool _extraLoggingForTest;
|
||||
// Can be set to obtain better insight into what validate sees/does.
|
||||
bool _logDiagnostics;
|
||||
|
||||
boost::optional<Timestamp> _validateTs = boost::none;
|
||||
};
|
||||
|
||||
@ -166,7 +166,8 @@ TEST_F(ValidateStateTest, NonExistentCollectionShouldThrowNamespaceNotFoundError
|
||||
CollectionValidation::ValidateState(opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kForeground,
|
||||
CollectionValidation::RepairMode::kNone),
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false),
|
||||
AssertionException,
|
||||
ErrorCodes::NamespaceNotFound);
|
||||
|
||||
@ -174,7 +175,8 @@ TEST_F(ValidateStateTest, NonExistentCollectionShouldThrowNamespaceNotFoundError
|
||||
CollectionValidation::ValidateState(opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kBackground,
|
||||
CollectionValidation::RepairMode::kNone),
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false),
|
||||
AssertionException,
|
||||
ErrorCodes::NamespaceNotFound);
|
||||
}
|
||||
@ -196,7 +198,8 @@ TEST_F(ValidateStateDiskTest, UncheckpointedCollectionShouldThrowCursorNotFoundE
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kBackground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
ASSERT_THROWS_CODE(
|
||||
validateState.initializeCursors(opCtx), AssertionException, ErrorCodes::CursorNotFound);
|
||||
}
|
||||
@ -221,7 +224,8 @@ TEST_F(ValidateStateTest, OpenCursorsOnAllIndexes) {
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kForeground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
validateState.initializeCursors(opCtx);
|
||||
|
||||
// Make sure all of the indexes were found and cursors opened against them. Including the
|
||||
@ -239,7 +243,8 @@ TEST_F(ValidateStateTest, OpenCursorsOnAllIndexes) {
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kForeground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
validateState.initializeCursors(opCtx);
|
||||
ASSERT_EQ(validateState.getIndexes().size(), 5);
|
||||
}
|
||||
@ -266,7 +271,8 @@ TEST_F(ValidateStateDiskTest, OpenCursorsOnCheckpointedIndexes) {
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kBackground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
validateState.initializeCursors(opCtx);
|
||||
|
||||
// Make sure the uncheckpoint'ed indexes are not found.
|
||||
@ -312,7 +318,8 @@ TEST_F(ValidateStateDiskTest, OpenCursorsOnConsistentlyCheckpointedIndexes) {
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kBackground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
validateState.initializeCursors(opCtx);
|
||||
ASSERT_EQ(validateState.getIndexes().size(), 3);
|
||||
}
|
||||
@ -346,7 +353,8 @@ TEST_F(ValidateStateDiskTest, CursorsAreNotOpenedAgainstCheckpointedIndexesThatW
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kBackground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
validateState.initializeCursors(opCtx);
|
||||
ASSERT_EQ(validateState.getIndexes().size(), 3);
|
||||
}
|
||||
@ -359,7 +367,8 @@ TEST_F(ValidateStateDiskTest, CursorsAreNotOpenedAgainstCheckpointedIndexesThatW
|
||||
opCtx,
|
||||
kNss,
|
||||
CollectionValidation::ValidateMode::kBackground,
|
||||
CollectionValidation::RepairMode::kNone);
|
||||
CollectionValidation::RepairMode::kNone,
|
||||
/*logDiagnostics=*/false);
|
||||
validateState.initializeCursors(opCtx);
|
||||
ASSERT_EQ(validateState.getIndexes().size(), 3);
|
||||
}
|
||||
|
||||
@ -539,6 +539,13 @@ Status Cloner::copyDb(OperationContext* opCtx,
|
||||
|
||||
// now build the secondary indexes
|
||||
for (auto&& params : createCollectionParams) {
|
||||
|
||||
// Indexes of sharded collections are not copied: the primary shard is not required to
|
||||
// have all indexes. The listIndexes cmd is sent to the shard owning the MinKey value.
|
||||
if (params.shardedColl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGV2(20422,
|
||||
"copying indexes for: {collectionInfo}",
|
||||
"Copying indexes",
|
||||
|
||||
@ -543,10 +543,9 @@ private:
|
||||
_createSchemaOnConfigSettings(opCtx, requestedVersion);
|
||||
_initializePlacementHistory(opCtx, requestedVersion);
|
||||
_setOnCurrentShardSinceFieldOnChunks(opCtx, requestedVersion);
|
||||
} else if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
_removeRecordPreImagesCollectionOption(opCtx);
|
||||
}
|
||||
|
||||
// TODO SERVER-68889 remove once 7.0 becomes last LTS
|
||||
@ -654,6 +653,33 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Removes collection option "recordPreImages" from all collection definitions.
|
||||
// TODO SERVER-74036: Remove once FCV 7.0 becomes last-LTS.
|
||||
void _removeRecordPreImagesCollectionOption(OperationContext* opCtx) {
|
||||
for (const auto& dbName : DatabaseHolder::get(opCtx)->getNames()) {
|
||||
Lock::DBLock dbLock(opCtx, dbName, MODE_IX);
|
||||
catalog::forEachCollectionFromDb(
|
||||
opCtx,
|
||||
dbName,
|
||||
MODE_X,
|
||||
[&](const CollectionPtr& collection) {
|
||||
// To remove collection option "recordPreImages" from persistent storage, issue
|
||||
// the "collMod" command with none of the parameters set.
|
||||
BSONObjBuilder responseBuilder;
|
||||
uassertStatusOK(processCollModCommand(
|
||||
opCtx, collection->ns(), CollMod{collection->ns()}, &responseBuilder));
|
||||
LOGV2(7383300,
|
||||
"Removed 'recordPreImages' collection option",
|
||||
"ns"_attr = collection->ns(),
|
||||
"collModResponse"_attr = responseBuilder.obj());
|
||||
return true;
|
||||
},
|
||||
[&](const CollectionPtr& collection) {
|
||||
return collection->getCollectionOptions().recordPreImagesOptionUsed;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// _runUpgrade performs all the upgrade specific code for setFCV. Any new feature specific
|
||||
// upgrade code should be placed in the _runUpgrade helper functions:
|
||||
// * _prepareForUpgrade: for any upgrade actions that should be done before taking the FCV full
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include "mongo/db/catalog/collection_validation.h"
|
||||
#include "mongo/db/client.h"
|
||||
#include "mongo/db/commands.h"
|
||||
#include "mongo/db/dbdirectclient.h"
|
||||
#include "mongo/db/query/internal_plans.h"
|
||||
#include "mongo/db/server_options.h"
|
||||
#include "mongo/db/storage/record_store.h"
|
||||
@ -42,6 +43,7 @@
|
||||
#include "mongo/logv2/log.h"
|
||||
#include "mongo/util/fail_point.h"
|
||||
#include "mongo/util/scopeguard.h"
|
||||
#include "mongo/util/testing_proctor.h"
|
||||
|
||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
|
||||
|
||||
@ -66,6 +68,77 @@ std::set<NamespaceString> _validationsInProgress;
|
||||
// finishes on any namespace.
|
||||
stdx::condition_variable _validationNotifier;
|
||||
|
||||
/**
|
||||
* Creates an aggregation command with a $collStats pipeline that fetches 'storageStats' and
|
||||
* 'count'.
|
||||
*/
|
||||
BSONObj makeCollStatsCommand(StringData collectionNameOnly) {
|
||||
BSONArrayBuilder pipelineBuilder;
|
||||
pipelineBuilder << BSON("$collStats"
|
||||
<< BSON("storageStats" << BSONObj() << "count" << BSONObj()));
|
||||
return BSON("aggregate" << collectionNameOnly << "pipeline" << pipelineBuilder.arr() << "cursor"
|
||||
<< BSONObj());
|
||||
}
|
||||
|
||||
/**
|
||||
* $collStats never returns more than a single document. If that ever changes in future, validate
|
||||
* must invariant so that the handling can be updated, but only invariant in testing environments,
|
||||
* never invariant because of debug logging in production situations.
|
||||
*/
|
||||
void verifyCommandResponse(const BSONObj& collStatsResult) {
|
||||
if (TestingProctor::instance().isEnabled()) {
|
||||
invariant(
|
||||
!collStatsResult.getObjectField("cursor").isEmpty() &&
|
||||
!collStatsResult.getObjectField("cursor").getObjectField("firstBatch").isEmpty(),
|
||||
str::stream() << "Expected a cursor to be present in the $collStats results: "
|
||||
<< collStatsResult.toString());
|
||||
invariant(collStatsResult.getObjectField("cursor").getIntField("id") == 0,
|
||||
str::stream() << "Expected cursor ID to be 0: " << collStatsResult.toString());
|
||||
} else {
|
||||
uassert(
|
||||
7463202,
|
||||
str::stream() << "Expected a cursor to be present in the $collStats results: "
|
||||
<< collStatsResult.toString(),
|
||||
!collStatsResult.getObjectField("cursor").isEmpty() &&
|
||||
!collStatsResult.getObjectField("cursor").getObjectField("firstBatch").isEmpty());
|
||||
uassert(7463203,
|
||||
str::stream() << "Expected cursor ID to be 0: " << collStatsResult.toString(),
|
||||
collStatsResult.getObjectField("cursor").getIntField("id") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the $collStats results for 'nss' to provide additional debug information for validation
|
||||
* failures.
|
||||
*/
|
||||
void logCollStats(OperationContext* opCtx, const NamespaceString& nss) {
|
||||
DBDirectClient client(opCtx);
|
||||
|
||||
BSONObj collStatsResult;
|
||||
try {
|
||||
// Run $collStats via aggregation.
|
||||
// Any command errors will throw and be caught in the 'catch'.
|
||||
client.runCommand(nss.dbName() /* DatabaseName */,
|
||||
makeCollStatsCommand(nss.coll()),
|
||||
collStatsResult /* command return results */);
|
||||
verifyCommandResponse(collStatsResult);
|
||||
|
||||
LOGV2_OPTIONS(7463200,
|
||||
logv2::LogTruncation::Disabled,
|
||||
"Corrupt namespace $collStats results",
|
||||
"namespace"_attr = nss,
|
||||
"collStats"_attr =
|
||||
collStatsResult.getObjectField("cursor").getObjectField("firstBatch"));
|
||||
} catch (const DBException& ex) {
|
||||
// Catch the error so that the validate error does not get overwritten by the attempt to add
|
||||
// debug logging.
|
||||
LOGV2_WARNING(7463201,
|
||||
"Failed to fetch $collStats for validation error",
|
||||
"namespace"_attr = nss,
|
||||
"error"_attr = ex.toStatus());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
@ -141,6 +214,7 @@ public:
|
||||
|
||||
const NamespaceString nss(CommandHelpers::parseNsCollectionRequired(dbName, cmdObj));
|
||||
bool background = cmdObj["background"].trueValue();
|
||||
bool logDiagnostics = cmdObj["logDiagnostics"].trueValue();
|
||||
|
||||
const bool fullValidate = cmdObj["full"].trueValue();
|
||||
if (background && fullValidate) {
|
||||
@ -299,8 +373,8 @@ public:
|
||||
}
|
||||
|
||||
ValidateResults validateResults;
|
||||
Status status =
|
||||
CollectionValidation::validate(opCtx, nss, mode, repairMode, &validateResults, &result);
|
||||
Status status = CollectionValidation::validate(
|
||||
opCtx, nss, mode, repairMode, &validateResults, &result, logDiagnostics);
|
||||
if (!status.isOK()) {
|
||||
return CommandHelpers::appendCommandStatusNoThrow(result, status);
|
||||
}
|
||||
@ -311,6 +385,7 @@ public:
|
||||
result.append("advice",
|
||||
"A corrupt namespace has been detected. See "
|
||||
"http://dochub.mongodb.org/core/data-recovery for recovery steps.");
|
||||
logCollStats(opCtx, nss);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@ -839,13 +839,21 @@ void LockerImpl::restoreLockState(OperationContext* opCtx, const Locker::LockSna
|
||||
getFlowControlTicket(opCtx, state.globalMode);
|
||||
|
||||
std::vector<OneLock>::const_iterator it = state.locks.begin();
|
||||
// If we locked the PBWM, it must be locked before the resourceIdGlobal and
|
||||
// resourceIdReplicationStateTransitionLock resources.
|
||||
// If we locked the PBWM, it must be locked before the
|
||||
// resourceIdFeatureCompatibilityVersion, resourceIdReplicationStateTransitionLock, and
|
||||
// resourceIdGlobal resources.
|
||||
if (it != state.locks.end() && it->resourceId == resourceIdParallelBatchWriterMode) {
|
||||
lock(opCtx, it->resourceId, it->mode);
|
||||
it++;
|
||||
}
|
||||
|
||||
// If we locked the FCV lock, it must be locked before the
|
||||
// resourceIdReplicationStateTransitionLock and resourceIdGlobal resources.
|
||||
if (it != state.locks.end() && it->resourceId == resourceIdFeatureCompatibilityVersion) {
|
||||
lock(opCtx, it->resourceId, it->mode);
|
||||
it++;
|
||||
}
|
||||
|
||||
// If we locked the RSTL, it must be locked before the resourceIdGlobal resource.
|
||||
if (it != state.locks.end() && it->resourceId == resourceIdReplicationStateTransitionLock) {
|
||||
lock(opCtx, it->resourceId, it->mode);
|
||||
@ -854,6 +862,8 @@ void LockerImpl::restoreLockState(OperationContext* opCtx, const Locker::LockSna
|
||||
|
||||
lockGlobal(opCtx, state.globalMode);
|
||||
for (; it != state.locks.end(); it++) {
|
||||
// Ensures we don't acquire locks out of order which can lead to deadlock.
|
||||
invariant(it->resourceId.getType() != ResourceType::RESOURCE_GLOBAL);
|
||||
lock(opCtx, it->resourceId, it->mode);
|
||||
}
|
||||
invariant(_modeForTicket != MODE_NONE);
|
||||
|
||||
@ -186,6 +186,24 @@ std::size_t CursorManager::timeoutCursors(OperationContext* opCtx, Date_t now) {
|
||||
return toDisposeWithoutMutex.size();
|
||||
}
|
||||
|
||||
std::vector<CursorId> CursorManager::getCursorIdsForNamespace(const NamespaceString& nss) {
|
||||
std::vector<CursorId> cursorIds;
|
||||
|
||||
// Lock and inspect one partition at a time in order to avoid contention. It is acceptable for
|
||||
// the output not to include info about cursors opened/closed while iterating.
|
||||
for (size_t partitionId = 0; partitionId < kNumPartitions; ++partitionId) {
|
||||
auto lockedPartition = _cursorMap->lockOnePartitionById(partitionId);
|
||||
for (auto it = lockedPartition->begin(); it != lockedPartition->end(); ++it) {
|
||||
auto* cursor = it->second;
|
||||
if (cursor->nss() == nss) {
|
||||
cursorIds.push_back(cursor->cursorid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cursorIds;
|
||||
}
|
||||
|
||||
StatusWith<ClientCursorPin> CursorManager::pinCursor(
|
||||
OperationContext* opCtx,
|
||||
CursorId id,
|
||||
|
||||
@ -193,6 +193,17 @@ public:
|
||||
std::pair<Status, int> killCursorsWithMatchingSessions(OperationContext* opCtx,
|
||||
const SessionKiller::Matcher& matcher);
|
||||
|
||||
/**
|
||||
* Returns a vector of open cursor ids registered on the `nss`. The result doesn't include
|
||||
* cursors registered for a different namespace but also acting on `nss` (e.g. in presence of
|
||||
* sub-pipelines).
|
||||
*
|
||||
* Locks/inspects one partition at a time, hence the result might not include new cursors being
|
||||
* opened on the namespace. The only guarantee is that the result will include any cursor opened
|
||||
* before calling this method and not closed before iterating the partition holding it.
|
||||
*/
|
||||
std::vector<CursorId> getCursorIdsForNamespace(const NamespaceString& nss);
|
||||
|
||||
/**
|
||||
* Set the CursorManager's ClockSource*.
|
||||
*/
|
||||
|
||||
@ -616,7 +616,8 @@ BucketSpec::BucketPredicate BucketSpec::createPredicatesOnBucketLevelField(
|
||||
|
||||
// If we have a leaf predicate on a meta field, we can map it to the bucket's meta field.
|
||||
// This includes comparisons such as $eq and $lte, as well as other non-comparison predicates
|
||||
// such as $exists, $mod, or $elemMatch.
|
||||
// such as $exists, or $mod. Unrenamable expressions can't be split into a whole bucket level
|
||||
// filter, when we should return nullptr.
|
||||
//
|
||||
// Metadata predicates are partially handled earlier, by splitting the match expression into a
|
||||
// metadata-only part, and measurement/time-only part. However, splitting a $match into two
|
||||
@ -634,12 +635,16 @@ BucketSpec::BucketPredicate BucketSpec::createPredicatesOnBucketLevelField(
|
||||
if (!includeMetaField)
|
||||
return handleIneligible(policy, matchExpr, "cannot handle an excluded meta field");
|
||||
|
||||
auto looseResult = matchExpr->shallowClone();
|
||||
expression::applyRenamesToExpression(
|
||||
looseResult.get(),
|
||||
{{bucketSpec.metaField().value(), timeseries::kBucketMetaFieldName.toString()}});
|
||||
auto tightResult = looseResult->shallowClone();
|
||||
return {std::move(looseResult), std::move(tightResult)};
|
||||
if (expression::hasOnlyRenameableMatchExpressionChildren(*matchExpr)) {
|
||||
auto looseResult = matchExpr->shallowClone();
|
||||
expression::applyRenamesToExpression(
|
||||
looseResult.get(),
|
||||
{{bucketSpec.metaField().value(), timeseries::kBucketMetaFieldName.toString()}});
|
||||
auto tightResult = looseResult->shallowClone();
|
||||
return {std::move(looseResult), std::move(tightResult)};
|
||||
} else {
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
}
|
||||
|
||||
if (matchExpr->matchType() == MatchExpression::AND) {
|
||||
|
||||
@ -300,6 +300,14 @@ std::pair<FLEBatchResult, write_ops::InsertCommandReply> processInsert(
|
||||
uint32_t numDocs = 0;
|
||||
write_ops::WriteCommandReplyBase writeBase;
|
||||
|
||||
if (documents.size() == 1) {
|
||||
auto serverPayload = EDCServerCollection::getEncryptedFieldInfo(documents[0]);
|
||||
if (serverPayload.size() == 0) {
|
||||
return std::pair<FLEBatchResult, write_ops::InsertCommandReply>{
|
||||
FLEBatchResult::kNotProcessed, write_ops::InsertCommandReply()};
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& document : documents) {
|
||||
const auto& [swResult, reply] =
|
||||
insertSingleDocument(opCtx, insertRequest, document, &stmtId, getTxns);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user