static void test_write_concern_basic (void) { mongoc_write_concern_t *write_concern; const bson_t *b; bson_iter_t iter; write_concern = mongoc_write_concern_new(); /* * Test defaults. */ assert(write_concern); assert(!mongoc_write_concern_get_fsync(write_concern)); assert(!mongoc_write_concern_get_journal(write_concern)); assert(mongoc_write_concern_get_w(write_concern) == MONGOC_WRITE_CONCERN_W_DEFAULT); assert(!mongoc_write_concern_get_wtimeout(write_concern)); assert(!mongoc_write_concern_get_wmajority(write_concern)); mongoc_write_concern_set_fsync(write_concern, TRUE); assert(mongoc_write_concern_get_fsync(write_concern)); mongoc_write_concern_set_fsync(write_concern, FALSE); assert(!mongoc_write_concern_get_fsync(write_concern)); mongoc_write_concern_set_journal(write_concern, TRUE); assert(mongoc_write_concern_get_journal(write_concern)); mongoc_write_concern_set_journal(write_concern, FALSE); assert(!mongoc_write_concern_get_journal(write_concern)); /* * Test changes to w. */ mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY); assert(mongoc_write_concern_get_wmajority(write_concern)); mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_DEFAULT); assert(!mongoc_write_concern_get_wmajority(write_concern)); mongoc_write_concern_set_wmajority(write_concern, 1000); assert(mongoc_write_concern_get_wmajority(write_concern)); assert(mongoc_write_concern_get_wtimeout(write_concern) == 1000); mongoc_write_concern_set_wtimeout(write_concern, 0); assert(!mongoc_write_concern_get_wtimeout(write_concern)); mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_DEFAULT); assert(mongoc_write_concern_get_w(write_concern) == MONGOC_WRITE_CONCERN_W_DEFAULT); mongoc_write_concern_set_w(write_concern, 3); assert(mongoc_write_concern_get_w(write_concern) == 3); /* * Check generated bson. */ mongoc_write_concern_set_fsync(write_concern, TRUE); mongoc_write_concern_set_journal(write_concern, TRUE); b = _mongoc_write_concern_freeze(write_concern); assert(bson_iter_init_find(&iter, b, "fsync") && BSON_ITER_HOLDS_BOOL(&iter) && bson_iter_bool(&iter)); assert(bson_iter_init_find(&iter, b, "j") && BSON_ITER_HOLDS_BOOL(&iter) && bson_iter_bool(&iter)); assert(bson_iter_init_find(&iter, b, "w") && BSON_ITER_HOLDS_INT32(&iter) && bson_iter_int32(&iter) == 3); assert(b); mongoc_write_concern_destroy(write_concern); }
static void test_write_concern_bson_includes_false_fsync_and_journal (void) { mongoc_write_concern_t *write_concern; const bson_t *gle; const bson_t *bson; bson_iter_t iter; write_concern = mongoc_write_concern_new(); /* * Check generated bson. */ ASSERT(write_concern); mongoc_write_concern_set_fsync(write_concern, false); mongoc_write_concern_set_journal(write_concern, false); gle = _mongoc_write_concern_get_gle(write_concern); ASSERT(bson_iter_init_find(&iter, gle, "getlasterror") && BSON_ITER_HOLDS_INT32(&iter) && bson_iter_int32(&iter) == 1); ASSERT(bson_iter_init_find(&iter, gle, "fsync") && BSON_ITER_HOLDS_BOOL(&iter) && !bson_iter_bool(&iter)); ASSERT(bson_iter_init_find(&iter, gle, "j") && BSON_ITER_HOLDS_BOOL(&iter) && !bson_iter_bool(&iter)); ASSERT(!bson_iter_init_find(&iter, gle, "w")); ASSERT(gle); bson = _mongoc_write_concern_get_bson(write_concern); ASSERT(!bson_iter_init_find(&iter, bson, "getlasterror")); ASSERT(bson_iter_init_find(&iter, bson, "fsync") && BSON_ITER_HOLDS_BOOL(&iter) && !bson_iter_bool(&iter)); ASSERT(bson_iter_init_find(&iter, bson, "j") && BSON_ITER_HOLDS_BOOL(&iter) && !bson_iter_bool(&iter)); ASSERT(!bson_iter_init_find(&iter, bson, "w")); ASSERT(bson); mongoc_write_concern_destroy(write_concern); }
void HHVM_METHOD(MongoDBDriverWriteConcern, __construct, const Variant &w, const Variant &w_timeout, const Variant &journal, const Variant &fsync) { MongoDBDriverWriteConcernData* data = Native::data<MongoDBDriverWriteConcernData>(this_); data->m_write_concern = mongoc_write_concern_new(); if (w.isInteger()) { mongoc_write_concern_set_w(data->m_write_concern, w.toInt64()); } else if (w.isString()) { String w_str = w.toString(); if (w_str.compare(s_MongoDriverWriteConcern_majority) == 0) { mongoc_write_concern_set_w(data->m_write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY); } else { mongoc_write_concern_set_wtag(data->m_write_concern, w_str.c_str()); } } if (!w_timeout.isNull()) { int64_t w_int = w_timeout.toInt64(); mongoc_write_concern_set_wtimeout(data->m_write_concern, w_int); } if (!journal.isNull()) { mongoc_write_concern_set_journal(data->m_write_concern, journal.toBoolean()); } if (!fsync.isNull()) { mongoc_write_concern_set_fsync(data->m_write_concern, fsync.toBoolean()); } }
static void test_invalid_write_concern (void) { mongoc_bulk_write_flags_t write_flags = MONGOC_BULK_WRITE_FLAGS_INIT; mongoc_write_command_t command; mongoc_write_result_t result; mongoc_collection_t *collection; mongoc_client_t *client; mongoc_write_concern_t *write_concern; mongoc_server_stream_t *server_stream; bson_t *doc; bson_t reply = BSON_INITIALIZER; bson_error_t error; bool r; client = test_framework_client_new (); assert(client); collection = get_test_collection(client, "test_invalid_write_concern"); assert(collection); write_concern = mongoc_write_concern_new(); assert(write_concern); mongoc_write_concern_set_w(write_concern, 0); mongoc_write_concern_set_journal(write_concern, true); assert(!mongoc_write_concern_is_valid (write_concern)); doc = BCON_NEW("_id", BCON_INT32(0)); _mongoc_write_command_init_insert(&command, doc, write_flags, ++client->cluster.operation_id, true); _mongoc_write_result_init (&result); server_stream = mongoc_cluster_stream_for_writes (&client->cluster, &error); ASSERT_OR_PRINT (server_stream, error); _mongoc_write_command_execute (&command, client, server_stream, collection->db, collection->collection, write_concern, 0, &result); r = _mongoc_write_result_complete (&result, 2, collection->write_concern, &reply, &error); assert(!r); ASSERT_CMPINT(error.domain, ==, MONGOC_ERROR_COMMAND); ASSERT_CMPINT(error.code, ==, MONGOC_ERROR_COMMAND_INVALID_ARG); _mongoc_write_command_destroy (&command); _mongoc_write_result_destroy (&result); bson_destroy(doc); mongoc_server_stream_cleanup (server_stream); mongoc_collection_destroy(collection); mongoc_client_destroy(client); mongoc_write_concern_destroy(write_concern); }
static void test_regex (void) { mongoc_collection_t *collection; mongoc_database_t *database; mongoc_write_concern_t *wr; mongoc_client_t *client; bson_error_t error = { 0 }; int64_t count; bson_t q = BSON_INITIALIZER; bson_t *doc; bool r; client = mongoc_client_new (gTestUri); ASSERT (client); database = get_test_database (client); ASSERT (database); collection = get_test_collection (client, "test_regex"); ASSERT (collection); wr = mongoc_write_concern_new (); mongoc_write_concern_set_journal (wr, true); doc = BCON_NEW ("hello", "/world"); r = mongoc_collection_insert (collection, MONGOC_INSERT_NONE, doc, wr, &error); ASSERT (r); BSON_APPEND_REGEX (&q, "hello", "^/wo", "i"); count = mongoc_collection_count (collection, MONGOC_QUERY_NONE, &q, 0, 0, NULL, &error); ASSERT (count > 0); ASSERT (!error.domain); r = mongoc_collection_drop (collection, &error); ASSERT (r); mongoc_write_concern_destroy (wr); bson_destroy (&q); bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_database_destroy(database); mongoc_client_destroy (client); }
static void test_invalid_write_concern (void) { mongoc_write_command_t command; mongoc_write_result_t result; mongoc_collection_t *collection; mongoc_client_t *client; mongoc_write_concern_t *write_concern; bson_t **docs; bson_t reply = BSON_INITIALIZER; bson_error_t error; bool r; client = test_framework_client_new (NULL); assert(client); collection = get_test_collection(client, "test_invalid_write_concern"); assert(collection); write_concern = mongoc_write_concern_new(); assert(write_concern); mongoc_write_concern_set_w(write_concern, 0); mongoc_write_concern_set_journal(write_concern, true); assert(!_mongoc_write_concern_is_valid(write_concern)); docs = bson_malloc(sizeof(bson_t*)); docs[0] = BCON_NEW("_id", BCON_INT32(0)); _mongoc_write_command_init_insert(&command, (const bson_t * const *)docs, 1, true, true); _mongoc_write_result_init (&result); _mongoc_write_command_execute (&command, client, 0, collection->db, collection->collection, write_concern, 0, &result); r = _mongoc_write_result_complete (&result, &reply, &error); assert(!r); assert(error.domain = MONGOC_ERROR_COMMAND); assert(error.code = MONGOC_ERROR_COMMAND_INVALID_ARG); _mongoc_write_command_destroy (&command); _mongoc_write_result_destroy (&result); bson_destroy(docs[0]); bson_free(docs); mongoc_collection_destroy(collection); mongoc_client_destroy(client); mongoc_write_concern_destroy(write_concern); }
static void test_write_concern_basic (void) { mongoc_write_concern_t *write_concern; const bson_t *gle; const bson_t *bson; bson_iter_t iter; write_concern = mongoc_write_concern_new(); BEGIN_IGNORE_DEPRECATIONS; /* * Test defaults. */ ASSERT(write_concern); ASSERT(!mongoc_write_concern_get_fsync(write_concern)); ASSERT(!mongoc_write_concern_get_journal(write_concern)); ASSERT(mongoc_write_concern_get_w(write_concern) == MONGOC_WRITE_CONCERN_W_DEFAULT); ASSERT(!mongoc_write_concern_get_wtimeout(write_concern)); ASSERT(!mongoc_write_concern_get_wmajority(write_concern)); mongoc_write_concern_set_fsync(write_concern, true); ASSERT(mongoc_write_concern_get_fsync(write_concern)); mongoc_write_concern_set_fsync(write_concern, false); ASSERT(!mongoc_write_concern_get_fsync(write_concern)); mongoc_write_concern_set_journal(write_concern, true); ASSERT(mongoc_write_concern_get_journal(write_concern)); mongoc_write_concern_set_journal(write_concern, false); ASSERT(!mongoc_write_concern_get_journal(write_concern)); /* * Test changes to w. */ mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY); ASSERT(mongoc_write_concern_get_wmajority(write_concern)); mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_DEFAULT); ASSERT(!mongoc_write_concern_get_wmajority(write_concern)); mongoc_write_concern_set_wmajority(write_concern, 1000); ASSERT(mongoc_write_concern_get_wmajority(write_concern)); ASSERT(mongoc_write_concern_get_wtimeout(write_concern) == 1000); mongoc_write_concern_set_wtimeout(write_concern, 0); ASSERT(!mongoc_write_concern_get_wtimeout(write_concern)); mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_DEFAULT); ASSERT(mongoc_write_concern_get_w(write_concern) == MONGOC_WRITE_CONCERN_W_DEFAULT); mongoc_write_concern_set_w(write_concern, 3); ASSERT(mongoc_write_concern_get_w(write_concern) == 3); /* * Check generated bson. */ mongoc_write_concern_set_fsync(write_concern, true); mongoc_write_concern_set_journal(write_concern, true); gle = _mongoc_write_concern_get_gle(write_concern); ASSERT(bson_iter_init_find(&iter, gle, "getlasterror") && BSON_ITER_HOLDS_INT32(&iter) && bson_iter_int32(&iter) == 1); ASSERT(bson_iter_init_find(&iter, gle, "fsync") && BSON_ITER_HOLDS_BOOL(&iter) && bson_iter_bool(&iter)); ASSERT(bson_iter_init_find(&iter, gle, "j") && BSON_ITER_HOLDS_BOOL(&iter) && bson_iter_bool(&iter)); ASSERT(bson_iter_init_find(&iter, gle, "w") && BSON_ITER_HOLDS_INT32(&iter) && bson_iter_int32(&iter) == 3); ASSERT(gle); bson = _mongoc_write_concern_get_bson(write_concern); ASSERT(!bson_iter_init_find(&iter, bson, "getlasterror")); ASSERT(bson_iter_init_find(&iter, bson, "fsync") && BSON_ITER_HOLDS_BOOL(&iter) && bson_iter_bool(&iter)); ASSERT(bson_iter_init_find(&iter, bson, "j") && BSON_ITER_HOLDS_BOOL(&iter) && bson_iter_bool(&iter)); ASSERT(bson_iter_init_find(&iter, bson, "w") && BSON_ITER_HOLDS_INT32(&iter) && bson_iter_int32(&iter) == 3); ASSERT(bson); mongoc_write_concern_destroy(write_concern); END_IGNORE_DEPRECATIONS; }
static void test_write_concern_fsync_and_journal_gle_and_validity (void) { mongoc_write_concern_t *write_concern = mongoc_write_concern_new(); /* * Journal and fsync should imply GLE regardless of w; however, journal and * fsync logically conflict with w=0 and w=-1, so a write concern with such * a combination of options will be considered invalid. */ /* No write concern needs GLE, but not "valid" */ ASSERT(mongoc_write_concern_is_acknowledged (NULL)); ASSERT(!mongoc_write_concern_is_valid (NULL)); /* Default write concern needs GLE and is valid */ ASSERT(write_concern); ASSERT(mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(mongoc_write_concern_is_valid (write_concern)); ASSERT(!mongoc_write_concern_journal_is_set (write_concern)); /* w=0 does not need GLE and is valid */ mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED); ASSERT(!mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(mongoc_write_concern_is_valid (write_concern)); ASSERT(!mongoc_write_concern_journal_is_set (write_concern)); /* fsync=true needs GLE, but it conflicts with w=0 */ mongoc_write_concern_set_fsync(write_concern, true); ASSERT(mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(!mongoc_write_concern_is_valid (write_concern)); ASSERT(!mongoc_write_concern_journal_is_set (write_concern)); mongoc_write_concern_set_fsync(write_concern, false); /* journal=true needs GLE, but it conflicts with w=0 */ mongoc_write_concern_set_journal(write_concern, true); ASSERT(mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(!mongoc_write_concern_is_valid (write_concern)); ASSERT(mongoc_write_concern_journal_is_set (write_concern)); mongoc_write_concern_set_journal(write_concern, false); /* w=-1 does not need GLE and is valid */ mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED); ASSERT(!mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(mongoc_write_concern_is_valid (write_concern)); ASSERT(mongoc_write_concern_journal_is_set (write_concern)); /* fsync=true needs GLE, but it conflicts with w=-1 */ mongoc_write_concern_set_fsync(write_concern, true); ASSERT(mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(!mongoc_write_concern_is_valid (write_concern)); ASSERT(mongoc_write_concern_journal_is_set (write_concern)); /* journal=true needs GLE, but it conflicts with w=-1 */ mongoc_write_concern_set_fsync(write_concern, false); mongoc_write_concern_set_journal(write_concern, true); ASSERT(mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(mongoc_write_concern_journal_is_set (write_concern)); /* fsync=true with w=default needs GLE and is valid */ mongoc_write_concern_set_journal(write_concern, false); mongoc_write_concern_set_fsync(write_concern, true); mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_DEFAULT); ASSERT(mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(mongoc_write_concern_is_valid (write_concern)); ASSERT(mongoc_write_concern_journal_is_set (write_concern)); /* journal=true with w=default needs GLE and is valid */ mongoc_write_concern_set_journal(write_concern, false); mongoc_write_concern_set_fsync(write_concern, true); mongoc_write_concern_set_w(write_concern, MONGOC_WRITE_CONCERN_W_DEFAULT); ASSERT(mongoc_write_concern_is_acknowledged (write_concern)); ASSERT(mongoc_write_concern_is_valid (write_concern)); ASSERT(mongoc_write_concern_journal_is_set (write_concern)); mongoc_write_concern_destroy(write_concern); }
static void _mongoc_uri_build_write_concern (mongoc_uri_t *uri) /* IN */ { mongoc_write_concern_t *write_concern; const char *str; bson_iter_t iter; int32_t wtimeoutms; int value; BSON_ASSERT (uri); write_concern = mongoc_write_concern_new (); if (bson_iter_init_find_case (&iter, &uri->options, "safe") && BSON_ITER_HOLDS_BOOL (&iter)) { mongoc_write_concern_set_w (write_concern, bson_iter_bool (&iter) ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED); } wtimeoutms = mongoc_uri_get_option_as_int32(uri, "wtimeoutms", 0); if (bson_iter_init_find_case (&iter, &uri->options, "journal") && BSON_ITER_HOLDS_BOOL (&iter)) { mongoc_write_concern_set_journal (write_concern, bson_iter_bool (&iter)); } if (bson_iter_init_find_case (&iter, &uri->options, "w")) { if (BSON_ITER_HOLDS_INT32 (&iter)) { value = bson_iter_int32 (&iter); switch (value) { case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED: case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED: /* Warn on conflict, since write concern will be validated later */ if (mongoc_write_concern_get_journal(write_concern)) { MONGOC_WARNING("Journal conflicts with w value [w=%d].", value); } mongoc_write_concern_set_w(write_concern, value); break; default: if (value > 0) { mongoc_write_concern_set_w (write_concern, value); if (value > 1) { mongoc_write_concern_set_wtimeout (write_concern, wtimeoutms); } break; } MONGOC_WARNING ("Unsupported w value [w=%d].", value); break; } } else if (BSON_ITER_HOLDS_UTF8 (&iter)) { str = bson_iter_utf8 (&iter, NULL); if (0 == strcasecmp ("majority", str)) { mongoc_write_concern_set_wmajority (write_concern, wtimeoutms); } else { mongoc_write_concern_set_wtag (write_concern, str); mongoc_write_concern_set_wtimeout (write_concern, wtimeoutms); } } else { BSON_ASSERT (false); } } uri->write_concern = write_concern; }
/* {{{ proto void MongoDB\Driver\WriteConcern::__construct(integer|string $w[, integer $wtimeout[, boolean $journal]]) Constructs a new WriteConcern */ static PHP_METHOD(WriteConcern, __construct) { php_phongo_writeconcern_t *intern; zend_error_handling error_handling; zval *w, *journal; phongo_long wtimeout = 0; SUPPRESS_UNUSED_WARNING(return_value) SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value_used) zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC); intern = Z_WRITECONCERN_OBJ_P(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|lz", &w, &wtimeout, &journal) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } zend_restore_error_handling(&error_handling TSRMLS_CC); intern->write_concern = mongoc_write_concern_new(); if (Z_TYPE_P(w) == IS_LONG) { if (Z_LVAL_P(w) < -3) { phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected w to be >= -3, %ld given", Z_LVAL_P(w)); return; } mongoc_write_concern_set_w(intern->write_concern, Z_LVAL_P(w)); } else if (Z_TYPE_P(w) == IS_STRING) { if (strcmp(Z_STRVAL_P(w), PHONGO_WRITE_CONCERN_W_MAJORITY) == 0) { mongoc_write_concern_set_w(intern->write_concern, MONGOC_WRITE_CONCERN_W_MAJORITY); } else { mongoc_write_concern_set_wtag(intern->write_concern, Z_STRVAL_P(w)); } } else { phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected w to be integer or string, %s given", zend_get_type_by_const(Z_TYPE_P(w))); return; } switch(ZEND_NUM_ARGS()) { case 3: if (Z_TYPE_P(journal) != IS_NULL) { #ifdef ZEND_ENGINE_3 mongoc_write_concern_set_journal(intern->write_concern, zend_is_true(journal)); #else mongoc_write_concern_set_journal(intern->write_concern, Z_BVAL_P(journal)); #endif } /* fallthrough */ case 2: if (wtimeout < 0) { phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected wtimeout to be >= 0, %" PHONGO_LONG_FORMAT " given", wtimeout); return; } if (wtimeout > INT32_MAX) { phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected wtimeout to be <= %" PRId32 ", %" PHONGO_LONG_FORMAT " given", INT32_MAX, wtimeout); return; } mongoc_write_concern_set_wtimeout(intern->write_concern, wtimeout); } } /* }}} */
static void test_exhaust_cursor (void) { mongoc_write_concern_t *wr; mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; mongoc_cursor_t *cursor2; mongoc_stream_t *stream; mongoc_cluster_node_t *node; const bson_t *doc; bson_t q; bson_t b[10]; bson_t *bptr[10]; int i; bool r; bson_error_t error; bson_oid_t oid; client = mongoc_client_new (gTestUri); assert (client); collection = get_test_collection (client, "test_exhaust_cursor"); assert (collection); mongoc_collection_drop(collection, &error); wr = mongoc_write_concern_new (); mongoc_write_concern_set_journal (wr, true); /* bulk insert some records to work on */ { bson_init(&q); for (i = 0; i < 10; i++) { bson_init(&b[i]); bson_oid_init(&oid, NULL); bson_append_oid(&b[i], "_id", -1, &oid); bson_append_int32(&b[i], "n", -1, i % 2); bptr[i] = &b[i]; } BEGIN_IGNORE_DEPRECATIONS; r = mongoc_collection_insert_bulk (collection, MONGOC_INSERT_NONE, (const bson_t **)bptr, 10, wr, &error); END_IGNORE_DEPRECATIONS; if (!r) { MONGOC_WARNING("Insert bulk failure: %s\n", error.message); } assert(r); } /* create a couple of cursors */ { cursor = mongoc_collection_find (collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, &q, NULL, NULL); cursor2 = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, &q, NULL, NULL); } /* Read from the exhaust cursor, ensure that we're in exhaust where we * should be and ensure that an early destroy properly causes a disconnect * */ { r = mongoc_cursor_next (cursor, &doc); assert (r); assert (doc); assert (cursor->in_exhaust); assert (client->in_exhaust); node = &client->cluster.nodes[cursor->hint - 1]; stream = node->stream; mongoc_cursor_destroy (cursor); /* make sure a disconnect happened */ assert (stream != node->stream); assert (! client->in_exhaust); } /* Grab a new exhaust cursor, then verify that reading from that cursor * (putting the client into exhaust), breaks a mid-stream read from a * regular cursor */ { cursor = mongoc_collection_find (collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, &q, NULL, NULL); for (i = 0; i < 5; i++) { r = mongoc_cursor_next (cursor2, &doc); assert (r); assert (doc); } r = mongoc_cursor_next (cursor, &doc); assert (r); assert (doc); doc = NULL; r = mongoc_cursor_next (cursor2, &doc); assert (!r); assert (!doc); mongoc_cursor_error(cursor2, &error); assert (error.domain == MONGOC_ERROR_CLIENT); assert (error.code == MONGOC_ERROR_CLIENT_IN_EXHAUST); mongoc_cursor_destroy (cursor2); } /* make sure writes fail as well */ { BEGIN_IGNORE_DEPRECATIONS; r = mongoc_collection_insert_bulk (collection, MONGOC_INSERT_NONE, (const bson_t **)bptr, 10, wr, &error); END_IGNORE_DEPRECATIONS; assert (!r); assert (error.domain == MONGOC_ERROR_CLIENT); assert (error.code == MONGOC_ERROR_CLIENT_IN_EXHAUST); } /* we're still in exhaust. * * 1. check that we can create a new cursor, as long as we don't read from it * 2. fully exhaust the exhaust cursor * 3. make sure that we don't disconnect at destroy * 4. make sure we can read the cursor we made during the exhuast */ { cursor2 = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, &q, NULL, NULL); node = &client->cluster.nodes[cursor->hint - 1]; stream = node->stream; for (i = 1; i < 10; i++) { r = mongoc_cursor_next (cursor, &doc); assert (r); assert (doc); } r = mongoc_cursor_next (cursor, &doc); assert (!r); assert (!doc); mongoc_cursor_destroy (cursor); assert (stream == node->stream); r = mongoc_cursor_next (cursor2, &doc); assert (r); assert (doc); } bson_destroy(&q); for (i = 0; i < 10; i++) { bson_destroy(&b[i]); } r = mongoc_collection_drop (collection, &error); assert (r); mongoc_write_concern_destroy (wr); mongoc_cursor_destroy (cursor2); mongoc_collection_destroy(collection); mongoc_client_destroy (client); }
static bool hippo_mongo_driver_manager_apply_wc(mongoc_uri_t *uri, const Array options) { int32_t wtimeoutms; mongoc_write_concern_t *new_wc; const mongoc_write_concern_t *old_wc; if (!(old_wc = mongoc_uri_get_write_concern(uri))) { throw MongoDriver::Utils::throwRunTimeException("mongoc_uri_t does not have a write concern"); return false; } if (options.size() == 0) { return true; } if ( !options.exists(s_MongoDBDriverManager_journal) && !options.exists(s_MongoDBDriverManager_safe) && !options.exists(s_MongoDBDriverManager_w) && !options.exists(s_MongoDBDriverManager_wtimeoutms) ) { return true; } wtimeoutms = mongoc_write_concern_get_wtimeout(old_wc); new_wc = mongoc_write_concern_copy(old_wc); if (options.exists(s_MongoDBDriverManager_safe) && options[s_MongoDBDriverManager_safe].isBoolean()) { mongoc_write_concern_set_w(new_wc, options[s_MongoDBDriverManager_safe].toBoolean() ? 1 : MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED); } if (options.exists(s_MongoDBDriverManager_wtimeoutms) && options[s_MongoDBDriverManager_wtimeoutms].isInteger()) { wtimeoutms = (int32_t) options[s_MongoDBDriverManager_wtimeoutms].toInt64(); } if (options.exists(s_MongoDBDriverManager_journal) && options[s_MongoDBDriverManager_journal].isBoolean()) { mongoc_write_concern_set_journal(new_wc, !!options[s_MongoDBDriverManager_journal].toBoolean()); } if (options.exists(s_MongoDBDriverManager_w)) { if (options[s_MongoDBDriverManager_w].isInteger()) { int32_t value = (int32_t) options[s_MongoDBDriverManager_w].toInt64(); switch (value) { case MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED: case MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED: mongoc_write_concern_set_w(new_wc, value); break; default: if (value > 0) { mongoc_write_concern_set_w(new_wc, value); break; } throw MongoDriver::Utils::throwInvalidArgumentException("Unsupported w value: " + Variant(value).toString()); mongoc_write_concern_destroy(new_wc); return false; } } else if (options[s_MongoDBDriverManager_w].isString()) { const char *str = options[s_MongoDBDriverManager_w].toString().c_str(); if (0 == strcasecmp("majority", str)) { mongoc_write_concern_set_wmajority(new_wc, wtimeoutms); } else { mongoc_write_concern_set_wtag(new_wc, str); } } } /* Only set wtimeout if it's still applicable; otherwise, clear it. */ if (mongoc_write_concern_get_w(new_wc) > 1 || mongoc_write_concern_get_wmajority(new_wc) || mongoc_write_concern_get_wtag(new_wc)) { mongoc_write_concern_set_wtimeout(new_wc, wtimeoutms); } else { mongoc_write_concern_set_wtimeout(new_wc, 0); } if (mongoc_write_concern_get_journal(new_wc)) { int32_t w = mongoc_write_concern_get_w(new_wc); if (w == MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED || w == MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED) { throw MongoDriver::Utils::throwInvalidArgumentException("Journal conflicts with w value: " + Variant(w).toString()); mongoc_write_concern_destroy(new_wc); return false; } } /* This may be redundant in light of the last check (unacknowledged w with * journal), but we'll check anyway in case additional validation is * implemented. */ if (!mongoc_write_concern_is_valid(new_wc)) { throw MongoDriver::Utils::throwInvalidArgumentException("Write concern is not valid"); mongoc_write_concern_destroy(new_wc); return false; } mongoc_uri_set_write_concern(uri, new_wc); mongoc_write_concern_destroy(new_wc); return true; }
static void _mongoc_uri_build_write_concern (mongoc_uri_t *uri) /* IN */ { mongoc_write_concern_t *write_concern; const char *str; bson_iter_t iter; int32_t wtimeoutms = 0; int value; BSON_ASSERT (uri); write_concern = mongoc_write_concern_new (); if (bson_iter_init_find_case (&iter, &uri->options, "safe") && BSON_ITER_HOLDS_BOOL (&iter) && !bson_iter_bool (&iter)) { mongoc_write_concern_set_w (write_concern, MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED); } if (bson_iter_init_find_case (&iter, &uri->options, "wtimeoutms") && BSON_ITER_HOLDS_INT32 (&iter)) { wtimeoutms = bson_iter_int32 (&iter); } if (bson_iter_init_find_case (&iter, &uri->options, "journal") && BSON_ITER_HOLDS_BOOL (&iter) && bson_iter_bool (&iter)) { mongoc_write_concern_set_journal (write_concern, true); } if (bson_iter_init_find_case (&iter, &uri->options, "w")) { if (BSON_ITER_HOLDS_INT32 (&iter)) { value = bson_iter_int32 (&iter); switch (value) { case -1: mongoc_write_concern_set_w (write_concern, MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED); break; case 0: mongoc_write_concern_set_w (write_concern, MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED); break; case 1: mongoc_write_concern_set_w (write_concern, MONGOC_WRITE_CONCERN_W_DEFAULT); break; default: if (value > 1) { mongoc_write_concern_set_w (write_concern, value); break; } MONGOC_WARNING ("Unsupported w value [w=%d].", value); break; } } else if (BSON_ITER_HOLDS_UTF8 (&iter)) { str = bson_iter_utf8 (&iter, NULL); if (0 == strcasecmp ("majority", str)) { mongoc_write_concern_set_wmajority (write_concern, wtimeoutms); } else { mongoc_write_concern_set_wtag (write_concern, str); } } else { BSON_ASSERT (false); } } uri->write_concern = write_concern; }
static void test_exhaust_cursor (bool pooled) { mongoc_stream_t *stream; mongoc_write_concern_t *wr; mongoc_client_t *client; mongoc_client_pool_t *pool = NULL; mongoc_collection_t *collection; mongoc_cursor_t *cursor; mongoc_cursor_t *cursor2; const bson_t *doc; bson_t q; bson_t b[10]; bson_t *bptr[10]; int i; bool r; uint32_t hint; bson_error_t error; bson_oid_t oid; int64_t timestamp1; if (pooled) { pool = test_framework_client_pool_new (); client = mongoc_client_pool_pop (pool); } else { client = test_framework_client_new (); } assert (client); collection = get_test_collection (client, "test_exhaust_cursor"); assert (collection); mongoc_collection_drop(collection, &error); wr = mongoc_write_concern_new (); mongoc_write_concern_set_journal (wr, true); /* bulk insert some records to work on */ { bson_init(&q); for (i = 0; i < 10; i++) { bson_init(&b[i]); bson_oid_init(&oid, NULL); bson_append_oid(&b[i], "_id", -1, &oid); bson_append_int32(&b[i], "n", -1, i % 2); bptr[i] = &b[i]; } BEGIN_IGNORE_DEPRECATIONS; ASSERT_OR_PRINT (mongoc_collection_insert_bulk ( collection, MONGOC_INSERT_NONE, (const bson_t **)bptr, 10, wr, &error), error); END_IGNORE_DEPRECATIONS; } /* create a couple of cursors */ { cursor = mongoc_collection_find (collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, &q, NULL, NULL); cursor2 = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, &q, NULL, NULL); } /* Read from the exhaust cursor, ensure that we're in exhaust where we * should be and ensure that an early destroy properly causes a disconnect * */ { r = mongoc_cursor_next (cursor, &doc); if (!r) { mongoc_cursor_error (cursor, &error); fprintf (stderr, "cursor error: %s\n", error.message); } assert (r); assert (doc); assert (cursor->in_exhaust); assert (client->in_exhaust); /* destroy the cursor, make sure a disconnect happened */ timestamp1 = get_timestamp (client, cursor); mongoc_cursor_destroy (cursor); assert (! client->in_exhaust); } /* Grab a new exhaust cursor, then verify that reading from that cursor * (putting the client into exhaust), breaks a mid-stream read from a * regular cursor */ { cursor = mongoc_collection_find (collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, &q, NULL, NULL); r = mongoc_cursor_next (cursor2, &doc); if (!r) { mongoc_cursor_error (cursor2, &error); fprintf (stderr, "cursor error: %s\n", error.message); } assert (r); assert (doc); assert (timestamp1 < get_timestamp (client, cursor2)); for (i = 0; i < 5; i++) { r = mongoc_cursor_next (cursor2, &doc); if (!r) { mongoc_cursor_error (cursor2, &error); fprintf (stderr, "cursor error: %s\n", error.message); } assert (r); assert (doc); } r = mongoc_cursor_next (cursor, &doc); assert (r); assert (doc); doc = NULL; r = mongoc_cursor_next (cursor2, &doc); assert (!r); assert (!doc); mongoc_cursor_error(cursor2, &error); assert (error.domain == MONGOC_ERROR_CLIENT); assert (error.code == MONGOC_ERROR_CLIENT_IN_EXHAUST); mongoc_cursor_destroy (cursor2); } /* make sure writes fail as well */ { BEGIN_IGNORE_DEPRECATIONS; r = mongoc_collection_insert_bulk (collection, MONGOC_INSERT_NONE, (const bson_t **)bptr, 10, wr, &error); END_IGNORE_DEPRECATIONS; assert (!r); assert (error.domain == MONGOC_ERROR_CLIENT); assert (error.code == MONGOC_ERROR_CLIENT_IN_EXHAUST); } /* we're still in exhaust. * * 1. check that we can create a new cursor, as long as we don't read from it * 2. fully exhaust the exhaust cursor * 3. make sure that we don't disconnect at destroy * 4. make sure we can read the cursor we made during the exhuast */ { cursor2 = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, &q, NULL, NULL); stream = (mongoc_stream_t *)mongoc_set_get(client->cluster.nodes, cursor->hint); hint = cursor->hint; for (i = 1; i < 10; i++) { r = mongoc_cursor_next (cursor, &doc); assert (r); assert (doc); } r = mongoc_cursor_next (cursor, &doc); assert (!r); assert (!doc); mongoc_cursor_destroy (cursor); assert (stream == (mongoc_stream_t *)mongoc_set_get(client->cluster.nodes, hint)); r = mongoc_cursor_next (cursor2, &doc); assert (r); assert (doc); } bson_destroy(&q); for (i = 0; i < 10; i++) { bson_destroy(&b[i]); } ASSERT_OR_PRINT (mongoc_collection_drop (collection, &error), error); mongoc_write_concern_destroy (wr); mongoc_cursor_destroy (cursor2); mongoc_collection_destroy(collection); if (pooled) { mongoc_client_pool_push (pool, client); mongoc_client_pool_destroy (pool); } else { mongoc_client_destroy (client); } }