Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
efb65cb
CXX-3320 migrate instance and logger to mongocxx::v1
eramongodb Sep 25, 2025
2892b35
Remove redundant redeclarations
eramongodb Sep 26, 2025
0370746
Remove redundant instance ctor overload
eramongodb Sep 26, 2025
4508456
Use std::_Exit instead of std::exit in subprocess
eramongodb Sep 29, 2025
40218af
Tweak rationale for disabling Valgrind leak checks for subprocesses
eramongodb Sep 29, 2025
3483624
Merge remote-tracking branch 'upstream/master' into HEAD
eramongodb Oct 2, 2025
75d5e9e
Fix typos in comments and strings
eramongodb Oct 2, 2025
cc5339f
Fix missing `&is_signal` argument to subprocess
eramongodb Oct 2, 2025
ba058a4
Simplify v_noabi implementation (capture pre-init logs)
eramongodb Oct 2, 2025
91b3d62
Document post-move state for instance class
eramongodb Oct 2, 2025
20b931c
Document non-copyability for instance class
eramongodb Oct 2, 2025
df7bf53
Preserve v_noabi log handler enabled message
eramongodb Oct 2, 2025
f24f3b6
Correctly condition v_noabi info message
eramongodb Oct 2, 2025
0be7784
Formatting
eramongodb Oct 2, 2025
f2ecef1
Merge remote-tracking branch 'upstream/master' into cxx-abi-v1-instance
eramongodb Oct 6, 2025
d2de21a
Merge remote-tracking branch 'upstream/master' into cxx-abi-v1-instance
eramongodb Oct 9, 2025
bf715d7
Merge remote-tracking branch 'upstream/master' into cxx-abi-v1-instance
eramongodb Oct 9, 2025
5160285
Merge remote-tracking branch 'upstream/master' into HEAD
eramongodb Oct 21, 2025
3d276c8
Use qualified explicit template specializations
eramongodb Oct 21, 2025
42cac6f
Remove extra doclines
eramongodb Oct 21, 2025
33c1853
Apply clangd IWYU fixes
eramongodb Oct 21, 2025
4ae0cd9
Add missing source_errc enumerator to CATCH_REGISTER_ENUM
eramongodb Oct 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions .evergreen/scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,25 @@ else
command -V valgrind
valgrind --version
run_test() {
valgrind_args=(
"--leak-check=full"
"--track-origins=yes"
"--num-callers=50"
"--error-exitcode=1"
"--error-limit=no"
"--read-var-info=yes"
"--suppressions=../etc/memcheck.suppressions"
)

# Prevent mongocxx::test::subprocess termination from confusing valgrind.
if [[ "${1:?}" =~ test_instance ]]; then
valgrind_args+=(
"--trace-children=no"
)
fi

echo "Running ${1:?}..."
valgrind --leak-check=full --track-origins=yes --num-callers=50 --error-exitcode=1 --error-limit=no --read-var-info=yes --suppressions=../etc/memcheck.suppressions "${1:?}" "${test_args[@]:?}" || return
valgrind "${1:?}" "${test_args[@]:?}" || return
echo "Running ${1:?}... done."
}
fi
Expand All @@ -304,7 +321,6 @@ else
run_test ./src/mongocxx/test/test_command_monitoring_specs
run_test ./src/mongocxx/test/test_instance
run_test ./src/mongocxx/test/test_transactions_specs
run_test ./src/mongocxx/test/test_logging
run_test ./src/mongocxx/test/test_retryable_reads_specs
run_test ./src/mongocxx/test/test_read_write_concern_specs
run_test ./src/mongocxx/test/test_unified_format_specs
Expand Down
81 changes: 78 additions & 3 deletions src/mongocxx/include/mongocxx/v1/exception.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@

#include <mongocxx/v1/detail/prelude.hpp>

#include <bsoncxx/v1/detail/macros.hpp>

#include <mongocxx/v1/config/export.hpp>

#include <system_error>
#include <type_traits>

