Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

CDRIVER-5856 add function to check if bulkwrite is acknowledged #2100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/libmongoc/doc/api.rst
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ API Reference
mongoc_bulkwriteopts_t
mongoc_bulkwriteresult_t
mongoc_bulkwriteexception_t
mongoc_bulkwrite_check_acknowledged_t
mongoc_bulk_operation_t
mongoc_change_stream_t
mongoc_client_encryption_t
Expand Down
19 changes: 19 additions & 0 deletions src/libmongoc/doc/mongoc_bulkwrite_check_acknowledged.rst
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
:man_page: mongoc_bulkwrite_check_acknowledged

mongoc_bulkwrite_check_acknowledged()
=====================================

Synopsis
--------

.. code-block:: c

mongoc_bulkwrite_check_acknowledged_t
mongoc_bulkwrite_check_acknowledged (const mongoc_bulkwrite_t * self, bson_error_t * error);

Description
-----------

Checks whether or not the previous call to :symbol:`mongoc_bulkwrite_execute` used an acknowledged write concern. If
an error occured, the ``is_ok`` member of :symbol:`mongoc_bulkwrite_check_acknowledged_t` will be ``false`` and
``error`` will be set.
25 changes: 25 additions & 0 deletions src/libmongoc/doc/mongoc_bulkwrite_check_acknowledged_t.rst
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
:man_page: mongoc_bulkwrite_check_acknowledged_t

mongoc_bulkwrite_check_acknowledged_t
=====================================

Synopsis
--------

.. code-block:: c

typedef struct {
bool is_ok; // true if no error
bool is_acknowledged; // true if the previous call to `mongoc_bulkwrite_execute` used an acknowledged write concern
} mongoc_bulkwrite_check_acknowledged_t;

Description
-----------

:symbol:`mongoc_bulkwrite_check_acknowledged_t` is returned by :symbol:`mongoc_bulkwrite_check_acknowledged`.

``is_ok`` is ``false`` if there was no previous call to :symbol:`mongoc_bulkwrite_execute` or if execution failed before
the write concern could be determined.

``is_acknowledged`` is ``true`` if the previous :symbol:`mongoc_bulkwrite_execute` call used an acknowledged write
concern.
2 changes: 1 addition & 1 deletion src/libmongoc/doc/mongoc_bulkwrite_execute.rst
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ Description
-----------

