mod_cdr_mongodb: update MongoDB driver to v0.6

This commit is contained in:
Daniel Swarbrick 2012-10-14 13:45:50 +02:00
parent 6533c9b92b
commit 10093b44c0
10 changed files with 543 additions and 126 deletions

View File

@ -1,5 +1,37 @@
# MongoDB C Driver History # MongoDB C Driver History
## 0.6
2012-6-3
** API CHANGE **
Version 0.6 supports write concern. This involves a backward-breaking
API change, as the write functions now take an optional write_concern
object.
The driver now also supports the MONGO_CONTINUE_ON_ERROR flag for
batch inserts.
The new function prototypes are as follows:
* int mongo_insert( mongo *conn, const char *ns, const bson *data,
mongo_write_concern *custom_write_concern );
* int mongo_insert_batch( mongo *conn, const char *ns,
const bson **data, int num, mongo_write_concern *custom_write_concern );
* int mongo_update( mongo *conn, const char *ns, const bson *cond,
const bson *op, int flags, mongo_write_concern *custom_write_concern,
int flags );
* int mongo_remove( mongo *conn, const char *ns, const bson *cond,
mongo_write_concern *custom_write_concern );
* Allow DBRefs (i.e., allows keys $ref, $id, and $db)
* Added mongo_create_capped_collection().
* Fixed some bugs in the SCons and Makefile build scripts.
* Fixes for SCons and Makefile shared library install targets.
* Other minor bug fixes.
## 0.5.2 ## 0.5.2
2012-5-4 2012-5-4

View File

