mongoc_client_pool_t * mongoc_client_pool_new (const mongoc_uri_t *uri) { mongoc_topology_t *topology; mongoc_client_pool_t *pool; const bson_t *b; bson_iter_t iter; ENTRY; BSON_ASSERT (uri); #ifndef MONGOC_ENABLE_SSL if (mongoc_uri_get_ssl (uri)) { MONGOC_ERROR ("Can't create SSL client pool," " SSL not enabled in this build."); return NULL; } #endif pool = (mongoc_client_pool_t *)bson_malloc0(sizeof *pool); mongoc_mutex_init(&pool->mutex); _mongoc_queue_init(&pool->queue); pool->uri = mongoc_uri_copy(uri); pool->min_pool_size = 0; pool->max_pool_size = 100; pool->size = 0; pool->topology_scanner_started = false; topology = mongoc_topology_new(uri, false); pool->topology = topology; mongoc_client_metadata_init (&pool->topology->scanner->ismaster_metadata); pool->error_api_version = MONGOC_ERROR_API_VERSION_LEGACY; b = mongoc_uri_get_options(pool->uri); if (bson_iter_init_find_case(&iter, b, "minpoolsize")) { if (BSON_ITER_HOLDS_INT32(&iter)) { pool->min_pool_size = BSON_MAX(0, bson_iter_int32(&iter)); } } if (bson_iter_init_find_case(&iter, b, "maxpoolsize")) { if (BSON_ITER_HOLDS_INT32(&iter)) { pool->max_pool_size = BSON_MAX(1, bson_iter_int32(&iter)); } } mongoc_counter_client_pools_active_inc(); RETURN(pool); }
/** writev against a gridfs file */ ssize_t mongoc_gridfs_file_writev (mongoc_gridfs_file_t *file, mongoc_iovec_t *iov, size_t iovcnt, uint32_t timeout_msec) { uint32_t bytes_written = 0; int32_t r; size_t i; uint32_t iov_pos; ENTRY; BSON_ASSERT (file); BSON_ASSERT (iov); BSON_ASSERT (iovcnt); BSON_ASSERT (timeout_msec <= INT_MAX); /* TODO: we should probably do something about timeout_msec here */ for (i = 0; i < iovcnt; i++) { iov_pos = 0; for (;; ) { if (!file->page) { _mongoc_gridfs_file_refresh_page (file); } r = _mongoc_gridfs_file_page_write (file->page, (uint8_t *)iov[i].iov_base + iov_pos, (uint32_t)(iov[i].iov_len - iov_pos)); BSON_ASSERT (r >= 0); iov_pos += r; file->pos += r; bytes_written += r; file->length = BSON_MAX (file->length, (int64_t)file->pos); if (iov_pos == iov[i].iov_len) { /** filled a bucket, keep going */ break; } else { /** flush the buffer, the next pass through will bring in a new page * * Our file pointer is now on the new page, so push it back one so * that flush knows to flush the old page rather than a new one. * This is a little hacky */ file->pos--; _mongoc_gridfs_file_flush_page (file); file->pos++; } } } file->is_dirty = 1; RETURN (bytes_written); }
mongoc_client_pool_t * mongoc_client_pool_new (const mongoc_uri_t *uri) { mongoc_topology_t *topology; mongoc_client_pool_t *pool; const bson_t *b; bson_iter_t iter; ENTRY; BSON_ASSERT (uri); pool = (mongoc_client_pool_t *)bson_malloc0(sizeof *pool); mongoc_mutex_init(&pool->mutex); _mongoc_queue_init(&pool->queue); pool->uri = mongoc_uri_copy(uri); pool->min_pool_size = 0; pool->max_pool_size = 100; pool->size = 0; topology = mongoc_topology_new(uri, false); pool->topology = topology; b = mongoc_uri_get_options(pool->uri); if (bson_iter_init_find_case(&iter, b, "minpoolsize")) { if (BSON_ITER_HOLDS_INT32(&iter)) { pool->min_pool_size = BSON_MAX(0, bson_iter_int32(&iter)); } } if (bson_iter_init_find_case(&iter, b, "maxpoolsize")) { if (BSON_ITER_HOLDS_INT32(&iter)) { pool->max_pool_size = BSON_MAX(1, bson_iter_int32(&iter)); } } mongoc_counter_client_pools_active_inc(); RETURN(pool); }
void _mongoc_write_result_merge (mongoc_write_result_t *result, /* IN */ mongoc_write_command_t *command, /* IN */ const bson_t *reply, /* IN */ uint32_t offset) { int32_t server_index = 0; const bson_value_t *value; bson_iter_t iter; bson_iter_t citer; bson_iter_t ar; int32_t n_upserted = 0; int32_t affected = 0; ENTRY; BSON_ASSERT (result); BSON_ASSERT (reply); if (bson_iter_init_find (&iter, reply, "n") && BSON_ITER_HOLDS_INT32 (&iter)) { affected = bson_iter_int32 (&iter); } if (bson_iter_init_find (&iter, reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY (&iter) && bson_iter_recurse (&iter, &citer) && bson_iter_next (&citer)) { result->failed = true; } switch (command->type) { case MONGOC_WRITE_COMMAND_INSERT: result->nInserted += affected; break; case MONGOC_WRITE_COMMAND_DELETE: result->nRemoved += affected; break; case MONGOC_WRITE_COMMAND_UPDATE: /* server returns each upserted _id with its index into this batch * look for "upserted": [{"index": 4, "_id": ObjectId()}, ...] */ if (bson_iter_init_find (&iter, reply, "upserted")) { if (BSON_ITER_HOLDS_ARRAY (&iter) && (bson_iter_recurse (&iter, &ar))) { while (bson_iter_next (&ar)) { if (BSON_ITER_HOLDS_DOCUMENT (&ar) && bson_iter_recurse (&ar, &citer) && bson_iter_find (&citer, "index") && BSON_ITER_HOLDS_INT32 (&citer)) { server_index = bson_iter_int32 (&citer); if (bson_iter_recurse (&ar, &citer) && bson_iter_find (&citer, "_id")) { value = bson_iter_value (&citer); _mongoc_write_result_append_upsert ( result, offset + server_index, value); n_upserted++; } } } } result->nUpserted += n_upserted; /* * XXX: The following addition to nMatched needs some checking. * I'm highly skeptical of it. */ result->nMatched += BSON_MAX (0, (affected - n_upserted)); } else { result->nMatched += affected; } if (bson_iter_init_find (&iter, reply, "nModified") && BSON_ITER_HOLDS_INT32 (&iter)) { result->nModified += bson_iter_int32 (&iter); } break; default: BSON_ASSERT (false); break; } if (bson_iter_init_find (&iter, reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY (&iter)) { _mongoc_write_result_merge_arrays ( offset, result, &result->writeErrors, &iter); } if (bson_iter_init_find (&iter, reply, "writeConcernError") && BSON_ITER_HOLDS_DOCUMENT (&iter)) { uint32_t len; const uint8_t *data; bson_t write_concern_error; char str[16]; const char *key; /* writeConcernError is a subdocument in the server response * append it to the result->writeConcernErrors array */ bson_iter_document (&iter, &len, &data); bson_init_static (&write_concern_error, data, len); bson_uint32_to_string ( result->n_writeConcernErrors, &key, str, sizeof str); if (!bson_append_document ( &result->writeConcernErrors, key, -1, &write_concern_error)) { MONGOC_ERROR ("Error adding \"%s\" to writeConcernErrors.\n", key); } result->n_writeConcernErrors++; } /* inefficient if there are ever large numbers: for each label in each err, * we linear-search result->errorLabels to see if it's included yet */ _mongoc_bson_array_copy_labels_to (reply, &result->errorLabels); EXIT; }
void _mongoc_write_result_merge (mongoc_write_result_t *result, /* IN */ mongoc_write_command_t *command, /* IN */ const bson_t *reply, /* IN */ uint32_t offset) { int32_t server_index = 0; const bson_value_t *value; bson_iter_t iter; bson_iter_t citer; bson_iter_t ar; int32_t n_upserted = 0; int32_t affected = 0; ENTRY; BSON_ASSERT (result); BSON_ASSERT (reply); if (bson_iter_init_find (&iter, reply, "n") && BSON_ITER_HOLDS_INT32 (&iter)) { affected = bson_iter_int32 (&iter); } if (bson_iter_init_find (&iter, reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY (&iter) && bson_iter_recurse (&iter, &citer) && bson_iter_next (&citer)) { result->failed = true; } switch (command->type) { case MONGOC_WRITE_COMMAND_INSERT: result->nInserted += affected; break; case MONGOC_WRITE_COMMAND_DELETE: result->nRemoved += affected; break; case MONGOC_WRITE_COMMAND_UPDATE: /* server returns each upserted _id with its index into this batch * look for "upserted": [{"index": 4, "_id": ObjectId()}, ...] */ if (bson_iter_init_find (&iter, reply, "upserted")) { if (BSON_ITER_HOLDS_ARRAY (&iter) && (bson_iter_recurse (&iter, &ar))) { while (bson_iter_next (&ar)) { if (BSON_ITER_HOLDS_DOCUMENT (&ar) && bson_iter_recurse (&ar, &citer) && bson_iter_find (&citer, "index") && BSON_ITER_HOLDS_INT32 (&citer)) { server_index = bson_iter_int32 (&citer); if (bson_iter_recurse (&ar, &citer) && bson_iter_find (&citer, "_id")) { value = bson_iter_value (&citer); _mongoc_write_result_append_upsert (result, offset + server_index, value); n_upserted++; } } } } result->nUpserted += n_upserted; /* * XXX: The following addition to nMatched needs some checking. * I'm highly skeptical of it. */ result->nMatched += BSON_MAX (0, (affected - n_upserted)); } else { result->nMatched += affected; } /* * SERVER-13001 - in a mixed sharded cluster a call to update could * return nModified (>= 2.6) or not (<= 2.4). If any call does not * return nModified we can't report a valid final count so omit the * field completely. */ if (bson_iter_init_find (&iter, reply, "nModified") && BSON_ITER_HOLDS_INT32 (&iter)) { result->nModified += bson_iter_int32 (&iter); } else { /* * nModified could be BSON_TYPE_NULL, which should also be omitted. */ result->omit_nModified = true; } break; default: BSON_ASSERT (false); break; } if (bson_iter_init_find (&iter, reply, "writeErrors") && BSON_ITER_HOLDS_ARRAY (&iter)) { _mongoc_write_result_merge_arrays (offset, result, &result->writeErrors, &iter); } if (bson_iter_init_find (&iter, reply, "writeConcernError") && BSON_ITER_HOLDS_DOCUMENT (&iter)) { uint32_t len; const uint8_t *data; bson_t write_concern_error; char str[16]; const char *key; /* writeConcernError is a subdocument in the server response * append it to the result->writeConcernErrors array */ bson_iter_document (&iter, &len, &data); bson_init_static (&write_concern_error, data, len); bson_uint32_to_string (result->n_writeConcernErrors, &key, str, sizeof str); bson_append_document (&result->writeConcernErrors, key, -1, &write_concern_error); result->n_writeConcernErrors++; } EXIT; }
/** writev against a gridfs file * timeout_msec is unused */ ssize_t mongoc_gridfs_file_writev (mongoc_gridfs_file_t *file, const mongoc_iovec_t *iov, size_t iovcnt, uint32_t timeout_msec) { uint32_t bytes_written = 0; int32_t r; size_t i; uint32_t iov_pos; ENTRY; BSON_ASSERT (file); BSON_ASSERT (iov); BSON_ASSERT (iovcnt); /* Pull in the correct page */ if (!file->page && !_mongoc_gridfs_file_refresh_page (file)) { return -1; } /* When writing past the end-of-file, fill the gap with zeros */ if (file->pos > file->length && !_mongoc_gridfs_file_extend (file)) { return -1; } for (i = 0; i < iovcnt; i++) { iov_pos = 0; for (;;) { if (!file->page && !_mongoc_gridfs_file_refresh_page (file)) { return -1; } /* write bytes until an iov is exhausted or the page is full */ r = _mongoc_gridfs_file_page_write ( file->page, (uint8_t *) iov[i].iov_base + iov_pos, (uint32_t) (iov[i].iov_len - iov_pos)); BSON_ASSERT (r >= 0); iov_pos += r; file->pos += r; bytes_written += r; file->length = BSON_MAX (file->length, (int64_t) file->pos); if (iov_pos == iov[i].iov_len) { /** filled a bucket, keep going */ break; } else { /** flush the buffer, the next pass through will bring in a new page */ if (!_mongoc_gridfs_file_flush_page (file)) { return -1; } } } } file->is_dirty = 1; RETURN (bytes_written); }