Executes a :symbol:`mongoc_bulkwrite_t`. Once executed, it is an error to call other functions on ``self``, aside from
:symbol:`mongoc_bulkwrite_destroy`.
:symbol:`mongoc_bulkwrite_check_acknowledged` and :symbol:`mongoc_bulkwrite_destroy`.
1 change: 1 addition & 0 deletions src/libmongoc/doc/mongoc_bulkwrite_t.rst
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ to execute the operation.
mongoc_bulkwrite_set_client
mongoc_bulkwrite_set_session
mongoc_bulkwrite_execute
mongoc_bulkwrite_check_acknowledged
mongoc_bulkwrite_destroy
36 changes: 30 additions & 6 deletions src/libmongoc/src/mongoc/mongoc-bulkwrite.c
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ struct _mongoc_bulkwrite_t {
// `executed` is set to true once `mongoc_bulkwrite_execute` is called.
// `mongoc_bulkwrite_t` may not be executed more than once.
bool executed;
// `is_acknowledged` is set in `mongoc_bulkwrite_execute` based on the chosen write concern.
mongoc_optional_t is_acknowledged;
// `ops` is a document sequence.
mongoc_buffer_t ops;
size_t n_ops;
Expand Down Expand Up @@ -187,6 +189,7 @@ mongoc_bulkwrite_t *
mongoc_bulkwrite_new(void)
{
mongoc_bulkwrite_t *bw = bson_malloc0(sizeof(mongoc_bulkwrite_t));
mongoc_optional_init(&bw->is_acknowledged);
_mongoc_buffer_init(&bw->ops, NULL, 0, NULL, NULL);
_mongoc_array_init(&bw->arrayof_modeldata, sizeof(modeldata_t));
return bw;
Expand Down Expand Up @@ -1533,7 +1536,6 @@ mongoc_bulkwrite_execute(mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
opts = &defaults;
}
bool is_ordered = mongoc_optional_is_set(&opts->ordered) ? mongoc_optional_value(&opts->ordered) : true; // default.
bool is_acknowledged = false;
// Create empty result and exception to collect results/errors from batches.
ret.res = _bulkwriteresult_new();
ret.exc = _bulkwriteexception_new();
Expand Down Expand Up @@ -1668,10 +1670,10 @@ mongoc_bulkwrite_execute(mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
_bulkwriteexception_set_error(ret.exc, &error);
goto fail;
}
is_acknowledged = mongoc_write_concern_is_acknowledged(wc);
mongoc_optional_set_value(&self->is_acknowledged, mongoc_write_concern_is_acknowledged(wc));
}

if (verboseresults && !is_acknowledged) {
if (verboseresults && !mongoc_optional_value(&self->is_acknowledged)) {
_mongoc_set_error(&error,
MONGOC_ERROR_COMMAND,
MONGOC_ERROR_COMMAND_INVALID_ARG,
Expand All @@ -1680,7 +1682,7 @@ mongoc_bulkwrite_execute(mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
goto fail;
}

if (is_ordered && !is_acknowledged) {
if (is_ordered && !mongoc_optional_value(&self->is_acknowledged)) {
_mongoc_set_error(&error,
MONGOC_ERROR_COMMAND,
MONGOC_ERROR_COMMAND_INVALID_ARG,
Expand Down Expand Up @@ -1868,7 +1870,7 @@ mongoc_bulkwrite_execute(mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
}

// Add to result and/or exception.
if (is_acknowledged) {
if (mongoc_optional_value(&self->is_acknowledged)) {
// Parse top-level fields.
if (!_bulkwritereturn_apply_reply(&ret, &cmd_reply)) {
goto batch_fail;
Expand Down Expand Up @@ -1965,7 +1967,8 @@ mongoc_bulkwrite_execute(mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
}
}
}
if (!is_acknowledged || !has_successful_results) {
if (!(mongoc_optional_is_set(&self->is_acknowledged) && mongoc_optional_value(&self->is_acknowledged) &&
has_successful_results)) {
mongoc_bulkwriteresult_destroy(ret.res);
ret.res = NULL;
}
Expand All @@ -1986,4 +1989,25 @@ mongoc_bulkwrite_execute(mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t
return ret;
}

MONGOC_EXPORT(mongoc_bulkwrite_check_acknowledged_t)
mongoc_bulkwrite_check_acknowledged(mongoc_bulkwrite_t const *self, bson_error_t *error)
{
BSON_ASSERT_PARAM(self);
BSON_OPTIONAL_PARAM(error);

mongoc_bulkwrite_check_acknowledged_t result = {.is_ok = mongoc_optional_is_set(&self->is_acknowledged),
.is_acknowledged = false};

if (result.is_ok) {
result.is_acknowledged = mongoc_optional_value(&self->is_acknowledged);
} else {
_mongoc_set_error(error,
MONGOC_ERROR_COMMAND,
MONGOC_ERROR_COMMAND_INVALID_ARG,
"bulk write has not been executed or execution failed");
}

return result;
}

MC_ENABLE_CONVERSION_WARNING_END
11 changes: 11 additions & 0 deletions src/libmongoc/src/mongoc/mongoc-bulkwrite.h
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,17 @@ mongoc_bulkwrite_set_session(mongoc_bulkwrite_t *self, mongoc_client_session_t *
// `mongoc_bulkwrite_execute` executes a bulk write operation.
MONGOC_EXPORT(mongoc_bulkwritereturn_t)
mongoc_bulkwrite_execute(mongoc_bulkwrite_t *self, const mongoc_bulkwriteopts_t *opts);

typedef struct {
bool is_ok; // true if no error
bool is_acknowledged; // true if the previous call to `mongoc_bulkwrite_execute` used an acknowledged write concern
} mongoc_bulkwrite_check_acknowledged_t;

// `mongoc_bulkwrite_check_acknowledged` checks whether or not the previous call to `mongoc_bulkwrite_execute` used an
// acknowledged write concern.
MONGOC_EXPORT(mongoc_bulkwrite_check_acknowledged_t)
mongoc_bulkwrite_check_acknowledged(mongoc_bulkwrite_t const *self, bson_error_t *error);

MONGOC_EXPORT(void)
mongoc_bulkwrite_destroy(mongoc_bulkwrite_t *self);

Expand Down
24 changes: 24 additions & 0 deletions src/libmongoc/tests/TestSuite.h
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,30 @@ _test_error(const char *format, ...) BSON_GNUC_PRINTF(1, 2);
#define ASSERT_CMPDOUBLE(a, eq, b) ASSERT_CMPINT_HELPER(a, eq, b, "f", double)
#define ASSERT_CMPVOID(a, eq, b) ASSERT_CMPINT_HELPER(a, eq, b, "p", void *)

// Returns "true" or "false". The result does _not_ need to be freed.
static inline char const *
_bool_to_str(bool b)
{
return b ? "true" : "false";
}

#define ASSERT_CMPBOOL(a, eq, b) \
do { \
/* evaluate once */ \
bool _a = a; \
bool _b = b; \
if (!((_a)eq(_b))) { \
MONGOC_STDERR_PRINTF("FAIL\n\nAssert Failure: %s %s %s\n%s:%d %s()\n", \
_bool_to_str(_a), \
BSON_STR(eq), \
_bool_to_str(_b), \
__FILE__, \
(int)(__LINE__), \
BSON_FUNC); \
abort(); \
} \
} while (0)

#define ASSERT_MEMCMP(a, b, n) \
do { \
const void *_a = (a); \
Expand Down
102 changes: 102 additions & 0 deletions src/libmongoc/tests/test-mongoc-bulkwrite.c
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,100 @@ test_bulkwrite_client_error_no_result(void *unused)

mongoc_client_destroy(client);
}

static void
_do_bulkwrite_check_acknowledged_test_case(mongoc_client_t *client,
mongoc_bulkwriteopts_t *opts,
bool is_acknowledged_expected)
{
mongoc_bulkwrite_t *bw = mongoc_client_bulkwrite_new(client);
bson_error_t error;
bool const ok = mongoc_bulkwrite_append_insertone(bw, "db.coll", tmp_bson("{}"), NULL /* opts */, &error);
ASSERT_OR_PRINT(ok, error);

mongoc_bulkwritereturn_t const bwr = mongoc_bulkwrite_execute(bw, opts);

ASSERT_NO_BULKWRITEEXCEPTION(bwr);

mongoc_bulkwrite_check_acknowledged_t const check_acknowledged = mongoc_bulkwrite_check_acknowledged(bw, &error);
ASSERT_OR_PRINT(check_acknowledged.is_ok, error);
ASSERT_CMPBOOL(check_acknowledged.is_acknowledged, ==, is_acknowledged_expected);

mongoc_bulkwriteexception_destroy(bwr.exc);
mongoc_bulkwriteresult_destroy(bwr.res);
mongoc_bulkwrite_destroy(bw);
}

static void
test_bulkwrite_check_acknowledged(void *unused)
{
BSON_UNUSED(unused);

mongoc_client_t *client = test_framework_new_default_client();

mongoc_bulkwriteopts_t *opts = mongoc_bulkwriteopts_new();
// To prevent bulk write exception "Cannot request unacknowledged write concern and ordered writes."
mongoc_bulkwriteopts_set_ordered(opts, false);

mongoc_write_concern_t *wc_acknowledged = mongoc_write_concern_new();
mongoc_write_concern_set_w(wc_acknowledged, 1);

mongoc_write_concern_t *wc_unacknowledged = mongoc_write_concern_new();
mongoc_write_concern_set_w(wc_unacknowledged, MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED);

// Client w/ unacknowledged write concern, no opts override
{
mongoc_client_set_write_concern(client, wc_unacknowledged);
mongoc_bulkwriteopts_set_writeconcern(opts, NULL);

_do_bulkwrite_check_acknowledged_test_case(client, opts, false /* is_acknowledged_expected */);
}

// Client w/ acknowledged write concern, no opts override
{
mongoc_client_set_write_concern(client, wc_acknowledged);
mongoc_bulkwriteopts_set_writeconcern(opts, NULL);

_do_bulkwrite_check_acknowledged_test_case(client, opts, true /* is_acknowledged_expected */);
}

// Client w/ unacknowledged write concern, opts override w/ acknowledged write concern
{
mongoc_client_set_write_concern(client, wc_unacknowledged);
mongoc_bulkwriteopts_set_writeconcern(opts, wc_acknowledged);

_do_bulkwrite_check_acknowledged_test_case(client, opts, true /* is_acknowledged_expected */);
}

// Client w/ acknowledged write concern, opts override w/ unacknowledged write concern
{
mongoc_client_set_write_concern(client, wc_acknowledged);
mongoc_bulkwriteopts_set_writeconcern(opts, wc_unacknowledged);

_do_bulkwrite_check_acknowledged_test_case(client, opts, false /* is_acknowledged_expected */);
}

// Calling `mongoc_bulkwrite_check_acknowledged` before `mongoc_bulkwrite_execute` is an error
{
mongoc_bulkwrite_t *bw = mongoc_client_bulkwrite_new(client);

bson_error_t error;
mongoc_bulkwrite_check_acknowledged_t const check_acknowledged = mongoc_bulkwrite_check_acknowledged(bw, &error);
ASSERT(!check_acknowledged.is_ok);
ASSERT_ERROR_CONTAINS(error,
MONGOC_ERROR_COMMAND,
MONGOC_ERROR_COMMAND_INVALID_ARG,
"bulk write has not been executed or execution failed");

mongoc_bulkwrite_destroy(bw);
}

mongoc_write_concern_destroy(wc_unacknowledged);
mongoc_write_concern_destroy(wc_acknowledged);
mongoc_bulkwriteopts_destroy(opts);
mongoc_client_destroy(client);
}

void
test_bulkwrite_install(TestSuite *suite)
{
Expand Down Expand Up @@ -835,4 +929,12 @@ test_bulkwrite_install(TestSuite *suite)
NULL /* ctx */,
test_framework_skip_if_max_wire_version_less_than_25 // require server 8.0
);

TestSuite_AddFull(suite,
"/bulkwrite/check_acknowledged",
test_bulkwrite_check_acknowledged,
NULL /* dtor */,
NULL /* ctx */,
test_framework_skip_if_max_wire_version_less_than_25 // require server 8.0
);
}

AltStyle によって変換されたページ (->オリジナル) /