Index: library/mongodb/nsfmongo.c =================================================================== diff -u -raa5b3f4293624fedf641985718ab15c82f5daf78 -r3d447c3c5b6f5b5becb6baa26950bbd06e60b9a4 --- library/mongodb/nsfmongo.c (.../nsfmongo.c) (revision aa5b3f4293624fedf641985718ab15c82f5daf78) +++ library/mongodb/nsfmongo.c (.../nsfmongo.c) (revision 3d447c3c5b6f5b5becb6baa26950bbd06e60b9a4) @@ -13,6 +13,8 @@ * packages. * * -gustaf neumann March 27, 2011 + * + * Copyright (C) 2011-2016 Gustaf Neumann */ #include #include @@ -48,6 +50,7 @@ NSF_BSON_INT32, NSF_BSON_INT64, NSF_BSON_DATE_TIME, + NSF_BSON_DECIMAL128, NSF_BSON_DOCUMENT, NSF_BSON_DOUBLE, NSF_BSON_MINKEY, @@ -67,6 +70,7 @@ "int32", "int64", "datetime", + "decimal128", "document", "double", "minkey", @@ -89,18 +93,18 @@ #define PARSE_CONTEXT_PREALLOC 20 typedef struct { - int status; - ClientData *clientData; /* 4 members pointer to the actual parse context data */ - Tcl_Obj **objv; - Tcl_Obj **full_objv; /* contains method as well */ - int *flags; - ClientData clientData_static[PARSE_CONTEXT_PREALLOC]; /* 3 members preallocated parse context data */ - Tcl_Obj *objv_static[PARSE_CONTEXT_PREALLOC+1]; - int flags_static[PARSE_CONTEXT_PREALLOC+1]; - int lastObjc; /* points to the first "unprocessed" argument */ - int objc; - int varArgs; /* does the parameter end with some kind of "args" */ - NsfObject *object; + ClientData *clientData; /* 4 members pointer to the actual parse context data */ + Tcl_Obj **objv; + Tcl_Obj **full_objv; /* contains method as well */ + unsigned int *flags; + ClientData clientData_static[PARSE_CONTEXT_PREALLOC]; /* 3 members preallocated parse context data */ + Tcl_Obj *objv_static[PARSE_CONTEXT_PREALLOC+1]; + unsigned int flags_static[PARSE_CONTEXT_PREALLOC+1]; + unsigned int status; + int lastObjc; /* points to the first "unprocessed" argument */ + int objc; + NsfObject *object; + int varArgs; /* does the parameter end with some kind of "args" */ } ParseContext; #define nr_elements(arr) ((int) (sizeof(arr) / sizeof(arr[0]))) @@ -121,32 +125,32 @@ #endif #if !defined(INT2PTR) && !defined(PTR2INT) -# if defined(HAVE_INTPTR_T) || defined(intptr_t) -# define INT2PTR(p) ((void *)(intptr_t)(p)) -# define PTR2INT(p) ((int)(intptr_t)(p)) -# else -# define INT2PTR(p) ((void *)(p)) -# define PTR2INT(p) ((int)(p)) -# endif +# if defined(HAVE_INTPTR_T) || defined(intptr_t) +# define INT2PTR(p) ((void *)(intptr_t)(p)) +# define PTR2INT(p) ((int)(intptr_t)(p)) +# else +# define INT2PTR(p) ((void *)(p)) +# define PTR2INT(p) ((int)(p)) +# endif #endif #if !defined(UINT2PTR) && !defined(PTR2UINT) -# if defined(HAVE_UINTPTR_T) || defined(uintptr_t) -# define UINT2PTR(p) ((void *)(uintptr_t)(p)) -# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p)) -# else -# define UINT2PTR(p) ((void *)(p)) -# define PTR2UINT(p) ((unsigned int)(p)) -# endif +# if defined(HAVE_UINTPTR_T) || defined(uintptr_t) +# define UINT2PTR(p) ((void *)(uintptr_t)(p)) +# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p)) +# else +# define UINT2PTR(p) ((void *)(p)) +# define PTR2UINT(p) ((unsigned int)(p)) +# endif #endif static int ArgumentParse(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], NsfObject *obj, Tcl_Obj *procName, Nsf_Param CONST *paramPtr, int nrParameters, int serial, - int doCheck, ParseContext *pc) { + unsigned int processFlags, ParseContext *pc) { return Nsf_ArgumentParse(interp, objc, objv, (Nsf_Object *)obj, - procName, paramPtr, nrParameters, serial, - doCheck, (Nsf_ParseContext *)pc); + procName, paramPtr, nrParameters, serial, + processFlags, (Nsf_ParseContext *)pc); } /*********************************************************************** @@ -176,18 +180,19 @@ *---------------------------------------------------------------------- */ Tcl_Obj * -BsonToList(Tcl_Interp *interp, const bson_t *data , int depth) { +BsonToList(Tcl_Interp *interp, const bson_t *data , int depth) +{ bson_iter_t i; - char oidhex[25]; - Tcl_Obj *resultObj, *elemObj; + char oidhex[25]; + Tcl_Obj *resultObj, *elemObj; bson_iter_init( &i , data ); resultObj = Tcl_NewListObj(0, NULL); while ( bson_iter_next( &i ) ){ - bson_type_t t = bson_iter_type( &i ); + bson_type_t t = bson_iter_type( &i ); nsfMongoTypes tag; - const char *key; + const char *key; if ( t == 0 ) break; @@ -202,6 +207,7 @@ case BSON_TYPE_BOOL: tag = NSF_BSON_BOOL; elemObj = Tcl_NewBooleanObj(bson_iter_bool( &i )); break; case BSON_TYPE_REGEX: { const char *options = NULL, *regex = NULL; + tag = NSF_BSON_REGEX; regex = bson_iter_regex( &i, &options ); elemObj = Tcl_NewListObj(0, NULL); @@ -210,10 +216,11 @@ break; } case BSON_TYPE_UTF8: { - uint32_t utf8_len; + uint32_t utf8_len; const char *string = bson_iter_utf8( &i, &utf8_len); + /*fprintf(stderr, "append UTF8: <%s> %d\n", string, utf8_len);*/ - tag = NSF_BSON_STRING; elemObj = Tcl_NewStringObj(string, utf8_len); + tag = NSF_BSON_STRING; elemObj = Tcl_NewStringObj(string, (int)utf8_len); break; } case BSON_TYPE_MINKEY: tag = NSF_BSON_MINKEY; elemObj = Tcl_NewStringObj("null", 4); break; @@ -227,17 +234,19 @@ } case BSON_TYPE_TIMESTAMP: { uint32_t timestamp, increment; + tag = NSF_BSON_TIMESTAMP; bson_iter_timestamp( &i, ×tamp, &increment ); elemObj = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, elemObj, Tcl_NewIntObj(timestamp)); - Tcl_ListObjAppendElement(interp, elemObj, Tcl_NewIntObj(increment)); + Tcl_ListObjAppendElement(interp, elemObj, Tcl_NewLongObj((long)timestamp)); + Tcl_ListObjAppendElement(interp, elemObj, Tcl_NewLongObj((long)increment)); break; } case BSON_TYPE_DOCUMENT: { const uint8_t *docbuf = NULL; - uint32_t doclen = 0; - bson_t b; + uint32_t doclen = 0; + bson_t b; + tag = NSF_BSON_DOCUMENT; bson_iter_document (&i, &doclen, &docbuf); bson_init_static(&b, docbuf, doclen); @@ -246,14 +255,26 @@ } case BSON_TYPE_ARRAY: { const uint8_t *docbuf = NULL; - uint32_t doclen = 0; - bson_t b; + uint32_t doclen = 0; + bson_t b; + tag = NSF_BSON_ARRAY; bson_iter_array(&i, &doclen, &docbuf); bson_init_static (&b, docbuf, doclen); elemObj = BsonToList(interp, &b , depth + 1 ); break; } + case BSON_TYPE_DECIMAL128: { + bson_decimal128_t decimal128; + char string[BSON_DECIMAL128_STRING]; + + tag = NSF_BSON_DECIMAL128; + bson_iter_decimal128( &i, &decimal128); + bson_decimal128_to_string (&decimal128, string); + elemObj = Tcl_NewStringObj(string, -1); + + break; + } default: tag = NSF_BSON_UNKNOWN; elemObj = Tcl_NewStringObj("", 0); @@ -287,7 +308,8 @@ *---------------------------------------------------------------------- */ bson_type_t -BsonTagToType(Tcl_Interp *interp, CONST char *tag) { +BsonTagToType(Tcl_Interp *interp, CONST char *tag) +{ char firstChar = *tag; switch (firstChar) { @@ -336,33 +358,38 @@ *---------------------------------------------------------------------- */ static int -BsonAppend(Tcl_Interp *interp, bson_t *bbPtr, CONST char *name, CONST char *tag, Tcl_Obj *value) { - int result = TCL_OK; +BsonAppend(Tcl_Interp *interp, bson_t *bbPtr, CONST char *name, CONST char *tag, Tcl_Obj *value) +{ + int result = TCL_OK; bson_type_t t = BsonTagToType(interp, tag); - int keyLength = strlen(name); + int keyLength = (int)strlen(name); /*fprintf(stderr, "BsonAppend: add name %s tag %s value '%s'\n", name, tag, ObjStr(value));*/ switch ( t ){ case BSON_TYPE_UTF8: { const char* string = ObjStr(value); - bson_append_utf8(bbPtr, name, keyLength, string, strlen(string)); + + bson_append_utf8(bbPtr, name, keyLength, string, (int)strlen(string)); break; } case BSON_TYPE_INT32: { int32_t v; + result = Tcl_GetIntFromObj(interp, value, &v); if (result != TCL_OK) break; bson_append_int32(bbPtr, name, keyLength, v); break; } case BSON_TYPE_DOUBLE: { double v; + result = Tcl_GetDoubleFromObj(interp, value, &v); if (result != TCL_OK) break; bson_append_double(bbPtr, name, keyLength, v); break; } + case BSON_TYPE_BOOL: { int v; result = Tcl_GetBooleanFromObj(interp, value, &v); @@ -372,6 +399,7 @@ } case BSON_TYPE_INT64: { long v; + result = Tcl_GetLongFromObj(interp, value, &v); if (result != TCL_OK) break; bson_append_int64(bbPtr, name, keyLength, v); @@ -380,21 +408,24 @@ case BSON_TYPE_MAXKEY: bson_append_maxkey(bbPtr, name, keyLength); break; + case BSON_TYPE_MINKEY: bson_append_minkey(bbPtr, name, keyLength); break; + case BSON_TYPE_NULL: { bson_append_null(bbPtr, name, keyLength); break; } case BSON_TYPE_OID: { bson_oid_t v; + bson_oid_init_from_string(&v, ObjStr(value)); bson_append_oid(bbPtr, name, keyLength, &v); break; } case BSON_TYPE_REGEX: { - int objc = 0; + int objc = 0; Tcl_Obj **objv; result = Tcl_ListObjGetElements(interp, value, &objc, &objv); @@ -406,13 +437,14 @@ } case BSON_TYPE_DATE_TIME: { long v; + result = Tcl_GetLongFromObj(interp, value, &v); if (result != TCL_OK) break; bson_append_date_time(bbPtr, name, keyLength, v); break; } case BSON_TYPE_TIMESTAMP: { - int timestamp, increment, objc = 0; + int timestamp, increment, objc = 0; Tcl_Obj **objv; result = Tcl_ListObjGetElements(interp, value, &objc, &objv); @@ -424,7 +456,7 @@ result = Tcl_GetIntFromObj(interp, objv[1], &increment); } if (result != TCL_OK) break; - bson_append_timestamp(bbPtr, name, keyLength, timestamp, increment); + bson_append_timestamp(bbPtr, name, keyLength, (uint32_t)timestamp, (uint32_t)increment); break; } case BSON_TYPE_DOCUMENT: @@ -445,7 +477,7 @@ } for (i = 0; i< objc; i += 3) { /*fprintf(stderr, "value %s, i %d, [0]: %s, [1]: %s, [2]: %s\n", ObjStr(value), i, - ObjStr(objv[i]), ObjStr(objv[i+1]), ObjStr(objv[i+2]));*/ + ObjStr(objv[i]), ObjStr(objv[i+1]), ObjStr(objv[i+2]));*/ result = BsonAppend(interp, childPtr, ObjStr(objv[i]), ObjStr(objv[i+1]), objv[i+2]); if (result != TCL_OK) break; } @@ -457,7 +489,13 @@ } break; } + case BSON_TYPE_DECIMAL128: { + bson_decimal128_t decimal128; + bson_decimal128_from_string (ObjStr(value), &decimal128); + bson_append_decimal128(bbPtr, name, keyLength, &decimal128); + break; + } case BSON_TYPE_BINARY: case BSON_TYPE_DBPOINTER: case BSON_TYPE_CODE: @@ -491,14 +529,16 @@ *---------------------------------------------------------------------- */ static int -BsonAppendObjv(Tcl_Interp *interp, bson_t *bPtr, int objc, Tcl_Obj **objv) { +BsonAppendObjv(Tcl_Interp *interp, bson_t *bPtr, int objc, Tcl_Obj **objv) +{ int i, result = TCL_OK; bson_init(bPtr); for (i = 0; i < objc; i += 3) { - char *name = ObjStr(objv[i]); - char *tag = ObjStr(objv[i+1]); + char *name = ObjStr(objv[i]); + char *tag = ObjStr(objv[i+1]); Tcl_Obj *value = objv[i+2]; + /*fprintf(stderr, "adding pair '%s' (%s) '%s'\n", name, tag, ObjStr(value));*/ result = BsonAppend(interp, bPtr, name, tag, value); if (result != TCL_OK) { @@ -513,16 +553,17 @@ * Define the api functions ***********************************************************************/ /* -cmd json::generate NsfMongoJsonGenerate { + cmd json::generate NsfMongoJsonGenerate { {-argName "list" -required 1 -type tclobj} -} + } */ static int -NsfMongoJsonGenerate(Tcl_Interp *interp, Tcl_Obj *listObj) { - bson_t list, *listPtr = &list; - size_t length; - char *jsonString; - int result, objc; +NsfMongoJsonGenerate(Tcl_Interp *interp, Tcl_Obj *listObj) +{ + bson_t list, *listPtr = &list; + size_t length; + char *jsonString; + int result, objc; Tcl_Obj **objv; result = Tcl_ListObjGetElements(interp, listObj, &objc, &objv); @@ -534,7 +575,7 @@ if (result == TCL_OK) { jsonString = bson_as_json(listPtr, &length); if (jsonString != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(jsonString, length)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(jsonString, (int)length)); bson_free(jsonString); } else { result = NsfPrintError(interp, "invalid bson string: %s", ObjStr(listObj)); @@ -546,15 +587,16 @@ return result; } /* -cmd json::parse NsfMongoJsonParse { + cmd json::parse NsfMongoJsonParse { {-argName "json" -required 1 -type tclobj} -} + } */ static int -NsfMongoJsonParse(Tcl_Interp *interp, Tcl_Obj *jsonObj) { - bson_t bson, *bsonPtr = &bson; - const char *jsonString; - int result, jsonLength; +NsfMongoJsonParse(Tcl_Interp *interp, Tcl_Obj *jsonObj) +{ + bson_t bson, *bsonPtr = &bson; + const char *jsonString; + int result, jsonLength; bson_error_t bsonError; jsonString = Tcl_GetStringFromObj(jsonObj, &jsonLength); @@ -571,13 +613,13 @@ } /* -cmd close NsfMongoClose { + cmd close NsfMongoClose { {-argName "conn" -required 1 -type mongoc_client_t -withObj 1} -} + } */ static int -NsfMongoClose(Tcl_Interp *interp, mongoc_client_t *clientPtr, Tcl_Obj *clientObj) { - +NsfMongoClose(Tcl_Interp *interp, mongoc_client_t *clientPtr, Tcl_Obj *clientObj) +{ #if defined(USE_CLIENT_POOL) mongoc_client_pool_push(mongoClientPool, clientPtr); #else @@ -589,13 +631,14 @@ } /* -cmd connect NsfMongoConnect { + cmd connect NsfMongoConnect { {-argName "-uri" -required 1 -nrargs 1} -} + } */ static int -NsfMongoConnect(Tcl_Interp *interp, CONST char *uri) { - char channelName[80]; +NsfMongoConnect(Tcl_Interp *interp, CONST char *uri) +{ + char channelName[80]; mongoc_client_t *clientPtr; if (uri == NULL) { @@ -618,7 +661,7 @@ #endif if (clientPtr == NULL) { - return NsfPrintError(interp, "failed to parse Mongo URI"); + return NsfPrintError(interp, "failed to parse Mongo URI"); } /* @@ -636,21 +679,22 @@ } /* -cmd run NsfMongoRunCmd { + cmd run NsfMongoRunCmd { {-argName "-nocomplain" -required 0 -nrargs 0} {-argName "conn" -required 1 -type mongoc_client_t} {-argName "db" -required 1} {-argName "cmd" -required 1 -type tclobj} -} + } */ static int NsfMongoRunCmd(Tcl_Interp *interp, int withNocomplain, mongoc_client_t *clientPtr, - CONST char *db, Tcl_Obj *cmdObj) { - bson_t cmd, *cmdPtr = &cmd, reply, *replyPtr = &reply; + CONST char *db, Tcl_Obj *cmdObj) +{ + bson_t cmd, *cmdPtr = &cmd, reply, *replyPtr = &reply; mongoc_read_prefs_t *readPrefsPtr = NULL; /* TODO: not used */ - bson_error_t bsonError; - int result, objc; - Tcl_Obj **objv; + bson_error_t bsonError; + int result, objc; + Tcl_Obj **objv; result = Tcl_ListObjGetElements(interp, cmdObj, &objc, &objv); if (result != TCL_OK || ((objc % 3) != 0)) { @@ -674,16 +718,17 @@ } /* -cmd status NsfMongoStatus { + cmd status NsfMongoStatus { {-argName "conn" -required 1 -type mongoc_client_t -withObj 1} -} + } */ static int -NsfMongoStatus(Tcl_Interp *interp, mongoc_client_t *clientPtr, Tcl_Obj *clientObj) { +NsfMongoStatus(Tcl_Interp *interp, mongoc_client_t *clientPtr, Tcl_Obj *clientObj) +{ mongoc_read_prefs_t *readPrefs = NULL; /* TODO: not handled */ - bson_t reply, *replyPtr = &reply; - bson_error_t bsonError; - int result = TCL_OK; + bson_t reply, *replyPtr = &reply; + bson_error_t bsonError; + int result = TCL_OK; if (likely(mongoc_client_get_server_status(clientPtr, readPrefs, replyPtr, &bsonError)) !=0) { Tcl_SetObjResult(interp, BsonToList(interp, replyPtr, 0)); @@ -697,18 +742,19 @@ /* -cmd collection::open NsfCollectionOpen { + cmd collection::open NsfCollectionOpen { {-argName "conn" -required 1 -type mongoc_client_t} {-argName "dbname" -required 1} {-argName "collectionname" -required 1} -} + } */ int NsfCollectionOpen(Tcl_Interp *interp, - mongoc_client_t *clientPtr, - const char *dbName, - const char *collectionName) { - int result = TCL_ERROR; + mongoc_client_t *clientPtr, + const char *dbName, + const char *collectionName) +{ + int result = TCL_ERROR; mongoc_collection_t *collectionPtr; collectionPtr = mongoc_client_get_collection(clientPtr, dbName, collectionName); @@ -726,40 +772,42 @@ if (collectionPtr == NULL) { result = NsfPrintError(interp, - "collection::open: could not open collection: %s.%s", - dbName, collectionName); + "collection::open: could not open collection: %s.%s", + dbName, collectionName); } return result; } /* -cmd collection::close NsfCollectionClose { + cmd collection::close NsfCollectionClose { {-argName "collection" -required 1 -type mongoc_collection_t -withObj 1} -} + } */ static int -NsfCollectionClose(Tcl_Interp *interp, mongoc_collection_t *collectionPtr, Tcl_Obj *clientObj) { +NsfCollectionClose(Tcl_Interp *interp, mongoc_collection_t *collectionPtr, Tcl_Obj *clientObj) +{ mongoc_collection_destroy(collectionPtr); Nsf_PointerDelete(ObjStr(clientObj), collectionPtr, 0); return TCL_OK; } /* -cmd collection::count NsfMongoCollectionCount { + cmd collection::count NsfMongoCollectionCount { {-argName "collection" -required 1 -type mongoc_collection_t} {-argName "query" -required 1 -type tclobj} -} + } */ static int NsfMongoCollectionCount(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *queryObj) { - int objc, result; - Tcl_Obj **objv; - int count; - bson_t query, *queryPtr = &query; + mongoc_collection_t *collectionPtr, + Tcl_Obj *queryObj) +{ + int objc, result; + int64_t count; + Tcl_Obj **objv; + bson_t query, *queryPtr = &query; bson_error_t bsonError; result = Tcl_ListObjGetElements(interp, queryObj, &objc, &objv); @@ -780,26 +828,27 @@ } bson_destroy( queryPtr ); - Tcl_SetObjResult(interp, Tcl_NewIntObj(count)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)count)); return TCL_OK; } /* -cmd "collection::delete" NsfMongoCollectionDelete { + cmd "collection::delete" NsfMongoCollectionDelete { {-argName "collection" -required 1 -type mongoc_collection_t} {-argName "condition" -required 1 -type tclobj} -} + } */ static int NsfMongoCollectionDelete(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *conditionObj) { - int objc, result, success; - Tcl_Obj **objv; - bson_t query, *queryPtr = &query; - bson_error_t bsonError; - mongoc_remove_flags_t removeFlags = 0; /* TODO: not handled */ + mongoc_collection_t *collectionPtr, + Tcl_Obj *conditionObj) +{ + int objc, result, success; + Tcl_Obj **objv; + bson_t query, *queryPtr = &query; + bson_error_t bsonError; + mongoc_remove_flags_t removeFlags = 0; /* TODO: not handled */ /* MONGOC_DELETE_SINGLE_REMOVE = 1 << 0,**/ const mongoc_write_concern_t *writeConcern = NULL; /* TODO: not handled yet */ @@ -819,7 +868,7 @@ } /* -cmd "collection::index" NsfMongoCollectionIndex { + cmd "collection::index" NsfMongoCollectionIndex { {-argName "collection" -required 1 -type mongoc_collection_t} {-argName "attributes" -required 1 -type tclobj} {-argName "-name" -required 0 -nrargs 1} @@ -828,24 +877,24 @@ {-argName "-sparse" -required 0 -nrargs 0} {-argName "-ttl" -required 0 -nrargs 1 -type int32} {-argName "-unique" -required 0 -nrargs 0} -} + } */ static int NsfMongoCollectionIndex(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *attributesObj, - CONST char *withName, - int withBackground, - int withDropdups, - int withSparse, - int withTtl, - int withUnique) { - int success = 0; - int objc, result; - Tcl_Obj **objv; - bson_t keys, *keysPtr = &keys; - bson_error_t bsonError; + mongoc_collection_t *collectionPtr, + Tcl_Obj *attributesObj, + CONST char *withName, + int withBackground, + int withDropdups, + int withSparse, + int withTtl, + int withUnique) +{ + int objc, result, success = 0; + Tcl_Obj **objv; + bson_t keys, *keysPtr = &keys; + bson_error_t bsonError; mongoc_index_opt_t options; result = Tcl_ListObjGetElements(interp, attributesObj, &objc, &objv); @@ -875,24 +924,26 @@ /* -cmd "collection::insert" NsfMongoCollectionInsert { + cmd "collection::insert" NsfMongoCollectionInsert { {-argName "collection" -required 1 -type mongoc_collection_t} {-argName "values" -required 1 -type tclobj} -} + } */ static int NsfMongoCollectionInsert(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *valuesObj) { - int i, objc, result, success; - Tcl_Obj **objv; - bson_t bson, *bsonPtr = &bson; - bson_oid_t oid; - bson_error_t bsonError; + mongoc_collection_t *collectionPtr, + Tcl_Obj *valuesObj) +{ + int i, objc, result, success; + Tcl_Obj **objv; + bson_t bson, *bsonPtr = &bson; + bson_oid_t oid; + bson_error_t bsonError; mongoc_insert_flags_t insertFlags = MONGOC_INSERT_NO_VALIDATE; /* otherwise, we can't insert a DBRef */ + /* TODO: insertFlags not handled: - MONGOC_INSERT_NONE = 0, - MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0, - MONGOC_INSERT_NO_VALIDATE = 1 << 31, + MONGOC_INSERT_NONE = 0, + MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0, + MONGOC_INSERT_NO_VALIDATE = 1 << 31, */ const mongoc_write_concern_t *writeConcern = NULL; /* TODO: not handled yet */ @@ -909,6 +960,7 @@ CONST char *name = ObjStr(objv[i]); CONST char *tag = ObjStr(objv[i+1]); Tcl_Obj *value = objv[i+2]; + /*fprintf(stderr, "adding pair '%s' (%s) '%s'\n", name, tag, ObjStr(value));*/ BsonAppend(interp, bsonPtr, name, tag, value); } @@ -927,85 +979,79 @@ } /* -cmd collection::query NsfMongoCollectionQuery { + cmd collection::query NsfMongoCollectionQuery { {-argName "collection" -required 1 -type mongoc_collection_t} - {-argName "query" -required 1 -type tclobj} - {-argName "-atts" -required 0 -nrargs 1 -type tclobj} - {-argName "-limit" -required 0 -type int32} - {-argName "-skip" -required 0 -type int32} -} + {-argName "filter" -required 1 -type tclobj} + {-argName "-opts" -required 0 -nrargs 1 -type tclobj} + } */ static int NsfMongoCollectionQuery(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *queryObj, Tcl_Obj *withAttsObj, - int withLimit, int withSkip) { - int objc1, objc2 = 0, result; - Tcl_Obj **objv1, **objv2 = NULL, *resultObj; - mongoc_cursor_t *cursor; - bson_t query, *queryPtr = &query; - bson_t atts, *attsPtr = &atts; - const bson_t *nextPtr; - mongoc_query_flags_t queryFlags = 0; /* TODO: not handled */ - mongoc_read_prefs_t *readPrefs = NULL; /* TODO: not handled */ + mongoc_collection_t *collectionPtr, + Tcl_Obj *filterObj, Tcl_Obj *withOptsObj) +{ + int objc1, objc2 = 0, result; + Tcl_Obj **objv1, **objv2 = NULL, *resultObj; + mongoc_cursor_t *cursor; + bson_t filter, *const filterPtr = &filter; + bson_t opts, *const optsPtr = &opts; + const bson_t *nextPtr; + mongoc_read_prefs_t *readPrefsPtr = NULL; /* TODO: not handled */ /*fprintf(stderr, "NsfMongoQuery: namespace %s withLimit %d withSkip %d\n", namespace, withLimit, withSkip);*/ - result = Tcl_ListObjGetElements(interp, queryObj, &objc1, &objv1); + result = Tcl_ListObjGetElements(interp, filterObj, &objc1, &objv1); if (result != TCL_OK || ((objc1 % 3) != 0)) { - return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(queryObj)); + return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(filterObj)); } - if (withAttsObj != NULL) { - result = Tcl_ListObjGetElements(interp, withAttsObj, &objc2, &objv2); + if (withOptsObj != NULL) { + result = Tcl_ListObjGetElements(interp, withOptsObj, &objc2, &objv2); if (result != TCL_OK || ((objc2 % 3) != 0)) { - return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(withAttsObj)); + return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(withOptsObj)); } } else { objc2 = 0; } - /* fprintf(stderr, "query # %d, atts # %d\n", objc1, objc2); */ - BsonAppendObjv(interp, queryPtr, objc1, objv1); - BsonAppendObjv(interp, attsPtr, objc2, objv2); + BsonAppendObjv(interp, filterPtr, objc1, objv1); + BsonAppendObjv(interp, optsPtr, objc2, objv2); resultObj = Tcl_NewListObj(0, NULL); - /* - * The last field of mongo_find is options, semantics are described here - * http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-OPQUERY - */ - cursor = mongoc_collection_find( collectionPtr, queryFlags, - withSkip, withLimit, 0 /* batch_size */, - queryPtr, attsPtr, readPrefs); + cursor = mongoc_collection_find_with_opts( collectionPtr, + filterPtr, + optsPtr, + readPrefsPtr); while( mongoc_cursor_next( cursor, &nextPtr ) == 1 ) { Tcl_ListObjAppendElement(interp, resultObj, BsonToList(interp, nextPtr, 0)); } mongoc_cursor_destroy( cursor ); - bson_destroy( queryPtr ); - bson_destroy( attsPtr ); + bson_destroy( filterPtr ); + bson_destroy( optsPtr ); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* -cmd "collection::stats" NsfMongoCollectionStats { + cmd "collection::stats" NsfMongoCollectionStats { {-argName "collection" -required 1 -type mongoc_collection_t} {-argName "-options" -required 0 -type tclobj} -} + } */ static int NsfMongoCollectionStats(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *optionsObj) { - int objc = 0, success; - Tcl_Obj **objv = NULL; - bson_t options, *optionsPtr = NULL; - bson_t stats, *statsPtr = &stats; + mongoc_collection_t *collectionPtr, + Tcl_Obj *optionsObj) +{ + int objc = 0, success; + Tcl_Obj **objv = NULL; + bson_t options, *optionsPtr = NULL; + bson_t stats, *statsPtr = &stats; bson_error_t bsonError; if (optionsObj != NULL) { @@ -1018,42 +1064,42 @@ BsonAppendObjv(interp, optionsPtr, objc, objv); } - success = mongoc_collection_stats(collectionPtr, optionsPtr, statsPtr, &bsonError); + success = mongoc_collection_stats(collectionPtr, optionsPtr, statsPtr, &bsonError); - if (optionsPtr != NULL) { - bson_destroy (optionsPtr); - } + if (optionsPtr != NULL) { + bson_destroy (optionsPtr); + } - if (success != 0) { - Tcl_SetObjResult(interp, BsonToList(interp, statsPtr, 0)); - bson_destroy (statsPtr); - return TCL_OK; - } else { - return NsfPrintError(interp, "mongo::collection::stats: error: %s", bsonError.message); - } + if (success != 0) { + Tcl_SetObjResult(interp, BsonToList(interp, statsPtr, 0)); + bson_destroy (statsPtr); + return TCL_OK; + } else { + return NsfPrintError(interp, "mongo::collection::stats: error: %s", bsonError.message); + } } /* -cmd "collection::update" NsfMongoCollectionUpdate { + cmd "collection::update" NsfMongoCollectionUpdate { {-argName "collection" -required 1 -type mongoc_collection_t} {-argName "cond" -required 1 -type tclobj} {-argName "values" -required 1 -type tclobj} {-argName "-upsert" -required 0 -nrargs 0} {-argName "-all" -required 0 -nrargs 0} -} + } */ static int NsfMongoCollectionUpdate(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *conditionObj, Tcl_Obj *valuesObj, - int withUpsert, int withAll) { + mongoc_collection_t *collectionPtr, + Tcl_Obj *conditionObj, Tcl_Obj *valuesObj, + int withUpsert, int withAll) { const mongoc_write_concern_t *writeConcern = NULL; /* TODO: not handled yet */ - mongoc_update_flags_t updateFlags = MONGOC_UPDATE_NO_VALIDATE; /* for dbrefs */ - bson_error_t bsonError; - bson_t cond, *condPtr = &cond, values, *valuesPtr = &values; - int objc, result, success; - Tcl_Obj **objv; + mongoc_update_flags_t updateFlags = MONGOC_UPDATE_NO_VALIDATE; /* for dbrefs */ + bson_error_t bsonError; + bson_t cond, *condPtr = &cond, values, *valuesPtr = &values; + int objc, result, success; + Tcl_Obj **objv; result = Tcl_ListObjGetElements(interp, conditionObj, &objc, &objv); if (result != TCL_OK || ((objc % 3) != 0)) { @@ -1086,27 +1132,28 @@ * Cursor interface ***********************************************************************/ /* -cmd cursor::aggregate NsfMongoCursorAggregate { + cmd cursor::aggregate NsfMongoCursorAggregate { {-argName "collection" -required 1 -type mongoc_collection_t} {-argName "pipeline" -required 1 -type tclobj} {-argName "options" -required 1 -type tclobj} {-argName "-tailable" -required 0 -nrargs 0} {-argName "-awaitdata" -required 0 -nrargs 0} -} + } */ static int NsfMongoCursorAggregate(Tcl_Interp *interp, mongoc_collection_t *collectionPtr, Tcl_Obj *pipelineObj, Tcl_Obj *optionsObj, int withTailable, - int withAwaitdata) { - int objc1, objc2, result; + int withAwaitdata) +{ + int objc1, objc2, result; mongoc_query_flags_t queryFlags = 0; - Tcl_Obj **objv1, **objv2 = NULL; - mongoc_cursor_t *cursor; - bson_t pipeline, *pipelinePtr = &pipeline; - bson_t options, *optionsPtr = &options; + Tcl_Obj **objv1, **objv2 = NULL; + mongoc_cursor_t *cursor; + bson_t pipeline, *pipelinePtr = &pipeline; + bson_t options, *optionsPtr = &options; mongoc_read_prefs_t *readPrefsPtr = NULL; /* TODO: not used */ result = Tcl_ListObjGetElements(interp, pipelineObj, &objc1, &objv1); @@ -1132,17 +1179,18 @@ queryFlags |= MONGOC_QUERY_AWAIT_DATA; } /* TODO: query flags: - MONGOC_QUERY_SLAVE_OK = 1 << 2, - MONGOC_QUERY_OPLOG_REPLAY = 1 << 3, - MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4, - MONGOC_QUERY_EXHAUST = 1 << 6, - MONGOC_QUERY_PARTIAL = 1 << 7, + MONGOC_QUERY_SLAVE_OK = 1 << 2, + MONGOC_QUERY_OPLOG_REPLAY = 1 << 3, + MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4, + MONGOC_QUERY_EXHAUST = 1 << 6, + MONGOC_QUERY_PARTIAL = 1 << 7, */ cursor = mongoc_collection_aggregate(collectionPtr, queryFlags, pipelinePtr, optionsPtr, readPrefsPtr); if (cursor != NULL) { char buffer[80]; + if (Nsf_PointerAdd(interp, buffer, "mongoc_cursor_t", cursor) == TCL_OK) { Tcl_SetObjResult(interp, Tcl_NewStringObj(buffer, -1)); } else { @@ -1160,67 +1208,47 @@ } /* -cmd cursor::find NsfMongoCursorFind { + cmd cursor::find NsfMongoCursorFind { {-argName "collection" -required 1 -type mongoc_collection_t} - {-argName "query" -required 1 -type tclobj} - {-argName "-atts" -required 0 -nrargs 1 -type tclobj} - {-argName "-limit" -required 0 -type int32} - {-argName "-skip" -required 0 -type int32} - {-argName "-tailable" -required 0 -nrargs 0} - {-argName "-awaitdata" -required 0 -nrargs 0} -} + {-argName "filter" -required 1 -type tclobj} + {-argName "-opts" -required 0 -nrargs 1 -type tclobj} + } */ static int NsfMongoCursorFind(Tcl_Interp *interp, - mongoc_collection_t *collectionPtr, - Tcl_Obj *queryObj, Tcl_Obj *withAttsObj, - int withLimit, int withSkip, - int withTailable, int withAwaitdata) { - int objc1, objc2 = 0, result; - mongoc_query_flags_t queryFlags = 0; - Tcl_Obj **objv1, **objv2 = NULL; - mongoc_cursor_t *cursor; - bson_t query, *queryPtr = &query; - bson_t atts, *attsPtr = &atts; + mongoc_collection_t *collectionPtr, + Tcl_Obj *filterObj, + Tcl_Obj *withOptsObj) +{ + int objc1, objc2 = 0, result; + Tcl_Obj **objv1, **objv2 = NULL; + mongoc_cursor_t *cursor; + bson_t filter, *filterPtr = &filter; + bson_t opts, *optsPtr = &opts; mongoc_read_prefs_t *readPrefsPtr = NULL; /* TODO: not used */ /*fprintf(stderr, "NsfMongoQuery: namespace %s withLimit %d withSkip %d\n", namespace, withLimit, withSkip);*/ - result = Tcl_ListObjGetElements(interp, queryObj, &objc1, &objv1); + result = Tcl_ListObjGetElements(interp, filterObj, &objc1, &objv1); if (result != TCL_OK || ((objc1 % 3) != 0)) { - return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(queryObj)); + return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(filterObj)); } - if (withAttsObj != NULL) { - result = Tcl_ListObjGetElements(interp, withAttsObj, &objc2, &objv2); + if (withOptsObj != NULL) { + result = Tcl_ListObjGetElements(interp, withOptsObj, &objc2, &objv2); if (result != TCL_OK || ((objc2 % 3) != 0)) { - return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(withAttsObj)); + return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(withOptsObj)); } } - BsonAppendObjv(interp, queryPtr, objc1, objv1); - BsonAppendObjv(interp, attsPtr, objc2, objv2); + BsonAppendObjv(interp, filterPtr, objc1, objv1); + BsonAppendObjv(interp, optsPtr, objc2, objv2); - /* - * The last field of mongo_find is options, semantics are described here - * http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-OPQUERY - */ - if (withTailable != 0) { - queryFlags |= MONGOC_QUERY_TAILABLE_CURSOR; - } - if (withAwaitdata != 0) { - queryFlags |= MONGOC_QUERY_AWAIT_DATA; - } - /* TODO: query flags: - MONGOC_QUERY_SLAVE_OK = 1 << 2, - MONGOC_QUERY_OPLOG_REPLAY = 1 << 3, - MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4, - MONGOC_QUERY_EXHAUST = 1 << 6, - MONGOC_QUERY_PARTIAL = 1 << 7, - */ - cursor = mongoc_collection_find(collectionPtr, queryFlags, - withSkip, withLimit, 0 /*TODO missing batch_size*/, - queryPtr, attsPtr, readPrefsPtr); + cursor = mongoc_collection_find_with_opts( collectionPtr, + filterPtr, + optsPtr, + readPrefsPtr); + if (cursor != NULL) { char buffer[80]; if (Nsf_PointerAdd(interp, buffer, "mongoc_cursor_t", cursor) == TCL_OK) { @@ -1233,37 +1261,39 @@ Tcl_ResetResult(interp); } - bson_destroy( queryPtr ); - bson_destroy( attsPtr ); + bson_destroy( filterPtr ); + bson_destroy( optsPtr ); return result; } /* -cmd cursor::next NsfMongoCursorNext { + cmd cursor::next NsfMongoCursorNext { {-argName "cursor" -required 1 -type mongoc_cursor_t} -} + } */ static int -NsfMongoCursorNext(Tcl_Interp *interp, mongoc_cursor_t *cursor) { - int result; +NsfMongoCursorNext(Tcl_Interp *interp, mongoc_cursor_t *cursor) +{ + int result; const bson_t *nextPtr; result = mongoc_cursor_next( cursor, &nextPtr ); if (result == 1) { Tcl_SetObjResult(interp, BsonToList(interp, nextPtr, 0)); } + return TCL_OK; } /* -cmd cursor::close NsfMongoCursorClose { + cmd cursor::close NsfMongoCursorClose { {-argName "cursor" -required 1 -type mongoc_cursor_t -withObj 1} -} + } */ static int -NsfMongoCursorClose(Tcl_Interp *interp, mongoc_cursor_t *cursor, Tcl_Obj *cursorObj) { - +NsfMongoCursorClose(Tcl_Interp *interp, mongoc_cursor_t *cursor, Tcl_Obj *cursorObj) +{ mongoc_cursor_destroy( cursor ); Nsf_PointerDelete(ObjStr(cursorObj), cursor, 0); @@ -1277,33 +1307,34 @@ ***********************************************************************/ /* -cmd gridfs::close NsfMongoGridFSClose { + cmd gridfs::close NsfMongoGridFSClose { {-argName "gfs" -required 1 -type mongoc_gridfs_t -withObj 1} -} + } */ static int -NsfMongoGridFSClose(Tcl_Interp *interp, mongoc_gridfs_t *gridfsPtr, Tcl_Obj *gridfsObj) { - +NsfMongoGridFSClose(Tcl_Interp *interp, mongoc_gridfs_t *gridfsPtr, Tcl_Obj *gridfsObj) +{ mongoc_gridfs_destroy(gridfsPtr); Nsf_PointerDelete(ObjStr(gridfsObj), gridfsPtr, 0); return TCL_OK; } /* -cmd gridfs::open NsfMongoGridFSOpen { + cmd gridfs::open NsfMongoGridFSOpen { {-argName "conn" -required 1 -type mongoc_client_t} {-argName "dbname" -required 1} {-argName "prefix" -required 1} -} + } */ static int NsfMongoGridFSOpen(Tcl_Interp *interp, mongoc_client_t *clientPtr, - CONST char *dbname, CONST char *prefix) { - char buffer[80]; - int result = TCL_OK; - bson_error_t bsonError; + CONST char *dbname, CONST char *prefix) +{ + char buffer[80]; + int result = TCL_OK; + bson_error_t bsonError; mongoc_gridfs_t *gfsPtr; gfsPtr = mongoc_client_get_gridfs(clientPtr, dbname, prefix, &bsonError); @@ -1330,27 +1361,28 @@ /* -cmd gridfile::create NsfMongoGridFileCreate { + cmd gridfile::create NsfMongoGridFileCreate { {-argName "-source" -required 1 -typeName "gridfilesource" -type "file|string"} {-argName "gfs" -required 1 -type mongoc_gridfs_t} {-argName "value" -required 1} {-argName "name" -required 1} {-argName "contenttype" -required 1} {-argName "-metadata" -required 0 -nrags 1 -type tclobj} -} + } */ static int NsfMongoGridFileCreate(Tcl_Interp *interp, GridfilesourceIdx_t withSource, - mongoc_gridfs_t *gridfsPtr, - CONST char *value, CONST char *name, - CONST char *contenttype, - Tcl_Obj *withMetadata - ) { - int result = TCL_OK; + mongoc_gridfs_t *gridfsPtr, + CONST char *value, CONST char *name, + CONST char *contenttype, + Tcl_Obj *withMetadata + ) +{ + int result = TCL_OK; mongoc_gridfs_file_opt_t fileOpts = {NULL}; - mongoc_gridfs_file_t *gridFile; - bson_t bsonMetaData, *bsonMetaDataPtr = &bsonMetaData; + mongoc_gridfs_file_t *gridFile; + bson_t bsonMetaData, *bsonMetaDataPtr = &bsonMetaData; if (withSource == GridfilesourceNULL) { withSource = GridfilesourceFileIdx; @@ -1371,9 +1403,9 @@ fileOpts.filename = name; fileOpts.content_type = contenttype; /* - const char *md5; - const bson_t *aliases; - uint32_t chunk_size; + const char *md5; + const bson_t *aliases; + uint32_t chunk_size; */ gridFile = mongoc_gridfs_create_file(gridfsPtr, &fileOpts); @@ -1389,17 +1421,18 @@ for (;; ) { ssize_t n = read(fd, iov.iov_base, MONGOC_GRIDFS_READ_CHUNK); + if (n > 0) { - iov.iov_len = n; - n = mongoc_gridfs_file_writev(gridFile, &iov, 1, 0); - if (n != iov.iov_len) { + iov.iov_len = (size_t)n; + n = mongoc_gridfs_file_writev(gridFile, &iov, 1, 0); + if ((size_t)n != iov.iov_len) { NsfLog(interp, NSF_LOG_WARN, "mongodb: write of %d bytes returned %d", iov.iov_len, n); } } else if (n == 0) { - break; + break; } else { - result = TCL_ERROR; - break; + result = TCL_ERROR; + break; } } close(fd); @@ -1420,54 +1453,63 @@ /* -cmd "gridfile::delete" NsfMongoGridFileDelete { + cmd "gridfile::delete" NsfMongoGridFileDelete { {-argName "gfs" -required 1 -type mongoc_gridfs_t} {-argName "query" -required 1 -type tclobj} -} + } */ static int NsfMongoGridFileDelete(Tcl_Interp *interp, - mongoc_gridfs_t *gridfsPtr, - Tcl_Obj *queryObj) { - bson_t query, *queryPtr = &query; - mongoc_cursor_t *files; - const bson_t *nextPtr; - bson_iter_t it; - Tcl_Obj **objv; - int objc, result; + mongoc_gridfs_t *gridfsPtr, + Tcl_Obj *queryObj) +{ + bson_t query, *queryPtr = &query; + mongoc_cursor_t *files; + const bson_t *nextPtr; + bson_iter_t it; + Tcl_Obj **objv; + int objc, result; + mongoc_read_prefs_t *readPrefsPtr = NULL; /* TODO: not handled */ result = Tcl_ListObjGetElements(interp, queryObj, &objc, &objv); if (result != TCL_OK || ((objc % 3) != 0)) { return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(queryObj)); } BsonAppendObjv(interp, queryPtr, objc, objv); - files = mongoc_collection_find( mongoc_gridfs_get_files(gridfsPtr), 0, - 0, 0, 0 /* batch_size */, - queryPtr, NULL, NULL); + files = mongoc_collection_find_with_opts( mongoc_gridfs_get_files(gridfsPtr), + queryPtr, NULL, readPrefsPtr); bson_destroy(queryPtr); - /* files should be a valid cursor even if the file doesn't exist */ + /* + * Files should be a valid cursor even if the file doesn't exist. + */ if ( files == NULL ) { return NsfPrintError(interp, "gridfs::remove_file: invalid cursor for files"); } - /* Remove each file and it's chunks from files named filename */ + /* + * Remove each file and it's chunks from files named filename. + */ while (mongoc_cursor_next(files, &nextPtr)) { - bson_t bson, *bsonPtr = &bson; + bson_t bson, *bsonPtr = &bson; bson_error_t bsonError; - bson_oid_t id; + bson_oid_t id; bson_iter_init_find(&it, nextPtr, "_id"); id = *bson_iter_oid(&it); - /* Remove the file with the specified id */ + /* + * Remove the file with the specified id. + */ bson_init(bsonPtr); bson_append_oid(bsonPtr, "_id", 3, &id); mongoc_collection_remove(mongoc_gridfs_get_files(gridfsPtr), 0, bsonPtr, NULL, &bsonError); bson_destroy(bsonPtr); - /* Remove all chunks from the file with the specified id */ + /* + * Remove all chunks from the file with the specified id. + */ bson_init(bsonPtr); bson_append_oid(bsonPtr, "files_id", 8, &id); mongoc_collection_remove(mongoc_gridfs_get_chunks(gridfsPtr), 0, bsonPtr, NULL, &bsonError); @@ -1479,32 +1521,33 @@ } /* -cmd gridfile::open NsfMongoGridFileOpen { + cmd gridfile::open NsfMongoGridFileOpen { {-argName "gfs" -required 1 -type mongoc_gridfs_t} - {-argName "query" -required 1 -type tclobj} -} + {-argName "filter" -required 1 -type tclobj} + } */ static int NsfMongoGridFileOpen(Tcl_Interp *interp, - mongoc_gridfs_t *gridfsPtr, - Tcl_Obj *queryObj) { + mongoc_gridfs_t *gridfsPtr, + Tcl_Obj *filterObj) +{ mongoc_gridfs_file_t* gridFilePtr; - bson_error_t bsonError; - int result, objc; - bson_t query, *queryPtr = &query; - Tcl_Obj **objv; + bson_error_t bsonError; + bson_t filter, *filterPtr = &filter; + int result, objc; + Tcl_Obj **objv; - /*fprintf(stderr, "NsfMongoQuery: namespace %s withLimit %d withSkip %d\n", + /*fprintf(stderr, "NsfMongoFilter: namespace %s withLimit %d withSkip %d\n", namespace, withLimit, withSkip);*/ - result = Tcl_ListObjGetElements(interp, queryObj, &objc, &objv); + result = Tcl_ListObjGetElements(interp, filterObj, &objc, &objv); if (result != TCL_OK || ((objc % 3) != 0)) { - return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(queryObj)); + return NsfPrintError(interp, "%s: must contain a multiple of 3 elements", ObjStr(filterObj)); } - BsonAppendObjv(interp, queryPtr, objc, objv); + BsonAppendObjv(interp, filterPtr, objc, objv); - gridFilePtr = mongoc_gridfs_find_one(gridfsPtr, queryPtr, &bsonError); + gridFilePtr = mongoc_gridfs_find_one_with_opts(gridfsPtr, filterPtr, NULL, &bsonError); if (gridFilePtr != NULL) { char buffer[80]; @@ -1519,7 +1562,7 @@ Tcl_ResetResult(interp); } - bson_destroy(queryPtr); + bson_destroy(filterPtr); return result; } @@ -1532,26 +1575,27 @@ ***********************************************************************/ /* -cmd gridfile::close NsfMongoGridFileClose { + cmd gridfile::close NsfMongoGridFileClose { {-argName "gridfile" -required 1 -type mongoc_gridfs_file_t -withObj 1} -} + } */ static int -NsfMongoGridFileClose(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr, Tcl_Obj *gridFileObj) { - +NsfMongoGridFileClose(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr, Tcl_Obj *gridFileObj) +{ mongoc_gridfs_file_destroy(gridFilePtr); Nsf_PointerDelete(ObjStr(gridFileObj), gridFilePtr, 0); return TCL_OK; } /* -cmd gridfile::get_contentlength NsfMongoGridFileGetContentlength { + cmd gridfile::get_contentlength NsfMongoGridFileGetContentlength { {-argName "gridfile" -required 1 -type mongoc_gridfs_file_t} -} + } */ static int -NsfMongoGridFileGetContentlength(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr) { +NsfMongoGridFileGetContentlength(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr) +{ int64_t len; len = mongoc_gridfs_file_get_length(gridFilePtr); @@ -1561,13 +1605,13 @@ } /* -cmd gridfile::get_contenttype NsfMongoGridFileGetContentType { + cmd gridfile::get_contenttype NsfMongoGridFileGetContentType { {-argName "gridfile" -required 1 -type mongoc_gridfs_file_t} -} + } */ static int -NsfMongoGridFileGetContentType(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr) { - +NsfMongoGridFileGetContentType(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr) +{ Tcl_SetObjResult(interp, Tcl_NewStringObj(mongoc_gridfs_file_get_content_type(gridFilePtr), -1)); return TCL_OK; @@ -1576,12 +1620,13 @@ /* -cmd gridfile::get_metadata NsfMongoGridFileGetMetaData { + cmd gridfile::get_metadata NsfMongoGridFileGetMetaData { {-argName "gridfile" -required 1 -type mongoc_gridfs_file_t} -} + } */ static int -NsfMongoGridFileGetMetaData(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr) { +NsfMongoGridFileGetMetaData(Tcl_Interp *interp, mongoc_gridfs_file_t* gridFilePtr) +{ const bson_t *metaDataPtr = mongoc_gridfs_file_get_metadata(gridFilePtr); if (metaDataPtr != NULL) { @@ -1591,37 +1636,41 @@ } /* -cmd gridfile::read NsfMongoGridFileRead { + cmd gridfile::read NsfMongoGridFileRead { {-argName "gridfile" -required 1 -type mongoc_gridfs_file_t} {-argName "size" -required 1 -type int} -} + } */ static int -NsfMongoGridFileRead(Tcl_Interp *interp, mongoc_gridfs_file_t *gridFilePtr, int size) { - int readSize; - Tcl_Obj *resultObj = Tcl_NewByteArrayObj(NULL, size); - struct iovec iov = { NULL, size }; +NsfMongoGridFileRead(Tcl_Interp *interp, mongoc_gridfs_file_t *gridFilePtr, int size) +{ + ssize_t readSize; + Tcl_Obj *resultObj = Tcl_NewByteArrayObj(NULL, size); + struct iovec iov = { NULL, (size_t)size }; + assert(size > 0); + iov.iov_base = Tcl_SetByteArrayLength(resultObj, size); readSize = mongoc_gridfs_file_readv(gridFilePtr, &iov, 1, - 0 /* min_bytes */, - 0 /* timeout_msec */); + 0 /* min_bytes */, + 0 /* timeout_msec */); /*fprintf(stderr, "NsfMongoGridFileRead want %d got %d\n", size, readSize);*/ - Tcl_SetByteArrayLength(resultObj, readSize); + Tcl_SetByteArrayLength(resultObj, (int)readSize); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* -cmd "gridfile::seek" NsfMongoGridFileSeek { + cmd "gridfile::seek" NsfMongoGridFileSeek { {-argName "gridfile" -required 1 -type mongoc_gridfs_file_t} {-argName "offset" -required 1 -type int32} -} + } */ static int -NsfMongoGridFileSeek(Tcl_Interp *interp, mongoc_gridfs_file_t *gridFilePtr, int offset) { +NsfMongoGridFileSeek(Tcl_Interp *interp, mongoc_gridfs_file_t *gridFilePtr, int offset) +{ int result; /* TODO: whence SEEK_SET, SEEK_CUR or SEEK_END; implementation of SEEK_END looks incorrect */ @@ -1635,13 +1684,14 @@ ***********************************************************************/ void -Nsfmongo_ThreadExit(ClientData clientData) { +Nsfmongo_ThreadExit(ClientData clientData) +{ /* * The exit might happen at a time, when tcl is already shut down. * We can't reliably call NsfLog. */ - /*fprintf(stderr, "+++ Nsfmongo_ThreadExit\n");*/ + fprintf(stderr, "+++ Nsfmongo_ThreadExit\n"); #if defined(USE_CLIENT_POOL) NsfMutexLock(&poolMutex); @@ -1660,7 +1710,8 @@ } void -Nsfmongo_Exit(ClientData clientData) { +Nsfmongo_Exit(ClientData clientData) +{ /* * The exit might happen at a time, when tcl is already shut down. * We can't reliably call NsfLog. @@ -1669,19 +1720,25 @@ * NsfLog(interp,NSF_LOG_NOTICE, "Nsfmongo Exit"); */ - /*fprintf(stderr, "+++ Nsfmongo_Exit\n");*/ + fprintf(stderr, "+++ Nsfmongo_Exit\n"); #if defined(TCL_THREADS) Tcl_DeleteThreadExitHandler(Nsfmongo_ThreadExit, clientData); #endif Tcl_Release(clientData); + + /* + * Release the state of mongo-c-driver explicitly. + */ + mongoc_cleanup(); } extern int -Nsfmongo_Init(Tcl_Interp * interp) { - int i; +Nsfmongo_Init(Tcl_Interp * interp) +{ + int i; static NsfMutex initMutex = 0; #ifdef USE_TCL_STUBS @@ -1721,23 +1778,29 @@ #endif /* - * Register global mongo tcl_objs + * Register global mongo Tcl_Objs once. */ NsfMutexLock(&initMutex); if (NsfMongoGlobalObjs == NULL) { NsfMongoGlobalObjs = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*)*nr_elements(NsfMongoGlobalStrings)); + for (i = 0; i < nr_elements(NsfMongoGlobalStrings); i++) { NsfMongoGlobalObjs[i] = Tcl_NewStringObj(NsfMongoGlobalStrings[i], -1); Tcl_IncrRefCount(NsfMongoGlobalObjs[i]); } + + /* + * Initializing state of mongo-c-driver explicitly. + */ + mongoc_init(); } NsfMutexUnlock(&initMutex); Nsf_EnumerationTypeRegister(interp, enumeratorConverterEntries); Nsf_CmdDefinitionRegister(interp, method_definitions); /* - * register the pointer converter + * Register the pointer converter. */ Nsf_PointerTypeRegister(interp, "mongoc_client_t", &mongoClientCount); Nsf_PointerTypeRegister(interp, "mongoc_collection_t", &mongoCollectionCount); @@ -1749,12 +1812,15 @@ Tcl_CreateNamespace(interp, method_command_namespace_names[i], 0, (Tcl_NamespaceDeleteProc *)NULL); } - /* create all method commands (will use the namespaces above) */ - for (i=0; i < nr_elements(method_definitions)-1; i++) { + /* + * Create all method commands (will use the namespaces above) + */ + for (i = 0; i < nr_elements(method_definitions)-1; i++) { Tcl_CreateObjCommand(interp, method_definitions[i].methodName, method_definitions[i].proc, 0, 0); } Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); + return TCL_OK; } @@ -1773,4 +1839,3 @@ * indent-tabs-mode: nil * End: */ -