@ -9,17 +9,31 @@ by providing an interface for platform-specific modules.
Until the 1.0 release, this driver should be considered alpha. Keep in mind that the API will be in flux until then. Until the 1.0 release, this driver should be considered alpha. Keep in mind that the API will be in flux until then.
# Documentation
Documentation exists in the project's `docs` folder. You can read the latest
docs online at (http://api.mongodb.org/c/current/).
The docs are built using Sphinx and Doxygen. If you have these tools installed, then
you can build the docs with scons:
scons docs
The html docs will appear in docs/html.
# Building # Building
First check out the version you want to build. *Always build from a particular tag, since HEAD may be First check out the version you want to build. *Always build from a particular tag, since HEAD may be
a work in progress.* For example, to build version 0.5.2, run: a work in progress.* For example, to build version 0.6, run:
git checkout v0.5.2 git checkout v0.6
You can then build the driver with scons: You can then build the driver with scons:
scons scons
For more build options, see the docs.
## Running the tests ## Running the tests
Make sure that you're running mongod on 127.0.0.1 on the default port (27017). The replica set Make sure that you're running mongod on 127.0.0.1 on the default port (27017). The replica set
test assumes a replica set with at least three nodes running at 127.0.0.1 and starting at port test assumes a replica set with at least three nodes running at 127.0.0.1 and starting at port
@ -35,14 +49,6 @@ Specific error codes and error strings are then stored in the `err` and `errstr`
`mongo` and `bson` objects. It is the client's responsibility to check for errors and handle `mongo` and `bson` objects. It is the client's responsibility to check for errors and handle
them appropriately. them appropriately.
# Docs
The docs are built using Sphinx and Doxygen. If you have these tools installed, then
you can build the docs with scons:
scons docs
The html docs will appear in docs/html.
# ISSUES # ISSUES
You can report bugs, request new features, and view this driver's roadmap You can report bugs, request new features, and view this driver's roadmap

View File

@ -32,7 +32,7 @@ static const int zero = 0;
/* Custom standard function pointers. */ /* Custom standard function pointers. */
void *( *bson_malloc_func )( size_t ) = malloc; void *( *bson_malloc_func )( size_t ) = malloc;
void *( *bson_realloc_func )( void *, size_t ) = realloc; void *( *bson_realloc_func )( void *, size_t ) = realloc;
void ( *bson_free )( void * ) = free; void ( *bson_free_func )( void * ) = free;
#ifdef R_SAFETY_NET #ifdef R_SAFETY_NET
bson_printf_func bson_printf; bson_printf_func bson_printf;
#else #else
@ -308,7 +308,7 @@ MONGO_EXPORT void bson_print_raw( const char *data , int depth ) {
------------------------------ */ ------------------------------ */
MONGO_EXPORT bson_iterator* bson_iterator_create() { MONGO_EXPORT bson_iterator* bson_iterator_create() {
return (bson_iterator*)malloc(sizeof(bson_iterator*)); return ( bson_iterator* )malloc( sizeof( bson_iterator ) );
} }
MONGO_EXPORT void bson_iterator_dispose(bson_iterator* i) { MONGO_EXPORT void bson_iterator_dispose(bson_iterator* i) {
@ -973,6 +973,10 @@ MONGO_EXPORT bson_err_handler set_bson_err_handler( bson_err_handler func ) {
return old; return old;
} }
MONGO_EXPORT void bson_free( void *ptr ) {
bson_free_func( ptr );
}
MONGO_EXPORT void *bson_malloc( int size ) { MONGO_EXPORT void *bson_malloc( int size ) {
void *p; void *p;
p = bson_malloc_func( size ); p = bson_malloc_func( size );

View File

@ -959,13 +959,15 @@ typedef int (*bson_sprintf_func)( char *, const char *, ... );
extern void *( *bson_malloc_func )( size_t ); extern void *( *bson_malloc_func )( size_t );
extern void *( *bson_realloc_func )( void *, size_t ); extern void *( *bson_realloc_func )( void *, size_t );
extern void ( *bson_free )( void * ); extern void ( *bson_free_func )( void * );
extern bson_printf_func bson_printf; extern bson_printf_func bson_printf;
extern bson_fprintf_func bson_fprintf; extern bson_fprintf_func bson_fprintf;
extern bson_sprintf_func bson_sprintf; extern bson_sprintf_func bson_sprintf;
extern bson_printf_func bson_errprintf; extern bson_printf_func bson_errprintf;
MONGO_EXPORT void bson_free( void *ptr );
/** /**
* Allocates memory and checks return value, exiting fatally if malloc() fails. * Allocates memory and checks return value, exiting fatally if malloc() fails.
* *

View File

@ -101,6 +101,24 @@ static int isLegalUTF8( const unsigned char *source, int length ) {
return 1; return 1;
} }
/* If the name is part of a db ref ($ref, $db, or $id), then return true. */
static int bson_string_is_db_ref( const unsigned char *string, const int length ) {
int result = 0;
if( length >= 4 ) {
if( string[1] == 'r' && string[2] == 'e' && string[3] == 'f' )
result = 1;
}
else if( length >= 3 ) {
if( string[1] == 'i' && string[2] == 'd' )
result = 1;
else if( string[1] == 'd' && string[2] == 'b' )
result = 1;
}
return result;
}
static int bson_validate_string( bson *b, const unsigned char *string, static int bson_validate_string( bson *b, const unsigned char *string,
const int length, const char check_utf8, const char check_dot, const int length, const char check_utf8, const char check_dot,
const char check_dollar ) { const char check_dollar ) {
@ -109,7 +127,8 @@ static int bson_validate_string( bson *b, const unsigned char *string,
int sequence_length = 1; int sequence_length = 1;
if( check_dollar && string[0] == '$' ) { if( check_dollar && string[0] == '$' ) {
b->err |= BSON_FIELD_INIT_DOLLAR; if( !bson_string_is_db_ref( string, length ) )
b->err |= BSON_FIELD_INIT_DOLLAR;
} }
while ( position < length ) { while ( position < length ) {

View File

@ -24,8 +24,8 @@
#include <ws2tcpip.h> // send,recv,socklen_t etc #include <ws2tcpip.h> // send,recv,socklen_t etc
#include <wspiapi.h> // addrinfo #include <wspiapi.h> // addrinfo
#else #else
#include <windows.h> #include <ws2tcpip.h> // send,recv,socklen_t etc
#include <winsock.h> #include <winsock2.h>
typedef int socklen_t; typedef int socklen_t;
#endif #endif
@ -33,11 +33,6 @@ typedef int socklen_t;
# define NI_MAXSERV 32 # define NI_MAXSERV 32
#endif #endif
static void mongo_clear_errors( mongo *conn ) {
conn->err = 0;
memset( conn->errstr, 0, MONGO_ERR_LEN );
}
int mongo_env_close_socket( int socket ) { int mongo_env_close_socket( int socket ) {
return closesocket( socket ); return closesocket( socket );
} }

View File

@ -170,7 +170,7 @@ static int gridfs_insert_file( gridfs *gfs, const char *name,
bson_append_string( &ret, "contentType", contenttype ); bson_append_string( &ret, "contentType", contenttype );
} }
bson_finish( &ret ); bson_finish( &ret );
result = mongo_insert( gfs->client, gfs->files_ns, &ret ); result = mongo_insert( gfs->client, gfs->files_ns, &ret, NULL );
bson_destroy( &ret ); bson_destroy( &ret );
return result; return result;
@ -198,7 +198,7 @@ MONGO_EXPORT int gridfs_store_buffer( gridfs *gfs, const char *data,
chunkLen = DEFAULT_CHUNK_SIZE < ( unsigned int )( end - data_ptr ) ? chunkLen = DEFAULT_CHUNK_SIZE < ( unsigned int )( end - data_ptr ) ?
DEFAULT_CHUNK_SIZE : ( unsigned int )( end - data_ptr ); DEFAULT_CHUNK_SIZE : ( unsigned int )( end - data_ptr );
oChunk = chunk_new( id, chunkNumber, data_ptr, chunkLen ); oChunk = chunk_new( id, chunkNumber, data_ptr, chunkLen );
mongo_insert( gfs->client, gfs->chunks_ns, oChunk ); mongo_insert( gfs->client, gfs->chunks_ns, oChunk, NULL );
chunk_free( oChunk ); chunk_free( oChunk );
chunkNumber++; chunkNumber++;
data_ptr += chunkLen; data_ptr += chunkLen;
@ -259,7 +259,7 @@ MONGO_EXPORT void gridfile_write_buffer( gridfile *gfile, const char *data,
memcpy( buffer + gfile->pending_len, data, data_partial_len ); memcpy( buffer + gfile->pending_len, data, data_partial_len );
oChunk = chunk_new( gfile->id, gfile->chunk_num, buffer, DEFAULT_CHUNK_SIZE ); oChunk = chunk_new( gfile->id, gfile->chunk_num, buffer, DEFAULT_CHUNK_SIZE );
mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk ); mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk, NULL );
chunk_free( oChunk ); chunk_free( oChunk );
gfile->chunk_num++; gfile->chunk_num++;
gfile->length += DEFAULT_CHUNK_SIZE; gfile->length += DEFAULT_CHUNK_SIZE;
@ -272,7 +272,7 @@ MONGO_EXPORT void gridfile_write_buffer( gridfile *gfile, const char *data,
while( chunks_to_write > 0 ) { while( chunks_to_write > 0 ) {
oChunk = chunk_new( gfile->id, gfile->chunk_num, data, DEFAULT_CHUNK_SIZE ); oChunk = chunk_new( gfile->id, gfile->chunk_num, data, DEFAULT_CHUNK_SIZE );
mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk ); mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk, NULL );
chunk_free( oChunk ); chunk_free( oChunk );
gfile->chunk_num++; gfile->chunk_num++;
chunks_to_write--; chunks_to_write--;
@ -302,7 +302,7 @@ MONGO_EXPORT int gridfile_writer_done( gridfile *gfile ) {
int response; int response;
if( gfile->pending_data ) { if( gfile->pending_data ) {
oChunk = chunk_new( gfile->id, gfile->chunk_num, gfile->pending_data, gfile->pending_len ); oChunk = chunk_new( gfile->id, gfile->chunk_num, gfile->pending_data, gfile->pending_len );
mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk ); mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk, NULL );
chunk_free( oChunk ); chunk_free( oChunk );
bson_free( gfile->pending_data ); bson_free( gfile->pending_data );
gfile->length += gfile->pending_len; gfile->length += gfile->pending_len;
@ -344,7 +344,7 @@ int gridfs_store_file( gridfs *gfs, const char *filename,
chunkLen = fread( buffer, 1, DEFAULT_CHUNK_SIZE, fd ); chunkLen = fread( buffer, 1, DEFAULT_CHUNK_SIZE, fd );
do { do {
oChunk = chunk_new( id, chunkNumber, buffer, chunkLen ); oChunk = chunk_new( id, chunkNumber, buffer, chunkLen );
mongo_insert( gfs->client, gfs->chunks_ns, oChunk ); mongo_insert( gfs->client, gfs->chunks_ns, oChunk, NULL );
chunk_free( oChunk ); chunk_free( oChunk );
length += chunkLen; length += chunkLen;
chunkNumber++; chunkNumber++;
@ -390,14 +390,14 @@ MONGO_EXPORT void gridfs_remove_filename( gridfs *gfs, const char *filename ) {
bson_init( &b ); bson_init( &b );
bson_append_oid( &b, "_id", &id ); bson_append_oid( &b, "_id", &id );
bson_finish( &b ); bson_finish( &b );
mongo_remove( gfs->client, gfs->files_ns, &b ); mongo_remove( gfs->client, gfs->files_ns, &b, NULL );
bson_destroy( &b ); bson_destroy( &b );
/* Remove all chunks from the file with the specified id */ /* Remove all chunks from the file with the specified id */
bson_init( &b ); bson_init( &b );
bson_append_oid( &b, "files_id", &id ); bson_append_oid( &b, "files_id", &id );
bson_finish( &b ); bson_finish( &b );
mongo_remove( gfs->client, gfs->chunks_ns, &b ); mongo_remove( gfs->client, gfs->chunks_ns, &b, NULL );
bson_destroy( &b ); bson_destroy( &b );
} }

View File

@ -57,6 +57,8 @@ const char* _get_host_port(mongo_host_port* hp) {
MONGO_EXPORT const char* mongo_get_primary(mongo* conn) { MONGO_EXPORT const char* mongo_get_primary(mongo* conn) {
mongo* conn_ = (mongo*)conn; mongo* conn_ = (mongo*)conn;
if( !(conn_->connected) || (conn_->primary->host == '\0') )
return NULL;
return _get_host_port(conn_->primary); return _get_host_port(conn_->primary);
} }
@ -122,7 +124,7 @@ MONGO_EXPORT void __mongo_set_error( mongo *conn, mongo_error_t err, const char
str_size = strlen( str ) + 1; str_size = strlen( str ) + 1;
errstr_size = str_size > MONGO_ERR_LEN ? MONGO_ERR_LEN : str_size; errstr_size = str_size > MONGO_ERR_LEN ? MONGO_ERR_LEN : str_size;
memcpy( conn->errstr, str, errstr_size ); memcpy( conn->errstr, str, errstr_size );
conn->errstr[errstr_size] = '\0'; conn->errstr[errstr_size-1] = '\0';
} }
} }
@ -134,6 +136,23 @@ MONGO_EXPORT void mongo_clear_errors( mongo *conn ) {
memset( conn->lasterrstr, 0, MONGO_ERR_LEN ); memset( conn->lasterrstr, 0, MONGO_ERR_LEN );
} }
/* Note: this function returns a char* which must be freed. */
static char *mongo_ns_to_cmd_db( const char *ns ) {
char *current = NULL;
char *cmd_db_name = NULL;
int len = 0;
for( current = (char *)ns; *current != '.'; current++ ) {
len++;
}
cmd_db_name = (char *)bson_malloc( len + 6 );
strncpy( cmd_db_name, ns, len );
strncpy( cmd_db_name + len, ".$cmd", 6 );
return cmd_db_name;
}
MONGO_EXPORT int mongo_validate_ns( mongo *conn, const char *ns ) { MONGO_EXPORT int mongo_validate_ns( mongo *conn, const char *ns ) {
char *last = NULL; char *last = NULL;
char *current = NULL; char *current = NULL;
@ -378,7 +397,6 @@ MONGO_EXPORT void mongo_init_sockets( void ) {
mongo_env_sock_init(); mongo_env_sock_init();
} }
MONGO_EXPORT void mongo_init( mongo *conn ) { MONGO_EXPORT void mongo_init( mongo *conn ) {
memset( conn, 0, sizeof( mongo ) ); memset( conn, 0, sizeof( mongo ) );
conn->max_bson_size = MONGO_DEFAULT_MAX_BSON_SIZE; conn->max_bson_size = MONGO_DEFAULT_MAX_BSON_SIZE;
@ -412,6 +430,8 @@ MONGO_EXPORT void mongo_replset_init( mongo *conn, const char *name ) {
memcpy( conn->replset->name, name, strlen( name ) + 1 ); memcpy( conn->replset->name, name, strlen( name ) + 1 );
conn->primary = bson_malloc( sizeof( mongo_host_port ) ); conn->primary = bson_malloc( sizeof( mongo_host_port ) );
conn->primary->host[0] = '\0';
conn->primary->next = NULL;
} }
static void mongo_replset_add_node( mongo_host_port **list, const char *host, int port ) { static void mongo_replset_add_node( mongo_host_port **list, const char *host, int port ) {
@ -736,12 +756,109 @@ static int mongo_cursor_bson_valid( mongo_cursor *cursor, const bson *bson ) {
return MONGO_OK; return MONGO_OK;
} }
/* MongoDB CRUD API */ static int mongo_check_last_error( mongo *conn, const char *ns,
mongo_write_concern *write_concern ) {
bson response = {NULL, 0};
bson fields;
bson_iterator it;
int res = 0;
char *cmd_ns = mongo_ns_to_cmd_db( ns );
res = mongo_find_one( conn, cmd_ns, write_concern->cmd, bson_empty( &fields ), &response );
bson_free( cmd_ns );
if( res != MONGO_OK )
return MONGO_ERROR;
else {
if( ( bson_find( &it, &response, "$err" ) == BSON_STRING ) ||
( bson_find( &it, &response, "err" ) == BSON_STRING ) ) {
__mongo_set_error( conn, MONGO_WRITE_ERROR,
"See conn->lasterrstr for details.", 0 );
mongo_set_last_error( conn, &it, &response );
return MONGO_ERROR;
} else
return MONGO_OK;
}
}
static int mongo_choose_write_concern( mongo *conn,
mongo_write_concern *custom_write_concern,
mongo_write_concern **write_concern ) {
if( custom_write_concern ) {
*write_concern = custom_write_concern;
}
else if( conn->write_concern ) {
*write_concern = conn->write_concern;
}
if( *write_concern && !((*write_concern)->cmd) ) {
__mongo_set_error( conn, MONGO_WRITE_CONCERN_INVALID,
"Must call mongo_write_concern_finish() before using *write_concern.", 0 );
return MONGO_ERROR;
}
else
return MONGO_OK;
}
/*********************************************************************
CRUD API
**********************************************************************/
MONGO_EXPORT int mongo_insert( mongo *conn, const char *ns,
const bson *bson, mongo_write_concern *custom_write_concern ) {
char *data;
mongo_message *mm;
mongo_write_concern *write_concern = NULL;
if( mongo_validate_ns( conn, ns ) != MONGO_OK )
return MONGO_ERROR;
if( mongo_bson_valid( conn, bson, 1 ) != MONGO_OK ) {
return MONGO_ERROR;
}
if( mongo_choose_write_concern( conn, custom_write_concern,
&write_concern ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
mm = mongo_message_create( 16 /* header */
+ 4 /* ZERO */
+ strlen( ns )
+ 1 + bson_size( bson )
, 0, 0, MONGO_OP_INSERT );
data = &mm->data;
data = mongo_data_append32( data, &ZERO );
data = mongo_data_append( data, ns, strlen( ns ) + 1 );
data = mongo_data_append( data, bson->data, bson_size( bson ) );
/* TODO: refactor so that we can send the insert message
and the getlasterror messages together. */
if( write_concern ) {
if( mongo_message_send( conn, mm ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
return mongo_check_last_error( conn, ns, write_concern );
}
else {
return mongo_message_send( conn, mm );
}
}
MONGO_EXPORT int mongo_insert_batch( mongo *conn, const char *ns, MONGO_EXPORT int mongo_insert_batch( mongo *conn, const char *ns,
const bson **bsons, int count ) { const bson **bsons, int count, mongo_write_concern *custom_write_concern,
int flags ) {
mongo_message *mm; mongo_message *mm;
mongo_write_concern *write_concern = NULL;
int i; int i;
char *data; char *data;
int overhead = 16 + 4 + strlen( ns ) + 1; int overhead = 16 + 4 + strlen( ns ) + 1;
@ -761,51 +878,44 @@ MONGO_EXPORT int mongo_insert_batch( mongo *conn, const char *ns,
return MONGO_ERROR; return MONGO_ERROR;
} }
if( mongo_choose_write_concern( conn, custom_write_concern,
&write_concern ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
mm = mongo_message_create( size , 0 , 0 , MONGO_OP_INSERT ); mm = mongo_message_create( size , 0 , 0 , MONGO_OP_INSERT );
data = &mm->data; data = &mm->data;
data = mongo_data_append32( data, &ZERO ); if( flags & MONGO_CONTINUE_ON_ERROR )
data = mongo_data_append32( data, &ONE );
else
data = mongo_data_append32( data, &ZERO );
data = mongo_data_append( data, ns, strlen( ns ) + 1 ); data = mongo_data_append( data, ns, strlen( ns ) + 1 );
for( i=0; i<count; i++ ) { for( i=0; i<count; i++ ) {
data = mongo_data_append( data, bsons[i]->data, bson_size( bsons[i] ) ); data = mongo_data_append( data, bsons[i]->data, bson_size( bsons[i] ) );
} }
return mongo_message_send( conn, mm ); /* TODO: refactor so that we can send the insert message
} * and the getlasterror messages together. */
if( write_concern ) {
if( mongo_message_send( conn, mm ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
MONGO_EXPORT int mongo_insert( mongo *conn , const char *ns , const bson *bson ) { return mongo_check_last_error( conn, ns, write_concern );
}
char *data; else {
mongo_message *mm; return mongo_message_send( conn, mm );
if( mongo_validate_ns( conn, ns ) != MONGO_OK )
return MONGO_ERROR;
/* Make sure that BSON is valid for insert. */
if( mongo_bson_valid( conn, bson, 1 ) != MONGO_OK ) {
return MONGO_ERROR;
} }
mm = mongo_message_create( 16 /* header */
+ 4 /* ZERO */
+ strlen( ns )
+ 1 + bson_size( bson )
, 0, 0, MONGO_OP_INSERT );
data = &mm->data;
data = mongo_data_append32( data, &ZERO );
data = mongo_data_append( data, ns, strlen( ns ) + 1 );
data = mongo_data_append( data, bson->data, bson_size( bson ) );
return mongo_message_send( conn, mm );
} }
MONGO_EXPORT int mongo_update( mongo *conn, const char *ns, const bson *cond, MONGO_EXPORT int mongo_update( mongo *conn, const char *ns, const bson *cond,
const bson *op, int flags ) { const bson *op, int flags, mongo_write_concern *custom_write_concern ) {
char *data; char *data;
mongo_message *mm; mongo_message *mm;
mongo_write_concern *write_concern = NULL;
/* Make sure that the op BSON is valid UTF-8. /* Make sure that the op BSON is valid UTF-8.
* TODO: decide whether to check cond as well. * TODO: decide whether to check cond as well.
@ -814,6 +924,11 @@ MONGO_EXPORT int mongo_update( mongo *conn, const char *ns, const bson *cond,
return MONGO_ERROR; return MONGO_ERROR;
} }
if( mongo_choose_write_concern( conn, custom_write_concern,
&write_concern ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
mm = mongo_message_create( 16 /* header */ mm = mongo_message_create( 16 /* header */
+ 4 /* ZERO */ + 4 /* ZERO */
+ strlen( ns ) + 1 + strlen( ns ) + 1
@ -829,12 +944,26 @@ MONGO_EXPORT int mongo_update( mongo *conn, const char *ns, const bson *cond,
data = mongo_data_append( data, cond->data, bson_size( cond ) ); data = mongo_data_append( data, cond->data, bson_size( cond ) );
data = mongo_data_append( data, op->data, bson_size( op ) ); data = mongo_data_append( data, op->data, bson_size( op ) );
return mongo_message_send( conn, mm ); /* TODO: refactor so that we can send the insert message
* and the getlasterror messages together. */
if( write_concern ) {
if( mongo_message_send( conn, mm ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
return mongo_check_last_error( conn, ns, write_concern );
}
else {
return mongo_message_send( conn, mm );
}
} }
MONGO_EXPORT int mongo_remove( mongo *conn, const char *ns, const bson *cond ) { MONGO_EXPORT int mongo_remove( mongo *conn, const char *ns, const bson *cond,
mongo_write_concern *custom_write_concern ) {
char *data; char *data;
mongo_message *mm; mongo_message *mm;
mongo_write_concern *write_concern = NULL;
/* Make sure that the BSON is valid UTF-8. /* Make sure that the BSON is valid UTF-8.
* TODO: decide whether to check cond as well. * TODO: decide whether to check cond as well.
@ -843,6 +972,11 @@ MONGO_EXPORT int mongo_remove( mongo *conn, const char *ns, const bson *cond ) {
return MONGO_ERROR; return MONGO_ERROR;
} }
if( mongo_choose_write_concern( conn, custom_write_concern,
&write_concern ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
mm = mongo_message_create( 16 /* header */ mm = mongo_message_create( 16 /* header */
+ 4 /* ZERO */ + 4 /* ZERO */
+ strlen( ns ) + 1 + strlen( ns ) + 1
@ -856,10 +990,99 @@ MONGO_EXPORT int mongo_remove( mongo *conn, const char *ns, const bson *cond ) {
data = mongo_data_append32( data, &ZERO ); data = mongo_data_append32( data, &ZERO );
data = mongo_data_append( data, cond->data, bson_size( cond ) ); data = mongo_data_append( data, cond->data, bson_size( cond ) );
return mongo_message_send( conn, mm ); /* TODO: refactor so that we can send the insert message
* and the getlasterror messages together. */
if( write_concern ) {
if( mongo_message_send( conn, mm ) == MONGO_ERROR ) {
return MONGO_ERROR;
}
return mongo_check_last_error( conn, ns, write_concern );
}
else {
return mongo_message_send( conn, mm );
}
} }
/*********************************************************************
Write Concern API
**********************************************************************/
MONGO_EXPORT void mongo_write_concern_init( mongo_write_concern *write_concern ) {
memset( write_concern, 0, sizeof( mongo_write_concern ) );
}
MONGO_EXPORT int mongo_write_concern_finish( mongo_write_concern *write_concern ) {
bson *command;
/* Destory any existing serialized write concern object and reuse it. */
if( write_concern->cmd ) {
bson_destroy( write_concern->cmd );
command = write_concern->cmd;
}
else
command = (bson *)bson_malloc( sizeof( bson ) );
if( !command ) {
return MONGO_ERROR;
}
bson_init( command );
bson_append_int( command, "getlasterror", 1 );
if( write_concern->mode ) {
bson_append_string( command, "w", write_concern->mode );
}
else if( write_concern->w ) {
bson_append_int( command, "w", write_concern->w );
}
if( write_concern->wtimeout ) {
bson_append_int( command, "wtimeout", write_concern->wtimeout );
}
if( write_concern->j ) {
bson_append_int( command, "j", write_concern->j );
}
if( write_concern->fsync ) {
bson_append_int( command, "fsync", write_concern->fsync );
}
bson_finish( command );
/* write_concern now owns the BSON command object.
* This is freed in mongo_write_concern_destroy(). */
write_concern->cmd = command;
return MONGO_OK;
}
MONGO_EXPORT void mongo_write_concern_destroy( mongo_write_concern *write_concern ) {
if( !write_concern )
return;
if( write_concern->cmd )
bson_destroy( write_concern->cmd );
bson_free( write_concern->cmd );
}
MONGO_EXPORT void mongo_set_write_concern( mongo *conn,
mongo_write_concern *write_concern ) {
conn->write_concern = write_concern;
}
/**
* Free the write_concern object (specifically, the BSON object that it holds).
*/
MONGO_EXPORT void mongo_write_concern_destroy( mongo_write_concern *write_concern );
static int mongo_cursor_op_query( mongo_cursor *cursor ) { static int mongo_cursor_op_query( mongo_cursor *cursor ) {
int res; int res;
bson empty; bson empty;
@ -1008,10 +1231,12 @@ MONGO_EXPORT int mongo_find_one( mongo *conn, const char *ns, const bson *query,
mongo_cursor_set_limit( cursor, 1 ); mongo_cursor_set_limit( cursor, 1 );
if ( mongo_cursor_next( cursor ) == MONGO_OK ) { if ( mongo_cursor_next( cursor ) == MONGO_OK ) {
bson_init_size( out, bson_size( (bson *)&cursor->current ) ); if( out ) {
memcpy( out->data, cursor->current.data, bson_init_size( out, bson_size( (bson *)&cursor->current ) );
bson_size( (bson *)&cursor->current ) ); memcpy( out->data, cursor->current.data,
out->finished = 1; bson_size( (bson *)&cursor->current ) );
out->finished = 1;
}
mongo_cursor_destroy( cursor ); mongo_cursor_destroy( cursor );
return MONGO_OK; return MONGO_OK;
} else { } else {
@ -1171,14 +1396,14 @@ MONGO_EXPORT int mongo_create_index( mongo *conn, const char *ns, const bson *ke
strncpy( idxns, ns, 1024-16 ); strncpy( idxns, ns, 1024-16 );
strcpy( strchr( idxns, '.' ), ".system.indexes" ); strcpy( strchr( idxns, '.' ), ".system.indexes" );
mongo_insert( conn, idxns, &b ); mongo_insert( conn, idxns, &b, NULL );
bson_destroy( &b ); bson_destroy( &b );
*strchr( idxns, '.' ) = '\0'; /* just db not ns */ *strchr( idxns, '.' ) = '\0'; /* just db not ns */
return mongo_cmd_get_last_error( conn, idxns, out ); return mongo_cmd_get_last_error( conn, idxns, out );
} }
bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *field, int options, bson *out ) { MONGO_EXPORT bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *field, int options, bson *out ) {
bson b; bson b;
bson_bool_t success; bson_bool_t success;
@ -1191,6 +1416,27 @@ bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *
return success; return success;
} }
MONGO_EXPORT int mongo_create_capped_collection( mongo *conn, const char *db,
const char *collection, int size, int max, bson *out ) {
bson b;
int result;
bson_init( &b );
bson_append_string( &b, "create", collection );
bson_append_bool( &b, "capped", 1 );
bson_append_int( &b, "size", size );
if( max > 0 )
bson_append_int( &b, "max", size );
bson_finish( &b );
result = mongo_run_command( conn, db, &b, out );
bson_destroy( &b );
return result;
}
MONGO_EXPORT double mongo_count( mongo *conn, const char *db, const char *ns, const bson *query ) { MONGO_EXPORT double mongo_count( mongo *conn, const char *db, const char *ns, const bson *query ) {
bson cmd; bson cmd;
bson out = {NULL, 0}; bson out = {NULL, 0};
@ -1404,7 +1650,7 @@ MONGO_EXPORT int mongo_cmd_add_user( mongo *conn, const char *db, const char *us
bson_append_finish_object( &pass_obj ); bson_append_finish_object( &pass_obj );
bson_finish( &pass_obj ); bson_finish( &pass_obj );
res = mongo_update( conn, ns, &user_obj, &pass_obj, MONGO_UPDATE_UPSERT ); res = mongo_update( conn, ns, &user_obj, &pass_obj, MONGO_UPDATE_UPSERT, NULL );
bson_free( ns ); bson_free( ns );
bson_destroy( &user_obj ); bson_destroy( &user_obj );

View File

@ -26,8 +26,8 @@
MONGO_EXTERN_C_START MONGO_EXTERN_C_START
#define MONGO_MAJOR 0 #define MONGO_MAJOR 0
#define MONGO_MINOR 5 #define MONGO_MINOR 6
#define MONGO_PATCH 2 #define MONGO_PATCH 0
#define MONGO_OK 0 #define MONGO_OK 0
#define MONGO_ERROR -1 #define MONGO_ERROR -1
@ -51,10 +51,12 @@ typedef enum mongo_error_t {
MONGO_SOCKET_ERROR, /**< Other socket error. */ MONGO_SOCKET_ERROR, /**< Other socket error. */
MONGO_READ_SIZE_ERROR, /**< The response is not the expected length. */ MONGO_READ_SIZE_ERROR, /**< The response is not the expected length. */
MONGO_COMMAND_FAILED, /**< The command returned with 'ok' value of 0. */ MONGO_COMMAND_FAILED, /**< The command returned with 'ok' value of 0. */
MONGO_WRITE_ERROR, /**< Write with given write_concern returned an error. */
MONGO_NS_INVALID, /**< The name for the ns (database or collection) is invalid. */ MONGO_NS_INVALID, /**< The name for the ns (database or collection) is invalid. */
MONGO_BSON_INVALID, /**< BSON not valid for the specified op. */ MONGO_BSON_INVALID, /**< BSON not valid for the specified op. */
MONGO_BSON_NOT_FINISHED, /**< BSON object has not been finished. */ MONGO_BSON_NOT_FINISHED, /**< BSON object has not been finished. */
MONGO_BSON_TOO_LARGE /**< BSON object exceeds max BSON size. */ MONGO_BSON_TOO_LARGE, /**< BSON object exceeds max BSON size. */
MONGO_WRITE_CONCERN_INVALID /**< Supplied write concern object is invalid. */
} mongo_error_t; } mongo_error_t;
typedef enum mongo_cursor_error_t { typedef enum mongo_cursor_error_t {
@ -85,6 +87,10 @@ enum mongo_update_opts {
MONGO_UPDATE_BASIC = 0x4 MONGO_UPDATE_BASIC = 0x4
}; };
enum mongo_insert_opts {
MONGO_CONTINUE_ON_ERROR = 0x1
};
enum mongo_cursor_opts { enum mongo_cursor_opts {
MONGO_TAILABLE = ( 1<<1 ), /**< Create a tailable cursor. */ MONGO_TAILABLE = ( 1<<1 ), /**< Create a tailable cursor. */
MONGO_SLAVE_OK = ( 1<<2 ), /**< Allow queries on a non-primary node. */ MONGO_SLAVE_OK = ( 1<<2 ), /**< Allow queries on a non-primary node. */
@ -137,6 +143,16 @@ typedef struct mongo_host_port {
struct mongo_host_port *next; struct mongo_host_port *next;
} mongo_host_port; } mongo_host_port;
typedef struct mongo_write_concern {
int w; /**< Number of nodes this write should be replicated to. */
int wtimeout; /**< Number of milliseconds before replication timeout. */
int j; /**< If non-zero, block until the journal sync. */
int fsync; /**< Same a j with journaling enabled; otherwise, call fsync. */
const char *mode; /**< Either "majority" or a getlasterrormode. Overrides w value. */
bson *cmd; /**< The BSON object representing the getlasterror command. */
} mongo_write_concern;
typedef struct { typedef struct {
mongo_host_port *seeds; /**< List of seeds provided by the user. */ mongo_host_port *seeds; /**< List of seeds provided by the user. */
mongo_host_port *hosts; /**< List of host/ports given by the replica set */ mongo_host_port *hosts; /**< List of host/ports given by the replica set */
@ -153,6 +169,7 @@ typedef struct mongo {
int op_timeout_ms; /**< Read and write timeout in milliseconds. */ int op_timeout_ms; /**< Read and write timeout in milliseconds. */
int max_bson_size; /**< Largest BSON object allowed on this connection. */ int max_bson_size; /**< Largest BSON object allowed on this connection. */
bson_bool_t connected; /**< Connection status. */ bson_bool_t connected; /**< Connection status. */
mongo_write_concern *write_concern; /**< The default write concern. */
mongo_error_t err; /**< Most recent driver error code. */ mongo_error_t err; /**< Most recent driver error code. */
int errcode; /**< Most recent errno or WSAGetLastError(). */ int errcode; /**< Most recent errno or WSAGetLastError(). */
@ -176,38 +193,9 @@ typedef struct {
int skip; /**< Bitfield containing cursor options. */ int skip; /**< Bitfield containing cursor options. */
} mongo_cursor; } mongo_cursor;
/* Connection API */ /*********************************************************************
Connection API
MONGO_EXPORT mongo* mongo_create(); **********************************************************************/
MONGO_EXPORT void mongo_dispose(mongo* conn);
MONGO_EXPORT int mongo_get_err(mongo* conn);
MONGO_EXPORT int mongo_is_connected(mongo* conn);
MONGO_EXPORT int mongo_get_op_timeout(mongo* conn);
MONGO_EXPORT const char* mongo_get_primary(mongo* conn);
MONGO_EXPORT int mongo_get_socket(mongo* conn) ;
MONGO_EXPORT int mongo_get_host_count(mongo* conn);
MONGO_EXPORT const char* mongo_get_host(mongo* conn, int i);
MONGO_EXPORT mongo_cursor* mongo_cursor_create();
MONGO_EXPORT void mongo_cursor_dispose(mongo_cursor* cursor);
MONGO_EXPORT int mongo_get_server_err(mongo* conn);
MONGO_EXPORT const char* mongo_get_server_err_string(mongo* conn);
/**
* Set an error this mongo connection object. Mostly for internal use.
*
* @param conn a mongo connection object.
* @param err a driver error code of mongo_error_t.
* @param errstr a string version of the error.
* @param errorcode Currently errno or WSAGetLastError().
*/
MONGO_EXPORT void __mongo_set_error( mongo *conn, mongo_error_t err,
const char *errstr, int errorcode );
/**
* Clear all errors stored on this mongo connection object.
*
* @param conn a mongo connection object.
*/
MONGO_EXPORT void mongo_clear_errors( mongo *conn );
/** Initialize sockets for Windows. /** Initialize sockets for Windows.
*/ */
@ -344,61 +332,130 @@ MONGO_EXPORT void mongo_disconnect( mongo *conn );
*/ */
MONGO_EXPORT void mongo_destroy( mongo *conn ); MONGO_EXPORT void mongo_destroy( mongo *conn );
/**
* Specify the write concern object that this connection should use
* by default for all writes (inserts, updates, and deletes). This value
* can be overridden by passing a write_concern object to any write function.
*
* @param conn a mongo object.
* @param write_concern pointer to a write concern object.
*
*/
MONGO_EXPORT void mongo_set_write_concern( mongo *conn,
mongo_write_concern *write_concern );
/*********************************************************************
CRUD API
**********************************************************************/
/** /**
* Insert a BSON document into a MongoDB server. This function * Insert a BSON document into a MongoDB server. This function
* will fail if the supplied BSON struct is not UTF-8 or if * will fail if the supplied BSON struct is not UTF-8 or if
* the keys are invalid for insert (contain '.' or start with '$'). * the keys are invalid for insert (contain '.' or start with '$').
* *
* The default write concern set on the conn object will be used.
*
* @param conn a mongo object. * @param conn a mongo object.
* @param ns the namespace. * @param ns the namespace.
* @param data the bson data. * @param data the bson data.
* @param custom_write_concern a write concern object that will
* override any write concern set on the conn object.
* *
* @return MONGO_OK or MONGO_ERROR. If the conn->err * @return MONGO_OK or MONGO_ERROR. If the conn->err
* field is MONGO_BSON_INVALID, check the err field * field is MONGO_BSON_INVALID, check the err field
* on the bson struct for the reason. * on the bson struct for the reason.
*/ */
MONGO_EXPORT int mongo_insert( mongo *conn, const char *ns, const bson *data ); MONGO_EXPORT int mongo_insert( mongo *conn, const char *ns, const bson *data,
mongo_write_concern *custom_write_concern );
/** /**
* Insert a batch of BSON documents into a MongoDB server. This function * Insert a batch of BSON documents into a MongoDB server. This function
* will fail if any of the documents to be inserted is invalid. * will fail if any of the documents to be inserted is invalid.
* *
* The default write concern set on the conn object will be used.
*
* @param conn a mongo object. * @param conn a mongo object.
* @param ns the namespace. * @param ns the namespace.
* @param data the bson data. * @param data the bson data.
* @param num the number of documents in data. * @param num the number of documents in data.
* @param custom_write_concern a write concern object that will
* override any write concern set on the conn object.
* @param flags flags on this batch insert. Currently, this value
* may be 0 or MONGO_CONTINUE_ON_ERROR, which will cause the
* batch insert to continue even if a given insert in the batch fails.
* *
* @return MONGO_OK or MONGO_ERROR. * @return MONGO_OK or MONGO_ERROR.
* *
*/ */
MONGO_EXPORT int mongo_insert_batch( mongo *conn , const char *ns , MONGO_EXPORT int mongo_insert_batch( mongo *conn, const char *ns,
const bson **data , int num ); const bson **data, int num, mongo_write_concern *custom_write_concern,
int flags );
/** /**
* Update a document in a MongoDB server. * Update a document in a MongoDB server.
* *
* The default write concern set on the conn object will be used.
*
* @param conn a mongo object. * @param conn a mongo object.
* @param ns the namespace. * @param ns the namespace.
* @param cond the bson update query. * @param cond the bson update query.
* @param op the bson update data. * @param op the bson update data.
* @param flags flags for the update. * @param flags flags for the update.
* @param custom_write_concern a write concern object that will
* override any write concern set on the conn object.
* *
* @return MONGO_OK or MONGO_ERROR with error stored in conn object. * @return MONGO_OK or MONGO_ERROR with error stored in conn object.
* *
*/ */
MONGO_EXPORT int mongo_update( mongo *conn, const char *ns, const bson *cond, MONGO_EXPORT int mongo_update( mongo *conn, const char *ns, const bson *cond,
const bson *op, int flags ); const bson *op, int flags, mongo_write_concern *custom_write_concern );
/** /**
* Remove a document from a MongoDB server. * Remove a document from a MongoDB server.
* *
* The default write concern set on the conn object will be used.
*
* @param conn a mongo object. * @param conn a mongo object.
* @param ns the namespace. * @param ns the namespace.
* @param cond the bson query. * @param cond the bson query.
* @param custom_write_concern a write concern object that will
* override any write concern set on the conn object.
* *
* @return MONGO_OK or MONGO_ERROR with error stored in conn object. * @return MONGO_OK or MONGO_ERROR with error stored in conn object.
*/ */
MONGO_EXPORT int mongo_remove( mongo *conn, const char *ns, const bson *cond ); MONGO_EXPORT int mongo_remove( mongo *conn, const char *ns, const bson *cond,
mongo_write_concern *custom_write_concern );
/*********************************************************************
Write Concern API
**********************************************************************/
/**
* Initialize a mongo_write_concern object. Effectively zeroes out the struct.
*
*/
MONGO_EXPORT void mongo_write_concern_init( mongo_write_concern *write_concern );
/**
* Finish this write concern object by serializing the literal getlasterror
* command that will be sent to the server.
*
* You must call mongo_write_concern_destroy() to free the serialized BSON.
*
*/
MONGO_EXPORT int mongo_write_concern_finish( mongo_write_concern *write_concern );
/**
* Free the write_concern object (specifically, the BSON that it owns).
*
*/
MONGO_EXPORT void mongo_write_concern_destroy( mongo_write_concern *write_concern );
/*********************************************************************
Cursor API
**********************************************************************/
/** /**
* Find documents in a MongoDB server. * Find documents in a MongoDB server.
@ -527,7 +584,10 @@ MONGO_EXPORT int mongo_cursor_destroy( mongo_cursor *cursor );
MONGO_EXPORT int mongo_find_one( mongo *conn, const char *ns, const bson *query, MONGO_EXPORT int mongo_find_one( mongo *conn, const char *ns, const bson *query,
const bson *fields, bson *out ); const bson *fields, bson *out );
/* MongoDB Helper Functions */
/*********************************************************************
Command API and Helpers
**********************************************************************/
/** /**
* Count the number of documents in a collection matching a query. * Count the number of documents in a collection matching a query.
@ -544,7 +604,7 @@ MONGO_EXPORT double mongo_count( mongo *conn, const char *db, const char *coll,
const bson *query ); const bson *query );
/** /**
* Create a compouned index. * Create a compound index.
* *
* @param conn a mongo object. * @param conn a mongo object.
* @param ns the namespace. * @param ns the namespace.
@ -556,7 +616,23 @@ MONGO_EXPORT double mongo_count( mongo *conn, const char *db, const char *coll,
* *
* @return MONGO_OK if index is created successfully; otherwise, MONGO_ERROR. * @return MONGO_OK if index is created successfully; otherwise, MONGO_ERROR.
*/ */
MONGO_EXPORT int mongo_create_index( mongo *conn, const char *ns, const bson *key, int options, bson *out ); MONGO_EXPORT int mongo_create_index( mongo *conn, const char *ns,
const bson *key, int options, bson *out );
/**
* Create a capped collection.
*
* @param conn a mongo object.
* @param ns the namespace (e.g., "dbname.collectioname")
* @param size the size of the capped collection in bytes.
* @param max the max number of documents this collection is
* allowed to contain. If zero, this argument will be ignored
* and the server will use the collection's size to age document out.
* If using this option, ensure that the total size can contain this
* number of documents.
*/
MONGO_EXPORT int mongo_create_capped_collection( mongo *conn, const char *db,
const char *collection, int size, int max, bson *out );
/** /**
* Create an index with a single key. * Create an index with a single key.
@ -569,11 +645,8 @@ MONGO_EXPORT int mongo_create_index( mongo *conn, const char *ns, const bson *ke
* *
* @return true if the index was created. * @return true if the index was created.
*/ */
bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *field, int options, bson *out ); MONGO_EXPORT bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns,
const char *field, int options, bson *out );
/* ----------------------------
COMMANDS
------------------------------ */
/** /**
* Run a command on a MongoDB server. * Run a command on a MongoDB server.
@ -585,7 +658,8 @@ bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *
* *
* @return MONGO_OK if the command ran without error. * @return MONGO_OK if the command ran without error.
*/ */
MONGO_EXPORT int mongo_run_command( mongo *conn, const char *db, const bson *command, bson *out ); MONGO_EXPORT int mongo_run_command( mongo *conn, const char *db,
const bson *command, bson *out );
/** /**
* Run a command that accepts a simple string key and integer value. * Run a command that accepts a simple string key and integer value.
@ -614,7 +688,8 @@ MONGO_EXPORT int mongo_simple_int_command( mongo *conn, const char *db,
* @return true if the command ran without error. * @return true if the command ran without error.
* *
*/ */
MONGO_EXPORT int mongo_simple_str_command( mongo *conn, const char *db, const char *cmd, const char *arg, bson *out ); MONGO_EXPORT int mongo_simple_str_command( mongo *conn, const char *db,
const char *cmd, const char *arg, bson *out );
/** /**
* Drop a database. * Drop a database.
@ -636,7 +711,8 @@ MONGO_EXPORT int mongo_cmd_drop_db( mongo *conn, const char *db );
* *
* @return true if the collection drop was successful. * @return true if the collection drop was successful.
*/ */
MONGO_EXPORT int mongo_cmd_drop_collection( mongo *conn, const char *db, const char *collection, bson *out ); MONGO_EXPORT int mongo_cmd_drop_collection( mongo *conn, const char *db,
const char *collection, bson *out );
/** /**
* Add a database user. * Add a database user.
@ -648,7 +724,8 @@ MONGO_EXPORT int mongo_cmd_drop_collection( mongo *conn, const char *db, const c
* *
* @return MONGO_OK or MONGO_ERROR. * @return MONGO_OK or MONGO_ERROR.
*/ */
MONGO_EXPORT int mongo_cmd_add_user( mongo *conn, const char *db, const char *user, const char *pass ); MONGO_EXPORT int mongo_cmd_add_user( mongo *conn, const char *db,
const char *user, const char *pass );
/** /**
* Authenticate a user. * Authenticate a user.
@ -660,7 +737,8 @@ MONGO_EXPORT int mongo_cmd_add_user( mongo *conn, const char *db, const char *us
* *
* @return MONGO_OK on sucess and MONGO_ERROR on failure. * @return MONGO_OK on sucess and MONGO_ERROR on failure.
*/ */
MONGO_EXPORT int mongo_cmd_authenticate( mongo *conn, const char *db, const char *user, const char *pass ); MONGO_EXPORT int mongo_cmd_authenticate( mongo *conn, const char *db,
const char *user, const char *pass );
/** /**
* Check if the current server is a master. * Check if the current server is a master.
@ -706,6 +784,41 @@ MONGO_EXPORT int mongo_cmd_get_prev_error( mongo *conn, const char *db, bson *ou
MONGO_EXPORT void mongo_cmd_reset_error( mongo *conn, const char *db ); MONGO_EXPORT void mongo_cmd_reset_error( mongo *conn, const char *db );
/*********************************************************************
Utility API
**********************************************************************/
MONGO_EXPORT mongo* mongo_create();
MONGO_EXPORT void mongo_dispose(mongo* conn);
MONGO_EXPORT int mongo_get_err(mongo* conn);
MONGO_EXPORT int mongo_is_connected(mongo* conn);
MONGO_EXPORT int mongo_get_op_timeout(mongo* conn);
MONGO_EXPORT const char* mongo_get_primary(mongo* conn);
MONGO_EXPORT int mongo_get_socket(mongo* conn) ;
MONGO_EXPORT int mongo_get_host_count(mongo* conn);
MONGO_EXPORT const char* mongo_get_host(mongo* conn, int i);
MONGO_EXPORT mongo_cursor* mongo_cursor_create();
MONGO_EXPORT void mongo_cursor_dispose(mongo_cursor* cursor);
MONGO_EXPORT int mongo_get_server_err(mongo* conn);
MONGO_EXPORT const char* mongo_get_server_err_string(mongo* conn);
/**
* Set an error on a mongo connection object. Mostly for internal use.
*
* @param conn a mongo connection object.
* @param err a driver error code of mongo_error_t.
* @param errstr a string version of the error.
* @param errorcode Currently errno or WSAGetLastError().
*/
MONGO_EXPORT void __mongo_set_error( mongo *conn, mongo_error_t err,
const char *errstr, int errorcode );
/**
* Clear all errors stored on a mongo connection object.
*
* @param conn a mongo connection object.
*/
MONGO_EXPORT void mongo_clear_errors( mongo *conn );
MONGO_EXTERN_C_END MONGO_EXTERN_C_END
#endif #endif

View File

@ -295,7 +295,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
switch_mutex_lock(globals.mongo_mutex); switch_mutex_lock(globals.mongo_mutex);
if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) { if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) {
if (globals.mongo_conn->err == MONGO_IO_ERROR) { if (globals.mongo_conn->err == MONGO_IO_ERROR) {
mongo_error_t db_status; mongo_error_t db_status;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MongoDB connection failed; attempting reconnect...\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MongoDB connection failed; attempting reconnect...\n");
@ -306,7 +306,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session)
status = SWITCH_STATUS_FALSE; status = SWITCH_STATUS_FALSE;
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n");
if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) { if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err);
status = SWITCH_STATUS_FALSE; status = SWITCH_STATUS_FALSE;
} }