namespace mongocxx {
namespace v1 {

Expand All @@ -28,14 +35,60 @@ namespace v1 {
///
/// @attention This feature is experimental! It is not ready for use!
///
enum class source_errc {};
enum class source_errc {
zero, ///< Zero.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be zero, or something like okay? Alternatively: set mongocxx = 1, give the enum a base type like int, and then have source_errc{} as the stand-in for zero, which is the non-error syntax for std::errc.

(I don't feel strongly about any of the above options, just something to consider.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be zero, or something like okay? Alternatively: set `mongocxx = 1 [...]

My reason for including the zero enumerator was twofold:

  • Avoid the need for explicit = 1 in the otherwise =-less list of enumerators (an inconsistency).
  • Force explicit handling of the zero case in switch cases via -Wswitch / -Wswitch-enum.

I opted for zero instead of okay to avoid implying anything beyond a description of the value itself, since "not zero" does not necessarily imply "not okay" or "not valid" given certain error code schemes (i.e. "HTTP status code 200").

give the enum a base type like int

The default underlying type for a scoped enumeration is int, so there is no need for explicit : int given enum class E.

mongocxx, ///< From the mongocxx library.
mongoc, ///< From the mongoc library.
mongocrypt, ///< From the mongocrypt library.
server, ///< From the MongoDB server.
};

///
/// The error category for @ref mongocxx::v1::source_errc.
///
/// @attention This feature is experimental! It is not ready for use!
///
MONGOCXX_ABI_EXPORT_CDECL(std::error_category const&) source_error_category();

///
/// Support implicit conversion to `std::error_condition`.
///
/// @attention This feature is experimental! It is not ready for use!
///
inline std::error_condition make_error_condition(source_errc code) {
return {static_cast<int>(code), v1::source_error_category()};
}

///
/// Enumeration identifying the type (cause) of a @ref mongocxx::v1 error.
///
/// @attention This feature is experimental! It is not ready for use!
///
enum class type_errc {};
enum class type_errc {
zero, ///< Zero.
invalid_argument, ///< An invalid argument passed to the throwing function.
runtime_error, ///< An erroneous condition was detected at runtime.
};

///
/// The error category for @ref mongocxx::v1::type_errc.
///
/// @attention This feature is experimental! It is not ready for use!
///
MONGOCXX_ABI_EXPORT_CDECL(std::error_category const&) type_error_category();

///
/// Support implicit conversion to `std::error_condition`.
///
/// @attention This feature is experimental! It is not ready for use!
///
inline std::error_condition make_error_condition(type_errc code) {
return {static_cast<int>(code), v1::type_error_category()};
}

BSONCXX_PRIVATE_WARNINGS_PUSH();
BSONCXX_PRIVATE_WARNINGS_DISABLE(MSVC(4251));
BSONCXX_PRIVATE_WARNINGS_DISABLE(MSVC(4275));

///
/// Base class for all exceptions thrown by @ref mongocxx::v1.
Expand All @@ -45,11 +98,33 @@ enum class type_errc {};
///
/// @attention This feature is experimental! It is not ready for use!
///
class exception {};
class exception : public std::system_error {
public:
~exception() override;

exception(exception&&) noexcept = default;
exception& operator=(exception&&) noexcept = default;
exception(exception const&) = default;
exception& operator=(exception const&) = default;

using std::system_error::system_error;
};

BSONCXX_PRIVATE_WARNINGS_POP();

} // namespace v1
} // namespace mongocxx

namespace std {

template <>
struct is_error_condition_enum<mongocxx::v1::source_errc> : true_type {};

template <>
struct is_error_condition_enum<mongocxx::v1::type_errc> : true_type {};

} // namespace std
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor tweak option: You can omit the outer namespace std and do:

template <> 
struct std::is_error_condition_enum<...>

with the std:: qualifier on the struct name. This isn't strictly better, but may reduce the amount of visual noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially attempted this pattern as well, but encountered compilation errors with GCC versions older than 7.1 (possibly related: CWG 275). However, we now require GCC 8 or newer as of #1415, so I think the suggestion is now viable:

# https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html
# https://gcc.gnu.org/projects/cxx-status.html
# https://gcc.gnu.org/releases.html
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.1")
message(FATAL_ERROR "GCC 8.1 or newer is required")
endif()


#include <mongocxx/v1/detail/postlude.hpp>

///
Expand Down
130 changes: 129 additions & 1 deletion src/mongocxx/include/mongocxx/v1/instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@

#include <mongocxx/v1/detail/prelude.hpp>

#include <mongocxx/v1/logger-fwd.hpp>

#include <mongocxx/v1/config/export.hpp>

#include <memory>
#include <system_error>
#include <type_traits>

namespace mongocxx {
namespace v1 {

Expand Down Expand Up @@ -50,15 +58,135 @@ namespace v1 {
/// @par Special exemptions
/// Only the following API are permitted to be used outside the lifetime of an instance object:
/// - @ref mongocxx::v1::logger
/// - @ref mongocxx::v1::default_logger
///
/// @see
/// - [Initialization and Cleanup (mongoc)](https://mongoc.org/libmongoc/current/init-cleanup.html)
///
class instance {};
class instance {
private:
class impl;
std::unique_ptr<impl> _impl;

public:
///
/// Cleanup the mongocxx (and mongoc) library.
///
/// Calls [`mongoc_init()`](https://mongoc.org/libmongoc/current/mongoc_cleanup.html).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Calls [`mongoc_init()`](https://mongoc.org/libmongoc/current/mongoc_cleanup.html).
/// Calls [`mongoc_cleanup()`](https://mongoc.org/libmongoc/current/mongoc_cleanup.html).

///
MONGOCXX_ABI_EXPORT_CDECL() ~instance();

///
/// This class is not moveable.
///
instance(instance&&) = delete;

///
/// This class is not moveable.
///
instance& operator=(instance&&) = delete;

///
/// This class is not copyable.
///
instance(instance const&) = delete;

///
/// This class is not copyable.
///
instance& operator=(instance const&) = delete;
Comment on lines +79 to +97
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relative breaking change: instance is made immovable as well as uncopyable. Allowing instance to be moved-from does not seem to be well-motivated.


///
/// Initialize the mongoc library with unstructured log messages disabled.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated documentation to clarify that this all applies to "unstructured log handling" to leave open the design space for "structured log handling" support by the C++ Driver.

Documentation also increased references to specific mongoc API to clarify behavior + defer much of the behavioral documentation to mongoc.

///
/// Calls [`mongoc_init()`](https://mongoc.org/libmongoc/current/mongoc_init.html) after disabling unstructured
/// log messages by calling `mongoc_log_set_handler(nullptr, nullptr)`.
///
/// @important To use mongoc's default log message handler, construct this object with
/// @ref instance(v1::default_logger tag) instead.
///
/// @throws mongocxx::v1::exception with @ref mongocxx::v1::instance::errc::multiple_instances if an `instance`
/// object has already been created.
///
/// @see
/// - [Custom Log Handlers (mongoc)](https://mongoc.org/libmongoc/current/unstructured_log.html#custom-log-handlers)
///
MONGOCXX_ABI_EXPORT_CDECL() instance();

///
/// Initialize the mongoc library with the custom unstructured log message handler.
///
/// Calls [`mongoc_init`](https://mongoc.org/libmongoc/current/mongoc_init.html) after registering the custom
/// unstructured log handler by calling `mongoc_log_set_handler()`.
///
/// @param handler Disable unstructured logging when null.
///
/// @throws mongocxx::v1::exception with @ref mongocxx::v1::instance::errc::multiple_instances if an `instance`
/// object has already been created.
///
/// @see
/// - [Custom Log Handlers (mongoc)](https://mongoc.org/libmongoc/current/unstructured_log.html#custom-log-handlers)
///
explicit MONGOCXX_ABI_EXPORT_CDECL() instance(std::unique_ptr<v1::logger> handler);

///
/// Initialize the mongoc library with its default unstructured log handler.
///
/// Calls [`mongoc_init`](https://mongoc.org/libmongoc/current/mongoc_init.html) without registering any custom
/// unstructured log handler.
///
/// @param tag Unused: only for overload resolution.
///
/// @throws mongocxx::v1::exception with @ref mongocxx::v1::instance::errc::multiple_instances if an `instance`
/// object has already been created.
///
explicit MONGOCXX_ABI_EXPORT_CDECL() instance(v1::default_logger tag);

///
/// Equivalent to @ref instance(std::unique_ptr<v1::logger> handler) when `handler == nullptr`.
///
/// @see
/// - [Custom Log Handlers (mongoc)](https://mongoc.org/libmongoc/current/unstructured_log.html#custom-log-handlers)
///
explicit MONGOCXX_ABI_EXPORT_CDECL() instance(std::nullptr_t);

///
/// Errors codes which may be returned by @ref mongocxx::v1::instance.
///
/// @attention This feature is experimental! It is not ready for use!
///
enum class errc {
zero, ///< Zero.
multiple_instances, ///< Cannot construct multiple instance objects in a given process.
};

///
/// The error category for @ref mongocxx::v1::instance::errc.
///
/// @attention This feature is experimental! It is not ready for use!
///
static MONGOCXX_ABI_EXPORT_CDECL(std::error_category const&) error_category();

///
/// Support implicit conversion to `std::error_code`.
///
/// @attention This feature is experimental! It is not ready for use!
///
friend std::error_code make_error_code(errc v) {
return {static_cast<int>(v), error_category()};
}
};

} // namespace v1
} // namespace mongocxx

namespace std {

template <>
struct is_error_code_enum<mongocxx::v1::instance::errc> : true_type {};

} // namespace std

#include <mongocxx/v1/detail/postlude.hpp>

///
Expand Down
7 changes: 6 additions & 1 deletion src/mongocxx/include/mongocxx/v1/logger-fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@

#include <mongocxx/v1/detail/prelude.hpp>

//

#include <mongocxx/v1/config/export.hpp>

namespace mongocxx {
namespace v1 {

enum class log_level;

class logger;
class MONGOCXX_ABI_EXPORT logger;

class default_logger;

} // namespace v1
Expand Down
Loading