diff options
author | Andrew Morrow <acm@mongodb.com> | 2020-05-17 16:41:54 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-27 16:10:48 +0000 |
commit | 17d9094752fec7dd29c9eedac9bd7cccb8cf8f6e (patch) | |
tree | e0e00f22fde4e42b99c92db6353e9fcde91b46f6 /src/mongo | |
parent | 2de03a25a0a3dc8f7e675c33ff9e1b1370532d41 (diff) | |
download | mongo-17d9094752fec7dd29c9eedac9bd7cccb8cf8f6e.tar.gz |
SERVER-48272 Reduce startup time for dynamically linked binaries
Minimizing the list of NEEDED entries directly attached to the core
programs reduces startup time for dynamically linked binaries by
approximately 40 percent.
Diffstat (limited to 'src/mongo')
24 files changed, 1010 insertions, 533 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 346879db8b6..80447a02e6a 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -336,7 +336,7 @@ env.Library( if env.TargetOSIs('windows'): generatedDbManifest = env.Substfile( - 'db/db.manifest.in', + 'db/mongod.manifest.in', SUBST_DICT=[ ('@mongo_version_major@', version_parts[0]), ('@mongo_version_minor@', version_parts[1]), @@ -346,16 +346,45 @@ if env.TargetOSIs('windows'): ]) env.Alias('generated-sources', generatedDbManifest) - env.Depends("db/db.res", generatedDbManifest) + env.Depends("db/mongod.res", generatedDbManifest) mongod = env.Program( target="mongod", source=[ - 'db/db.cpp', - 'db/logical_session_cache_factory_mongod.cpp', - 'db/read_write_concern_defaults_cache_lookup_mongod.cpp', - ] + env.WindowsResourceFile("db/db.rc"), + 'db/mongod.cpp' + ] + env.WindowsResourceFile("db/mongod.rc"), + LIBDEPS=[ + # NOTE: Do not add new libdeps (public or private) here unless + # required by the linker to satisfy symbol dependencies from + # the files listed above in `sources`. If you need to add a + # library to inject a static or mongo initializer to mongod, + # please add that library as a private libdep of + # mongod_initializers. + 'base', + 'mongod_main', + 'util/quick_exit', + ], + AIB_COMPONENT="mongod", + AIB_COMPONENTS_EXTRA=[ + "core", + "default", + "dist", + "dist-test", + "servers", + "integration-tests", + ], +) + +env.Library( + target="mongod_initializers", + source=[ + # NOTE: If you add an additional source file here, please delete + # the file db/mongod_initializers.cpp. + "db/mongod_initializers.cpp", + ], LIBDEPS_PRIVATE=[ + # NOTE: If you need to add a static or mongo initializer to mongod startup, + # please add that library here, as a private library dependency. '$BUILD_DIR/third_party/shim_snappy', 'base', 'db/auth/auth_op_observer', @@ -473,14 +502,90 @@ mongod = env.Program( 'util/version_impl', 'watchdog/watchdog_mongod', ], - AIB_COMPONENT="mongod", - AIB_COMPONENTS_EXTRA=[ - "core", - "default", - "dist", - "dist-test", - "servers", - "integration-tests", + LIBDEPS=[ + # NOTE: This list must remain empty. Please only add to LIBDEPS_PRIVATE + ], +) + +env.Library( + target="mongod_main", + source=[ + 'db/mongod_main.cpp', + 'db/logical_session_cache_factory_mongod.cpp', + 'db/read_write_concern_defaults_cache_lookup_mongod.cpp', + ], + LIBDEPS_PRIVATE=[ + # NOTE: Do not add new libdeps (public or private) here unless + # required by the linker to satisfy symbol dependencies from + # the files listed above in `sources`. If you need to add a + # library to inject a static or mongo initializer to mongod, + # please add that library as a private libdep of + # mongod_initializers. + 'base', + 'client/clientdriver_minimal', + 'db/auth/auth_op_observer', + 'db/catalog/catalog_impl', + 'db/catalog/collection', + 'db/catalog/health_log', + 'db/commands/mongod', + 'db/concurrency/flow_control_ticketholder', + 'db/concurrency/lock_manager', + 'db/free_mon/free_mon_mongod', + 'db/ftdc/ftdc_mongod', + 'db/index/index_access_method_factory', + 'db/index/index_access_methods', + 'db/index_builds_coordinator_mongod', + 'db/initialize_server_security_state', + 'db/initialize_snmp', + 'db/keys_collection_client_direct', + 'db/kill_sessions', + 'db/kill_sessions_local', + 'db/log_process_details', + 'db/logical_clock', + 'db/mirror_maestro', + 'db/mongod_options', + 'db/op_observer', + 'db/periodic_runner_job_abort_expired_transactions', + 'db/pipeline/process_interface/mongod_process_interface_factory', + 'db/repair_database_and_check_version', + 'db/repl/drop_pending_collection_reaper', + 'db/repl/repl_coordinator_impl', + 'db/repl/replication_recovery', + 'db/repl/serveronly_repl', + 'db/repl/storage_interface_impl', + 'db/repl/topology_coordinator', + 'db/s/op_observer_sharding_impl', + 'db/s/sessions_collection_config_server', + 'db/s/sharding_runtime_d', + 'db/serverinit', + 'db/service_context_d', + 'db/service_liaison_mongod', + 'db/sessions_collection_rs', + 'db/sessions_collection_standalone', + 'db/startup_warnings_mongod', + 'db/storage/backup_cursor_hooks', + 'db/storage/flow_control', + 'db/storage/flow_control_parameters', + 'db/storage/storage_control', + 'db/storage/storage_engine_common', + 'db/system_index', + 'db/ttl_d', + 'mongod_initializers', + 's/grid', + 's/sessions_collection_sharded', + 's/sessions_collection_sharded', + 'scripting/scripting', + 'transport/service_entry_point', + 'transport/transport_layer_manager', + 'util/cmdline_utils/cmdline_utils', + 'util/concurrency/thread_pool', + 'util/latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [], + 'util/net/ssl_manager', + 'util/signal_handlers', + 'watchdog/watchdog_mongod', + ], + LIBDEPS=[ + # NOTE: This list must remain empty. Please only add to LIBDEPS_PRIVATE ], ) @@ -491,7 +596,7 @@ if not hygienic: if env.TargetOSIs('windows'): generatedServerManifest = env.Substfile( - 's/server.manifest.in', + 's/mongos.manifest.in', SUBST_DICT=[ ('@mongo_version_major@', version_parts[0]), ('@mongo_version_minor@', version_parts[1]), @@ -501,7 +606,7 @@ if env.TargetOSIs('windows'): ]) env.Alias('generated-sources', generatedServerManifest) - env.Depends("s/server.res", generatedServerManifest) + env.Depends("s/mongos.res", generatedServerManifest) mongotrafficreader = env.Program( @@ -524,19 +629,39 @@ if not hygienic: mongos = env.Program( target='mongos', source=[ - "db/read_write_concern_defaults_cache_lookup_mongos.cpp", + 's/mongos.cpp', + ] + env.WindowsResourceFile("s/mongos.rc"), + LIBDEPS=[ + # NOTE: Do not add new libdeps (public or private) here unless + # required by the linker to satisfy symbol dependencies from + # the files listed above in `sources`. If you need to add a + # library to inject a static or mongo initializer to mongos, + # please add that library as a private libdep of + # mongos_initializers. + 'base', + 'mongos_main', + 'util/quick_exit' + ], + AIB_COMPONENT="mongos", + AIB_COMPONENTS_EXTRA=[ + "core", + "dist", + "dist-test", + "servers", + "integration-tests", + ], +) + +env.Library( + target='mongos_initializers', + source=[ 's/cluster_cursor_stats.cpp', - 's/mongos_options.cpp', - 's/mongos_options_init.cpp', - env.Idlc('s/mongos_options.idl')[0], 's/router_transactions_server_status.cpp', 's/s_sharding_server_status.cpp', - 's/server.cpp', - 's/service_entry_point_mongos.cpp', - 's/sharding_uptime_reporter.cpp', - 's/version_mongos.cpp', - ] + env.WindowsResourceFile("s/server.rc"), - LIBDEPS=[ + ], + LIBDEPS_PRIVATE=[ + # NOTE: If you need to add a static or mongo initializer to mongos startup, + # please add that library here, as a private library dependency. 'db/audit', 'db/auth/authmongos', 'db/commands/server_status', @@ -576,76 +701,81 @@ mongos = env.Program( 'util/latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [], 'util/net/ssl_options_server' if get_option('ssl') == 'on' else '', 'util/ntservice', + 'util/options_parser/options_parser', + 'util/options_parser/options_parser_init', 'util/version_impl', ], + LIBDEPS=[ + # NOTE: This list must remain empty. Please only add to LIBDEPS_PRIVATE + ], +) + +env.Library( + target='mongos_main', + source=[ + 'db/read_write_concern_defaults_cache_lookup_mongos.cpp', + 's/mongos_main.cpp', + 's/mongos_options.cpp', + 's/mongos_options_init.cpp', + env.Idlc('s/mongos_options.idl')[0], + 's/service_entry_point_mongos.cpp', + 's/sharding_uptime_reporter.cpp', + 's/version_mongos.cpp', + ], LIBDEPS_PRIVATE=[ - 'util/options_parser/options_parser_init', - 'util/options_parser/options_parser', + # NOTE: Do not add new libdeps (public or private) here unless + # required by the linker to satisfy symbol dependencies from + # the files listed above in `sources`. If you need to add a + # library to inject a static or mongo initializer to mongos, + # please add that library as a private libdep of + # mongos_initializers. + 'db/audit', + 'db/auth/authmongos', + 'db/ftdc/ftdc_mongos', + 'db/initialize_server_security_state', + 'db/log_process_details', + 'db/read_write_concern_defaults', + 'db/serverinit', + 'db/service_liaison_mongos', + 'db/session_catalog', + 'db/startup_warnings_common', + 'mongos_initializers', + 's/client/sharding_client', + 's/cluster_last_error_info', + 's/commands/cluster_commands', + 's/committed_optime_metadata_hook', + 's/common_s', + 's/mongos_topology_coordinator', + 's/query/cluster_cursor_cleanup_job', + 's/sessions_collection_sharded', + 's/sharding_egress_metadata_hook_for_mongos', + 's/sharding_initialization', + 's/sharding_router_api', + 'transport/service_entry_point', + 'transport/transport_layer_manager', + 'util/latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [], + 'util/net/ssl_manager', + 'util/periodic_runner_factory', + 'util/signal_handlers', + ], + LIBDEPS=[ + # NOTE: This list must remain empty. Please only add to LIBDEPS_PRIVATE ], - AIB_COMPONENT="mongos", - AIB_COMPONENTS_EXTRA=[ - "core", - "dist", - "dist-test", - "servers", - "integration-tests", - ] ) + if not hygienic: env.Install('#/', mongos) -env.Library("linenoise_utf8", - source=[ - "shell/linenoise_utf8.cpp", - ]) - # --- shell --- if not has_option('noshell') and usemozjs: - shell_core_env = env.Clone() - if has_option("safeshell"): - shell_core_env.Append(CPPDEFINES=["MONGO_SAFE_SHELL"]) - shell_core_env.Library("shell_core", - source=[ - "shell/linenoise.cpp", - "shell/mk_wcwidth.cpp" - ], - LIBDEPS=[ - 'client/clientdriver_network', - 'db/catalog/index_key_validate', - 'db/logical_session_id_helpers', - 'db/mongohasher', - 'db/query/command_request_response', - 'db/query/query_request', - 'db/server_options_core', - 'db/traffic_reader', - 'linenoise_utf8', - 'rpc/protocol', - 'scripting/scripting', - 'shell/benchrun', - 'shell/mongojs', - 'shell/shell_utils', - 'transport/message_compressor', - 'transport/transport_layer_manager', - 'util/net/network', - 'util/options_parser/options_parser_init', - 'util/password', - 'util/processinfo', - 'util/signal_handlers', - 'util/version_impl', - 'executor/thread_pool_task_executor', - 'executor/network_interface_thread_pool', - 'executor/network_interface_factory' - ], - ) - shellEnv = env.Clone() if env.TargetOSIs('windows'): shellEnv.Append(LIBS=["winmm.lib"]) generatedMongoManifest = shellEnv.Substfile( - 'shell/shell.manifest.in', + 'shell/mongo.manifest.in', SUBST_DICT=[ ('@mongo_version_major@', version_parts[0]), ('@mongo_version_minor@', version_parts[1]), @@ -654,31 +784,22 @@ if not has_option('noshell') and usemozjs: ('@mongo_version_extra_str@', version_extra), ]) shellEnv.Alias('generated-sources', generatedMongoManifest) - shellEnv.Depends("shell/shell.res", generatedMongoManifest) + shellEnv.Depends("shell/mongo.res", generatedMongoManifest) mongo_shell = shellEnv.Program( - "mongo", - [ - "shell/dbshell.cpp", - "shell/mongodbcr.cpp", - "shell/shell_options_init.cpp", - ] + env.WindowsResourceFile("shell/shell.rc"), + target="mongo", + source=[ + "shell/mongo.cpp", + ] + env.WindowsResourceFile("shell/mongo.rc"), LIBDEPS=[ - "$BUILD_DIR/third_party/shim_pcrecpp", - "shell_core", - "db/server_options_core", - "client/clientdriver_network", - "shell/kms_shell" if get_option('ssl') == 'on' else '', - "shell/encrypted_dbclient" if get_option('ssl') == 'on' else '', - "$BUILD_DIR/mongo/util/password", - '$BUILD_DIR/mongo/db/storage/duplicate_key_error_info', - "$BUILD_DIR/mongo/db/views/resolved_view", - ], - LIBDEPS_PRIVATE=[ - 'shell/shell_options_register', - 'transport/message_compressor_options_client', - "$BUILD_DIR/mongo/client/connection_string", - '$BUILD_DIR/mongo/util/net/ssl_options_client' if get_option('ssl') == 'on' else '', + # NOTE: Do not add new libdeps (public or private) here unless + # required by the linker to satisfy symbol dependencies from + # the files listed above in `sources`. If you need to add a + # library to inject a static or mongo initializer to mongo, + # please add that library as a private libdep of + # mongo_initializers. + 'base', + 'mongo_main', ], AIB_COMPONENT="mongo", AIB_COMPONENTS_EXTRA=[ @@ -690,6 +811,79 @@ if not has_option('noshell') and usemozjs: ], ) + env.Library( + target="mongo_initializers", + source=[ + "shell/mongodbcr.cpp", + "shell/shell_options_init.cpp", + ], + LIBDEPS_PRIVATE=[ + # NOTE: If you need to add a static or mongo initializer to mongo startup, + # please add that library here, as a private library dependency. + "$BUILD_DIR/third_party/shim_pcrecpp", + "client/clientdriver_network", + "client/connection_string", + "db/catalog/index_key_validate", + "db/logical_session_id_helpers", + "db/mongohasher", + "db/query/command_request_response", + "db/query/query_request", + "db/server_options_core", + "db/storage/duplicate_key_error_info", + "db/traffic_reader", + "db/views/resolved_view", + "executor/network_interface_factory", + "executor/network_interface_thread_pool", + "executor/thread_pool_task_executor", + "rpc/protocol", + "scripting/scripting", + "shell/benchrun", + "shell/encrypted_dbclient" if get_option('ssl') == 'on' else '', + "shell/kms_shell" if get_option('ssl') == 'on' else '', + "shell/mongojs", + "shell/shell_options_register", + "shell/shell_utils", + "transport/message_compressor", + "transport/message_compressor_options_client", + "transport/transport_layer_manager", + "util/net/network", + "util/net/ssl_options_client" if get_option('ssl') == 'on' else '', + "util/options_parser/options_parser_init", + "util/password", + "util/processinfo", + "util/signal_handlers", + "util/version_impl", + ], + LIBDEPS=[ + # NOTE: This list must remain empty. Please only add to LIBDEPS_PRIVATE + ], + + ) + + env.Library( + target="mongo_main", + source=[ + "shell/mongo_main.cpp", + ], + LIBDEPS_PRIVATE=[ + # NOTE: Do not add new libdeps (public or private) here unless + # required by the linker to satisfy symbol dependencies from + # the files listed above in `sources`. If you need to add a + # library to inject a static or mongo initializer to mongo, + # please add that library as a private libdep of + # mongo_initializers. + "mongo_initializers", + "shell/linenoise", + "shell/shell_utils", + "transport/transport_layer", + "util/net/ssl_manager", + "util/signal_handlers", + ], + LIBDEPS=[ + # NOTE: This list must remain empty. Please only add to LIBDEPS_PRIVATE + ], + ) + if not hygienic: shellEnv.Install( '#/', mongo_shell ) else: diff --git a/src/mongo/db/fts/unicode/SConscript b/src/mongo/db/fts/unicode/SConscript index 85f71077606..2b783364d64 100644 --- a/src/mongo/db/fts/unicode/SConscript +++ b/src/mongo/db/fts/unicode/SConscript @@ -48,7 +48,7 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/base', - '$BUILD_DIR/mongo/linenoise_utf8', + '$BUILD_DIR/mongo/shell/linenoise_utf8', ] ) diff --git a/src/mongo/db/mongod.cpp b/src/mongo/db/mongod.cpp new file mode 100644 index 00000000000..3fd8f53c106 --- /dev/null +++ b/src/mongo/db/mongod.cpp @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/db/mongod_main.h" +#include "mongo/util/quick_exit.h" +#include "mongo/util/text.h" + +#if defined(_WIN32) +// In Windows, wmain() is an alternate entry point for main(), and receives the same parameters +// as main() but encoded in Windows Unicode (UTF-16); "wide" 16-bit wchar_t characters. The +// WindowsCommandLine object converts these wide character strings to a UTF-8 coded equivalent +// and makes them available through the argv() and envp() members. This enables mongoDbMain() +// to process UTF-8 encoded arguments and environment variables without regard to platform. +int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) { + mongo::WindowsCommandLine wcl(argc, argvW, envpW); + int exitCode = mongo::mongod_main(argc, wcl.argv(), wcl.envp()); + mongo::quickExit(exitCode); +} +#else +int main(int argc, char* argv[], char** envp) { + int exitCode = mongo::mongod_main(argc, argv, envp); + mongo::quickExit(exitCode); +} +#endif diff --git a/src/mongo/db/db.manifest.in b/src/mongo/db/mongod.manifest.in index ea9d02d9a83..ea9d02d9a83 100644 --- a/src/mongo/db/db.manifest.in +++ b/src/mongo/db/mongod.manifest.in diff --git a/src/mongo/db/db.rc b/src/mongo/db/mongod.rc index 343ea2d7642..c2fbc5c9751 100644 --- a/src/mongo/db/db.rc +++ b/src/mongo/db/mongod.rc @@ -53,4 +53,4 @@ BEGIN END END -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "mongo/db/db.manifest" +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "mongo/db/mongod.manifest" diff --git a/src/mongo/db/mongod_initializers.cpp b/src/mongo/db/mongod_initializers.cpp new file mode 100644 index 00000000000..854bf218172 --- /dev/null +++ b/src/mongo/db/mongod_initializers.cpp @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +// This file intentionally blank. mongod_initializers.cpp exists only to provide +// a compilable source file for systems which cannot produce a library with no sources. diff --git a/src/mongo/db/db.cpp b/src/mongo/db/mongod_main.cpp index bc4554893f6..759df7503c3 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/mongod_main.cpp @@ -31,6 +31,8 @@ #include "mongo/platform/basic.h" +#include "mongo/db/mongod_main.h" + #include <boost/filesystem/operations.hpp> #include <boost/optional.hpp> #include <fstream> @@ -1262,7 +1264,9 @@ void shutdownTask(const ShutdownTaskArgs& shutdownArgs) { #endif } -int mongoDbMain(int argc, char* argv[], char** envp) { +} // namespace + +int mongod_main(int argc, char* argv[], char** envp) { ThreadSafetyContext::getThreadSafetyContext()->forbidMultiThreading(); registerShutdownTask(shutdownTask); @@ -1339,23 +1343,4 @@ int mongoDbMain(int argc, char* argv[], char** envp) { return 0; } -} // namespace } // namespace mongo - -#if defined(_WIN32) -// In Windows, wmain() is an alternate entry point for main(), and receives the same parameters -// as main() but encoded in Windows Unicode (UTF-16); "wide" 16-bit wchar_t characters. The -// WindowsCommandLine object converts these wide character strings to a UTF-8 coded equivalent -// and makes them available through the argv() and envp() members. This enables mongoDbMain() -// to process UTF-8 encoded arguments and environment variables without regard to platform. -int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) { - mongo::WindowsCommandLine wcl(argc, argvW, envpW); - int exitCode = mongo::mongoDbMain(argc, wcl.argv(), wcl.envp()); - mongo::quickExit(exitCode); -} -#else -int main(int argc, char* argv[], char** envp) { - int exitCode = mongo::mongoDbMain(argc, argv, envp); - mongo::quickExit(exitCode); -} -#endif diff --git a/src/mongo/db/mongod_main.h b/src/mongo/db/mongod_main.h new file mode 100644 index 00000000000..0e5a8e06383 --- /dev/null +++ b/src/mongo/db/mongod_main.h @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +namespace mongo { + +int mongod_main(int argc, char* argv[], char** envp); + +} // namespace mongo diff --git a/src/mongo/db/storage/SConscript b/src/mongo/db/storage/SConscript index e32b8ba329a..4d5f1ef273b 100644 --- a/src/mongo/db/storage/SConscript +++ b/src/mongo/db/storage/SConscript @@ -186,9 +186,9 @@ env.Library( ], LIBDEPS= ['$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/service_context'], - PROGDEPS_DEPENDENTS=[ - '$BUILD_DIR/mongo/mongod', - '$BUILD_DIR/mongo/mongos', + LIBDEPS_DEPENDENTS=[ + '$BUILD_DIR/mongo/mongod_initializers', + '$BUILD_DIR/mongo/mongos_initializers', ], ) @@ -201,8 +201,8 @@ env.Library( '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/service_context', ], - PROGDEPS_DEPENDENTS=[ - '$BUILD_DIR/mongo/mongod', + LIBDEPS_DEPENDENTS=[ + '$BUILD_DIR/mongo/mongod_initializers', ], ) diff --git a/src/mongo/db/storage/wiredtiger/SConscript b/src/mongo/db/storage/wiredtiger/SConscript index 79bc99ec83a..d679a2ed6b9 100644 --- a/src/mongo/db/storage/wiredtiger/SConscript +++ b/src/mongo/db/storage/wiredtiger/SConscript @@ -18,10 +18,11 @@ env.Library( ], LIBDEPS= ['$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/service_context'], - PROGDEPS_DEPENDENTS=[ - '$BUILD_DIR/mongo/mongod', - '$BUILD_DIR/mongo/mongos', + LIBDEPS_DEPENDENTS=[ + '$BUILD_DIR/mongo/mongod_initializers', + '$BUILD_DIR/mongo/mongos_initializers', ], + ) if wiredtiger: diff --git a/src/mongo/dbtests/SConscript b/src/mongo/dbtests/SConscript index c220ba2b041..3337f065559 100644 --- a/src/mongo/dbtests/SConscript +++ b/src/mongo/dbtests/SConscript @@ -129,10 +129,12 @@ if not has_option('noshell') and usemozjs: ], LIBDEPS=[ "$BUILD_DIR/mongo/bson/mutable/mutable_bson_test_utils", + "$BUILD_DIR/mongo/client/clientdriver_network", "$BUILD_DIR/mongo/client/replica_set_monitor_protocol_test_util", "$BUILD_DIR/mongo/db/auth/authmongod", "$BUILD_DIR/mongo/db/bson/dotted_path_support", "$BUILD_DIR/mongo/db/catalog/collection_validation", + "$BUILD_DIR/mongo/db/catalog/index_key_validate", "$BUILD_DIR/mongo/db/catalog/multi_index_block", "$BUILD_DIR/mongo/db/catalog_raii", "$BUILD_DIR/mongo/db/commands/mongod", @@ -142,10 +144,13 @@ if not has_option('noshell') and usemozjs: "$BUILD_DIR/mongo/db/index/index_access_methods", "$BUILD_DIR/mongo/db/index/index_build_interceptor", "$BUILD_DIR/mongo/db/logical_clock", + "$BUILD_DIR/mongo/db/logical_session_id_helpers", "$BUILD_DIR/mongo/db/logical_time_metadata_hook", + "$BUILD_DIR/mongo/db/mongohasher", "$BUILD_DIR/mongo/db/query/collation/collator_interface_mock", "$BUILD_DIR/mongo/db/query/command_request_response", "$BUILD_DIR/mongo/db/query/query_planner_test_lib", + "$BUILD_DIR/mongo/db/query/query_request", "$BUILD_DIR/mongo/db/query/query_test_service_context", "$BUILD_DIR/mongo/db/query_exec", "$BUILD_DIR/mongo/db/repl/drop_pending_collection_reaper", @@ -158,20 +163,34 @@ if not has_option('noshell') and usemozjs: "$BUILD_DIR/mongo/db/repl/storage_interface_impl", "$BUILD_DIR/mongo/db/repl/timestamp_block", "$BUILD_DIR/mongo/db/s/op_observer_sharding_impl", + "$BUILD_DIR/mongo/db/server_options_core", "$BUILD_DIR/mongo/db/sessions_collection_standalone", "$BUILD_DIR/mongo/db/storage/biggie/storage_biggie", "$BUILD_DIR/mongo/db/storage/durable_catalog_impl", "$BUILD_DIR/mongo/db/storage/ephemeral_for_test/storage_ephemeral_for_test", - "$BUILD_DIR/mongo/db/storage/storage_engine_impl", "$BUILD_DIR/mongo/db/storage/storage_debug_util", + "$BUILD_DIR/mongo/db/storage/storage_engine_impl", "$BUILD_DIR/mongo/db/storage/wiredtiger/storage_wiredtiger" if wiredtiger else [], + "$BUILD_DIR/mongo/db/traffic_reader", "$BUILD_DIR/mongo/db/transaction", - "$BUILD_DIR/mongo/shell_core", + "$BUILD_DIR/mongo/executor/network_interface_factory", + "$BUILD_DIR/mongo/executor/network_interface_thread_pool", + "$BUILD_DIR/mongo/executor/thread_pool_task_executor", + "$BUILD_DIR/mongo/rpc/protocol", + "$BUILD_DIR/mongo/scripting/scripting", + "$BUILD_DIR/mongo/shell/benchrun", + "$BUILD_DIR/mongo/shell/mongojs", + "$BUILD_DIR/mongo/shell/shell_utils", + "$BUILD_DIR/mongo/transport/message_compressor", "$BUILD_DIR/mongo/transport/message_compressor_options_server", "$BUILD_DIR/mongo/transport/transport_layer_manager", "$BUILD_DIR/mongo/util/clock_source_mock", "$BUILD_DIR/mongo/util/net/network", + "$BUILD_DIR/mongo/util/options_parser/options_parser_init", + "$BUILD_DIR/mongo/util/password", + "$BUILD_DIR/mongo/util/processinfo", "$BUILD_DIR/mongo/util/progress_meter", + "$BUILD_DIR/mongo/util/signal_handlers", "$BUILD_DIR/mongo/util/version_impl", "mocklib", "testframework", diff --git a/src/mongo/s/mongos.cpp b/src/mongo/s/mongos.cpp new file mode 100644 index 00000000000..d9cc1790464 --- /dev/null +++ b/src/mongo/s/mongos.cpp @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/s/mongos_main.h" +#include "mongo/util/exit.h" +#include "mongo/util/text.h" + +#if defined(_WIN32) +// In Windows, wmain() is an alternate entry point for main(), and receives the same parameters +// as main() but encoded in Windows Unicode (UTF-16); "wide" 16-bit wchar_t characters. The +// WindowsCommandLine object converts these wide character strings to a UTF-8 coded equivalent +// and makes them available through the argv() and envp() members. This enables mongoSMain() +// to process UTF-8 encoded arguments and environment variables without regard to platform. +int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) { + mongo::WindowsCommandLine wcl(argc, argvW, envpW); + mongo::exitCleanly(mongo::mongos_main(argc, wcl.argv(), wcl.envp())); +} +#else +int main(int argc, char* argv[], char** envp) { + mongo::exitCleanly(mongo::mongos_main(argc, argv, envp)); +} +#endif diff --git a/src/mongo/s/server.manifest.in b/src/mongo/s/mongos.manifest.in index cec56019b5e..cec56019b5e 100644 --- a/src/mongo/s/server.manifest.in +++ b/src/mongo/s/mongos.manifest.in diff --git a/src/mongo/s/server.rc b/src/mongo/s/mongos.rc index 8677f261e16..fbc7c08c4f9 100644 --- a/src/mongo/s/server.rc +++ b/src/mongo/s/mongos.rc @@ -53,4 +53,4 @@ BEGIN END END -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "mongo/s/server.manifest" +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "mongo/s/mongos.manifest" diff --git a/src/mongo/s/server.cpp b/src/mongo/s/mongos_main.cpp index cf86f70a63d..6894950f899 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/mongos_main.cpp @@ -31,6 +31,8 @@ #include "mongo/platform/basic.h" +#include "mongo/s/mongos_main.h" + #include <boost/optional.hpp> #include <memory> @@ -883,7 +885,6 @@ ExitCode main(ServiceContext* serviceContext) { return runMongosServer(serviceContext); } -namespace { MONGO_INITIALIZER_GENERAL(ForkServer, ("EndStartupOptionHandling"), ("default")) (InitializerContext* context) { forkServerOrDie(); @@ -913,7 +914,7 @@ MONGO_INITIALIZER_GENERAL(setSSLManagerType, MONGO_NO_PREREQUISITES, ("SSLManage } // namespace -ExitCode mongoSMain(int argc, char* argv[], char** envp) { +ExitCode mongos_main(int argc, char* argv[], char** envp) { setMongos(); if (argc < 1) @@ -985,21 +986,4 @@ ExitCode mongoSMain(int argc, char* argv[], char** envp) { } } -} // namespace } // namespace mongo - -#if defined(_WIN32) -// In Windows, wmain() is an alternate entry point for main(), and receives the same parameters -// as main() but encoded in Windows Unicode (UTF-16); "wide" 16-bit wchar_t characters. The -// WindowsCommandLine object converts these wide character strings to a UTF-8 coded equivalent -// and makes them available through the argv() and envp() members. This enables mongoSMain() -// to process UTF-8 encoded arguments and environment variables without regard to platform. -int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) { - mongo::WindowsCommandLine wcl(argc, argvW, envpW); - mongo::exitCleanly(mongo::mongoSMain(argc, wcl.argv(), wcl.envp())); -} -#else -int main(int argc, char* argv[], char** envp) { - mongo::exitCleanly(mongo::mongoSMain(argc, argv, envp)); -} -#endif diff --git a/src/mongo/s/mongos_main.h b/src/mongo/s/mongos_main.h new file mode 100644 index 00000000000..e68edc33563 --- /dev/null +++ b/src/mongo/s/mongos_main.h @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/util/exit_code.h" + +namespace mongo { + +ExitCode mongos_main(int argc, char* argv[], char** envp); + +} // namespace mongo diff --git a/src/mongo/shell/SConscript b/src/mongo/shell/SConscript index 21dd85b2b9b..bdf17c86167 100644 --- a/src/mongo/shell/SConscript +++ b/src/mongo/shell/SConscript @@ -165,8 +165,8 @@ env.Library( "kms_shell.cpp", ], LIBDEPS_PRIVATE=[ - '$BUILD_DIR/mongo/shell_core', 'kms', + 'shell_utils', ], ) @@ -190,6 +190,27 @@ scriptingEnv.Library( ], ) +env.Library( + target="linenoise_utf8", + source=[ + "linenoise_utf8.cpp", + ], +) + +env.Library( + target="linenoise", + source=[ + "linenoise.cpp", + "mk_wcwidth.cpp" + ], + LIBDEPS=[ + '$BUILD_DIR/mongo/base', + ], + LIBDEPS_PRIVATE=[ + "linenoise_utf8", + ], +) + env.CppUnitTest( target='shell_test', source=[ diff --git a/src/mongo/shell/mongo.cpp b/src/mongo/shell/mongo.cpp new file mode 100644 index 00000000000..e6e0b199951 --- /dev/null +++ b/src/mongo/shell/mongo.cpp @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/shell/mongo_main.h" +#include "mongo/util/quick_exit.h" +#include "mongo/util/text.h" + +#ifdef _WIN32 +int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) { + mongo::WindowsCommandLine wcl(argc, argvW, envpW); + mongo::quickExit(mongo::mongo_main(argc, wcl.argv(), wcl.envp())); +} +#else // #ifdef _WIN32 +int main(int argc, char* argv[], char** envp) { + mongo::quickExit(mongo::mongo_main(argc, argv, envp)); +} +#endif // #ifdef _WIN32 diff --git a/src/mongo/shell/shell.manifest.in b/src/mongo/shell/mongo.manifest.in index 2f5ee512ee0..2f5ee512ee0 100644 --- a/src/mongo/shell/shell.manifest.in +++ b/src/mongo/shell/mongo.manifest.in diff --git a/src/mongo/shell/shell.rc b/src/mongo/shell/mongo.rc index b5e67185eb6..fe63acd0e3d 100644 --- a/src/mongo/shell/shell.rc +++ b/src/mongo/shell/mongo.rc @@ -53,4 +53,4 @@ BEGIN END END -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "mongo/shell/shell.manifest" +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "mongo/shell/mongo.manifest" diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/mongo_main.cpp index 2a4fd0b761f..a7051081d3f 100644 --- a/src/mongo/shell/dbshell.cpp +++ b/src/mongo/shell/mongo_main.cpp @@ -31,6 +31,8 @@ #include "mongo/platform/basic.h" +#include "mongo/shell/mongo_main.h" + #include <boost/core/null_deleter.hpp> #include <boost/filesystem/operations.hpp> #include <boost/log/attributes/value_extraction.hpp> @@ -98,13 +100,14 @@ #endif using namespace std::literals::string_literals; -using namespace mongo; + +namespace mongo { +namespace { bool gotInterrupted = false; bool inMultiLine = false; static AtomicWord<bool> atPrompt(false); // can eval before getting to prompt -namespace { const std::string kDefaultMongoHost = "127.0.0.1"s; const std::string kDefaultMongoPort = "27017"s; const std::string kDefaultMongoURL = "mongodb://"s + kDefaultMongoHost + ":"s + kDefaultMongoPort; @@ -213,10 +216,6 @@ public: } }; -} // namespace - -namespace mongo { - enum ShellExitCode : int { kDBException = 1, kInputFileError = -3, @@ -227,7 +226,6 @@ enum ShellExitCode : int { }; Scope* shellMainScope; -} // namespace mongo bool isSessionTimedOut() { static Date_t previousCommandTime = Date_t::now(); @@ -697,7 +695,6 @@ static void edit(const std::string& whatToEdit) { } } -namespace { bool mechanismRequiresPassword(const MongoURI& uri) { if (const auto authMechanisms = uri.getOption("authMechanism")) { constexpr std::array<StringData, 3> passwordlessMechanisms{ @@ -711,465 +708,461 @@ bool mechanismRequiresPassword(const MongoURI& uri) { } return true; } + } // namespace -int _main(int argc, char* argv[], char** envp) { - registerShutdownTask([] { - // NOTE: This function may be called at any time. It must not - // depend on the prior execution of mongo initializers or the - // existence of threads. - ::killOps(); - ::shellHistoryDone(); - }); +int mongo_main(int argc, char* argv[], char** envp) { - setupSignalHandlers(); - setupSignals(); + try { + + registerShutdownTask([] { + // NOTE: This function may be called at any time. It must not + // depend on the prior execution of mongo initializers or the + // existence of threads. + killOps(); + shellHistoryDone(); + }); - // Log to stdout for any early logging before we re-configure the logger - auto& lv2Manager = logv2::LogManager::global(); - logv2::LogDomainGlobal::ConfigurationOptions lv2Config; - uassertStatusOK(lv2Manager.getGlobalDomainInternal().configure(lv2Config)); + setupSignalHandlers(); + setupSignals(); - mongo::shell_utils::RecordMyLocation(argv[0]); + // Log to stdout for any early logging before we re-configure the logger + auto& lv2Manager = logv2::LogManager::global(); + logv2::LogDomainGlobal::ConfigurationOptions lv2Config; + uassertStatusOK(lv2Manager.getGlobalDomainInternal().configure(lv2Config)); - mongo::runGlobalInitializersOrDie(argc, argv, envp); - setGlobalServiceContext(ServiceContext::make()); - // TODO This should use a TransportLayerManager or TransportLayerFactory - auto serviceContext = getGlobalServiceContext(); + mongo::shell_utils::RecordMyLocation(argv[0]); - OCSPManager::get()->startThreadPool(); + mongo::runGlobalInitializersOrDie(argc, argv, envp); + setGlobalServiceContext(ServiceContext::make()); + // TODO This should use a TransportLayerManager or TransportLayerFactory + auto serviceContext = getGlobalServiceContext(); - transport::TransportLayerASIO::Options opts; - opts.enableIPv6 = shellGlobalParams.enableIPv6; - opts.mode = transport::TransportLayerASIO::Options::kEgress; + OCSPManager::get()->startThreadPool(); - serviceContext->setTransportLayer( - std::make_unique<transport::TransportLayerASIO>(opts, nullptr)); - auto tlPtr = serviceContext->getTransportLayer(); - uassertStatusOK(tlPtr->setup()); - uassertStatusOK(tlPtr->start()); + transport::TransportLayerASIO::Options opts; + opts.enableIPv6 = shellGlobalParams.enableIPv6; + opts.mode = transport::TransportLayerASIO::Options::kEgress; - // hide password from ps output - redactPasswordOptions(argc, argv); + serviceContext->setTransportLayer( + std::make_unique<transport::TransportLayerASIO>(opts, nullptr)); + auto tlPtr = serviceContext->getTransportLayer(); + uassertStatusOK(tlPtr->setup()); + uassertStatusOK(tlPtr->start()); - ErrorExtraInfo::invariantHaveAllParsers(); + // hide password from ps output + redactPasswordOptions(argc, argv); - if (!mongo::serverGlobalParams.quiet.load()) - std::cout << mongoShellVersion(VersionInfoInterface::instance()) << std::endl; + ErrorExtraInfo::invariantHaveAllParsers(); - auto consoleSink = boost::make_shared<boost::log::sinks::synchronous_sink<ShellBackend>>(); - consoleSink->set_filter(logv2::ComponentSettingsFilter(lv2Manager.getGlobalDomain(), - lv2Manager.getGlobalSettings())); - consoleSink->set_formatter(ShellFormatter()); + if (!mongo::serverGlobalParams.quiet.load()) + std::cout << mongoShellVersion(VersionInfoInterface::instance()) << std::endl; - consoleSink->locked_backend()->add_stream( - boost::shared_ptr<std::ostream>(&logv2::Console::out(), boost::null_deleter())); + auto consoleSink = boost::make_shared<boost::log::sinks::synchronous_sink<ShellBackend>>(); + consoleSink->set_filter(logv2::ComponentSettingsFilter(lv2Manager.getGlobalDomain(), + lv2Manager.getGlobalSettings())); + consoleSink->set_formatter(ShellFormatter()); - consoleSink->locked_backend()->auto_flush(); + consoleSink->locked_backend()->add_stream( + boost::shared_ptr<std::ostream>(&logv2::Console::out(), boost::null_deleter())); - // Remove the initial config from above when setting this sink, otherwise we log everything - // twice. - lv2Config.makeDisabled(); - uassertStatusOK(lv2Manager.getGlobalDomainInternal().configure(lv2Config)); + consoleSink->locked_backend()->auto_flush(); - boost::log::core::get()->add_sink(std::move(consoleSink)); + // Remove the initial config from above when setting this sink, otherwise we log everything + // twice. + lv2Config.makeDisabled(); + uassertStatusOK(lv2Manager.getGlobalDomainInternal().configure(lv2Config)); - // Get the URL passed to the shell - std::string& cmdlineURI = shellGlobalParams.url; + boost::log::core::get()->add_sink(std::move(consoleSink)); - // Parse the output of getURIFromArgs which will determine if --host passed in a URI - MongoURI parsedURI; - parsedURI = uassertStatusOK(MongoURI::parse(getURIFromArgs( - cmdlineURI, str::escape(shellGlobalParams.dbhost), str::escape(shellGlobalParams.port)))); + // Get the URL passed to the shell + std::string& cmdlineURI = shellGlobalParams.url; - // TODO: add in all of the relevant shellGlobalParams to parsedURI - parsedURI.setOptionIfNecessary("compressors"s, shellGlobalParams.networkMessageCompressors); - parsedURI.setOptionIfNecessary("authMechanism"s, shellGlobalParams.authenticationMechanism); - parsedURI.setOptionIfNecessary("authSource"s, shellGlobalParams.authenticationDatabase); - parsedURI.setOptionIfNecessary("gssapiServiceName"s, shellGlobalParams.gssapiServiceName); - parsedURI.setOptionIfNecessary("gssapiHostName"s, shellGlobalParams.gssapiHostName); + // Parse the output of getURIFromArgs which will determine if --host passed in a URI + MongoURI parsedURI; + parsedURI = + uassertStatusOK(MongoURI::parse(getURIFromArgs(cmdlineURI, + str::escape(shellGlobalParams.dbhost), + str::escape(shellGlobalParams.port)))); + + // TODO: add in all of the relevant shellGlobalParams to parsedURI + parsedURI.setOptionIfNecessary("compressors"s, shellGlobalParams.networkMessageCompressors); + parsedURI.setOptionIfNecessary("authMechanism"s, shellGlobalParams.authenticationMechanism); + parsedURI.setOptionIfNecessary("authSource"s, shellGlobalParams.authenticationDatabase); + parsedURI.setOptionIfNecessary("gssapiServiceName"s, shellGlobalParams.gssapiServiceName); + parsedURI.setOptionIfNecessary("gssapiHostName"s, shellGlobalParams.gssapiHostName); #ifdef MONGO_CONFIG_SSL - if (!awsIam::saslAwsClientGlobalParams.awsSessionToken.empty()) { - parsedURI.setOptionIfNecessary("authmechanismproperties"s, - std::string("AWS_SESSION_TOKEN:") + - awsIam::saslAwsClientGlobalParams.awsSessionToken); - } + if (!awsIam::saslAwsClientGlobalParams.awsSessionToken.empty()) { + parsedURI.setOptionIfNecessary("authmechanismproperties"s, + std::string("AWS_SESSION_TOKEN:") + + awsIam::saslAwsClientGlobalParams.awsSessionToken); + } #endif - if (const auto authMechanisms = parsedURI.getOption("authMechanism")) { - std::stringstream ss; - ss << "DB.prototype._defaultAuthenticationMechanism = \"" - << str::escape(authMechanisms.get()) << "\";" << std::endl; - mongo::shell_utils::dbConnect += ss.str(); - } + if (const auto authMechanisms = parsedURI.getOption("authMechanism")) { + std::stringstream ss; + ss << "DB.prototype._defaultAuthenticationMechanism = \"" + << str::escape(authMechanisms.get()) << "\";" << std::endl; + mongo::shell_utils::dbConnect += ss.str(); + } - if (const auto gssapiServiveName = parsedURI.getOption("gssapiServiceName")) { - std::stringstream ss; - ss << "DB.prototype._defaultGssapiServiceName = \"" << str::escape(gssapiServiveName.get()) - << "\";" << std::endl; - mongo::shell_utils::dbConnect += ss.str(); - } + if (const auto gssapiServiveName = parsedURI.getOption("gssapiServiceName")) { + std::stringstream ss; + ss << "DB.prototype._defaultGssapiServiceName = \"" + << str::escape(gssapiServiveName.get()) << "\";" << std::endl; + mongo::shell_utils::dbConnect += ss.str(); + } - if (!shellGlobalParams.nodb) { // connect to db - bool usingPassword = !shellGlobalParams.password.empty(); + if (!shellGlobalParams.nodb) { // connect to db + bool usingPassword = !shellGlobalParams.password.empty(); - if (mechanismRequiresPassword(parsedURI) && - (parsedURI.getUser().size() || shellGlobalParams.username.size())) { - usingPassword = true; - } + if (mechanismRequiresPassword(parsedURI) && + (parsedURI.getUser().size() || shellGlobalParams.username.size())) { + usingPassword = true; + } - if (usingPassword && parsedURI.getPassword().empty()) { - if (!shellGlobalParams.password.empty()) { - parsedURI.setPassword(stdx::as_const(shellGlobalParams.password)); - } else { - parsedURI.setPassword(mongo::askPassword()); + if (usingPassword && parsedURI.getPassword().empty()) { + if (!shellGlobalParams.password.empty()) { + parsedURI.setPassword(stdx::as_const(shellGlobalParams.password)); + } else { + parsedURI.setPassword(mongo::askPassword()); + } } - } - if (parsedURI.getUser().empty() && !shellGlobalParams.username.empty()) { - parsedURI.setUser(stdx::as_const(shellGlobalParams.username)); - } + if (parsedURI.getUser().empty() && !shellGlobalParams.username.empty()) { + parsedURI.setUser(stdx::as_const(shellGlobalParams.username)); + } - std::stringstream ss; - if (mongo::serverGlobalParams.quiet.load()) { - ss << "__quiet = true;" << std::endl; - } + std::stringstream ss; + if (mongo::serverGlobalParams.quiet.load()) { + ss << "__quiet = true;" << std::endl; + } - ss << "db = connect( \"" << parsedURI.canonicalizeURIAsString() << "\");" << std::endl; + ss << "db = connect( \"" << parsedURI.canonicalizeURIAsString() << "\");" << std::endl; - if (shellGlobalParams.shouldRetryWrites || parsedURI.getRetryWrites()) { - // If the --retryWrites cmdline argument or retryWrites URI param was specified, then - // replace the global `db` object with a DB object started in a session. The resulting - // Mongo connection checks its _retryWrites property. - ss << "db = db.getMongo().startSession().getDatabase(db.getName());" << std::endl; - } + if (shellGlobalParams.shouldRetryWrites || parsedURI.getRetryWrites()) { + // If the --retryWrites cmdline argument or retryWrites URI param was specified, + // then replace the global `db` object with a DB object started in a session. The + // resulting Mongo connection checks its _retryWrites property. + ss << "db = db.getMongo().startSession().getDatabase(db.getName());" << std::endl; + } - mongo::shell_utils::dbConnect += ss.str(); - } + mongo::shell_utils::dbConnect += ss.str(); + } - mongo::ScriptEngine::setConnectCallback(mongo::shell_utils::onConnect); - mongo::ScriptEngine::setup(); - mongo::getGlobalScriptEngine()->setJSHeapLimitMB(shellGlobalParams.jsHeapLimitMB); - mongo::getGlobalScriptEngine()->setScopeInitCallback(mongo::shell_utils::initScope); - mongo::getGlobalScriptEngine()->enableJIT(!shellGlobalParams.nojit); - mongo::getGlobalScriptEngine()->enableJavaScriptProtection( - shellGlobalParams.javascriptProtection); + mongo::ScriptEngine::setConnectCallback(mongo::shell_utils::onConnect); + mongo::ScriptEngine::setup(); + mongo::getGlobalScriptEngine()->setJSHeapLimitMB(shellGlobalParams.jsHeapLimitMB); + mongo::getGlobalScriptEngine()->setScopeInitCallback(mongo::shell_utils::initScope); + mongo::getGlobalScriptEngine()->enableJIT(!shellGlobalParams.nojit); + mongo::getGlobalScriptEngine()->enableJavaScriptProtection( + shellGlobalParams.javascriptProtection); - auto poolGuard = makeGuard([] { ScriptEngine::dropScopeCache(); }); + auto poolGuard = makeGuard([] { ScriptEngine::dropScopeCache(); }); - std::unique_ptr<mongo::Scope> scope(mongo::getGlobalScriptEngine()->newScope()); - shellMainScope = scope.get(); + std::unique_ptr<mongo::Scope> scope(mongo::getGlobalScriptEngine()->newScope()); + shellMainScope = scope.get(); - if (shellGlobalParams.runShell && !mongo::serverGlobalParams.quiet.load()) - std::cout << "type \"help\" for help" << std::endl; + if (shellGlobalParams.runShell && !mongo::serverGlobalParams.quiet.load()) + std::cout << "type \"help\" for help" << std::endl; - // Load and execute /etc/mongorc.js before starting shell - std::string rcGlobalLocation; + // Load and execute /etc/mongorc.js before starting shell + std::string rcGlobalLocation; #ifndef _WIN32 - rcGlobalLocation = "/etc/mongorc.js"; + rcGlobalLocation = "/etc/mongorc.js"; #else - wchar_t programDataPath[MAX_PATH]; - if (S_OK == SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, programDataPath)) { - rcGlobalLocation = str::stream() - << toUtf8String(programDataPath) << "\\MongoDB\\mongorc.js"; - } + wchar_t programDataPath[MAX_PATH]; + if (S_OK == SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, programDataPath)) { + rcGlobalLocation = str::stream() + << toUtf8String(programDataPath) << "\\MongoDB\\mongorc.js"; + } #endif - if (!rcGlobalLocation.empty() && ::mongo::shell_utils::fileExists(rcGlobalLocation)) { - if (!scope->execFile(rcGlobalLocation, false, true)) { - std::cout << "The \"" << rcGlobalLocation << "\" file could not be executed" - << std::endl; + if (!rcGlobalLocation.empty() && ::mongo::shell_utils::fileExists(rcGlobalLocation)) { + if (!scope->execFile(rcGlobalLocation, false, true)) { + std::cout << "The \"" << rcGlobalLocation << "\" file could not be executed" + << std::endl; + } } - } - if (!shellGlobalParams.script.empty()) { - mongo::shell_utils::MongoProgramScope s; - if (!scope->exec(shellGlobalParams.script, "(shell eval)", false, true, false)) { - std::cout << "exiting with code " << static_cast<int>(kEvalError) << std::endl; - return kEvalError; + if (!shellGlobalParams.script.empty()) { + mongo::shell_utils::MongoProgramScope s; + if (!scope->exec(shellGlobalParams.script, "(shell eval)", false, true, false)) { + std::cout << "exiting with code " << static_cast<int>(kEvalError) << std::endl; + return kEvalError; + } + scope->exec("shellPrintHelper( __lastres__ );", "(shell2 eval)", true, true, false); } - scope->exec("shellPrintHelper( __lastres__ );", "(shell2 eval)", true, true, false); - } - for (size_t i = 0; i < shellGlobalParams.files.size(); ++i) { - mongo::shell_utils::MongoProgramScope s; + for (size_t i = 0; i < shellGlobalParams.files.size(); ++i) { + mongo::shell_utils::MongoProgramScope s; - if (shellGlobalParams.files.size() > 1) - std::cout << "loading file: " << shellGlobalParams.files[i] << std::endl; + if (shellGlobalParams.files.size() > 1) + std::cout << "loading file: " << shellGlobalParams.files[i] << std::endl; - if (!scope->execFile(shellGlobalParams.files[i], false, true)) { - std::cout << "failed to load: " << shellGlobalParams.files[i] << std::endl; - std::cout << "exiting with code " << static_cast<int>(kInputFileError) << std::endl; - return kInputFileError; - } + if (!scope->execFile(shellGlobalParams.files[i], false, true)) { + std::cout << "failed to load: " << shellGlobalParams.files[i] << std::endl; + std::cout << "exiting with code " << static_cast<int>(kInputFileError) << std::endl; + return kInputFileError; + } - // Check if the process left any running child processes. - std::vector<ProcessId> pids = mongo::shell_utils::getRunningMongoChildProcessIds(); + // Check if the process left any running child processes. + std::vector<ProcessId> pids = mongo::shell_utils::getRunningMongoChildProcessIds(); - if (!pids.empty()) { - std::cout << "terminating the following processes started by " - << shellGlobalParams.files[i] << ": "; - std::copy(pids.begin(), pids.end(), std::ostream_iterator<ProcessId>(std::cout, " ")); - std::cout << std::endl; + if (!pids.empty()) { + std::cout << "terminating the following processes started by " + << shellGlobalParams.files[i] << ": "; + std::copy( + pids.begin(), pids.end(), std::ostream_iterator<ProcessId>(std::cout, " ")); + std::cout << std::endl; - if (mongo::shell_utils::KillMongoProgramInstances() != EXIT_SUCCESS) { - std::cout << "one more more child processes exited with an error during " - << shellGlobalParams.files[i] << std::endl; - std::cout << "exiting with code " << static_cast<int>(kProcessTerminationError) - << std::endl; - return kProcessTerminationError; - } + if (mongo::shell_utils::KillMongoProgramInstances() != EXIT_SUCCESS) { + std::cout << "one more more child processes exited with an error during " + << shellGlobalParams.files[i] << std::endl; + std::cout << "exiting with code " << static_cast<int>(kProcessTerminationError) + << std::endl; + return kProcessTerminationError; + } - bool failIfUnterminatedProcesses = false; - const StringData code = - "function() { return typeof TestData === 'object' && TestData !== null && " - "TestData.hasOwnProperty('failIfUnterminatedProcesses') && " - "TestData.failIfUnterminatedProcesses; }"_sd; - shellMainScope->invokeSafe(code.rawData(), nullptr, nullptr); - failIfUnterminatedProcesses = shellMainScope->getBoolean("__returnValue"); - - if (failIfUnterminatedProcesses) { - std::cout << "exiting with a failure due to unterminated processes, " - "a call to MongoRunner.stopMongod(), ReplSetTest#stopSet(), or " - "ShardingTest#stop() may be missing from the test" - << std::endl; - std::cout << "exiting with code " << static_cast<int>(kUnterminatedProcess) - << std::endl; - return kUnterminatedProcess; + bool failIfUnterminatedProcesses = false; + const StringData code = + "function() { return typeof TestData === 'object' && TestData !== null && " + "TestData.hasOwnProperty('failIfUnterminatedProcesses') && " + "TestData.failIfUnterminatedProcesses; }"_sd; + shellMainScope->invokeSafe(code.rawData(), nullptr, nullptr); + failIfUnterminatedProcesses = shellMainScope->getBoolean("__returnValue"); + + if (failIfUnterminatedProcesses) { + std::cout << "exiting with a failure due to unterminated processes, " + "a call to MongoRunner.stopMongod(), ReplSetTest#stopSet(), or " + "ShardingTest#stop() may be missing from the test" + << std::endl; + std::cout << "exiting with code " << static_cast<int>(kUnterminatedProcess) + << std::endl; + return kUnterminatedProcess; + } } } - } - if (shellGlobalParams.files.size() == 0 && shellGlobalParams.script.empty()) - shellGlobalParams.runShell = true; + if (shellGlobalParams.files.size() == 0 && shellGlobalParams.script.empty()) + shellGlobalParams.runShell = true; - bool lastLineSuccessful = true; - if (shellGlobalParams.runShell) { - mongo::shell_utils::MongoProgramScope s; - // If they specify norc, assume it's not their first time - bool hasMongoRC = shellGlobalParams.norc; - std::string rcLocation; - if (!shellGlobalParams.norc) { + bool lastLineSuccessful = true; + if (shellGlobalParams.runShell) { + mongo::shell_utils::MongoProgramScope s; + // If they specify norc, assume it's not their first time + bool hasMongoRC = shellGlobalParams.norc; + std::string rcLocation; + if (!shellGlobalParams.norc) { #ifndef _WIN32 - if (getenv("HOME") != nullptr) - rcLocation = str::stream() << getenv("HOME") << "/.mongorc.js"; + if (getenv("HOME") != nullptr) + rcLocation = str::stream() << getenv("HOME") << "/.mongorc.js"; #else - if (getenv("HOMEDRIVE") != nullptr && getenv("HOMEPATH") != nullptr) - rcLocation = str::stream() - << toUtf8String(_wgetenv(L"HOMEDRIVE")) << toUtf8String(_wgetenv(L"HOMEPATH")) - << "\\.mongorc.js"; + if (getenv("HOMEDRIVE") != nullptr && getenv("HOMEPATH") != nullptr) + rcLocation = str::stream() + << toUtf8String(_wgetenv(L"HOMEDRIVE")) + << toUtf8String(_wgetenv(L"HOMEPATH")) << "\\.mongorc.js"; #endif - if (!rcLocation.empty() && ::mongo::shell_utils::fileExists(rcLocation)) { - hasMongoRC = true; - if (!scope->execFile(rcLocation, false, true)) { - std::cout - << "The \".mongorc.js\" file located in your home folder could not be " - "executed" - << std::endl; - std::cout << "exiting with code " << static_cast<int>(kMongorcError) - << std::endl; - return kMongorcError; + if (!rcLocation.empty() && ::mongo::shell_utils::fileExists(rcLocation)) { + hasMongoRC = true; + if (!scope->execFile(rcLocation, false, true)) { + std::cout + << "The \".mongorc.js\" file located in your home folder could not be " + "executed" + << std::endl; + std::cout << "exiting with code " << static_cast<int>(kMongorcError) + << std::endl; + return kMongorcError; + } } } - } - if (!hasMongoRC && isatty(fileno(stdin))) { - std::cout - << "Welcome to the MongoDB shell.\n" - "For interactive help, type \"help\".\n" - "For more comprehensive documentation, see\n\thttp://docs.mongodb.org/\n" - "Questions? Try the support group\n\thttp://groups.google.com/group/mongodb-user" - << std::endl; - File f; - f.open(rcLocation.c_str(), false); // Create empty .mongorc.js file - } + if (!hasMongoRC && isatty(fileno(stdin))) { + std::cout + << "Welcome to the MongoDB shell.\n" + "For interactive help, type \"help\".\n" + "For more comprehensive documentation, see\n\thttp://docs.mongodb.org/\n" + "Questions? Try the support " + "group\n\thttp://groups.google.com/group/mongodb-user" + << std::endl; + File f; + f.open(rcLocation.c_str(), false); // Create empty .mongorc.js file + } - if (!shellGlobalParams.nodb && !mongo::serverGlobalParams.quiet.load() && - isatty(fileno(stdin))) { - scope->exec( - "shellHelper( 'show', 'startupWarnings' )", "(shellwarnings)", false, true, false); - - scope->exec( - "shellHelper( 'show', 'freeMonitoring' )", "(freeMonitoring)", false, true, false); - - scope->exec("shellHelper( 'show', 'automationNotices' )", - "(automationnotices)", - false, - true, - false); - - scope->exec("shellHelper( 'show', 'nonGenuineMongoDBCheck' )", - "(nonGenuineMongoDBCheck)", - false, - true, - false); - } + if (!shellGlobalParams.nodb && !mongo::serverGlobalParams.quiet.load() && + isatty(fileno(stdin))) { + scope->exec("shellHelper( 'show', 'startupWarnings' )", + "(shellwarnings)", + false, + true, + false); + + scope->exec("shellHelper( 'show', 'freeMonitoring' )", + "(freeMonitoring)", + false, + true, + false); + + scope->exec("shellHelper( 'show', 'automationNotices' )", + "(automationnotices)", + false, + true, + false); + + scope->exec("shellHelper( 'show', 'nonGenuineMongoDBCheck' )", + "(nonGenuineMongoDBCheck)", + false, + true, + false); + } - shellHistoryInit(); + shellHistoryInit(); - std::string prompt; - int promptType; + std::string prompt; + int promptType; - while (1) { - inMultiLine = false; - gotInterrupted = false; + while (1) { + inMultiLine = false; + gotInterrupted = false; - promptType = scope->type("prompt"); - if (promptType == String) { - prompt = scope->getString("prompt"); - } else if ((promptType == Code) && execPrompt(*scope, "prompt", prompt)) { - } else if (execPrompt(*scope, "defaultPrompt", prompt)) { - } else { - prompt = "> "; - } + promptType = scope->type("prompt"); + if (promptType == String) { + prompt = scope->getString("prompt"); + } else if ((promptType == Code) && execPrompt(*scope, "prompt", prompt)) { + } else if (execPrompt(*scope, "defaultPrompt", prompt)) { + } else { + prompt = "> "; + } - char* line = shellReadline(prompt.c_str()); + char* line = shellReadline(prompt.c_str()); - char* linePtr = line; // can't clobber 'line', we need to free() it later - if (linePtr) { - while (linePtr[0] == ' ') - ++linePtr; - int lineLen = strlen(linePtr); - while (lineLen > 0 && linePtr[lineLen - 1] == ' ') - linePtr[--lineLen] = 0; - } + char* linePtr = line; // can't clobber 'line', we need to free() it later + if (linePtr) { + while (linePtr[0] == ' ') + ++linePtr; + int lineLen = strlen(linePtr); + while (lineLen > 0 && linePtr[lineLen - 1] == ' ') + linePtr[--lineLen] = 0; + } - if (!linePtr || (strlen(linePtr) == 4 && strstr(linePtr, "exit"))) { - if (!mongo::serverGlobalParams.quiet.load()) - std::cout << "bye" << std::endl; - if (line) + if (!linePtr || (strlen(linePtr) == 4 && strstr(linePtr, "exit"))) { + if (!mongo::serverGlobalParams.quiet.load()) + std::cout << "bye" << std::endl; + if (line) + free(line); + break; + } + + std::string code = linePtr; + if (code == "exit" || code == "exit;") { free(line); - break; - } + break; + } - std::string code = linePtr; - if (code == "exit" || code == "exit;") { - free(line); - break; - } + // Support idle session lifetime limits + if (isSessionTimedOut()) { + std::cout << "Idle Connection Timeout: Shell session has expired" << std::endl; + if (line) + free(line); + break; + } - // Support idle session lifetime limits - if (isSessionTimedOut()) { - std::cout << "Idle Connection Timeout: Shell session has expired" << std::endl; - if (line) + if (code == "cls") { free(line); - break; - } - - if (code == "cls") { - free(line); - linenoiseClearScreen(); - continue; - } + linenoiseClearScreen(); + continue; + } - if (code.size() == 0) { - free(line); - continue; - } + if (code.size() == 0) { + free(line); + continue; + } - if (str::startsWith(linePtr, "edit ")) { - shellHistoryAdd(linePtr); + if (str::startsWith(linePtr, "edit ")) { + shellHistoryAdd(linePtr); - const char* s = linePtr + 5; // skip "edit " - while (*s && isspace(*s)) - s++; + const char* s = linePtr + 5; // skip "edit " + while (*s && isspace(*s)) + s++; - edit(s); - free(line); - continue; - } + edit(s); + free(line); + continue; + } - gotInterrupted = false; - code = finishCode(code); - if (gotInterrupted) { - std::cout << std::endl; - free(line); - continue; - } + gotInterrupted = false; + code = finishCode(code); + if (gotInterrupted) { + std::cout << std::endl; + free(line); + continue; + } - if (code.size() == 0) { - free(line); - break; - } + if (code.size() == 0) { + free(line); + break; + } - bool wascmd = false; - { - std::string cmd = linePtr; - std::string::size_type firstSpace; - if ((firstSpace = cmd.find(" ")) != std::string::npos) - cmd = cmd.substr(0, firstSpace); + bool wascmd = false; + { + std::string cmd = linePtr; + std::string::size_type firstSpace; + if ((firstSpace = cmd.find(" ")) != std::string::npos) + cmd = cmd.substr(0, firstSpace); + + if (cmd.find("\"") == std::string::npos) { + try { + lastLineSuccessful = scope->exec( + std::string("__iscmd__ = shellHelper[\"") + cmd + "\"];", + "(shellhelp1)", + false, + true, + true); + if (scope->getBoolean("__iscmd__")) { + lastLineSuccessful = + scope->exec(std::string("shellHelper( \"") + cmd + "\" , \"" + + code.substr(cmd.size()) + "\");", + "(shellhelp2)", + false, + true, + false); + wascmd = true; + } + } catch (std::exception& e) { + std::cout << "error2:" << e.what() << std::endl; + wascmd = true; + lastLineSuccessful = false; + } + } + } - if (cmd.find("\"") == std::string::npos) { + if (!wascmd) { try { lastLineSuccessful = - scope->exec(std::string("__iscmd__ = shellHelper[\"") + cmd + "\"];", - "(shellhelp1)", - false, - true, - true); - if (scope->getBoolean("__iscmd__")) { - lastLineSuccessful = - scope->exec(std::string("shellHelper( \"") + cmd + "\" , \"" + - code.substr(cmd.size()) + "\");", - "(shellhelp2)", - false, - true, - false); - wascmd = true; + scope->exec(code.c_str(), "(shell)", false, true, false); + if (lastLineSuccessful) { + scope->exec( + "shellPrintHelper( __lastres__ );", "(shell2)", true, true, false); } } catch (std::exception& e) { - std::cout << "error2:" << e.what() << std::endl; - wascmd = true; + std::cout << "error:" << e.what() << std::endl; lastLineSuccessful = false; } } - } - if (!wascmd) { - try { - lastLineSuccessful = scope->exec(code.c_str(), "(shell)", false, true, false); - if (lastLineSuccessful) { - scope->exec( - "shellPrintHelper( __lastres__ );", "(shell2)", true, true, false); - } - } catch (std::exception& e) { - std::cout << "error:" << e.what() << std::endl; - lastLineSuccessful = false; - } + shellHistoryAdd(code.c_str()); + free(line); } - shellHistoryAdd(code.c_str()); - free(line); + shellHistoryDone(); } - shellHistoryDone(); - } - - return (lastLineSuccessful ? 0 : 1); -} + return (lastLineSuccessful ? 0 : 1); -#ifdef _WIN32 -int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) { - int returnCode; - try { - WindowsCommandLine wcl(argc, argvW, envpW); - returnCode = _main(argc, wcl.argv(), wcl.envp()); - } catch (mongo::DBException& e) { + } catch (DBException& e) { std::cout << "exception: " << e.what() << std::endl; std::cout << "exiting with code " << static_cast<int>(kDBException) << std::endl; - returnCode = kDBException; + return kDBException; } - quickExit(returnCode); } -#else // #ifdef _WIN32 -int main(int argc, char* argv[], char** envp) { - int returnCode; - try { - returnCode = _main(argc, argv, envp); - } catch (mongo::DBException& e) { - std::cout << "exception: " << e.what() << std::endl; - std::cout << "exiting with code " << static_cast<int>(kDBException) << std::endl; - returnCode = kDBException; - } - quickExit(returnCode); -} -#endif // #ifdef _WIN32 + +} // namespace mongo diff --git a/src/mongo/shell/mongo_main.h b/src/mongo/shell/mongo_main.h new file mode 100644 index 00000000000..b16b2ed5203 --- /dev/null +++ b/src/mongo/shell/mongo_main.h @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2020-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +namespace mongo { + +int mongo_main(int argc, char* argv[], char** envp); + +} // namespace mongo diff --git a/src/mongo/shell/shell_utils.cpp b/src/mongo/shell/shell_utils.cpp index 84e4c1ef4fd..ae93862b113 100644 --- a/src/mongo/shell/shell_utils.cpp +++ b/src/mongo/shell/shell_utils.cpp @@ -475,11 +475,8 @@ void installShellUtils(Scope& scope) { scope.injectNative("fileExists", fileExistsJS); scope.injectNative("isInteractive", isInteractive); -#ifndef MONGO_SAFE_SHELL - // can't launch programs installShellUtilsLauncher(scope); installShellUtilsExtended(scope); -#endif } void setEnterpriseShellCallback(EnterpriseShellCallback* callback) { diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript index b56fb05fa70..2ec5e638b83 100644 --- a/src/mongo/util/SConscript +++ b/src/mongo/util/SConscript @@ -260,10 +260,11 @@ if env['MONGO_ALLOCATOR'] in ['tcmalloc', 'tcmalloc-experimental']: '$BUILD_DIR/mongo/idl/server_parameter', 'processinfo', ], - PROGDEPS_DEPENDENTS=[ - '$BUILD_DIR/mongo/mongod', - '$BUILD_DIR/mongo/mongos', + LIBDEPS_DEPENDENTS=[ + '$BUILD_DIR/mongo/mongos_initializers', + '$BUILD_DIR/mongo/mongod_initializers', ], + ) env.Library( |