void _mongoc_cursor_cursorid_init_with_reply (mongoc_cursor_t *cursor, bson_t *reply, uint32_t server_id) { mongoc_cursor_cursorid_t *cid; cursor->sent = true; cursor->server_id = server_id; cid = (mongoc_cursor_cursorid_t *)cursor->iface_data; BSON_ASSERT (cid); bson_destroy (&cid->array); if (!bson_steal (&cid->array, reply)) { bson_steal (&cid->array, bson_copy (reply)); } if (!_mongoc_cursor_cursorid_start_batch (cursor)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Couldn't parse cursor document"); } }
mongoc_cursor_t * _mongoc_cursor_cmd_new_from_reply (mongoc_client_t *client, const bson_t *cmd, const bson_t *opts, bson_t *reply) { mongoc_cursor_t *cursor = _mongoc_cursor_cmd_new (client, NULL, cmd, opts, NULL, NULL, NULL); data_cmd_t *data = (data_cmd_t *) cursor->impl.data; data->reading_from = CMD_RESPONSE; cursor->state = IN_BATCH; bson_destroy (&data->response.reply); if (!bson_steal (&data->response.reply, reply)) { bson_destroy (&data->response.reply); BSON_ASSERT (bson_steal (&data->response.reply, bson_copy (reply))); } if (!_mongoc_cursor_start_reading_response (cursor, &data->response)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Couldn't parse cursor document"); } return cursor; }
void _mongoc_cursor_impl_find_opquery_init (mongoc_cursor_t *cursor, bson_t *filter) { data_find_opquery_t *data = bson_malloc0 (sizeof (*data)); _mongoc_cursor_response_legacy_init (&data->response_legacy); bson_steal (&data->filter, filter); cursor->impl.prime = _prime; cursor->impl.pop_from_batch = _pop_from_batch; cursor->impl.get_next_batch = _get_next_batch; cursor->impl.destroy = _destroy; cursor->impl.clone = _clone; cursor->impl.data = data; }
static bool txn_finish (mongoc_client_session_t *session, mongoc_txn_intent_t intent, bson_t *reply, bson_error_t *error) { const char *cmd_name; bson_t cmd = BSON_INITIALIZER; bson_t opts = BSON_INITIALIZER; bson_error_t err_local; bson_error_t *err_ptr = error ? error : &err_local; bson_t reply_local = BSON_INITIALIZER; mongoc_write_err_type_t error_type; bool r = false; _mongoc_bson_init_if_set (reply); cmd_name = (intent == TXN_COMMIT ? "commitTransaction" : "abortTransaction"); if (!mongoc_client_session_append (session, &opts, err_ptr)) { GOTO (done); } if (session->txn.opts.write_concern) { if (!mongoc_write_concern_append (session->txn.opts.write_concern, &opts)) { bson_set_error (err_ptr, MONGOC_ERROR_TRANSACTION, MONGOC_ERROR_TRANSACTION_INVALID_STATE, "Invalid transaction write concern"); GOTO (done); } } BSON_APPEND_INT32 (&cmd, cmd_name, 1); /* will be reinitialized by mongoc_client_write_command_with_opts */ bson_destroy (&reply_local); r = mongoc_client_write_command_with_opts ( session->client, "admin", &cmd, &opts, &reply_local, err_ptr); /* Transactions Spec: "Drivers MUST retry the commitTransaction command once * after it fails with a retryable error", same for abort */ error_type = _mongoc_write_error_get_type (r, err_ptr, &reply_local); if (error_type == MONGOC_WRITE_ERR_RETRY) { bson_destroy (&reply_local); r = mongoc_client_write_command_with_opts ( session->client, "admin", &cmd, &opts, &reply_local, err_ptr); error_type = _mongoc_write_error_get_type (r, err_ptr, &reply_local); } /* Transactions Spec: "add the UnknownTransactionCommitResult error label * when commitTransaction fails with a network error, server selection * error, or write concern failed / timeout." */ if (intent == TXN_COMMIT && reply) { if ((!r && err_ptr->domain == MONGOC_ERROR_SERVER_SELECTION) || error_type == MONGOC_WRITE_ERR_RETRY || error_type == MONGOC_WRITE_ERR_WRITE_CONCERN) { bson_copy_to_excluding_noinit ( &reply_local, reply, "errorLabels", NULL); copy_labels_plus_unknown_commit_result (&reply_local, reply); } else { /* maintain invariants: reply & reply_local are valid until the end */ bson_destroy (reply); bson_steal (reply, &reply_local); bson_init (&reply_local); } } else if (intent == TXN_ABORT && !r) { /* we won't return an error from abortTransaction, so warn */ MONGOC_WARNING ("Error in %s: %s", cmd_name, err_ptr->message); } done: bson_destroy (&reply_local); bson_destroy (&cmd); bson_destroy (&opts); return r; }
static bool txn_commit (mongoc_client_session_t *session, bool explicitly_retrying, bson_t *reply, bson_error_t *error) { bson_t cmd = BSON_INITIALIZER; bson_t opts = BSON_INITIALIZER; bson_error_t err_local; bson_error_t *err_ptr = error ? error : &err_local; bson_t reply_local = BSON_INITIALIZER; mongoc_write_err_type_t error_type; bool r = false; bool retrying_after_error = false; mongoc_write_concern_t *retry_wc = NULL; _mongoc_bson_init_if_set (reply); BSON_APPEND_INT32 (&cmd, "commitTransaction", 1); retry: if (!mongoc_client_session_append (session, &opts, err_ptr)) { GOTO (done); } /* Transactions Spec: "When commitTransaction is retried, either by the * driver's internal retry-once logic or explicitly by the user calling * commitTransaction again, drivers MUST apply w:majority to the write * concern of the commitTransaction command." */ if (!retry_wc && (retrying_after_error || explicitly_retrying)) { retry_wc = create_commit_retry_wc (session->txn.opts.write_concern ? session->txn.opts.write_concern : session->client->write_concern); } if (retry_wc || session->txn.opts.write_concern) { if (!mongoc_write_concern_append ( retry_wc ? retry_wc : session->txn.opts.write_concern, &opts)) { bson_set_error (err_ptr, MONGOC_ERROR_TRANSACTION, MONGOC_ERROR_TRANSACTION_INVALID_STATE, "Invalid transaction write concern"); GOTO (done); } } /* will be reinitialized by mongoc_client_write_command_with_opts */ bson_destroy (&reply_local); r = mongoc_client_write_command_with_opts ( session->client, "admin", &cmd, &opts, &reply_local, err_ptr); /* Transactions Spec: "Drivers MUST retry the commitTransaction command once * after it fails with a retryable error", same for abort */ error_type = _mongoc_write_error_get_type (r, err_ptr, &reply_local); if (!retrying_after_error && error_type == MONGOC_WRITE_ERR_RETRY) { retrying_after_error = true; /* retry after error only once */ bson_reinit (&opts); GOTO (retry); } /* Transactions Spec: "add the UnknownTransactionCommitResult error label * when commitTransaction fails with a network error, server selection * error, or write concern failed / timeout." */ if (reply) { if ((!r && err_ptr->domain == MONGOC_ERROR_SERVER_SELECTION) || error_type == MONGOC_WRITE_ERR_RETRY || error_type == MONGOC_WRITE_ERR_WRITE_CONCERN) { bson_copy_to_excluding_noinit ( &reply_local, reply, "errorLabels", NULL); copy_labels_plus_unknown_commit_result (&reply_local, reply); } else { /* maintain invariants: reply & reply_local are valid until the end */ bson_destroy (reply); bson_steal (reply, &reply_local); bson_init (&reply_local); } } done: bson_destroy (&reply_local); bson_destroy (&cmd); bson_destroy (&opts); if (retry_wc) { mongoc_write_concern_destroy (retry_wc); } return r; }