rpm  5.4.15
mongo.c
Go to the documentation of this file.
1 
5 /* Copyright 2009, 2010 10gen Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #include "system.h"
21 
22 #include <arpa/inet.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <netdb.h>
27 #include <netinet/in.h>
28 #include <netinet/tcp.h>
29 #include <fcntl.h>
30 
31 #include <rpmiotypes.h>
32 #include <rpmio.h> /* for *Pool methods */
33 #include <rpmlog.h>
34 #include <rpmurl.h>
35 
36 #define _RPMMGO_INTERNAL
37 #include <mongo.h>
38 
39 #include "debug.h"
40 
41 /*@unchecked@*/
42 int _rpmmgo_debug = 0;
43 
44 /*@unchecked@*/ /*@relnull@*/
46 
47 /* only need one of these */
48 static const int zero = 0;
49 static const int one = 1;
50 
51 /*==============================================================*/
52 /* --- gridfs.h */
53 
54 enum {DEFAULT_CHUNK_SIZE = 256 * 1024};
55 
56 typedef uint64_t gridfs_offset;
57 
58 /* A GridFS represents a single collection of GridFS files in the database. */
59 typedef struct {
61  const char *dbname;
62  const char *prefix;
63  const char *files_ns;
64  const char *chunks_ns;
66 } gridfs;
67 
68 /* A GridFile is a single GridFS file. */
69 typedef struct {
74  char *remote_name;
75  char *content_type;
77  int chunk_num;
78  char *pending_data;
79  size_t pending_len;
80  int flags;
81  int chunkSize;
82 } gridfile;
83 
86  GRIDFILE_NOMD5 = ( 1<<0 )
87 };
88 
89 #ifndef _MSC_VER
90 static char *_strupr(char *str);
91 #ifdef UNUSED
92 static char *_strlwr(char *str);
93 #endif
94 #endif
95 
96 typedef int ( *gridfs_chunk_filter_func )( char** targetBuf, size_t* targetLen, const char* srcBuf, size_t srcLen, int flags );
97 typedef size_t ( *gridfs_pending_data_size_func ) (int flags);
98 
105 
115 MONGO_EXPORT int gridfs_init( mongo *client, const char *dbname,
116  const char *prefix, gridfs *gfs );
117 
124 MONGO_EXPORT void gridfs_destroy( gridfs *gfs );
125 
134 MONGO_EXPORT int gridfile_init( gridfs *gfs, const bson *meta, gridfile *gfile );
135 
141 MONGO_EXPORT void gridfile_destroy( gridfile *gfile );
142 
151 MONGO_EXPORT int gridfile_writer_init( gridfile *gfile, gridfs *gfs, const char *remote_name,
152  const char *content_type, int flags );
153 
165 
174 
185 MONGO_EXPORT int gridfs_store_buffer( gridfs *gfs, const char *data, gridfs_offset length,
186  const char *remotename,
187  const char *contenttype, int flags );
188 
198 MONGO_EXPORT int gridfs_store_file( gridfs *gfs, const char *filename,
199  const char *remotename, const char *contenttype, int flags );
200 
210 MONGO_EXPORT int gridfs_remove_filename( gridfs *gfs, const char *filename );
211 
222 MONGO_EXPORT int gridfs_find_query( gridfs *gfs, const bson *query, gridfile *gfile );
223 
233 MONGO_EXPORT int gridfs_find_filename( gridfs *gfs, const char *filename, gridfile *gfile );
234 
240 
247 MONGO_EXPORT const char *gridfile_get_filename( const gridfile *gfile );
248 
255 MONGO_EXPORT int gridfile_get_chunksize( const gridfile *gfile );
256 
265 
274 MONGO_EXPORT const char *gridfile_get_contenttype( const gridfile *gfile );
275 
284 
292 MONGO_EXPORT const char *gridfile_get_md5( const gridfile *gfile );
293 
302 
312 MONGO_EXPORT const char *gridfile_get_field( gridfile *gfile,
313  const char *name );
314 
322 
331 
340 
347 MONGO_EXPORT int gridfile_get_flags( const gridfile *gfile );
348 
358  const char *name );
359 
374 MONGO_EXPORT void gridfile_get_metadata( const gridfile *gfile, bson* metadata, bson_bool_t copyData );
375 
382 MONGO_EXPORT int gridfile_get_numchunks( const gridfile *gfile );
383 
390 MONGO_EXPORT void gridfile_get_chunk( gridfile *gfile, int n, bson* out );
391 
401 MONGO_EXPORT mongo_cursor *gridfile_get_chunks( gridfile *gfile, size_t start, size_t size );
402 
410 
424 
436 
443 
450 
457 
458 /*==============================================================*/
459 /* --- gridfs.c */
460 
461 #ifndef _MSC_VER
462 static char *_strupr(char *str)
463 {
464  char *s = str;
465  while (*s) {
466  *s = toupper((unsigned char)*s);
467  ++s;
468  }
469  return str;
470 }
471 #ifdef UNUSED
472 static char *_strlwr(char *str)
473 {
474  char *s = str;
475  while (*s) {
476  *s = tolower((unsigned char)*s);
477  ++s;
478  }
479  return str;
480 }
481 #endif
482 #endif
483 
484 /* Memory allocation functions */
486  return ( gridfs* )bson_malloc( sizeof( gridfs ) );
487 }
488 
490  bson_free( gfs );
491 }
492 
494  gridfile* gfile = (gridfile*)bson_malloc(sizeof(gridfile));
495  memset( gfile, 0, sizeof ( gridfile ) );
496  return gfile;
497 }
498 
500  bson_free( gf );
501 }
502 
504  *out = *gf->meta;
505 }
506 
507 /* Default chunk pre and post processing logic */
508 static int gridfs_default_chunk_filter(char** targetBuf, size_t* targetLen, const char* srcData, size_t srcLen, int flags) {
509  *targetBuf = (char *) srcData;
510  *targetLen = srcLen;
511  return 0;
512 }
513 
515  return DEFAULT_CHUNK_SIZE;
516 }
517 /* End of default functions for chunks pre and post processing */
518 
522 
524  gridfs_write_filter = writeFilter;
525  gridfs_read_filter = readFilter;
526  gridfs_pending_data_size = pendingDataNeededSize;
527 }
528 
529 static bson *chunk_new(bson_oid_t id, int chunkNumber, char** dataBuf, const char* srcData, size_t len, int flags ) {
530  bson *b = bson_alloc();
531  size_t dataBufLen = 0;
532 
533  if( gridfs_write_filter( dataBuf, &dataBufLen, srcData, len, flags) != 0 ) {
534  return NULL;
535  }
536  bson_init_size(b, (int) dataBufLen + 128); /* a little space for field names, files_id, and n */
537  bson_append_oid(b, "files_id", &id);
538  bson_append_int(b, "n", chunkNumber);
539  bson_append_binary(b, "data", BSON_BIN_BINARY, *dataBuf, (int)dataBufLen);
540  bson_finish(b);
541  return b;
542 }
543 
544 static void chunk_free(bson *oChunk) {
545  if( oChunk ) {
546  bson_destroy(oChunk);
547  bson_dealloc(oChunk);
548  }
549 }
550 /* End of memory allocation functions */
551 
552 /* -------------- */
553 /* gridfs methods */
554 /* -------------- */
555 
556 /* gridfs constructor */
557 MONGO_EXPORT int gridfs_init(mongo *client, const char *dbname, const char *prefix, gridfs *gfs) {
558 
559  bson b;
560 
561  gfs->caseInsensitive = 0;
562  gfs->client = client;
563 
564  /* Allocate space to own the dbname */
565  gfs->dbname = (const char*)bson_malloc((int)strlen(dbname) + 1);
566  strcpy((char*)gfs->dbname, dbname);
567 
568  /* Allocate space to own the prefix */
569  if (prefix == NULL) {
570  prefix = "fs";
571  }
572  gfs->prefix = (const char*)bson_malloc((int)strlen(prefix) + 1);
573  strcpy((char*)gfs->prefix, prefix);
574 
575  /* Allocate space to own files_ns */
576  gfs->files_ns = (const char*)bson_malloc((int)(strlen(prefix) + strlen(dbname) + strlen(".files") + 2));
577  strcpy((char*)gfs->files_ns, dbname);
578  strcat((char*)gfs->files_ns, ".");
579  strcat((char*)gfs->files_ns, prefix);
580  strcat((char*)gfs->files_ns, ".files");
581 
582  /* Allocate space to own chunks_ns */
583  gfs->chunks_ns = (const char*)bson_malloc((int)(strlen(prefix) + strlen(dbname) + strlen(".chunks") + 2));
584  strcpy((char*)gfs->chunks_ns, dbname);
585  strcat((char*)gfs->chunks_ns, ".");
586  strcat((char*)gfs->chunks_ns, prefix);
587  strcat((char*)gfs->chunks_ns, ".chunks");
588 
589  bson_init(&b);
590  bson_append_int(&b, "filename", 1);
591  bson_finish(&b);
592  if( mongo_create_index(gfs->client, gfs->files_ns, &b, NULL, 0, NULL) != MONGO_OK) {
593  bson_destroy( &b );
594  gridfs_destroy( gfs );
595  return MONGO_ERROR;
596  }
597  bson_destroy(&b);
598 
599  bson_init(&b);
600  bson_append_int(&b, "files_id", 1);
601  bson_append_int(&b, "n", 1);
602  bson_finish(&b);
603  if( mongo_create_index(gfs->client, gfs->chunks_ns, &b, NULL, MONGO_INDEX_UNIQUE, NULL) != MONGO_OK ) {
604  bson_destroy(&b);
605  gridfs_destroy( gfs );
606  return MONGO_ERROR;
607  }
608  bson_destroy(&b);
609 
610  return MONGO_OK;
611 }
612 
613 /* gridfs destructor */
615  if( gfs == NULL ) return;
616  if( gfs->dbname ) {
617  bson_free((char*)gfs->dbname);
618  gfs->dbname = NULL;
619  }
620  if( gfs->prefix ) {
621  bson_free((char*)gfs->prefix);
622  gfs->prefix = NULL;
623  }
624  if( gfs->files_ns ) {
625  bson_free((char*)gfs->files_ns);
626  gfs->files_ns = NULL;
627  }
628  if( gfs->chunks_ns ) {
629  bson_free((char*)gfs->chunks_ns);
630  gfs->chunks_ns = NULL;
631  }
632 }
633 
634 /* gridfs accesors */
635 
637  return gfs->caseInsensitive;
638 }
639 
641  gfs->caseInsensitive = newValue;
642 }
643 
644 static int bson_append_string_uppercase( bson *b, const char *name, const char *str, bson_bool_t upperCase ) {
645  char *strUpperCase;
646  if ( upperCase ) {
647  int res;
648  strUpperCase = (char *) bson_malloc( (int) strlen( str ) + 1 );
649  strcpy(strUpperCase, str);
650  _strupr(strUpperCase);
651  res = bson_append_string( b, name, strUpperCase );
652  bson_free( strUpperCase );
653  return res;
654  } else {
655  return bson_append_string( b, name, str );
656  }
657 }
658 
659 static int gridfs_insert_file(gridfs *gfs, const char *name, const bson_oid_t id, gridfs_offset length, const char *contenttype, int flags, int chunkSize) {
660  bson command[1];
661  bson ret[1];
662  bson res[1];
663  bson_iterator it[1];
664  bson q[1];
665  int result;
666  int64_t d;
667 
668  /* If you don't care about calculating MD5 hash for a particular file, simply pass the GRIDFILE_NOMD5 value on the flag param */
669  if( !( flags & GRIDFILE_NOMD5 ) ) {
670  /* Check run md5 */
671  bson_init(command);
672  bson_append_oid(command, "filemd5", &id);
673  bson_append_string(command, "root", gfs->prefix);
674  bson_finish(command);
675  result = mongo_run_command(gfs->client, gfs->dbname, command, res);
676  bson_destroy(command);
677  if (result != MONGO_OK)
678  return result;
679  }
680 
681  /* Create and insert BSON for file metadata */
682  bson_init(ret);
683  bson_append_oid(ret, "_id", &id);
684  if (name != NULL && *name != '\0') {
685  bson_append_string_uppercase( ret, "filename", name, gfs->caseInsensitive );
686  }
687  bson_append_long(ret, "length", length);
688  bson_append_int(ret, "chunkSize", chunkSize);
689  d = (bson_date_t)1000 * time(NULL);
690  bson_append_date(ret, "uploadDate", d);
691  if( !( flags & GRIDFILE_NOMD5 ) ) {
692  if (bson_find(it, res, "md5") != BSON_EOO )
693  bson_append_string(ret, "md5", bson_iterator_string(it));
694  else
695  bson_append_string(ret, "md5", "");
696  bson_destroy(res);
697  } else {
698  bson_append_string(ret, "md5", "");
699  }
700  if (contenttype != NULL && *contenttype != '\0') {
701  bson_append_string(ret, "contentType", contenttype);
702  }
703  if ( gfs->caseInsensitive ) {
704  if (name != NULL && *name != '\0') {
705  bson_append_string(ret, "realFilename", name);
706  }
707  }
708  bson_append_int(ret, "flags", flags);
709  bson_finish(ret);
710 
711  bson_init(q);
712  bson_append_oid(q, "_id", &id);
713  bson_finish(q);
714 
715  result = mongo_update(gfs->client, gfs->files_ns, q, ret, MONGO_UPDATE_UPSERT, NULL);
716 
717  bson_destroy(ret);
718  bson_destroy(q);
719 
720  return result;
721 }
722 
723 MONGO_EXPORT int gridfs_store_buffer(gridfs *gfs, const char *data, gridfs_offset length, const char *remotename, const char *contenttype, int flags ) {
724  gridfile gfile;
725  gridfs_offset bytes_written;
726 
727  gridfile_init( gfs, NULL, &gfile );
728  gridfile_writer_init( &gfile, gfs, remotename, contenttype, flags );
729 
730  bytes_written = gridfile_write_buffer( &gfile, data, length );
731 
732  gridfile_writer_done( &gfile );
733  gridfile_destroy( &gfile );
734 
735  return bytes_written == length ? MONGO_OK : MONGO_ERROR;
736 }
737 
738 MONGO_EXPORT int gridfs_store_file(gridfs *gfs, const char *filename, const char *remotename, const char *contenttype, int flags ) {
740  FILE *fd;
741  gridfs_offset chunkLen;
742  gridfile gfile;
743  gridfs_offset bytes_written = 0;
744 
745  /* Open the file and the correct stream */
746  if (strcmp(filename, "-") == 0) {
747  fd = stdin;
748  } else {
749  fd = fopen(filename, "rb");
750  if (fd == NULL) {
751  return MONGO_ERROR;
752  }
753  }
754 
755  /* Optional Remote Name */
756  if (remotename == NULL || *remotename == '\0') {
757  remotename = filename;
758  }
759 
760  if( gridfile_init( gfs, NULL, &gfile ) != MONGO_OK ) return MONGO_ERROR;
761  if( gridfile_writer_init( &gfile, gfs, remotename, contenttype, flags ) != MONGO_OK ){
762  gridfile_destroy( &gfile );
763  return MONGO_ERROR;
764  }
765 
766  chunkLen = fread(buffer, 1, DEFAULT_CHUNK_SIZE, fd);
767  while( chunkLen != 0 ) {
768  bytes_written = gridfile_write_buffer( &gfile, buffer, chunkLen );
769  if( bytes_written != chunkLen ) break;
770  chunkLen = fread(buffer, 1, DEFAULT_CHUNK_SIZE, fd);
771  }
772 
773  gridfile_writer_done( &gfile );
774  gridfile_destroy( &gfile );
775 
776  /* Close the file stream */
777  if ( fd != stdin ) {
778  fclose( fd );
779  }
780  return ( chunkLen == 0) || ( bytes_written == chunkLen ) ? MONGO_OK : MONGO_ERROR;
781 }
782 
783 MONGO_EXPORT int gridfs_remove_filename(gridfs *gfs, const char *filename) {
784  bson query[1];
785  mongo_cursor *files;
786  bson file[1];
787  bson_iterator it[1];
788  bson_oid_t id;
789  bson b[1];
790  int ret = MONGO_ERROR;
791 
792  bson_init(query);
793  bson_append_string_uppercase( query, "filename", filename, gfs->caseInsensitive );
794  bson_finish(query);
795  files = mongo_find(gfs->client, gfs->files_ns, query, NULL, 0, 0, 0);
796  bson_destroy(query);
797 
798  /* files should be a valid cursor even if the file doesn't exist */
799  if ( files == NULL ) return MONGO_ERROR;
800 
801  /* Remove each file and it's chunks from files named filename */
802  while (mongo_cursor_next(files) == MONGO_OK) {
803  *file = files->current;
804  bson_find(it, file, "_id");
805  id = *bson_iterator_oid(it);
806 
807  /* Remove the file with the specified id */
808  bson_init(b);
809  bson_append_oid(b, "_id", &id);
810  bson_finish(b);
811  mongo_remove(gfs->client, gfs->files_ns, b, NULL);
812  bson_destroy(b);
813 
814  /* Remove all chunks from the file with the specified id */
815  bson_init(b);
816  bson_append_oid(b, "files_id", &id);
817  bson_finish(b);
818  ret = mongo_remove(gfs->client, gfs->chunks_ns, b, NULL);
819  bson_destroy(b);
820  }
821 
822  mongo_cursor_destroy(files);
823  return ret;
824 }
825 
827 
828  bson uploadDate[1];
829  bson finalQuery[1];
830  bson out[1];
831  int i;
832 
833  bson_init(uploadDate);
834  bson_append_int(uploadDate, "uploadDate", - 1);
835  bson_finish(uploadDate);
836 
837  bson_init(finalQuery);
838  bson_append_bson(finalQuery, "query", query);
839  bson_append_bson(finalQuery, "orderby", uploadDate);
840  bson_finish(finalQuery);
841 
842  i = (mongo_find_one(gfs->client, gfs->files_ns, finalQuery, NULL, out) == MONGO_OK);
843  bson_destroy(uploadDate);
844  bson_destroy(finalQuery);
845  if (!i) {
846  return MONGO_ERROR;
847  } else {
848  gridfile_init(gfs, out, gfile);
849  bson_destroy(out);
850  return MONGO_OK;
851  }
852 }
853 
854 MONGO_EXPORT int gridfs_find_filename(gridfs *gfs, const char *filename, gridfile *gfile){
855  bson query[1];
856  int res;
857 
858  bson_init(query);
859  bson_append_string_uppercase( query, "filename", filename, gfs->caseInsensitive );
860  bson_finish(query);
861  res = gridfs_find_query(gfs, query, gfile);
862  bson_destroy(query);
863  return res;
864 }
865 
866 /* ---------------- */
867 /* gridfile methods */
868 /* ---------------- */
869 
870 /* gridfile private methods forward declarations */
871 static int gridfile_flush_pendingchunk(gridfile *gfile);
872 static void gridfile_init_flags(gridfile *gfile);
873 static void gridfile_init_length(gridfile *gfile);
874 static void gridfile_init_chunkSize(gridfile *gfile);
875 
876 /* gridfile constructors, destructors and memory management */
877 
878 MONGO_EXPORT int gridfile_init( gridfs *gfs, const bson *meta, gridfile *gfile ) {
879  gfile->gfs = gfs;
880  gfile->pos = 0;
881  gfile->pending_len = 0;
882  gfile->pending_data = NULL;
883  gfile->meta = bson_alloc();
884  if (gfile->meta == NULL) {
885  return MONGO_ERROR;
886  } if( meta ) {
887  bson_copy(gfile->meta, meta);
888  } else {
889  bson_init_empty(gfile->meta);
890  }
891  gridfile_init_chunkSize( gfile );
892  gridfile_init_length( gfile );
893  gridfile_init_flags( gfile );
894  return MONGO_OK;
895 }
896 
898 
899  int response = MONGO_OK;
900 
901  if (gfile->pending_len) {
902  /* write any remaining pending chunk data.
903  * pending data will always take up less than one chunk */
904  response = gridfile_flush_pendingchunk(gfile);
905  }
906  if( gfile->pending_data ) {
907  bson_free(gfile->pending_data);
908  gfile->pending_data = NULL;
909  }
910  if( response == MONGO_OK ) {
911  /* insert into files collection */
912  response = gridfs_insert_file(gfile->gfs, gfile->remote_name, gfile->id, gfile->length, gfile->content_type, gfile->flags, gfile->chunkSize);
913  }
914  if( gfile->remote_name ) {
915  bson_free(gfile->remote_name);
916  gfile->remote_name = NULL;
917  }
918  if( gfile->content_type ) {
919  bson_free(gfile->content_type);
920  gfile->content_type = NULL;
921  }
922  return response;
923 }
924 
925 static void gridfile_init_chunkSize(gridfile *gfile){
926  bson_iterator it[1];
927 
928  if (bson_find(it, gfile->meta, "chunkSize") != BSON_EOO)
929  if (bson_iterator_type(it) == BSON_INT)
930  gfile->chunkSize = bson_iterator_int(it);
931  else
932  gfile->chunkSize = (int)bson_iterator_long(it);
933  else
934  gfile->chunkSize = DEFAULT_CHUNK_SIZE;
935 }
936 
937 static void gridfile_init_length(gridfile *gfile) {
938  bson_iterator it[1];
939 
940  if (bson_find(it, gfile->meta, "length") != BSON_EOO)
941  if (bson_iterator_type(it) == BSON_INT)
942  gfile->length = (gridfs_offset)bson_iterator_int(it);
943  else
944  gfile->length = (gridfs_offset)bson_iterator_long(it);
945  else
946  gfile->length = 0;
947 }
948 
949 static void gridfile_init_flags(gridfile *gfile) {
950  bson_iterator it[1];
951 
952  if( bson_find(it, gfile->meta, "flags") != BSON_EOO )
953  gfile->flags = bson_iterator_int(it);
954  else
955  gfile->flags = 0;
956 }
957 
958 MONGO_EXPORT int gridfile_writer_init(gridfile *gfile, gridfs *gfs, const char *remote_name, const char *content_type, int flags ) {
959  gridfile tmpFile;
960 
961  gfile->gfs = gfs;
962  if (gridfs_find_filename(gfs, remote_name, &tmpFile) == MONGO_OK) {
963  if( gridfile_exists(&tmpFile) ) {
964  /* If file exists, then let's initialize members dedicated to coordinate writing operations
965  with existing file metadata */
966  gfile->id = gridfile_get_id( &tmpFile );
967  gridfile_init_length( &tmpFile );
968  gfile->length = tmpFile.length;
969  gfile->chunkSize = gridfile_get_chunksize( gfile );
970  if( flags != GRIDFILE_DEFAULT) {
971  gfile->flags = flags;
972  } else {
973  gridfile_init_flags( &tmpFile );
974  gfile->flags = tmpFile.flags;
975  }
976  }
977  gridfile_destroy( &tmpFile );
978  } else {
979  /* File doesn't exist, let's create a new bson id and initialize length to zero */
980  bson_oid_gen(&(gfile->id));
981  gfile->length = 0;
982  /* File doesn't exist, lets use the flags passed as a parameter to this procedure call */
983  gfile->flags = flags;
984  }
985 
986  /* We initialize chunk_num with zero, but it will get always calculated when calling
987  gridfile_load_pending_data_with_pos_chunk() or when calling gridfile_write_buffer() */
988  gfile->chunk_num = 0;
989  gfile->pos = 0;
990 
991  gfile->remote_name = (char*)bson_malloc((int)strlen(remote_name) + 1);
992  strcpy((char*)gfile->remote_name, remote_name);
993 
994  gfile->content_type = (char*)bson_malloc((int)strlen(content_type) + 1);
995  strcpy((char*)gfile->content_type, content_type);
996 
997  gfile->pending_len = 0;
998  /* Let's pre-allocate DEFAULT_CHUNK_SIZE bytes into pending_data then we don't need to worry
999  about doing realloc everywhere we want use the pending_data buffer */
1000  gfile->pending_data = (char*) bson_malloc((int)gridfs_pending_data_size(gfile->flags));
1001 
1002  return MONGO_OK;
1003 }
1004 
1006  if( gfile->meta ) {
1007  bson_destroy(gfile->meta);
1008  bson_dealloc(gfile->meta);
1009  gfile->meta = NULL;
1010  }
1011 }
1012 
1013 /* gridfile accessors */
1014 
1016  bson_iterator it[1];
1017 
1018  if (bson_find(it, gfile->meta, "_id") != BSON_EOO)
1019  if (bson_iterator_type(it) == BSON_OID)
1020  return *bson_iterator_oid(it);
1021  else
1022  return gfile->id;
1023  else
1024  return gfile->id;
1025 }
1026 
1028  /* File exists if gfile and gfile->meta BOTH are != NULL */
1029  return (bson_bool_t)(gfile != NULL && gfile->meta != NULL);
1030 }
1031 
1032 MONGO_EXPORT const char *gridfile_get_filename( const gridfile *gfile ) {
1033  bson_iterator it[1];
1034 
1035  if (gfile->gfs->caseInsensitive && bson_find( it, gfile->meta, "realFilename" ) != BSON_EOO)
1036  return bson_iterator_string(it);
1037  if (bson_find(it, gfile->meta, "filename") != BSON_EOO)
1038  return bson_iterator_string(it);
1039  else
1040  return gfile->remote_name;
1041 }
1042 
1044  bson_iterator it[1];
1045 
1046  if (gfile->chunkSize)
1047  return gfile->chunkSize;
1048  else if (bson_find(it, gfile->meta, "chunkSize") != BSON_EOO)
1049  return bson_iterator_int(it);
1050  else
1051  return DEFAULT_CHUNK_SIZE;
1052 }
1053 
1055  gridfs_offset estimatedLen;
1056  estimatedLen = gfile->pending_len ? gfile->chunk_num * gridfile_get_chunksize( gfile ) + gfile->pending_len : gfile->length;
1057  return MAX( estimatedLen, gfile->length );
1058 }
1059 
1060 MONGO_EXPORT const char *gridfile_get_contenttype( const gridfile *gfile ) {
1061  bson_iterator it[1];
1062 
1063  if ( bson_find(it, gfile->meta, "contentType") != BSON_EOO )
1064  return bson_iterator_string(it);
1065  else
1066  return NULL;
1067 }
1068 
1070  bson_iterator it[1];
1071 
1072  if (bson_find(it, gfile->meta, "uploadDate") != BSON_EOO)
1073  return bson_iterator_date(it);
1074  else
1075  return 0;
1076 }
1077 
1078 MONGO_EXPORT const char *gridfile_get_md5( const gridfile *gfile ) {
1079  bson_iterator it[1];
1080 
1081  if (bson_find(it, gfile->meta, "md5") != BSON_EOO )
1082  return bson_iterator_string(it);
1083  else
1084  return NULL;
1085 }
1086 
1088  gfile->flags = flags;
1089 }
1090 
1092  return gfile->flags;
1093 }
1094 
1095 MONGO_EXPORT const char *gridfile_get_field(gridfile *gfile, const char *name) {
1096  bson_iterator it[1];
1097 
1098  if (bson_find(it, gfile->meta, name) != BSON_EOO)
1099  return bson_iterator_value(it);
1100  else
1101  return NULL;
1102 }
1103 
1105  bson_iterator it[1];
1106 
1107  if (bson_find(it, gfile->meta, name) != BSON_EOO)
1108  return bson_iterator_bool(it);
1109  else
1110  return 0;
1111 }
1112 
1114  bson_iterator it[1];
1115 
1116  if (bson_find(it, gfile->meta, "metadata") != BSON_EOO)
1117  bson_iterator_subobject_init(it, out, copyData);
1118  else
1119  bson_init_empty(out);
1120 }
1121 
1122 /* ++++++++++++++++++++++++++++++++ */
1123 /* gridfile data management methods */
1124 /* ++++++++++++++++++++++++++++++++ */
1125 
1127  bson_iterator it[1];
1128  gridfs_offset length;
1129  gridfs_offset chunkSize;
1130  double numchunks;
1131 
1132  if (bson_find(it, gfile->meta, "length") != BSON_EOO)
1133  if (bson_iterator_type(it) == BSON_INT)
1134  length = (gridfs_offset)bson_iterator_int(it);
1135  else
1136  length = (gridfs_offset)bson_iterator_long(it);
1137  else
1138  length = 0;
1139 
1140  if (bson_find(it, gfile->meta, "chunkSize") != BSON_EOO)
1141  if (bson_iterator_type(it) == BSON_INT)
1142  chunkSize = bson_iterator_int(it);
1143  else
1144  chunkSize = (int)bson_iterator_long(it);
1145  else
1146  chunkSize = DEFAULT_CHUNK_SIZE;
1147 
1148  numchunks = ((double)length / (double)chunkSize);
1149  return (numchunks - (int)numchunks > 0) ? (int)(numchunks + 1): (int)(numchunks);
1150 }
1151 
1152 static void gridfile_prepare_chunk_key_bson(bson *q, bson_oid_t *id, int chunk_num) {
1153  bson_init(q);
1154  bson_append_int(q, "n", chunk_num);
1155  bson_append_oid(q, "files_id", id);
1156  bson_finish(q);
1157 }
1158 
1160  bson *oChunk;
1161  bson q[1];
1162  char* targetBuf = NULL;
1163  int res = MONGO_OK;
1164 
1165  if (gfile->pending_len) {
1166  size_t finish_position_after_flush;
1167  oChunk = chunk_new( gfile->id, gfile->chunk_num, &targetBuf, gfile->pending_data, gfile->pending_len, gfile->flags );
1168  gridfile_prepare_chunk_key_bson( q, &gfile->id, gfile->chunk_num );
1169  res = mongo_update(gfile->gfs->client, gfile->gfs->chunks_ns, q, oChunk, MONGO_UPDATE_UPSERT, NULL);
1170  bson_destroy(q);
1171  chunk_free(oChunk);
1172  if( res == MONGO_OK ){
1173  finish_position_after_flush = (gfile->chunk_num * gfile->chunkSize) + gfile->pending_len;
1174  if (finish_position_after_flush > gfile->length)
1175  gfile->length = finish_position_after_flush;
1176  gfile->chunk_num++;
1177  gfile->pending_len = 0;
1178  }
1179  }
1180  if (targetBuf && targetBuf != gfile->pending_data)
1181  bson_free( targetBuf );
1182  return res;
1183 }
1184 
1186  int chunk_len;
1187  const char *chunk_data;
1188  bson_iterator it[1];
1189  bson chk;
1190  char* targetBuffer = NULL;
1191  size_t targetBufferLen = 0;
1192 
1193  chk.dataSize = 0;
1194  gridfile_get_chunk(gfile, (int)(gfile->pos / DEFAULT_CHUNK_SIZE), &chk);
1195  if (chk.dataSize <= 5) {
1196  if( chk.data ) {
1197  bson_destroy( &chk );
1198  }
1199  return MONGO_ERROR;
1200  }
1201  if( bson_find(it, &chk, "data") != BSON_EOO){
1202  chunk_len = bson_iterator_bin_len(it);
1203  chunk_data = bson_iterator_bin_data(it);
1204  gridfs_read_filter( &targetBuffer, &targetBufferLen, chunk_data, (size_t)chunk_len, gfile->flags );
1205  gfile->pending_len = (int)targetBufferLen;
1206  gfile->chunk_num = (int)(gfile->pos / DEFAULT_CHUNK_SIZE);
1207  if( targetBufferLen ) {
1208  memcpy(gfile->pending_data, targetBuffer, targetBufferLen);
1209  }
1210  } else {
1211  bson_destroy( &chk );
1212  return MONGO_ERROR;
1213  }
1214  bson_destroy( &chk );
1215  if( targetBuffer && targetBuffer != chunk_data )
1216  bson_free( targetBuffer );
1217  return MONGO_OK;
1218 }
1219 
1221 
1222  bson *oChunk;
1223  bson q[1];
1224  size_t buf_pos, buf_bytes_to_write;
1225  gridfs_offset bytes_left = length;
1226  char* targetBuf = NULL;
1227  int memAllocated = 0;
1228 
1229  gfile->chunk_num = (int)(gfile->pos / DEFAULT_CHUNK_SIZE);
1230  buf_pos = (int)(gfile->pos - (gfile->pos / DEFAULT_CHUNK_SIZE) * DEFAULT_CHUNK_SIZE);
1231  /* First let's see if our current position is an an offset > 0 from the beginning of the current chunk.
1232  If so, then we need to preload current chunk and merge the data into it using the pending_data field
1233  of the gridfile gfile object. We will flush the data if we fill in the chunk */
1234  if( buf_pos ) {
1235  if( !gfile->pending_len && gridfile_load_pending_data_with_pos_chunk( gfile ) != MONGO_OK ) return 0;
1236  buf_bytes_to_write = (size_t)MIN( length, DEFAULT_CHUNK_SIZE - buf_pos );
1237  memcpy( &gfile->pending_data[buf_pos], data, buf_bytes_to_write);
1238  if ( buf_bytes_to_write + buf_pos > gfile->pending_len ) {
1239  gfile->pending_len = buf_bytes_to_write + buf_pos;
1240  }
1241  gfile->pos += buf_bytes_to_write;
1242  if( buf_bytes_to_write + buf_pos >= DEFAULT_CHUNK_SIZE && gridfile_flush_pendingchunk(gfile) != MONGO_OK ) return 0;
1243  bytes_left -= buf_bytes_to_write;
1244  data += buf_bytes_to_write;
1245  }
1246 
1247  /* If there's still more data to be written and they happen to be full chunks, we will loop thru and
1248  write all full chunks without the need for preloading the existing chunk */
1249  while( bytes_left >= DEFAULT_CHUNK_SIZE ) {
1250  int res;
1251  if( (oChunk = chunk_new( gfile->id, gfile->chunk_num, &targetBuf, data, DEFAULT_CHUNK_SIZE, gfile->flags )) == NULL) return length - bytes_left;
1252  memAllocated = targetBuf != data;
1253  gridfile_prepare_chunk_key_bson(q, &gfile->id, gfile->chunk_num);
1254  res = mongo_update(gfile->gfs->client, gfile->gfs->chunks_ns, q, oChunk, MONGO_UPDATE_UPSERT, NULL);
1255  bson_destroy(q );
1256  chunk_free(oChunk);
1257  if( res != MONGO_OK ) return length - bytes_left;
1258  bytes_left -= DEFAULT_CHUNK_SIZE;
1259  gfile->chunk_num++;
1260  gfile->pos += DEFAULT_CHUNK_SIZE;
1261  if (gfile->pos > gfile->length) {
1262  gfile->length = gfile->pos;
1263  }
1264  data += DEFAULT_CHUNK_SIZE;
1265  }
1266 
1267  /* Finally, if there's still remaining bytes left to write, we will preload the current chunk and merge the
1268  remaining bytes into pending_data buffer */
1269  if ( bytes_left > 0 ) {
1270  /* Let's preload the chunk we are writing IF the current chunk is not already in memory
1271  AND if after writing the remaining buffer there's should be trailing data that we don't
1272  want to loose */
1273  if( !gfile->pending_len && gfile->pos + bytes_left < gfile->length && gridfile_load_pending_data_with_pos_chunk( gfile ) != MONGO_OK )
1274  return length - bytes_left;
1275  memcpy( gfile->pending_data, data, (size_t) bytes_left );
1276  if( bytes_left > gfile->pending_len )
1277  gfile->pending_len = (int) bytes_left;
1278  gfile->pos += bytes_left;
1279  }
1280 
1281  if( memAllocated ){
1282  bson_free( targetBuf );
1283  }
1284  return length;
1285 }
1286 
1288  bson query[1];
1289 
1290  bson_oid_t id;
1291  int result;
1292 
1293  bson_init(query);
1294  id = gridfile_get_id( gfile );
1295  bson_append_oid(query, "files_id", &id);
1296  bson_append_int(query, "n", n);
1297  bson_finish(query);
1298 
1299  result = (mongo_find_one(gfile->gfs->client, gfile->gfs->chunks_ns, query, NULL, out) == MONGO_OK);
1300  bson_destroy(query);
1301  if (!result)
1302  bson_copy(out, bson_shared_empty());
1303 }
1304 
1306  bson_iterator it[1];
1307  bson_oid_t id;
1308  bson gte[1];
1309  bson query[1];
1310  bson orderby[1];
1311  bson command[1];
1312  mongo_cursor *cursor;
1313 
1314  if( bson_find(it, gfile->meta, "_id") != BSON_EOO)
1315  id = *bson_iterator_oid(it);
1316  else
1317  id = gfile->id;
1318 
1319  bson_init(query);
1320  bson_append_oid(query, "files_id", &id);
1321  if (size == 1) {
1322  bson_append_int(query, "n", (int)start);
1323  } else {
1324  bson_init(gte);
1325  bson_append_int(gte, "$gte", (int)start);
1326  bson_finish(gte);
1327  bson_append_bson(query, "n", gte);
1328  bson_destroy(gte);
1329  }
1330  bson_finish(query);
1331 
1332  bson_init(orderby);
1333  bson_append_int(orderby, "n", 1);
1334  bson_finish(orderby);
1335 
1336  bson_init(command);
1337  bson_append_bson(command, "query", query);
1338  bson_append_bson(command, "orderby", orderby);
1339  bson_finish(command);
1340 
1341  cursor = mongo_find(gfile->gfs->client, gfile->gfs->chunks_ns, command, NULL, (int)size, 0, 0);
1342 
1343  bson_destroy(command);
1344  bson_destroy(query);
1345  bson_destroy(orderby);
1346 
1347  return cursor;
1348 }
1349 
1350 static gridfs_offset gridfile_read_from_pending_buffer(gridfile *gfile, gridfs_offset totalBytesToRead, char* buf, int *first_chunk);
1351 static gridfs_offset gridfile_load_from_chunks(gridfile *gfile, int total_chunks, gridfs_offset chunksize, mongo_cursor *chunks, char* buf,
1352  gridfs_offset bytes_left);
1353 
1355  mongo_cursor *chunks;
1356 
1357  int first_chunk;
1358  int total_chunks;
1359  gridfs_offset chunksize;
1360  gridfs_offset contentlength;
1361  gridfs_offset bytes_left;
1362  gridfs_offset realSize = 0;
1363 
1364  contentlength = gridfile_get_contentlength(gfile);
1365  chunksize = gridfile_get_chunksize(gfile);
1366  size = MIN( contentlength - gfile->pos, size );
1367  bytes_left = size;
1368 
1369  first_chunk = (int)((gfile->pos) / chunksize);
1370  total_chunks = (int)((gfile->pos + size - 1) / chunksize) - first_chunk + 1;
1371 
1372  if( (realSize = gridfile_read_from_pending_buffer( gfile, bytes_left, buf, &first_chunk )) > 0 ) {
1373  gfile->pos += realSize;
1374  if( --total_chunks <= 0) {
1375  return realSize;
1376  }
1377  buf += realSize;
1378  bytes_left -= realSize;
1379  if( gridfile_flush_pendingchunk( gfile ) != MONGO_OK ){
1380  /* Let's abort the read operation here because we could not flush the buffer */
1381  return realSize;
1382  }
1383  };
1384 
1385  chunks = gridfile_get_chunks(gfile, first_chunk, total_chunks);
1386  realSize += gridfile_load_from_chunks( gfile, total_chunks, chunksize, chunks, buf, bytes_left);
1387  mongo_cursor_destroy(chunks);
1388 
1389  gfile->pos += realSize;
1390 
1391  return realSize;
1392 }
1393 
1394 static gridfs_offset gridfile_read_from_pending_buffer(gridfile *gfile, gridfs_offset totalBytesToRead, char* buf,
1395  int *first_chunk){
1396  gridfs_offset realSize = 0;
1397  if( gfile->pending_len > 0 && *first_chunk == gfile->chunk_num) {
1398  char *chunk_data;
1399  gridfs_offset chunksize = gridfile_get_chunksize(gfile);
1400  gridfs_offset ofs = gfile->pos - gfile->chunk_num * chunksize;
1401  realSize = MIN( totalBytesToRead, gfile->pending_len - ofs );
1402  chunk_data = gfile->pending_data + ofs;
1403  memcpy( buf, chunk_data, (size_t)realSize );
1404  (*first_chunk)++;
1405  };
1406  return realSize;
1407 }
1408 
1409 static gridfs_offset gridfile_fill_buf_from_chunk(gridfile *gfile, const bson *chunk, gridfs_offset chunksize, char **buf, int *allocatedMem, char **targetBuf,
1410  size_t *targetBufLen, gridfs_offset *bytes_left, int chunkNo);
1411 
1412 static gridfs_offset gridfile_load_from_chunks(gridfile *gfile, int total_chunks, gridfs_offset chunksize, mongo_cursor *chunks, char* buf,
1413  gridfs_offset bytes_left){
1414  int i;
1415  char* targetBuf = NULL;
1416  size_t targetBufLen = 0;
1417  int allocatedMem = 0;
1418  gridfs_offset realSize = 0;
1419 
1420  for (i = 0; i < total_chunks; i++) {
1421  if( mongo_cursor_next(chunks) != MONGO_OK ){
1422  break;
1423  }
1424  realSize += gridfile_fill_buf_from_chunk( gfile, &chunks->current, chunksize, &buf, &allocatedMem, &targetBuf, &targetBufLen, &bytes_left, i);
1425  }
1426  if( allocatedMem ) {
1427  bson_free( targetBuf );
1428  }
1429  return realSize;
1430 }
1431 
1432 static gridfs_offset gridfile_fill_buf_from_chunk(gridfile *gfile, const bson *chunk, gridfs_offset chunksize, char **buf, int *allocatedMem, char **targetBuf,
1433  size_t *targetBufLen, gridfs_offset *bytes_left, int chunkNo){
1434  bson_iterator it[1];
1435  gridfs_offset chunk_len;
1436  const char *chunk_data;
1437 
1438  if( bson_find(it, chunk, "data") != BSON_EOO ) {
1439  chunk_len = bson_iterator_bin_len(it);
1440  chunk_data = bson_iterator_bin_data(it);
1441  if( gridfs_read_filter( targetBuf, targetBufLen, chunk_data, (size_t)chunk_len, gfile->flags ) != 0) return 0;
1442  *allocatedMem = *targetBuf != chunk_data;
1443  chunk_data = *targetBuf;
1444  if (chunkNo == 0) {
1445  chunk_data += (gfile->pos) % chunksize;
1446  *targetBufLen -= (size_t)( (gfile->pos) % chunksize );
1447  }
1448  if (*bytes_left > *targetBufLen) {
1449  memcpy(*buf, chunk_data, *targetBufLen);
1450  *bytes_left -= *targetBufLen;
1451  *buf += *targetBufLen;
1452  return *targetBufLen;
1453  } else {
1454  memcpy(*buf, chunk_data, (size_t)(*bytes_left));
1455  return *bytes_left;
1456  }
1457  } else {
1458  bson_fatal_msg( 0, "Chunk object doesn't have 'data' attribute" );
1459  return 0;
1460  }
1461 }
1462 
1464  gridfs_offset length;
1465  gridfs_offset chunkSize;
1466  gridfs_offset newPos;
1467 
1468  chunkSize = gridfile_get_chunksize( gfile );
1469  length = gridfile_get_contentlength( gfile );
1470  newPos = MIN( length, offset );
1471 
1472  /* If we are seeking to the next chunk or prior to the current chunks let's flush the pending chunk */
1473  if (gfile->pending_len && (newPos >= (gfile->chunk_num + 1) * chunkSize || newPos < gfile->chunk_num * chunkSize) &&
1474  gridfile_flush_pendingchunk( gfile ) != MONGO_OK ) return gfile->pos;
1475  gfile->pos = newPos;
1476  return newPos;
1477 }
1478 
1480  char buffer[DEFAULT_CHUNK_SIZE];
1481  size_t data_read, data_written = 0;
1482  gridfs_offset total_written = 0;
1483 
1484  do {
1485  data_read = (size_t)gridfile_read_buffer( gfile, buffer, DEFAULT_CHUNK_SIZE );
1486  if( data_read > 0 ){
1487  data_written = fwrite( buffer, sizeof(char), data_read, stream );
1488  total_written += data_written;
1489  }
1490  } while(( data_read > 0 ) && ( data_written == data_read ));
1491 
1492  return total_written;
1493 }
1494 
1495 static int gridfile_remove_chunks( gridfile *gfile, int deleteFromChunk){
1496  bson q[1];
1497  bson_oid_t id = gridfile_get_id( gfile );
1498  int res;
1499 
1500  bson_init( q );
1501  bson_append_oid(q, "files_id", &id);
1502  if( deleteFromChunk >= 0 ) {
1503  bson_append_start_object( q, "n" );
1504  bson_append_int( q, "$gte", deleteFromChunk );
1505  bson_append_finish_object( q );
1506  }
1507  bson_finish( q );
1508  res = mongo_remove( gfile->gfs->client, gfile->gfs->chunks_ns, q, NULL);
1509  bson_destroy( q );
1510  return res;
1511 }
1512 
1514 
1515  int deleteFromChunk;
1516 
1517  if ( newSize > gridfile_get_contentlength( gfile ) ) {
1518  return gridfile_seek( gfile, gridfile_get_contentlength( gfile ) );
1519  }
1520  if( newSize > 0 ) {
1521  deleteFromChunk = (int)(newSize / gridfile_get_chunksize( gfile ));
1522  if( gridfile_seek(gfile, newSize) != newSize ) return gfile->length;
1523  if( gfile->pos % gridfile_get_chunksize( gfile ) ) {
1524  if( !gfile->pending_len && gridfile_load_pending_data_with_pos_chunk( gfile ) != MONGO_OK ) return gfile->length;
1525  gfile->pending_len = gfile->pos % gridfile_get_chunksize( gfile ); /* This will truncate the preloaded chunk */
1526  if( gridfile_flush_pendingchunk( gfile ) != MONGO_OK ) return gfile->length;
1527  deleteFromChunk++;
1528  }
1529  /* Now let's remove the trailing chunks resulting from truncation */
1530  if( gridfile_remove_chunks( gfile, deleteFromChunk ) != MONGO_OK ) return gfile->length;
1531  gfile->length = newSize;
1532  } else {
1533  /* Expected file size is zero. We will remove ALL chunks */
1534  if( gridfile_remove_chunks( gfile, -1 ) != MONGO_OK) return gfile->length;
1535  gfile->length = 0;
1536  gfile->pos = 0;
1537  }
1538  return gfile->length;
1539 }
1540 
1542  gridfs_offset fileSize, newSize, curPos, toWrite, bufSize;
1543 
1544  char* buf;
1545 
1546  fileSize = gridfile_get_contentlength( gfile );
1547  newSize = fileSize + bytesToExpand;
1548  curPos = fileSize;
1549  bufSize = gridfile_get_chunksize ( gfile );
1550  buf = (char*)bson_malloc( (size_t)bufSize );
1551 
1552  memset( buf, 0, (size_t)bufSize );
1553  gridfile_seek( gfile, fileSize );
1554 
1555  while( curPos < newSize ) {
1556  toWrite = bufSize - curPos % bufSize;
1557  if( toWrite + curPos > newSize ) {
1558  toWrite = newSize - curPos;
1559  }
1560  /* If driver doesn't write all data request, we will cancel expansion and return how far we got... */
1561  if( gridfile_write_buffer( gfile, (const char*)buf, toWrite ) != toWrite) return curPos;
1562  curPos += toWrite;
1563  }
1564 
1565  bson_free( buf );
1566  return newSize;
1567 }
1568 
1570  gridfs_offset fileSize;
1571 
1572  fileSize = gridfile_get_contentlength( gfile );
1573  if( newSize <= fileSize ) {
1574  return gridfile_truncate( gfile, newSize );
1575  } else {
1576  return gridfile_expand( gfile, newSize - fileSize );
1577  }
1578 }
1579 
1580 /*==============================================================*/
1581 /* --- env.h */
1582 #define INVALID_SOCKET (-1)
1583 
1584 /*==============================================================*/
1585 /* --- env.c */
1586 
1587 #ifndef NI_MAXSERV
1588 # define NI_MAXSERV 32
1589 #endif
1590 
1592  return close( socket );
1593 }
1594 
1595 static int mongo_env_sock_init( void ) {
1596  return 0;
1597 }
1598 
1599 static int mongo_env_write_socket( mongo *conn, const void *buf, size_t len ) {
1600  const char *cbuf = buf;
1601 #ifdef __APPLE__
1602  int flags = 0;
1603 #else
1604  int flags = MSG_NOSIGNAL;
1605 #endif
1606 
1607  while ( len ) {
1608  ssize_t sent = send( conn->sock, cbuf, len, flags );
1609  if ( sent == -1 ) {
1610  if (errno == EPIPE)
1611  conn->connected = 0;
1612  __mongo_set_error( conn, MONGO_IO_ERROR, strerror( errno ), errno );
1613  return MONGO_ERROR;
1614  }
1615  cbuf += sent;
1616  len -= sent;
1617  }
1618 
1619  return MONGO_OK;
1620 }
1621 
1622 static int mongo_env_read_socket( mongo *conn, void *buf, size_t len ) {
1623  char *cbuf = buf;
1624  while ( len ) {
1625  ssize_t sent = recv( conn->sock, cbuf, len, 0 );
1626  if ( sent == 0 || sent == -1 ) {
1627  __mongo_set_error( conn, MONGO_IO_ERROR, strerror( errno ), errno );
1628  return MONGO_ERROR;
1629  }
1630  cbuf += sent;
1631  len -= sent;
1632  }
1633 
1634  return MONGO_OK;
1635 }
1636 
1638  struct timeval tv;
1639  tv.tv_sec = millis / 1000;
1640  tv.tv_usec = ( millis % 1000 ) * 1000;
1641 
1642  if ( setsockopt( conn->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof( tv ) ) == -1 ) {
1643  conn->err = MONGO_IO_ERROR;
1644  __mongo_set_error( conn, MONGO_IO_ERROR, "setsockopt SO_RCVTIMEO failed.", errno );
1645  return MONGO_ERROR;
1646  }
1647 
1648  if ( setsockopt( conn->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof( tv ) ) == -1 ) {
1649  __mongo_set_error( conn, MONGO_IO_ERROR, "setsockopt SO_SNDTIMEO failed.", errno );
1650  return MONGO_ERROR;
1651  }
1652 
1653  return MONGO_OK;
1654 }
1655 
1656 static int mongo_env_unix_socket_connect( mongo *conn, const char *sock_path ) {
1657  struct sockaddr_un addr = {};
1658  int status, len;
1659 
1660  conn->connected = 0;
1661 
1662  conn->sock = socket( AF_UNIX, SOCK_STREAM, 0 );
1663 
1664  if ( conn->sock == INVALID_SOCKET ) {
1665  return MONGO_ERROR;
1666  }
1667 
1668  addr.sun_family = AF_UNIX;
1669  strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) - 1 );
1670  len = sizeof( addr );
1671 
1672  status = connect( conn->sock, (struct sockaddr *) &addr, len );
1673  if( status < 0 ) {
1674  mongo_env_close_socket( conn->sock );
1675  conn->sock = 0;
1676  conn->err = MONGO_CONN_FAIL;
1677  return MONGO_ERROR;
1678  }
1679 
1680  conn->connected = 1;
1681 
1682  return MONGO_OK;
1683 }
1684 
1685 static int mongo_env_socket_connect( mongo *conn, const char *host, int port ) {
1686  char port_str[NI_MAXSERV];
1687  int status;
1688 
1689  struct addrinfo ai_hints;
1690  struct addrinfo *ai_list = NULL;
1691  struct addrinfo *ai_ptr = NULL;
1692 
1693  if ( port < 0 ) {
1694  return mongo_env_unix_socket_connect( conn, host );
1695  }
1696 
1697  conn->sock = 0;
1698  conn->connected = 0;
1699  sprintf(port_str,"%d",port);
1700 
1701  bson_sprintf( port_str, "%d", port );
1702 
1703  memset( &ai_hints, 0, sizeof( ai_hints ) );
1704 #ifdef AI_ADDRCONFIG
1705  ai_hints.ai_flags = AI_ADDRCONFIG;
1706 #endif
1707  ai_hints.ai_family = AF_UNSPEC;
1708  ai_hints.ai_socktype = SOCK_STREAM;
1709 
1710  status = getaddrinfo( host, port_str, &ai_hints, &ai_list );
1711  if ( status != 0 ) {
1712  bson_errprintf( "getaddrinfo failed: %s", gai_strerror( status ) );
1713  conn->err = MONGO_CONN_ADDR_FAIL;
1714  return MONGO_ERROR;
1715  }
1716 
1717  for ( ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) {
1718  conn->sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
1719  if ( conn->sock == INVALID_SOCKET ) {
1720  continue;
1721  }
1722 
1723  status = connect( conn->sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen );
1724  if ( status != 0 ) {
1725  mongo_env_close_socket( conn->sock );
1726  conn->sock = 0;
1727  continue;
1728  }
1729 #if __APPLE__
1730  {
1731  int flag = 1;
1732  if ( setsockopt( conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
1733  ( void * ) &flag, sizeof( flag ) ) == -1 ) {
1734  conn->err = MONGO_IO_ERROR;
1735  __mongo_set_error( conn, MONGO_IO_ERROR, "setsockopt SO_NOSIGPIPE failed.", errno );
1736  return MONGO_ERROR;
1737  }
1738  }
1739 #endif
1740 
1741  if ( ai_ptr->ai_protocol == IPPROTO_TCP ) {
1742  int flag = 1;
1743  if ( setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY,
1744  ( void * ) &flag, sizeof( flag ) ) == -1 ) {
1745  conn->err = MONGO_IO_ERROR;
1746  __mongo_set_error( conn, MONGO_IO_ERROR, "setsockopt SO_NOSIGPIPE failed.", errno );
1747  return MONGO_ERROR;
1748  }
1749  if ( conn->op_timeout_ms > 0 )
1751  }
1752 
1753  conn->connected = 1;
1754  break;
1755  }
1756 
1757  freeaddrinfo( ai_list );
1758 
1759  if ( ! conn->connected ) {
1760  conn->err = MONGO_CONN_FAIL;
1761  return MONGO_ERROR;
1762  }
1763 
1764  return MONGO_OK;
1765 }
1766 
1767 /*==============================================================*/
1768 /* --- mongo.c */
1769 
1771  return ( mongo* )bson_malloc( sizeof( mongo ) );
1772 }
1773 
1774 
1776  bson_free( conn );
1777 }
1778 
1780  return conn->err;
1781 }
1782 
1783 
1785  return conn->connected != 0;
1786 }
1787 
1788 
1790  return conn->op_timeout_ms;
1791 }
1792 
1793 
1794 static const char* _get_host_port(mongo_host_port* hp) {
1795  static char _hp[sizeof(hp->host)+12];
1796  bson_sprintf(_hp, "%s:%d", hp->host, hp->port);
1797  return _hp;
1798 }
1799 
1800 
1802  mongo* conn_ = (mongo*)conn;
1803  if( !(conn_->connected) || (conn_->primary->host[0] == '\0') )
1804  return NULL;
1805  return _get_host_port(conn_->primary);
1806 }
1807 
1808 
1810  mongo* conn_ = (mongo*)conn;
1811  return conn_->sock;
1812 }
1813 
1814 
1816  mongo_replica_set* r = conn->replica_set;
1817  mongo_host_port* hp;
1818  int count = 0;
1819  if (!r) return 0;
1820  for (hp = r->hosts; hp; hp = hp->next)
1821  ++count;
1822  return count;
1823 }
1824 
1825 
1827  mongo_replica_set* r = conn->replica_set;
1828  mongo_host_port* hp;
1829  int count = 0;
1830  if (!r) return 0;
1831  for (hp = r->hosts; hp; hp = hp->next) {
1832  if (count == i)
1833  return _get_host_port(hp);
1834  ++count;
1835  }
1836  return 0;
1837 }
1838 
1840  return ( mongo_write_concern* )bson_malloc( sizeof( mongo_write_concern ) );
1841 }
1842 
1843 
1845  bson_free( write_concern );
1846 }
1847 
1848 
1850  return ( mongo_cursor* )bson_malloc( sizeof( mongo_cursor ) );
1851 }
1852 
1853 
1855  bson_free( cursor );
1856 }
1857 
1858 
1860  return conn->lasterrcode;
1861 }
1862 
1863 
1865  return conn->lasterrstr;
1866 }
1867 
1869  int errcode ) {
1870  size_t str_size = 1;
1871  conn->err = err;
1872  conn->errcode = errcode;
1873  if( str ) {
1874  str_size = strlen( str ) + 1;
1875  if (str_size > MONGO_ERR_LEN) str_size = MONGO_ERR_LEN;
1876  memcpy( conn->errstr, str, str_size );
1877  }
1878  conn->errstr[str_size-1] = '\0';
1879 }
1880 
1882  conn->err = MONGO_CONN_SUCCESS;
1883  conn->errcode = 0;
1884  conn->lasterrcode = 0;
1885  conn->errstr[0] = 0;
1886  conn->lasterrstr[0] = 0;
1887 }
1888 
1889 /* Note: this function returns a char* which must be freed. */
1890 static char *mongo_ns_to_cmd_db( const char *ns ) {
1891  char *current = NULL;
1892  char *cmd_db_name = NULL;
1893  int len = 0;
1894 
1895  for( current = (char *)ns; *current != '.'; current++ ) {
1896  len++;
1897  }
1898 
1899  cmd_db_name = (char *)bson_malloc( len + 6 );
1900  strncpy( cmd_db_name, ns, len );
1901  strncpy( cmd_db_name + len, ".$cmd", 6 );
1902 
1903  return cmd_db_name;
1904 }
1905 
1907  char *last = NULL;
1908  char *current = NULL;
1909  const char *db_name = ns;
1910  char *collection_name = NULL;
1911  char errmsg[64];
1912  int ns_len = 0;
1913 
1914  /* If the first character is a '.', fail. */
1915  if( *ns == '.' ) {
1916  __mongo_set_error( conn, MONGO_NS_INVALID, "ns cannot start with a '.'.", 0 );
1917  return MONGO_ERROR;
1918  }
1919 
1920  /* Find the division between database and collection names. */
1921  for( current = (char *)ns; *current != '\0'; current++ ) {
1922  if( *current == '.' ) {
1923  current++;
1924  break;
1925  }
1926  }
1927 
1928  /* Fail if the collection part starts with a dot. */
1929  if( *current == '.' ) {
1930  __mongo_set_error( conn, MONGO_NS_INVALID, "ns cannot start with a '.'.", 0 );
1931  return MONGO_ERROR;
1932  }
1933 
1934  /* Fail if collection length is 0.
1935  * or the ns doesn't contain a '.'. */
1936  if( *current == '\0' ) {
1937  __mongo_set_error( conn, MONGO_NS_INVALID, "Collection name missing.", 0 );
1938  return MONGO_ERROR;
1939  }
1940 
1941 
1942  /* Point to the beginning of the collection name. */
1943  collection_name = current;
1944 
1945  /* Ensure that the database name is greater than one char.*/
1946  if( collection_name - 1 == db_name ) {
1947  __mongo_set_error( conn, MONGO_NS_INVALID, "Database name missing.", 0 );
1948  return MONGO_ERROR;
1949  }
1950 
1951  /* Go back and validate the database name. */
1952  for( current = (char *)db_name; *current != '.'; current++ ) {
1953  switch( *current ) {
1954  case ' ':
1955  case '$':
1956  case '/':
1957  case '\\':
1959  "Database name may not contain ' ', '$', '/', or '\\'", 0 );
1960  return MONGO_ERROR;
1961  default:
1962  break;
1963  }
1964 
1965  ns_len++;
1966  }
1967 
1968  /* Add one to the length for the '.' character. */
1969  ns_len++;
1970 
1971  /* Now validate the collection name. */
1972  for( current = collection_name; *current != '\0'; current++ ) {
1973 
1974  /* Cannot have two consecutive dots. */
1975  if( last && *last == '.' && *current == '.' ) {
1977  "Collection may not contain two consecutive '.'", 0 );
1978  return MONGO_ERROR;
1979  }
1980 
1981  /* Cannot contain a '$' */
1982  if( *current == '$' ) {
1984  "Collection may not contain '$'", 0 );
1985  return MONGO_ERROR;
1986  }
1987 
1988  last = current;
1989  ns_len++;
1990  }
1991 
1992  if( ns_len > 128 ) {
1993  bson_sprintf( errmsg, "Namespace too long; has %d but must <= 128.",
1994  ns_len );
1995  __mongo_set_error( conn, MONGO_NS_INVALID, errmsg, 0 );
1996  return MONGO_ERROR;
1997  }
1998 
1999  /* Cannot end with a '.' */
2000  if( *(current - 1) == '.' ) {
2002  "Collection may not end with '.'", 0 );
2003  return MONGO_ERROR;
2004  }
2005 
2006  return MONGO_OK;
2007 }
2008 
2010  bson_iterator iter[1];
2011  int result_len = bson_iterator_string_len( it );
2012  const char *result_string = bson_iterator_string( it );
2013  int len = result_len < MONGO_ERR_LEN ? result_len : MONGO_ERR_LEN;
2014  memcpy( conn->lasterrstr, result_string, len );
2015  iter[0] = *it; // no side effects on the passed iter
2016  if( bson_find( iter, obj, "code" ) != BSON_NULL )
2017  conn->lasterrcode = bson_iterator_int( iter );
2018 }
2019 
2020 static const int ZERO = 0;
2021 static const int ONE = 1;
2022 static mongo_message *mongo_message_create( size_t len , int id , int responseTo , int op ) {
2023  mongo_message *mm;
2024 
2025  if( len >= INT32_MAX) {
2026  return NULL;
2027  }
2028  mm = ( mongo_message * )bson_malloc( len );
2029  if ( !id )
2030  id = rand();
2031 
2032  /* native endian (converted on send) */
2033  mm->head.len = ( int )len;
2034  mm->head.id = id;
2035  mm->head.responseTo = responseTo;
2036  mm->head.op = op;
2037 
2038  return mm;
2039 }
2040 
2041 /* Always calls bson_free(mm) */
2043  mongo_header head; /* little endian */
2044  int res;
2045  bson_little_endian32( &head.len, &mm->head.len );
2046  bson_little_endian32( &head.id, &mm->head.id );
2048  bson_little_endian32( &head.op, &mm->head.op );
2049 
2050  res = mongo_env_write_socket( conn, &head, sizeof( head ) );
2051  if( res != MONGO_OK ) {
2052  bson_free( mm );
2053  return res;
2054  }
2055 
2056  res = mongo_env_write_socket( conn, &mm->data, mm->head.len - sizeof( head ) );
2057  if( res != MONGO_OK ) {
2058  bson_free( mm );
2059  return res;
2060  }
2061 
2062  bson_free( mm );
2063  return MONGO_OK;
2064 }
2065 
2066 static int mongo_read_response( mongo *conn, mongo_reply **reply ) {
2067  mongo_header head; /* header from network */
2068  mongo_reply_fields fields; /* header from network */
2069  mongo_reply *out; /* native endian */
2070  unsigned int len;
2071  int res;
2072 
2073  if ( ( res = mongo_env_read_socket( conn, &head, sizeof( head ) ) ) != MONGO_OK ||
2074  ( res = mongo_env_read_socket( conn, &fields, sizeof( fields ) ) ) != MONGO_OK ) {
2075  return res;
2076  }
2077 
2078  bson_little_endian32( &len, &head.len );
2079 
2080  if ( len < sizeof( head )+sizeof( fields ) || len > 64*1024*1024 )
2081  return MONGO_READ_SIZE_ERROR; /* most likely corruption */
2082 
2083  /*
2084  * mongo_reply matches the wire for observed environments (MacOS, Linux, Windows VC), but
2085  * the following incorporates possible differences with type sizes and padding/packing
2086  *
2087  * assert( sizeof(mongo_reply) - sizeof(char) - 16 - 20 + len >= len );
2088  * printf( "sizeof(mongo_reply) - sizeof(char) - 16 - 20 = %ld\n", sizeof(mongo_reply) - sizeof(char) - 16 - 20 );
2089  */
2090  out = ( mongo_reply * )bson_malloc( sizeof(mongo_reply) - sizeof(char) + len - 16 - 20 );
2091 
2092  out->head.len = len;
2093  bson_little_endian32( &out->head.id, &head.id );
2095  bson_little_endian32( &out->head.op, &head.op );
2096 
2097  bson_little_endian32( &out->fields.flag, &fields.flag );
2098  bson_little_endian64( &out->fields.cursorID, &fields.cursorID );
2099  bson_little_endian32( &out->fields.start, &fields.start );
2100  bson_little_endian32( &out->fields.num, &fields.num );
2101 
2102  res = mongo_env_read_socket( conn, &out->objs, len - 16 - 20 ); /* was len-sizeof( head )-sizeof( fields ) */
2103  if( res != MONGO_OK ) {
2104  bson_free( out );
2105  return res;
2106  }
2107 
2108  *reply = out;
2109 
2110  return MONGO_OK;
2111 }
2112 
2113 
2114 static char *mongo_data_append( char *start , const void *data , size_t len ) {
2115  memcpy( start , data , len );
2116  return start + len;
2117 }
2118 
2119 static char *mongo_data_append32( char *start , const void *data ) {
2120  bson_little_endian32( start , data );
2121  return start + 4;
2122 }
2123 
2124 static char *mongo_data_append64( char *start , const void *data ) {
2125  bson_little_endian64( start , data );
2126  return start + 8;
2127 }
2128 
2129 /* Connection API */
2130 
2132  bson out;
2133  bson_iterator it;
2134  bson_bool_t ismaster = 0;
2135  int max_bson_size = MONGO_DEFAULT_MAX_BSON_SIZE;
2136 
2137  if ( mongo_simple_int_command( conn, "admin", "ismaster", 1, &out ) != MONGO_OK )
2138  return MONGO_ERROR;
2139 
2140  if( bson_find( &it, &out, "ismaster" ) )
2141  ismaster = bson_iterator_bool( &it );
2142  if( bson_find( &it, &out, "maxBsonObjectSize" ) )
2143  max_bson_size = bson_iterator_int( &it );
2144  conn->max_bson_size = max_bson_size;
2145 
2146  bson_destroy( &out );
2147 
2148  if( ismaster )
2149  return MONGO_OK;
2150  else {
2151  conn->err = MONGO_CONN_NOT_MASTER;
2152  return MONGO_ERROR;
2153  }
2154 }
2155 
2158 }
2159 
2160 /* WC1 is completely static */
2161 static char WC1_data[] = {23,0,0,0,16,103,101,116,108,97,115,116,101,114,114,111,114,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
2162 static bson WC1_cmd = {
2163  WC1_data, WC1_data, 128, 1, 0
2164 };
2165 static mongo_write_concern WC1 = { 1, 0, 0, 0, 0, &WC1_cmd }; /* w = 1 */
2166 
2168  memset( conn, 0, sizeof( mongo ) );
2170  mongo_set_write_concern( conn, &WC1 );
2171 }
2172 
2173 MONGO_EXPORT int mongo_client( mongo *conn , const char *host, int port ) {
2174  mongo_init( conn );
2175 
2176  conn->primary = (mongo_host_port*)bson_malloc( sizeof( mongo_host_port ) );
2177  snprintf( conn->primary->host, MAXHOSTNAMELEN, "%s", host);
2178  conn->primary->port = port;
2179  conn->primary->next = NULL;
2180 
2181  if( mongo_env_socket_connect( conn, host, port ) != MONGO_OK )
2182  return MONGO_ERROR;
2183 
2184  return mongo_check_is_master( conn );
2185 }
2186 
2187 MONGO_EXPORT int mongo_connect( mongo *conn , const char *host, int port ) {
2188  int ret;
2189  bson_errprintf("WARNING: mongo_connect() is deprecated, please use mongo_client()\n");
2190  ret = mongo_client( conn, host, port );
2191  mongo_set_write_concern( conn, 0 );
2192  return ret;
2193 }
2194 
2196  mongo_init( conn );
2197 
2198  conn->replica_set = (mongo_replica_set*)bson_malloc( sizeof( mongo_replica_set ) );
2199  conn->replica_set->primary_connected = 0;
2200  conn->replica_set->seeds = NULL;
2201  conn->replica_set->hosts = NULL;
2202  conn->replica_set->name = ( char * )bson_malloc( strlen( name ) + 1 );
2203  memcpy( conn->replica_set->name, name, strlen( name ) + 1 );
2204 
2205  conn->primary = (mongo_host_port*)bson_malloc( sizeof( mongo_host_port ) );
2206  conn->primary->host[0] = '\0';
2207  conn->primary->next = NULL;
2208 }
2209 
2211  bson_errprintf("WARNING: mongo_replset_init() is deprecated, please use mongo_replica_set_init()\n");
2212  mongo_replica_set_init( conn, name );
2213 }
2214 
2215 static void mongo_replica_set_add_node( mongo_host_port **list, const char *host, int port ) {
2216  mongo_host_port *host_port = (mongo_host_port*)bson_malloc( sizeof( mongo_host_port ) );
2217  host_port->port = port;
2218  host_port->next = NULL;
2219  snprintf( host_port->host, MAXHOSTNAMELEN, "%s", host);
2220 
2221  if( *list == NULL )
2222  *list = host_port;
2223  else {
2224  mongo_host_port *p = *list;
2225  while( p->next != NULL )
2226  p = p->next;
2227  p->next = host_port;
2228  }
2229 }
2230 
2232  mongo_host_port *node = *list;
2233  mongo_host_port *prev;
2234 
2235  while( node != NULL ) {
2236  prev = node;
2237  node = node->next;
2238  bson_free( prev );
2239  }
2240 
2241  *list = NULL;
2242 }
2243 
2245  mongo_replica_set_add_node( &conn->replica_set->seeds, host, port );
2246 }
2247 
2249  bson_errprintf("WARNING: mongo_replset_add_seed() is deprecated, please use mongo_replica_set_add_seed()\n");
2250  mongo_replica_set_add_node( &conn->replica_set->seeds, host, port );
2251 }
2252 
2253 void mongo_parse_host( const char *host_string, mongo_host_port *host_port ) {
2254  int len, idx, split;
2255  len = split = idx = 0;
2256 
2257  /* Split the host_port string at the ':' */
2258  while( 1 ) {
2259  if( *( host_string + len ) == '\0' )
2260  break;
2261  if( *( host_string + len ) == ':' )
2262  split = len;
2263 
2264  len++;
2265  }
2266 
2267  /* If 'split' is set, we know the that port exists;
2268  * Otherwise, we set the default port. */
2269  idx = split ? split : len;
2270  memcpy( host_port->host, host_string, idx );
2271  memcpy( host_port->host + idx, "\0", 1 );
2272  if( split )
2273  host_port->port = atoi( host_string + idx + 1 );
2274  else
2275  host_port->port = MONGO_DEFAULT_PORT;
2276 }
2277 
2279  bson out[1];
2280  const char *data;
2281  bson_iterator it[1];
2282  bson_iterator it_sub[1];
2283  const char *host_string;
2284  mongo_host_port *host_port = NULL;
2285 
2286  if( mongo_simple_int_command( conn, "admin", "ismaster", 1, out ) == MONGO_OK ) {
2287 
2288  if( bson_find( it, out, "hosts" ) ) {
2289  data = bson_iterator_value( it );
2290  bson_iterator_from_buffer( it_sub, data );
2291 
2292  /* Iterate over host list, adding each host to the
2293  * connection's host list. */
2294  while( bson_iterator_next( it_sub ) ) {
2295  host_string = bson_iterator_string( it_sub );
2296 
2297  host_port = (mongo_host_port*)bson_malloc( sizeof( mongo_host_port ) );
2298 
2299  if( host_port ) {
2300  mongo_parse_host( host_string, host_port );
2302  host_port->host, host_port->port );
2303 
2304  bson_free( host_port );
2305  host_port = NULL;
2306  }
2307  }
2308  }
2309  }
2310 
2311  bson_destroy(out);
2312  mongo_env_close_socket( conn->sock );
2313  conn->sock = 0;
2314  conn->connected = 0;
2315 }
2316 
2317 /* Find out whether the current connected node is master, and
2318  * verify that the node's replica set name matched the provided name
2319  */
2321 
2322  bson out[1];
2323  bson_iterator it[1];
2324  bson_bool_t ismaster = 0;
2325  const char *set_name;
2326  int max_bson_size = MONGO_DEFAULT_MAX_BSON_SIZE;
2327 
2328  if ( mongo_simple_int_command( conn, "admin", "ismaster", 1, out ) == MONGO_OK ) {
2329  if( bson_find( it, out, "ismaster" ) )
2330  ismaster = bson_iterator_bool( it );
2331 
2332  if( bson_find( it, out, "maxBsonObjectSize" ) )
2333  max_bson_size = bson_iterator_int( it );
2334  conn->max_bson_size = max_bson_size;
2335 
2336  if( bson_find( it, out, "setName" ) ) {
2337  set_name = bson_iterator_string( it );
2338  if( strcmp( set_name, conn->replica_set->name ) != 0 ) {
2339  bson_destroy( out );
2340  conn->err = MONGO_CONN_BAD_SET_NAME;
2341  return MONGO_ERROR;
2342  }
2343  }
2344  }
2345 
2346  bson_destroy( out );
2347 
2348  if( ismaster ) {
2349  conn->replica_set->primary_connected = 1;
2350  }
2351  else {
2352  mongo_env_close_socket( conn->sock );
2353  }
2354 
2355  return MONGO_OK;
2356 }
2357 
2359 
2360  int res = 0;
2361  mongo_host_port *node;
2362 
2363  conn->sock = 0;
2364  conn->connected = 0;
2365 
2366  /* First iterate over the seed nodes to get the canonical list of hosts
2367  * from the replica set. Break out once we have a host list.
2368  */
2369  node = conn->replica_set->seeds;
2370  while( node != NULL ) {
2371  res = mongo_env_socket_connect( conn, ( const char * )&node->host, node->port );
2372  if( res == MONGO_OK ) {
2374  if( conn->replica_set->hosts )
2375  break;
2376  }
2377  node = node->next;
2378  }
2379 
2380  /* Iterate over the host list, checking for the primary node. */
2381  if( !conn->replica_set->hosts ) {
2382  conn->err = MONGO_CONN_NO_PRIMARY;
2383  return MONGO_ERROR;
2384  }
2385  else {
2386  node = conn->replica_set->hosts;
2387 
2388  while( node != NULL ) {
2389  res = mongo_env_socket_connect( conn, ( const char * )&node->host, node->port );
2390 
2391  if( res == MONGO_OK ) {
2392  if( mongo_replica_set_check_host( conn ) != MONGO_OK )
2393  return MONGO_ERROR;
2394 
2395  /* Primary found, so return. */
2396  else if( conn->replica_set->primary_connected ) {
2397  conn->primary = bson_malloc( sizeof( mongo_host_port ) );
2398  snprintf( conn->primary->host, MAXHOSTNAMELEN, "%s", node->host );
2399  conn->primary->port = node->port;
2400  return MONGO_OK;
2401  }
2402 
2403  /* No primary, so close the connection. */
2404  else {
2405  mongo_env_close_socket( conn->sock );
2406  conn->sock = 0;
2407  conn->connected = 0;
2408  }
2409  }
2410 
2411  node = node->next;
2412  }
2413  }
2414 
2415 
2416  conn->err = MONGO_CONN_NO_PRIMARY;
2417  return MONGO_ERROR;
2418 }
2419 
2421  int ret;
2422  bson_errprintf("WARNING: mongo_replset_connect() is deprecated, please use mongo_replica_set_client()\n");
2423  ret = mongo_replica_set_client( conn );
2424  mongo_set_write_concern( conn, 0 );
2425  return ret;
2426 }
2427 
2429  conn->op_timeout_ms = millis;
2430  if( conn->sock && conn->connected )
2431  mongo_env_set_socket_op_timeout( conn, millis );
2432 
2433  return MONGO_OK;
2434 }
2435 
2437  int res;
2438  mongo_disconnect( conn );
2439 
2440  if( conn->replica_set ) {
2441  conn->replica_set->primary_connected = 0;
2443  conn->replica_set->hosts = NULL;
2444  res = mongo_replica_set_client( conn );
2445  return res;
2446  }
2447  else
2448  return mongo_env_socket_connect( conn, conn->primary->host, conn->primary->port );
2449 }
2450 
2452  if( ! conn->connected )
2453  return MONGO_ERROR;
2454 
2455  return mongo_simple_int_command( conn, "admin", "ping", 1, NULL );
2456 }
2457 
2459  if( ! conn->connected )
2460  return;
2461 
2462  if( conn->replica_set ) {
2463  conn->replica_set->primary_connected = 0;
2465  conn->replica_set->hosts = NULL;
2466  }
2467 
2468  mongo_env_close_socket( conn->sock );
2469 
2470  conn->sock = 0;
2471  conn->connected = 0;
2472 }
2473 
2475  mongo_disconnect( conn );
2476 
2477  if( conn->replica_set ) {
2480  bson_free( conn->replica_set->name );
2481  bson_free( conn->replica_set );
2482  conn->replica_set = NULL;
2483  }
2484 
2485  bson_free( conn->primary );
2486 
2487  mongo_clear_errors( conn );
2488 }
2489 
2490 /* Determine whether this BSON object is valid for the given operation. */
2491 static int mongo_bson_valid( mongo *conn, const bson *bson, int write ) {
2492  int size;
2493 
2494  if( ! bson->finished ) {
2495  conn->err = MONGO_BSON_NOT_FINISHED;
2496  return MONGO_ERROR;
2497  }
2498 
2499  size = bson_size( bson );
2500  if( size > conn->max_bson_size ) {
2501  conn->err = MONGO_BSON_TOO_LARGE;
2502  return MONGO_ERROR;
2503  }
2504 
2505  if( bson->err & BSON_NOT_UTF8 ) {
2506  conn->err = MONGO_BSON_INVALID;
2507  return MONGO_ERROR;
2508  }
2509 
2510  if( write ) {
2511  if( ( bson->err & BSON_FIELD_HAS_DOT ) ||
2512  ( bson->err & BSON_FIELD_INIT_DOLLAR ) ) {
2513 
2514  conn->err = MONGO_BSON_INVALID;
2515  return MONGO_ERROR;
2516 
2517  }
2518  }
2519 
2520  conn->err = MONGO_CONN_SUCCESS;
2521 
2522  return MONGO_OK;
2523 }
2524 
2525 /* Determine whether this BSON object is valid for the given operation. */
2526 static int mongo_cursor_bson_valid( mongo_cursor *cursor, const bson *bson ) {
2527  if( ! bson->finished ) {
2528  cursor->err = MONGO_CURSOR_BSON_ERROR;
2529  cursor->conn->err = MONGO_BSON_NOT_FINISHED;
2530  return MONGO_ERROR;
2531  }
2532 
2533  if( bson->err & BSON_NOT_UTF8 ) {
2534  cursor->err = MONGO_CURSOR_BSON_ERROR;
2535  cursor->conn->err = MONGO_BSON_INVALID;
2536  return MONGO_ERROR;
2537  }
2538 
2539  return MONGO_OK;
2540 }
2541 
2542 static int mongo_check_last_error( mongo *conn, const char *ns,
2544  bson response[1];
2545  bson_iterator it[1];
2546  int res = 0;
2547  char *cmd_ns = mongo_ns_to_cmd_db( ns );
2548 
2549  res = mongo_find_one( conn, cmd_ns, write_concern->cmd, bson_shared_empty( ), response );
2550  bson_free( cmd_ns );
2551 
2552  if (res == MONGO_OK &&
2553  (bson_find( it, response, "$err" ) == BSON_STRING ||
2554  bson_find( it, response, "err" ) == BSON_STRING)) {
2555 
2557  "See conn->lasterrstr for details.", 0 );
2558  mongo_set_last_error( conn, it, response );
2559  res = MONGO_ERROR;
2560  }
2561 
2562  bson_destroy( response );
2563  return res;
2564 }
2565 
2569 
2570  if( custom_write_concern ) {
2571  *write_concern = custom_write_concern;
2572  }
2573  else if( conn->write_concern ) {
2574  *write_concern = conn->write_concern;
2575  }
2576  if ( *write_concern && (*write_concern)->w < 1 ) {
2577  *write_concern = 0; /* do not generate getLastError request */
2578  }
2579  if( *write_concern && !((*write_concern)->cmd) ) {
2581  "Must call mongo_write_concern_finish() before using *write_concern.", 0 );
2582  return MONGO_ERROR;
2583  }
2584  else
2585  return MONGO_OK;
2586 }
2587 
2588 
2589 /*********************************************************************
2590 CRUD API
2591 **********************************************************************/
2592 
2594  if( write_concern ) {
2595  if( mongo_message_send( conn, mm ) == MONGO_ERROR ) {
2596  return MONGO_ERROR;
2597  }
2598 
2599  return mongo_check_last_error( conn, ns, write_concern );
2600  }
2601  else {
2602  return mongo_message_send( conn, mm );
2603  }
2604 }
2605 
2608 
2609  char *data;
2610  mongo_message *mm;
2612 
2613  if( mongo_validate_ns( conn, ns ) != MONGO_OK )
2614  return MONGO_ERROR;
2615 
2616  if( mongo_bson_valid( conn, bson, 1 ) != MONGO_OK ) {
2617  return MONGO_ERROR;
2618  }
2619 
2620  if( mongo_choose_write_concern( conn, custom_write_concern,
2621  &write_concern ) == MONGO_ERROR ) {
2622  return MONGO_ERROR;
2623  }
2624 
2625  mm = mongo_message_create( 16 /* header */
2626  + 4 /* ZERO */
2627  + strlen( ns )
2628  + 1 + bson_size( bson )
2629  , 0, 0, MONGO_OP_INSERT );
2630  if( mm == NULL ) {
2631  conn->err = MONGO_BSON_TOO_LARGE;
2632  return MONGO_ERROR;
2633  }
2634 
2635  data = &mm->data;
2636  data = mongo_data_append32( data, &ZERO );
2637  data = mongo_data_append( data, ns, strlen( ns ) + 1 );
2638  mongo_data_append( data, bson->data, bson_size( bson ) );
2639 
2640  return mongo_message_send_and_check_write_concern( conn, ns, mm, write_concern );
2641 }
2642 
2644  const bson **bsons, int count, mongo_write_concern *custom_write_concern,
2645  int flags ) {
2646 
2647  mongo_message *mm;
2649  int i;
2650  char *data;
2651  size_t overhead = 16 + 4 + strlen( ns ) + 1;
2652  size_t size = overhead;
2653 
2654  if( mongo_validate_ns( conn, ns ) != MONGO_OK )
2655  return MONGO_ERROR;
2656 
2657  for( i=0; i<count; i++ ) {
2658  size += bson_size( bsons[i] );
2659  if( mongo_bson_valid( conn, bsons[i], 1 ) != MONGO_OK )
2660  return MONGO_ERROR;
2661  }
2662 
2663  if( ( size - overhead ) > (size_t)conn->max_bson_size ) {
2664  conn->err = MONGO_BSON_TOO_LARGE;
2665  return MONGO_ERROR;
2666  }
2667 
2668  if( mongo_choose_write_concern( conn, custom_write_concern,
2669  &write_concern ) == MONGO_ERROR ) {
2670  return MONGO_ERROR;
2671  }
2672 
2673  mm = mongo_message_create( size , 0 , 0 , MONGO_OP_INSERT );
2674  if( mm == NULL ) {
2675  conn->err = MONGO_BSON_TOO_LARGE;
2676  return MONGO_ERROR;
2677  }
2678 
2679  data = &mm->data;
2680  if( flags & MONGO_CONTINUE_ON_ERROR )
2681  data = mongo_data_append32( data, &ONE );
2682  else
2683  data = mongo_data_append32( data, &ZERO );
2684  data = mongo_data_append( data, ns, strlen( ns ) + 1 );
2685 
2686  for( i=0; i<count; i++ ) {
2687  data = mongo_data_append( data, bsons[i]->data, bson_size( bsons[i] ) );
2688  }
2689 
2690  return mongo_message_send_and_check_write_concern( conn, ns, mm, write_concern );
2691 }
2692 
2693 MONGO_EXPORT int mongo_update( mongo *conn, const char *ns, const bson *cond,
2695 
2696  char *data;
2697  mongo_message *mm;
2699 
2700  /* Make sure that the op BSON is valid UTF-8.
2701  * TODO: decide whether to check cond as well.
2702  * */
2703  if( mongo_bson_valid( conn, ( bson * )op, 0 ) != MONGO_OK ) {
2704  return MONGO_ERROR;
2705  }
2706 
2707  if( mongo_choose_write_concern( conn, custom_write_concern,
2708  &write_concern ) == MONGO_ERROR ) {
2709  return MONGO_ERROR;
2710  }
2711 
2712  mm = mongo_message_create( 16 /* header */
2713  + 4 /* ZERO */
2714  + strlen( ns ) + 1
2715  + 4 /* flags */
2716  + bson_size( cond )
2717  + bson_size( op )
2718  , 0 , 0 , MONGO_OP_UPDATE );
2719  if( mm == NULL ) {
2720  conn->err = MONGO_BSON_TOO_LARGE;
2721  return MONGO_ERROR;
2722  }
2723 
2724  data = &mm->data;
2725  data = mongo_data_append32( data, &ZERO );
2726  data = mongo_data_append( data, ns, strlen( ns ) + 1 );
2727  data = mongo_data_append32( data, &flags );
2728  data = mongo_data_append( data, cond->data, bson_size( cond ) );
2729  mongo_data_append( data, op->data, bson_size( op ) );
2730 
2731  return mongo_message_send_and_check_write_concern( conn, ns, mm, write_concern );
2732 }
2733 
2734 MONGO_EXPORT int mongo_remove( mongo *conn, const char *ns, const bson *cond,
2736 
2737  char *data;
2738  mongo_message *mm;
2740 
2741  /* Make sure that the BSON is valid UTF-8.
2742  * TODO: decide whether to check cond as well.
2743  * */
2744  if( mongo_bson_valid( conn, ( bson * )cond, 0 ) != MONGO_OK ) {
2745  return MONGO_ERROR;
2746  }
2747 
2748  if( mongo_choose_write_concern( conn, custom_write_concern,
2749  &write_concern ) == MONGO_ERROR ) {
2750  return MONGO_ERROR;
2751  }
2752 
2753  mm = mongo_message_create( 16 /* header */
2754  + 4 /* ZERO */
2755  + strlen( ns ) + 1
2756  + 4 /* ZERO */
2757  + bson_size( cond )
2758  , 0 , 0 , MONGO_OP_DELETE );
2759  if( mm == NULL ) {
2760  conn->err = MONGO_BSON_TOO_LARGE;
2761  return MONGO_ERROR;
2762  }
2763 
2764  data = &mm->data;
2765  data = mongo_data_append32( data, &ZERO );
2766  data = mongo_data_append( data, ns, strlen( ns ) + 1 );
2767  data = mongo_data_append32( data, &ZERO );
2768  mongo_data_append( data, cond->data, bson_size( cond ) );
2769 
2770  return mongo_message_send_and_check_write_concern( conn, ns, mm, write_concern );
2771 }
2772 
2773 
2774 /*********************************************************************
2775 Write Concern API
2776 **********************************************************************/
2777 
2779  memset( write_concern, 0, sizeof( mongo_write_concern ) );
2780 }
2781 
2783  bson *command;
2784 
2785  /* Destory any existing serialized write concern object and reuse it. */
2786  if( write_concern->cmd ) {
2787  bson_destroy( write_concern->cmd );
2788  command = write_concern->cmd;
2789  }
2790  else
2791  command = bson_alloc();
2792 
2793  if( !command ) {
2794  return MONGO_ERROR;
2795  }
2796 
2797  bson_init( command );
2798 
2799  bson_append_int( command, "getlasterror", 1 );
2800 
2801  if( write_concern->mode ) {
2802  bson_append_string( command, "w", write_concern->mode );
2803  }
2804 
2805  else if( write_concern->w && write_concern->w > 1 ) {
2806  bson_append_int( command, "w", write_concern->w );
2807  }
2808 
2809  if( write_concern->wtimeout ) {
2810  bson_append_int( command, "wtimeout", write_concern->wtimeout );
2811  }
2812 
2813  if( write_concern->j ) {
2814  bson_append_int( command, "j", write_concern->j );
2815  }
2816 
2817  if( write_concern->fsync ) {
2818  bson_append_int( command, "fsync", write_concern->fsync );
2819  }
2820 
2821  bson_finish( command );
2822 
2823  /* write_concern now owns the BSON command object.
2824  * This is freed in mongo_write_concern_destroy(). */
2825  write_concern->cmd = command;
2826 
2827  return MONGO_OK;
2828 }
2829 
2834  if( !write_concern )
2835  return;
2836 
2837  if( write_concern->cmd ) {
2838  bson_destroy( write_concern->cmd );
2839  bson_dealloc( write_concern->cmd );
2840  write_concern->cmd = NULL;
2841  }
2842 }
2843 
2846 
2847  conn->write_concern = write_concern;
2848 }
2849 
2851  return write_concern->w;
2852 }
2853 
2855  return write_concern->wtimeout;
2856 }
2857 
2859  return write_concern->j;
2860 }
2861 
2863  return write_concern->fsync;
2864 }
2865 
2867  return write_concern->mode;
2868 }
2869 
2871  return write_concern->cmd;
2872 }
2873 
2875  write_concern->w = w;
2876 }
2877 
2879  write_concern->wtimeout = wtimeout;
2880 
2881 }
2882 
2884  write_concern->j = j;
2885 }
2886 
2888  write_concern->fsync = fsync;
2889 
2890 }
2891 
2893  write_concern->mode = mode;
2894 }
2895 
2896 static int mongo_cursor_op_query( mongo_cursor *cursor ) {
2897  int res;
2898  char *data;
2899  mongo_message *mm;
2900  bson temp;
2901  bson_iterator it;
2902 
2903  /* Clear any errors. */
2904  mongo_clear_errors( cursor->conn );
2905 
2906  /* Set up default values for query and fields, if necessary. */
2907  if( ! cursor->query )
2908  cursor->query = bson_shared_empty( );
2909  else if( mongo_cursor_bson_valid( cursor, cursor->query ) != MONGO_OK )
2910  return MONGO_ERROR;
2911 
2912  if( ! cursor->fields )
2913  cursor->fields = bson_shared_empty( );
2914  else if( mongo_cursor_bson_valid( cursor, cursor->fields ) != MONGO_OK )
2915  return MONGO_ERROR;
2916 
2917  mm = mongo_message_create( 16 + /* header */
2918  4 + /* options */
2919  strlen( cursor->ns ) + 1 + /* ns */
2920  4 + 4 + /* skip,return */
2921  bson_size( cursor->query ) +
2922  bson_size( cursor->fields ) ,
2923  0 , 0 , MONGO_OP_QUERY );
2924  if( mm == NULL ) {
2925  return MONGO_ERROR;
2926  }
2927 
2928  data = &mm->data;
2929  data = mongo_data_append32( data , &cursor->options );
2930  data = mongo_data_append( data , cursor->ns , strlen( cursor->ns ) + 1 );
2931  data = mongo_data_append32( data , &cursor->skip );
2932  data = mongo_data_append32( data , &cursor->limit );
2933  data = mongo_data_append( data , cursor->query->data , bson_size( cursor->query ) );
2934  if ( cursor->fields )
2935  data = mongo_data_append( data , cursor->fields->data , bson_size( cursor->fields ) );
2936 
2937  bson_fatal_msg( ( data == ( ( char * )mm ) + mm->head.len ), "query building fail!" );
2938 
2939  res = mongo_message_send( cursor->conn , mm );
2940  if( res != MONGO_OK ) {
2941  return MONGO_ERROR;
2942  }
2943 
2944  res = mongo_read_response( cursor->conn, ( mongo_reply ** )&( cursor->reply ) );
2945  if( res != MONGO_OK ) {
2946  return MONGO_ERROR;
2947  }
2948 
2949  if( cursor->reply->fields.num == 1 ) {
2950  bson_init_finished_data( &temp, &cursor->reply->objs, 0 );
2951  if( bson_find( &it, &temp, "$err" ) ) {
2952  mongo_set_last_error( cursor->conn, &it, &temp );
2953  cursor->err = MONGO_CURSOR_QUERY_FAIL;
2954  return MONGO_ERROR;
2955  }
2956  }
2957 
2958  cursor->seen += cursor->reply->fields.num;
2959  cursor->flags |= MONGO_CURSOR_QUERY_SENT;
2960  return MONGO_OK;
2961 }
2962 
2963 static int mongo_cursor_get_more( mongo_cursor *cursor ) {
2964  int res;
2965 
2966  if( cursor->limit > 0 && cursor->seen >= cursor->limit ) {
2967  cursor->err = MONGO_CURSOR_EXHAUSTED;
2968  return MONGO_ERROR;
2969  }
2970  else if( ! cursor->reply ) {
2971  cursor->err = MONGO_CURSOR_INVALID;
2972  return MONGO_ERROR;
2973  }
2974  else if( ! cursor->reply->fields.cursorID ) {
2975  cursor->err = MONGO_CURSOR_EXHAUSTED;
2976  return MONGO_ERROR;
2977  }
2978  else {
2979  char *data;
2980  size_t sl = strlen( cursor->ns )+1;
2981  int limit = 0;
2982  mongo_message *mm;
2983 
2984  if( cursor->limit > 0 )
2985  limit = cursor->limit - cursor->seen;
2986 
2987  mm = mongo_message_create( 16 /*header*/
2988  +4 /*ZERO*/
2989  +sl
2990  +4 /*numToReturn*/
2991  +8 /*cursorID*/
2992  , 0, 0, MONGO_OP_GET_MORE );
2993  if( mm == NULL ) {
2994  return MONGO_ERROR;
2995  }
2996 
2997  data = &mm->data;
2998  data = mongo_data_append32( data, &ZERO );
2999  data = mongo_data_append( data, cursor->ns, sl );
3000  data = mongo_data_append32( data, &limit );
3001  mongo_data_append64( data, &cursor->reply->fields.cursorID );
3002 
3003  bson_free( cursor->reply );
3004  res = mongo_message_send( cursor->conn, mm );
3005  if( res != MONGO_OK ) {
3006  mongo_cursor_destroy( cursor );
3007  return MONGO_ERROR;
3008  }
3009 
3010  res = mongo_read_response( cursor->conn, &( cursor->reply ) );
3011  if( res != MONGO_OK ) {
3012  mongo_cursor_destroy( cursor );
3013  return MONGO_ERROR;
3014  }
3015  cursor->current.data = NULL;
3016  cursor->seen += cursor->reply->fields.num;
3017 
3018  return MONGO_OK;
3019  }
3020 }
3021 
3023  const bson *fields, int limit, int skip, int options ) {
3024 
3025  mongo_cursor *cursor = mongo_cursor_alloc();
3026  mongo_cursor_init( cursor, conn, ns );
3027  cursor->flags |= MONGO_CURSOR_MUST_FREE;
3028 
3029  mongo_cursor_set_query( cursor, query );
3030  mongo_cursor_set_fields( cursor, fields );
3031  mongo_cursor_set_limit( cursor, limit );
3032  mongo_cursor_set_skip( cursor, skip );
3033  mongo_cursor_set_options( cursor, options );
3034 
3035  if( mongo_cursor_op_query( cursor ) == MONGO_OK )
3036  return cursor;
3037  else {
3038  mongo_cursor_destroy( cursor );
3039  return NULL;
3040  }
3041 }
3042 
3043 MONGO_EXPORT int mongo_find_one( mongo *conn, const char *ns, const bson *query,
3044  const bson *fields, bson *out ) {
3045  int ret;
3046  mongo_cursor cursor[1];
3047  mongo_cursor_init( cursor, conn, ns );
3048  mongo_cursor_set_query( cursor, query );
3049  mongo_cursor_set_fields( cursor, fields );
3050  mongo_cursor_set_limit( cursor, 1 );
3051 
3052  ret = mongo_cursor_next(cursor);
3053  if (ret == MONGO_OK && out)
3054  ret = bson_copy(out, &cursor->current);
3055  if (ret != MONGO_OK && out)
3056  bson_init_zero(out);
3057 
3058  mongo_cursor_destroy( cursor );
3059  return ret;
3060 }
3061 
3062 MONGO_EXPORT void mongo_cursor_init( mongo_cursor *cursor, mongo *conn, const char *ns ) {
3063  memset( cursor, 0, sizeof( mongo_cursor ) );
3064  cursor->conn = conn;
3065  cursor->ns = ( const char * )bson_malloc( strlen( ns ) + 1 );
3066  strncpy( ( char * )cursor->ns, ns, strlen( ns ) + 1 );
3067  cursor->current.data = NULL;
3068 }
3069 
3071  cursor->query = query;
3072 }
3073 
3075  cursor->fields = fields;
3076 }
3077 
3079  cursor->skip = skip;
3080 }
3081 
3083  cursor->limit = limit;
3084 }
3085 
3087  cursor->options = options;
3088 }
3089 
3091  return cursor->current.data;
3092 }
3093 
3095  return (const bson *)&(cursor->current);
3096 }
3097 
3099  char *next_object;
3100  char *message_end;
3101 
3102  if( cursor == NULL ) return MONGO_ERROR;
3103 
3104  if( ! ( cursor->flags & MONGO_CURSOR_QUERY_SENT ) )
3105  if( mongo_cursor_op_query( cursor ) != MONGO_OK )
3106  return MONGO_ERROR;
3107 
3108  if( !cursor->reply )
3109  return MONGO_ERROR;
3110 
3111  /* no data */
3112  if ( cursor->reply->fields.num == 0 ) {
3113 
3114  /* Special case for tailable cursors. */
3115  if( cursor->reply->fields.cursorID ) {
3116  if( ( mongo_cursor_get_more( cursor ) != MONGO_OK ) ||
3117  cursor->reply->fields.num == 0 ) {
3118  return MONGO_ERROR;
3119  }
3120  }
3121 
3122  else
3123  return MONGO_ERROR;
3124  }
3125 
3126  /* first */
3127  if ( cursor->current.data == NULL ) {
3128  bson_init_finished_data( &cursor->current, &cursor->reply->objs, 0 );
3129  return MONGO_OK;
3130  }
3131 
3132  next_object = cursor->current.data + bson_size( &cursor->current );
3133  message_end = ( char * )cursor->reply + cursor->reply->head.len;
3134 
3135  if ( next_object >= message_end ) {
3136  if( mongo_cursor_get_more( cursor ) != MONGO_OK )
3137  return MONGO_ERROR;
3138 
3139  if ( cursor->reply->fields.num == 0 ) {
3140  /* Special case for tailable cursors. */
3141  if ( cursor->reply->fields.cursorID ) {
3142  cursor->err = MONGO_CURSOR_PENDING;
3143  return MONGO_ERROR;
3144  }
3145  else
3146  return MONGO_ERROR;
3147  }
3148 
3149  bson_init_finished_data( &cursor->current, &cursor->reply->objs, 0 );
3150  }
3151  else {
3152  bson_init_finished_data( &cursor->current, next_object, 0 );
3153  }
3154 
3155  return MONGO_OK;
3156 }
3157 
3159  int result = MONGO_OK;
3160  char *data;
3161 
3162  if ( !cursor ) return result;
3163 
3164  /* Kill cursor if live. */
3165  if ( cursor->reply && cursor->reply->fields.cursorID ) {
3166  mongo *conn = cursor->conn;
3167  mongo_message *mm = mongo_message_create( 16 /*header*/
3168  +4 /*ZERO*/
3169  +4 /*numCursors*/
3170  +8 /*cursorID*/
3171  , 0, 0, MONGO_OP_KILL_CURSORS );
3172  if( mm == NULL ) {
3173  return MONGO_ERROR;
3174  }
3175  data = &mm->data;
3176  data = mongo_data_append32( data, &ZERO );
3177  data = mongo_data_append32( data, &ONE );
3178  mongo_data_append64( data, &cursor->reply->fields.cursorID );
3179 
3180  result = mongo_message_send( conn, mm );
3181  }
3182 
3183  bson_free( cursor->reply );
3184  bson_free( ( void * )cursor->ns );
3185 
3186  if( cursor->flags & MONGO_CURSOR_MUST_FREE )
3187  bson_free( cursor );
3188 
3189  return result;
3190 }
3191 
3192 /* MongoDB Helper Functions */
3193 
3194 #define INDEX_NAME_BUFFER_SIZE 255
3195 #define INDEX_NAME_MAX_LENGTH (INDEX_NAME_BUFFER_SIZE - 1)
3196 
3197 MONGO_EXPORT int mongo_create_index( mongo *conn, const char *ns, const bson *key, const char *name, int options, bson *out ) {
3198  bson b;
3199  bson_iterator it;
3200  char default_name[INDEX_NAME_BUFFER_SIZE] = {'\0'};
3201  size_t len = 0;
3202  size_t remaining;
3203  char idxns[1024];
3204  char *p = NULL;
3205 
3206  if ( !name ) {
3207  bson_iterator_init( &it, key );
3208  while( len < INDEX_NAME_MAX_LENGTH && bson_iterator_next( &it ) ) {
3209  remaining = INDEX_NAME_MAX_LENGTH - len;
3210  strncat( default_name, bson_iterator_key( &it ), remaining );
3211  len = strlen( default_name );
3212  remaining = INDEX_NAME_MAX_LENGTH - len;
3213  strncat( default_name, ( bson_iterator_int( &it ) < 0 ) ? "_-1" : "_1", remaining );
3214  len = strlen( default_name );
3215  }
3216  }
3217 
3218  bson_init( &b );
3219  bson_append_bson( &b, "key", key );
3220  bson_append_string( &b, "ns", ns );
3221  bson_append_string( &b, "name", name ? name : default_name );
3222  if ( options & MONGO_INDEX_UNIQUE )
3223  bson_append_bool( &b, "unique", 1 );
3224  if ( options & MONGO_INDEX_DROP_DUPS )
3225  bson_append_bool( &b, "dropDups", 1 );
3226  if ( options & MONGO_INDEX_BACKGROUND )
3227  bson_append_bool( &b, "background", 1 );
3228  if ( options & MONGO_INDEX_SPARSE )
3229  bson_append_bool( &b, "sparse", 1 );
3230  bson_finish( &b );
3231 
3232  strncpy( idxns, ns, 1024-16 );
3233  p = strchr( idxns, '.' );
3234  if ( !p ) {
3235  bson_destroy( &b );
3236  return MONGO_ERROR;
3237  }
3238  strcpy( p, ".system.indexes" );
3239  if ( mongo_insert( conn, idxns, &b, NULL ) != MONGO_OK) {
3240  bson_destroy( &b );
3241  return MONGO_ERROR;
3242  }
3243  bson_destroy( &b );
3244 
3245  *strchr( idxns, '.' ) = '\0'; /* just db not ns */
3246  return mongo_cmd_get_last_error( conn, idxns, out );
3247 }
3248 
3250  bson b[1];
3251  bson_bool_t success;
3252 
3253  bson_init( b );
3254  bson_append_int( b, field, 1 );
3255  bson_finish( b );
3256 
3257  success = mongo_create_index( conn, ns, b, NULL, options, out );
3258  bson_destroy( b );
3259  return success;
3260 }
3261 
3263  const char *collection, int size, int max, bson *out ) {
3264 
3265  bson b[1];
3266  int result;
3267 
3268  bson_init( b );
3269  bson_append_string( b, "create", collection );
3270  bson_append_bool( b, "capped", 1 );
3271  bson_append_int( b, "size", size );
3272  if( max > 0 )
3273  bson_append_int( b, "max", size );
3274  bson_finish( b );
3275 
3276  result = mongo_run_command( conn, db, b, out );
3277 
3278  bson_destroy( b );
3279 
3280  return result;
3281 }
3282 
3283 MONGO_EXPORT double mongo_count( mongo *conn, const char *db, const char *coll, const bson *query ) {
3284  bson cmd[1];
3285  bson out[1];
3286  double count = MONGO_ERROR; // -1
3287 
3288  bson_init( cmd );
3289  bson_append_string( cmd, "count", coll );
3290  if ( query && bson_size( query ) > 5 ) /* not empty */
3291  bson_append_bson( cmd, "query", query );
3292  bson_finish( cmd );
3293 
3294  if( mongo_run_command( conn, db, cmd, out ) == MONGO_OK ) {
3295  bson_iterator it[1];
3296  if( bson_find( it, out, "n" ) )
3297  count = bson_iterator_double( it );
3298  }
3299  bson_destroy( out );
3300  bson_destroy( cmd );
3301  return count;
3302 }
3303 
3305  bson *out ) {
3306  bson response[1];
3307  bson_iterator it[1];
3308  size_t sl = strlen( db );
3309  char *ns = (char*) bson_malloc( sl + 5 + 1 ); /* ".$cmd" + nul */
3310  int res = 0;
3311 
3312  strcpy( ns, db );
3313  strcpy( ns+sl, ".$cmd" );
3314 
3315  res = mongo_find_one( conn, ns, command, bson_shared_empty( ), response );
3316  bson_free( ns );
3317 
3318  if (res == MONGO_OK && (!bson_find( it, response, "ok" ) || !bson_iterator_bool( it )) ) {
3319  conn->err = MONGO_COMMAND_FAILED;
3320  bson_destroy( response );
3321  res = MONGO_ERROR;
3322  }
3323 
3324  if (out)
3325  if (res == MONGO_OK)
3326  *out = *response;
3327  else
3328  bson_init_zero(out);
3329  else if (res == MONGO_OK)
3330  bson_destroy(response);
3331 
3332  return res;
3333 }
3334 
3336  const char *cmdstr, int arg, bson *out ) {
3337 
3338  bson cmd[1];
3339  int result;
3340 
3341  bson_init( cmd );
3342  bson_append_int( cmd, cmdstr, arg );
3343  bson_finish( cmd );
3344 
3345  result = mongo_run_command( conn, db, cmd, out );
3346 
3347  bson_destroy( cmd );
3348 
3349  return result;
3350 }
3351 
3353  const char *cmdstr, const char *arg, bson *out ) {
3354 
3355  int result;
3356  bson cmd;
3357  bson_init( &cmd );
3358  bson_append_string( &cmd, cmdstr, arg );
3359  bson_finish( &cmd );
3360 
3361  result = mongo_run_command( conn, db, &cmd, out );
3362 
3363  bson_destroy( &cmd );
3364 
3365  return result;
3366 }
3367 
3369  return mongo_simple_int_command( conn, db, "dropDatabase", 1, NULL );
3370 }
3371 
3372 MONGO_EXPORT int mongo_cmd_drop_collection( mongo *conn, const char *db, const char *collection, bson *out ) {
3373  return mongo_simple_str_command( conn, db, "drop", collection, out );
3374 }
3375 
3377  mongo_simple_int_command( conn, db, "reseterror", 1, NULL );
3378 }
3379 
3380 static int mongo_cmd_get_error_helper( mongo *conn, const char *db,
3381  bson *realout, const char *cmdtype ) {
3382 
3383  bson out[1];
3384  bson_bool_t haserror = 0;
3385 
3386  /* Reset last error codes. */
3387  mongo_clear_errors( conn );
3388  bson_init_zero(out);
3389 
3390  /* If there's an error, store its code and string in the connection object. */
3391  if( mongo_simple_int_command( conn, db, cmdtype, 1, out ) == MONGO_OK ) {
3392  bson_iterator it[1];
3393  haserror = ( bson_find( it, out, "err" ) != BSON_NULL );
3394  if( haserror ) mongo_set_last_error( conn, it, out );
3395  }
3396 
3397  if( realout )
3398  *realout = *out; /* transfer of ownership */
3399  else
3400  bson_destroy( out );
3401 
3402  if( haserror )
3403  return MONGO_ERROR;
3404  else
3405  return MONGO_OK;
3406 }
3407 
3409  return mongo_cmd_get_error_helper( conn, db, out, "getpreverror" );
3410 }
3411 
3413  return mongo_cmd_get_error_helper( conn, db, out, "getlasterror" );
3414 }
3415 
3417  bson out[1];
3418  bson_bool_t ismaster = 0;
3419 
3420  int res = mongo_simple_int_command( conn, "admin", "ismaster", 1, out );
3421  if (res == MONGO_OK) {
3422  bson_iterator it[1];
3423  if (bson_find( it, out, "ismaster") != BSON_EOO )
3424  ismaster = bson_iterator_bool( it );
3425  if (realout)
3426  *realout = *out; /* transfer of ownership */
3427  else
3428  bson_destroy( out );
3429  } else if (realout)
3430  bson_init_zero(realout);
3431 
3432  return ismaster;
3433 }
3434 
3435 static int mongo_pass_digest( mongo *conn, const char *user, const char *pass, char hex_digest[33] ) {
3436 
3437  if( strlen( user ) >= INT32_MAX || strlen( pass ) >= INT32_MAX ) {
3438  conn->err = MONGO_BSON_TOO_LARGE;
3439  return MONGO_ERROR;
3440  }
3441 
3443  const char * _digest = NULL;
3444  int xx;
3445  xx = rpmDigestUpdate(ctx, user, strlen(user));
3446  xx = rpmDigestUpdate(ctx, ":mongo:", 7);
3447  xx = rpmDigestUpdate(ctx, pass, strlen(pass));
3448  xx = rpmDigestFinal(ctx, &_digest, NULL, 1);
3449  strncpy(hex_digest, _digest, 32+1);
3450  _digest = _free(_digest);
3451  }
3452 
3453  return MONGO_OK;
3454 }
3455 
3456 MONGO_EXPORT int mongo_cmd_add_user( mongo *conn, const char *db, const char *user, const char *pass ) {
3457  bson user_obj;
3458  bson pass_obj;
3459  char hex_digest[33];
3460  char *ns = bson_malloc( strlen( db ) + strlen( ".system.users" ) + 1 );
3461  int res;
3462 
3463  strcpy( ns, db );
3464  strcpy( ns+strlen( db ), ".system.users" );
3465 
3466  res = mongo_pass_digest( conn, user, pass, hex_digest );
3467  if (res != MONGO_OK) {
3468  free(ns);
3469  return res;
3470  }
3471 
3472  bson_init( &user_obj );
3473  bson_append_string( &user_obj, "user", user );
3474  bson_finish( &user_obj );
3475 
3476  bson_init( &pass_obj );
3477  bson_append_start_object( &pass_obj, "$set" );
3478  bson_append_string( &pass_obj, "pwd", hex_digest );
3479  bson_append_finish_object( &pass_obj );
3480  bson_finish( &pass_obj );
3481 
3482  res = mongo_update( conn, ns, &user_obj, &pass_obj, MONGO_UPDATE_UPSERT, NULL );
3483 
3484  bson_free( ns );
3485  bson_destroy( &user_obj );
3486  bson_destroy( &pass_obj );
3487 
3488  return res;
3489 }
3490 
3491 MONGO_EXPORT bson_bool_t mongo_cmd_authenticate( mongo *conn, const char *db, const char *user, const char *pass ) {
3492  bson from_db;
3493  bson cmd;
3494  const char *nonce;
3495  int result;
3496 
3497  char hex_digest[32+1];
3498 
3499  if( mongo_simple_int_command( conn, db, "getnonce", 1, &from_db ) == MONGO_OK ) {
3500  bson_iterator it;
3501  if (bson_find(&it, &from_db, "nonce") != BSON_EOO )
3502  nonce = bson_iterator_string( &it );
3503  else
3504  return MONGO_ERROR;
3505  } else {
3506  return MONGO_ERROR;
3507  }
3508 
3509  result = mongo_pass_digest( conn, user, pass, hex_digest );
3510  if( result != MONGO_OK ) {
3511  return result;
3512  }
3513 
3514  if( strlen( nonce ) >= INT32_MAX || strlen( user ) >= INT32_MAX ) {
3515  conn->err = MONGO_BSON_TOO_LARGE;
3516  return MONGO_ERROR;
3517  }
3518 
3520  const char * _digest = NULL;
3521  int xx;
3522  xx = rpmDigestUpdate(ctx, nonce, strlen(nonce));
3523  xx = rpmDigestUpdate(ctx, user, strlen(user));
3524  xx = rpmDigestUpdate(ctx, hex_digest, 32);
3525  xx = rpmDigestFinal(ctx, &_digest, NULL, 1);
3526  strncpy(hex_digest, _digest, 32+1);
3527  hex_digest[32] = '\0';
3528  _digest = _free(_digest);
3529  }
3530 
3531  bson_init( &cmd );
3532  bson_append_int( &cmd, "authenticate", 1 );
3533  bson_append_string( &cmd, "user", user );
3534  bson_append_string( &cmd, "nonce", nonce );
3535  bson_append_string( &cmd, "key", hex_digest );
3536  bson_finish( &cmd );
3537 
3538  result = mongo_run_command( conn, db, &cmd, NULL );
3539 
3540  bson_destroy( &from_db );
3541  bson_destroy( &cmd );
3542 
3543  return result;
3544 }
3545 
3546 /*==============================================================*/
3547 
3548 static void rpmmgoFini(void * _mgo)
3549  /*@globals fileSystem @*/
3550  /*@modifies *_mgo, fileSystem @*/
3551 {
3552  rpmmgo mgo = (rpmmgo) _mgo;
3553 
3554  mgo->fn = _free(mgo->fn);
3555 }
3556 
3557 /*@unchecked@*/ /*@only@*/ /*@null@*/
3559 
3561  /*@globals _rpmmgoPool, fileSystem @*/
3562  /*@modifies pool, _rpmmgoPool, fileSystem @*/
3563 {
3564  rpmmgo mgo;
3565 
3566  if (_rpmmgoPool == NULL) {
3567  _rpmmgoPool = rpmioNewPool("mgo", sizeof(*mgo), -1, _rpmmgo_debug,
3568  NULL, NULL, rpmmgoFini);
3569  pool = _rpmmgoPool;
3570  }
3571  mgo = (rpmmgo) rpmioGetPool(pool, sizeof(*mgo));
3572  memset(((char *)mgo)+sizeof(mgo->_item), 0, sizeof(*mgo)-sizeof(mgo->_item));
3573  return mgo;
3574 }
3575 
3576 rpmmgo rpmmgoNew(const char * fn, int flags)
3577 {
3578  rpmmgo mgo = rpmmgoGetPool(_rpmmgoPool);
3579 
3580  if (fn)
3581  mgo->fn = xstrdup(fn);
3582 
3583  return rpmmgoLink(mgo);
3584 }
static char * mongo_data_append32(char *start, const void *data)
Definition: mongo.c:2119
MONGO_EXPORT int mongo_get_err(mongo *conn)
Definition: mongo.c:1779
const bson * b
Definition: bson.h:280
int w
Number of total replica write copies to complete including the primary.
Definition: mongo.h:172
int options
Bitfield containing cursor options.
Definition: mongo.h:216
rpmmgo rpmmgoLink(rpmmgo mgo)
Reference a mongo wrapper instance.
const char const double d
Definition: bson.h:800
MONGO_EXPORT void gridfs_dealloc(gridfs *gfs)
Definition: mongo.c:489
mongo_error_t
Definition: mongo.h:66
MONGO_EXPORT void mongo_write_concern_set_wtimeout(mongo_write_concern *write_concern, int wtimeout)
Definition: mongo.c:2878
const char * chunks_ns
The namespace where the file's metadata is stored
Definition: mongo.c:64
static const int one
Definition: mongo.c:49
gridfs_offset length
The gridfile's content type
Definition: mongo.c:76
MONGO_EXPORT void mongo_replica_set_add_seed(mongo *conn, const char *host, int port)
Definition: mongo.c:2244
MONGO_EXPORT bson_bool_t gridfile_get_boolean(const gridfile *gfile, const char *name)
Returns a boolean field in GridFile specified by name.
Definition: mongo.c:1104
int id
Definition: mongo.h:141
SOCKET sock
Socket file descriptor.
Definition: mongo.h:191
const char const char * coll
Definition: mongo.h:697
MONGO_EXPORT bson_oid_t gridfile_get_id(const gridfile *gfile)
Returns the _id in GridFile specified by name.
Definition: mongo.c:1015
static rpmmgo rpmmgoGetPool(rpmioPool pool)
Definition: mongo.c:3560
static int gridfs_insert_file(gridfs *gfs, const char *name, const bson_oid_t id, gridfs_offset length, const char *contenttype, int flags, int chunkSize)
Definition: mongo.c:659
An error occurred while reading or writing on the socket.
Definition: mongo.h:75
MONGO_EXPORT gridfs_offset gridfile_get_contentlength(const gridfile *gfile)
Returns the length of GridFile's data.
Definition: mongo.c:1054
MONGO_EXPORT int gridfile_init(gridfs *gfs, const bson *meta, gridfile *gfile)
Initializes a GridFile containing the GridFS and file bson.
Definition: mongo.c:878
const char const char size_t len
Definition: bson.h:823
const bson * query
Bitfield containing cursor options.
Definition: mongo.h:214
int max_bson_size
Largest BSON object allowed on this connection.
Definition: mongo.h:195
const char int port
Definition: mongo.h:251
MONGO_EXPORT int gridfs_find_query(gridfs *gfs, const bson *query, gridfile *gfile)
Find the first file matching the provided query within the GridFS files collection, and return the file as a GridFile.
Definition: mongo.c:826
static void mongo_set_last_error(mongo *conn, bson_iterator *it, bson *obj)
Definition: mongo.c:2009
MONGO_EXPORT void gridfs_destroy(gridfs *gfs)
Destroys a GridFS object.
Definition: mongo.c:614
static char WC1_data[]
Definition: mongo.c:2161
A key or a string is not valid UTF-8.
Definition: bson.h:68
const char const char * cmd
Definition: mongo.h:777
MONGO_EXPORT gridfs_offset gridfile_write_file(gridfile *gfile, FILE *stream)
Writes the GridFile to a stream.
Definition: mongo.c:1479
int _rpmmgo_debug
Definition: mongo.c:42
mongo_host_port * seeds
List of seeds provided by the user.
Definition: mongo.h:182
MONGO_EXPORT int gridfs_init(mongo *client, const char *dbname, const char *prefix, gridfs *gfs)
Initializes a GridFS object.
Definition: mongo.c:557
MONGO_EXPORT int mongo_cursor_destroy(mongo_cursor *cursor)
Definition: mongo.c:3158
#define MAX(x, y)
Definition: rpmevr.c:28
int err
Bitfield representing errors or warnings on this buffer.
Definition: bson.h:119
const char const bson mongo_write_concern * custom_write_concern
Definition: mongo.h:463
MONGO_EXPORT const char * mongo_get_primary(mongo *conn)
Definition: mongo.c:1801
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
The command returned with 'ok' value of 0.
Definition: mongo.h:78
MONGO_EXPORT bson * mongo_write_concern_get_cmd(mongo_write_concern *write_concern)
Definition: mongo.c:2870
MONGO_EXPORT SOCKET mongo_get_socket(mongo *conn)
Definition: mongo.c:1809
MONGO_EXPORT int mongo_connect(mongo *conn, const char *host, int port)
Definition: mongo.c:2187
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest context.
Definition: digest.c:247
const bson * obj
Definition: bson.h:269
bson_sprintf_func bson_sprintf
Definition: bson.c:373
const char const bson * cond
Definition: mongo.h:505
MONGO_EXPORT void gridfile_dealloc(gridfile *gf)
Definition: mongo.c:499
static int mongo_env_read_socket(mongo *conn, void *buf, size_t len)
Definition: mongo.c:1622
MONGO_EXPORT int mongo_remove(mongo *conn, const char *ns, const bson *cond, mongo_write_concern *custom_write_concern)
Definition: mongo.c:2734
MONGO_EXPORT void mongo_cursor_set_fields(mongo_cursor *cursor, const bson *fields)
Definition: mongo.c:3074
Definition: bson.h:93
#define MONGO_OK
Definition: mongo.h:53
static const int ZERO
Definition: mongo.c:2020
const char int time
Definition: bson.h:1005
static int mongo_message_send(mongo *conn, mongo_message *mm)
Definition: mongo.c:2042
MONGO_EXPORT const char * mongo_get_host(mongo *conn, int i)
Definition: mongo.c:1826
static gridfs_offset gridfile_load_from_chunks(gridfile *gfile, int total_chunks, gridfs_offset chunksize, mongo_cursor *chunks, char *buf, gridfs_offset bytes_left)
Definition: mongo.c:1412
MONGO_EXPORT int gridfs_remove_filename(gridfs *gfs, const char *filename)
Removes the files referenced by filename from the db.
Definition: mongo.c:783
Definition: bson.h:90
mongo_write_concern * write_concern
Definition: mongo.h:419
static char * mongo_data_append64(char *start, const void *data)
Definition: mongo.c:2124
gridfs_offset pos
The GridFile's bson object where all its metadata is located
Definition: mongo.c:72
MONGO_EXPORT int mongo_check_connection(mongo *conn)
Definition: mongo.c:2451
const char const char * field
Definition: mongo.h:734
int bson_iterator_string_len(const bson_iterator *i)
Get the string length of the BSON object currently pointed to by the iterator.
Definition: bson.c:853
MONGO_EXPORT void mongo_cursor_set_limit(mongo_cursor *cursor, int limit)
Definition: mongo.c:3082
const char * ns
owned by cursor
Definition: mongo.h:209
int len
Definition: mongo.h:140
MONGO_EXPORT int mongo_write_concern_get_fsync(mongo_write_concern *write_concern)
Definition: mongo.c:2862
int bson_init_size(bson *b, int size)
Initialize a BSON object for building and allocate a data buffer of a given size. ...
Definition: bson.c:941
static size_t gridfs_default_pending_data_size(int flags)
Definition: mongo.c:514
bson * cmd
The BSON object representing the getlasterror command.
Definition: mongo.h:178
BSON object has not been finished.
Definition: mongo.h:82
int errno
rpmmgo rpmmgoNew(const char *fn, int flags)
Create and load a mongo wrapper.
Definition: mongo.c:3576
const char bson_date_t millis
Definition: bson.h:1017
MONGO_EXPORT void mongo_replset_init(mongo *conn, const char *name)
Definition: mongo.c:2210
const char * files_ns
The prefix of the GridFS's collections, default is NULL
Definition: mongo.c:63
static bson * chunk_new(bson_oid_t id, int chunkNumber, char **dataBuf, const char *srcData, size_t len, int flags)
Definition: mongo.c:529
bson bson_bool_t copyData
Definition: bson.h:491
MONGO_EXPORT gridfs_offset gridfile_truncate(gridfile *gfile, gridfs_offset newSize)
Definition: mongo.c:1513
char objs
Definition: mongo.h:161
Connection success!
Definition: mongo.h:67
const char * buffer
Definition: bson.h:289
MONGO_EXPORT int mongo_find_one(mongo *conn, const char *ns, const bson *query, const bson *fields, bson *out)
Definition: mongo.c:3043
MONGO_EXPORT void gridfile_get_metadata(const gridfile *gfile, bson *metadata, bson_bool_t copyData)
Returns the metadata of GridFile.
Definition: mongo.c:1113
static gridfs_offset gridfile_fill_buf_from_chunk(gridfile *gfile, const bson *chunk, gridfs_offset chunksize, char **buf, int *allocatedMem, char **targetBuf, size_t *targetBufLen, gridfs_offset *bytes_left, int chunkNo)
Definition: mongo.c:1432
static int mongo_env_set_socket_op_timeout(mongo *conn, int millis)
Definition: mongo.c:1637
mongo * client
Definition: mongo.c:60
int chunk_num
The length of this gridfile
Definition: mongo.c:77
int dataSize
The number of bytes allocated to char *data.
Definition: bson.h:116
bson_bool_t caseInsensitive
Definition: mongo.c:65
MONGO_EXPORT const char * mongo_cursor_data(mongo_cursor *cursor)
Definition: mongo.c:3090
BSON not valid for the specified op.
Definition: mongo.h:81
bson_oid_t id
The position is the offset in the file
Definition: mongo.c:73
MONGO_EXPORT int mongo_set_op_timeout(mongo *conn, int millis)
Definition: mongo.c:2428
int chunkSize
Store here special flags such as: No MD5 calculation and Zlib Compression enabled ...
Definition: mongo.c:81
int op_timeout_ms
Read and write timeout in milliseconds.
Definition: mongo.h:194
int lasterrcode
getlasterror code from the server.
Definition: mongo.h:202
static void gridfile_init_flags(gridfile *gfile)
Definition: mongo.c:949
mongo_replica_set * replica_set
replica_set object if connected to a replica set.
Definition: mongo.h:190
char * data
Pointer to a block of data in this BSON object.
Definition: bson.h:114
MONGO_EXPORT const char * gridfile_get_filename(const gridfile *gfile)
Returns the filename of GridFile.
Definition: mongo.c:1032
static int mongo_message_send_and_check_write_concern(mongo *conn, const char *ns, mongo_message *mm, mongo_write_concern *write_concern)
Definition: mongo.c:2593
MONGO_EXPORT gridfs_offset gridfile_write_buffer(gridfile *gfile, const char *data, gridfs_offset length)
Write to a GridFS file incrementally.
Definition: mongo.c:1220
static int mongo_env_sock_init(void)
Definition: mongo.c:1595
Given rs name doesn't match this replica set.
Definition: mongo.h:72
#define MONGO_EXPORT
Definition: bson.h:42
MONGO_EXPORT int gridfile_get_flags(const gridfile *gfile)
gets the flags of the GridFile
Definition: mongo.c:1091
static int mongo_cursor_op_query(mongo_cursor *cursor)
Definition: mongo.c:2896
int flags
Length of pending_data buffer
Definition: mongo.c:80
Definition: mongo.c:59
MONGO_EXPORT mongo_write_concern * mongo_write_concern_alloc(void)
Definition: mongo.c:1839
int fsync
Definition: mongo.h:439
int limit
Bitfield containing cursor options.
Definition: mongo.h:217
static char * mongo_data_append(char *start, const void *data, size_t len)
Definition: mongo.c:2114
The server returned an '$err' object, indicating query failure.
Definition: mongo.h:91
mongo_header head
Definition: mongo.h:159
MONGO_EXPORT const char * gridfile_get_field(gridfile *gfile, const char *name)
Returns the field in GridFile specified by name.
Definition: mongo.c:1095
const char * str
Definition: bson.h:593
Yet Another syslog(3) API clone.
static int mongo_check_last_error(mongo *conn, const char *ns, mongo_write_concern *write_concern)
Definition: mongo.c:2542
MONGO_EXPORT void mongo_init_sockets(void)
Definition: mongo.c:2156
#define MONGO_ERROR
Definition: mongo.h:54
MONGO_EXPORT void mongo_write_concern_set_w(mongo_write_concern *write_concern, int w)
Definition: mongo.c:2874
MONGO_EXPORT void gridfs_set_caseInsensitive(gridfs *gfs, bson_bool_t newValue)
Sets the caseInsensitive flag value of gfs.
Definition: mongo.c:640
mongo * conn
connection is not owned by cursor
Definition: mongo.h:208
gridfs * gfs
Definition: mongo.c:70
static void chunk_free(bson *oChunk)
Definition: mongo.c:544
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:986
mongo_reply_fields fields
Definition: mongo.h:160
static void rpmmgoFini(void *_mgo)
Definition: mongo.c:3548
char errstr[128]
String version of error.
Definition: mongo.h:201
mongo * conn
Definition: mongo.h:579
int w
Definition: mongo.h:436
static gridfs_chunk_filter_func gridfs_write_filter
Definition: mongo.c:519
const char * mode
Definition: mongo.h:440
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
MONGO_EXPORT int mongo_get_host_count(mongo *conn)
Definition: mongo.c:1815
MONGO_EXPORT int mongo_cmd_drop_collection(mongo *conn, const char *db, const char *collection, bson *out)
Definition: mongo.c:3372
uint64_t gridfs_offset
Definition: mongo.c:56
MONGO_EXPORT void mongo_disconnect(mongo *conn)
Definition: mongo.c:2458
static int gridfile_flush_pendingchunk(gridfile *gfile)
Definition: mongo.c:1159
MONGO_EXPORT void mongo_cmd_reset_error(mongo *conn, const char *db)
Definition: mongo.c:3376
static void gridfile_init_chunkSize(gridfile *gfile)
Definition: mongo.c:925
MONGO_EXPORT const char * gridfile_get_md5(const gridfile *gfile)
Returns the MD5 of GridFile.
Definition: mongo.c:1078
MONGO_EXPORT void mongo_write_concern_init(mongo_write_concern *write_concern)
Definition: mongo.c:2778
#define MONGO_DEFAULT_PORT
Definition: mongo.h:56
MONGO_EXPORT mongo_cursor * mongo_cursor_alloc(void)
Definition: mongo.c:1849
The cursor has timed out or is not recognized.
Definition: mongo.h:89
bson_printf_func bson_errprintf
Definition: bson.c:376
static int mongo_env_socket_connect(mongo *conn, const char *host, int port)
Definition: mongo.c:1685
Tailable cursor still alive but no data.
Definition: mongo.h:90
static gridfs_chunk_filter_func gridfs_read_filter
Definition: mongo.c:520
mongo_error_t err
Definition: mongo.h:922
const char const bson * command
Definition: mongo.h:762
const char const bson * data
Definition: mongo.h:463
MONGO_EXPORT void mongo_clear_errors(mongo *conn)
Definition: mongo.c:1881
MONGO_EXPORT void mongo_cursor_set_query(mongo_cursor *cursor, const bson *query)
Definition: mongo.c:3070
static void gridfile_prepare_chunk_key_bson(bson *q, bson_oid_t *id, int chunk_num)
Definition: mongo.c:1152
MONGO_EXPORT void mongo_replset_add_seed(mongo *conn, const char *host, int port)
Definition: mongo.c:2248
MONGO_EXPORT void mongo_write_concern_destroy(mongo_write_concern *write_concern)
Free the write_concern object (specifically, the BSON object that it holds).
Definition: mongo.c:2833
const char const bson const bson int limit
Definition: mongo.h:569
int seen
Number returned so far.
Definition: mongo.h:211
The name for the ns (database or collection) is invalid.
Definition: mongo.h:80
MONGO_EXPORT void __mongo_set_error(mongo *conn, mongo_error_t err, const char *str, int errcode)
Definition: mongo.c:1868
static mongo_write_concern WC1
Definition: mongo.c:2165
size_t pending_len
A buffer storing data still to be written to chunks
Definition: mongo.c:79
mongo_host_port * primary
Primary connection info.
Definition: mongo.h:189
int errcode
Most recent errno or WSAGetLastError().
Definition: mongo.h:200
static int mongo_pass_digest(mongo *conn, const char *user, const char *pass, char hex_digest[33])
Definition: mongo.c:3435
static const char * file
Definition: parseFiles.c:20
Definition: bson.h:113
static int mongo_bson_valid(mongo *conn, const bson *bson, int write)
Definition: mongo.c:2491
MONGO_EXPORT int mongo_write_concern_get_j(mongo_write_concern *write_concern)
Definition: mongo.c:2858
MONGO_EXPORT int mongo_insert_batch(mongo *conn, const char *ns, const bson **bsons, int count, mongo_write_concern *custom_write_concern, int flags)
Definition: mongo.c:2643
mongo_reply * reply
reply is owned by cursor
Definition: mongo.h:207
MONGO_EXPORT void mongo_write_concern_set_fsync(mongo_write_concern *write_concern, int fsync)
Definition: mongo.c:2887
MONGO_EXPORT int gridfile_get_chunksize(const gridfile *gfile)
Returns the size of the chunks of the GridFile.
Definition: mongo.c:1043
Digest private data.
Definition: digest.c:130
MONGO_EXPORT int mongo_cursor_next(mongo_cursor *cursor)
Definition: mongo.c:3098
MONGO_EXPORT int mongo_cmd_get_last_error(mongo *conn, const char *db, bson *out)
Definition: mongo.c:3412
MONGO_EXPORT int mongo_is_connected(mongo *conn)
Definition: mongo.c:1784
mongo_cursor_error_t err
Errors on this cursor.
Definition: mongo.h:213
const char const bson const bson int int skip
Definition: mongo.h:569
const char const bson const bson * fields
Definition: mongo.h:569
#define INDEX_NAME_BUFFER_SIZE
Definition: mongo.c:3194
const char const char const char * pass
Definition: mongo.h:828
static int mongo_replica_set_check_host(mongo *conn)
Definition: mongo.c:2320
BSON object exceeds max BSON size.
Definition: mongo.h:83
static int gridfile_remove_chunks(gridfile *gfile, int deleteFromChunk)
Definition: mongo.c:1495
const char const char * user
Definition: mongo.h:828
int mongo_env_close_socket(SOCKET socket)
Definition: mongo.c:1591
MONGO_EXPORT int mongo_insert(mongo *conn, const char *ns, const bson *bson, mongo_write_concern *custom_write_concern)
Definition: mongo.c:2606
MONGO_EXPORT int gridfs_find_filename(gridfs *gfs, const char *filename, gridfile *gfile)
Find the first file referenced by filename within the GridFS and return it as a GridFile.
Definition: mongo.c:854
static const char * _get_host_port(mongo_host_port *hp)
Definition: mongo.c:1794
static int mongo_choose_write_concern(mongo *conn, mongo_write_concern *custom_write_concern, mongo_write_concern **write_concern)
Definition: mongo.c:2566
char * pending_data
The number of the current chunk being written to
Definition: mongo.c:78
Write with given write_concern returned an error.
Definition: mongo.h:79
MONGO_EXPORT int mongo_cmd_get_prev_error(mongo *conn, const char *db, bson *out)
Definition: mongo.c:3408
MONGO_EXPORT int mongo_run_command(mongo *conn, const char *db, const bson *command, bson *out)
Definition: mongo.c:3304
char * name
Name of the replica set.
Definition: mongo.h:184
MONGO_EXPORT int mongo_cmd_drop_db(mongo *conn, const char *db)
Definition: mongo.c:3368
MONGO_EXPORT void gridfile_get_descriptor(gridfile *gf, bson *out)
Definition: mongo.c:503
MONGO_EXPORT void gridfile_set_flags(gridfile *gfile, int flags)
Sets the flags of the GridFile.
Definition: mongo.c:1087
const char const bson const bson * op
Definition: mongo.h:505
MONGO_EXPORT bson_date_t gridfile_get_uploaddate(const gridfile *gfile)
Returns the upload date of GridFile.
Definition: mongo.c:1069
MONGO_EXPORT int gridfile_writer_init(gridfile *gfile, gridfs *gfs, const char *remote_name, const char *content_type, int flags)
Initializes a gridfile for writing incrementally with gridfs_write_buffer.
Definition: mongo.c:958
const char const char * collection
Definition: mongo.h:749
#define INDEX_NAME_MAX_LENGTH
Definition: mongo.c:3195
gridfile_storage_type
Definition: mongo.c:84
static int mongo_cmd_get_error_helper(mongo *conn, const char *db, bson *realout, const char *cmdtype)
Definition: mongo.c:3380
MONGO_EXPORT gridfile * gridfile_create(void)
Definition: mongo.c:493
void mongo_parse_host(const char *host_string, mongo_host_port *host_port)
Utility function for converting a host-port string to a mongo_host_port.
Definition: mongo.c:2253
MONGO_EXPORT int gridfile_get_numchunks(const gridfile *gfile)
Returns the number of chunks in the GridFile.
Definition: mongo.c:1126
static const int ONE
Definition: mongo.c:2021
static int gridfile_load_pending_data_with_pos_chunk(gridfile *gfile)
Definition: mongo.c:1185
const char const char int arg
Definition: mongo.h:777
MONGO_EXPORT gridfs_offset gridfile_set_size(gridfile *gfile, gridfs_offset newSize)
Definition: mongo.c:1569
static const int zero
Definition: mongo.c:48
static int mongo_env_write_socket(mongo *conn, const void *buf, size_t len)
Definition: mongo.c:1599
const char * host
Definition: mongo.h:251
static bson WC1_cmd
Definition: mongo.c:2162
void bson_little_endian32(void *outp, const void *inp)
Definition: bson.c:55
MONGO_EXPORT void mongo_init(mongo *conn)
Definition: mongo.c:2167
#define MAXHOSTNAMELEN
Definition: mongo.h:63
MONGO_EXPORT int mongo_simple_str_command(mongo *conn, const char *db, const char *cmdstr, const char *arg, bson *out)
Definition: mongo.c:3352
MONGO_EXPORT int mongo_replica_set_client(mongo *conn)
Definition: mongo.c:2358
char lasterrstr[128]
getlasterror string from the server.
Definition: mongo.h:203
int responseTo
Definition: mongo.h:142
MONGO_EXPORT const char * gridfile_get_contenttype(const gridfile *gfile)
Returns the MIME type of the GridFile.
Definition: mongo.c:1060
MONGO_EXPORT int mongo_update(mongo *conn, const char *ns, const bson *cond, const bson *op, int flags, mongo_write_concern *custom_write_concern)
Definition: mongo.c:2693
MONGO_EXPORT int mongo_simple_int_command(mongo *conn, const char *db, const char *cmdstr, int arg, bson *out)
Definition: mongo.c:3335
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
Can't find primary in replica set.
Definition: mongo.h:73
MONGO_EXPORT bson_bool_t mongo_create_simple_index(mongo *conn, const char *ns, const char *field, int options, bson *out)
Definition: mongo.c:3249
MONGO_EXPORT void mongo_write_concern_set_j(mongo_write_concern *write_concern, int j)
Definition: mongo.c:2883
The response is not the expected length.
Definition: mongo.h:77
MONGO_EXPORT gridfs_offset gridfile_read_buffer(gridfile *gfile, char *buf, gridfs_offset size)
Reads length bytes from the GridFile to a buffer and updates the position in the file.
Definition: mongo.c:1354
MONGO_EXPORT void mongo_set_write_concern(mongo *conn, mongo_write_concern *write_concern)
Definition: mongo.c:2844
mongo_header head
Definition: mongo.h:147
mongo_host_port * hosts
List of host/ports given by the replica set.
Definition: mongo.h:183
bson_bool_t connected
Connection status.
Definition: mongo.h:196
const char * prefix
The root database name
Definition: mongo.c:62
int wtimeout
Number of milliseconds before replication timeout.
Definition: mongo.h:173
MONGO_EXPORT int gridfs_store_buffer(gridfs *gfs, const char *data, gridfs_offset length, const char *remotename, const char *contenttype, int flags)
Store a buffer as a GridFS file.
Definition: mongo.c:723
#define INVALID_SOCKET
Definition: mongo.c:1582
void bson_fatal_msg(int ok, const char *msg)
Exit fatally with an error message.
Definition: bson.c:1442
MONGO_EXPORT void mongo_cursor_set_options(mongo_cursor *cursor, int options)
Definition: mongo.c:3086
Warning: key starts with '$' character.
Definition: bson.h:70
MONGO_EXPORT int gridfs_store_file(gridfs *gfs, const char *filename, const char *remotename, const char *contenttype, int flags)
Open the file referenced by filename and store it as a GridFS file.
Definition: mongo.c:738
int skip
Bitfield containing cursor options.
Definition: mongo.h:218
MONGO_EXPORT bson_bool_t mongo_cmd_authenticate(mongo *conn, const char *db, const char *user, const char *pass)
Definition: mongo.c:3491
int wtimeout
Definition: mongo.h:437
int64_t cursorID
Definition: mongo.h:153
int flags
Flags used internally by this drivers.
Definition: mongo.h:210
An error occured while calling getaddrinfo().
Definition: mongo.h:70
const char const int i
Definition: bson.h:778
bson_bool_t finished
When finished, the BSON object can no longer be modified.
Definition: bson.h:117
MONGO_EXPORT double mongo_count(mongo *conn, const char *db, const char *coll, const bson *query)
Definition: mongo.c:3283
const char const bson * query
Definition: mongo.h:569
rpmmgo _rpmmgoI
Definition: mongo.c:45
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
MONGO_EXPORT void mongo_replica_set_init(mongo *conn, const char *name)
Definition: mongo.c:2195
const char const bson * key
Definition: mongo.h:717
const bson * fields
Bitfield containing cursor options.
Definition: mongo.h:215
static const char * prefix[]
Tables for prefixing and suffixing patterns, according to the -w, -x, and -F options.
Definition: rpmgrep.c:183
const char const bson const bson bson * out
Definition: mongo.h:678
const char const char int int max
Definition: mongo.h:749
static int mongo_check_is_master(mongo *conn)
Definition: mongo.c:2131
Initial query has been sent.
Definition: mongo.h:99
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
MONGO_EXPORT bson_bool_t gridfs_get_caseInsensitive(const gridfs *gfs)
Returns the caseInsensitive flag value of gfs.
Definition: mongo.c:636
MONGO_EXPORT gridfs_offset gridfile_expand(gridfile *gfile, gridfs_offset bytesToExpand)
Definition: mongo.c:1541
bson * meta
The GridFS where the GridFile is located
Definition: mongo.c:71
MONGO_EXPORT void gridfile_destroy(gridfile *gfile)
Destroys the GridFile.
Definition: mongo.c:1005
MONGO_EXPORT bson_bool_t gridfile_exists(const gridfile *gfile)
Returns whether or not the GridFile exists.
Definition: mongo.c:1027
const char * dbname
The client to db-connection.
Definition: mongo.c:61
MONGO_EXPORT gridfs * gridfs_alloc(void)
Definition: mongo.c:485
const char const char size_t size
Definition: bson.h:895
static void mongo_replica_set_add_node(mongo_host_port **list, const char *host, int port)
Definition: mongo.c:2215
int j
If non-zero, block until the journal sync.
Definition: mongo.h:174
int bson_bool_t
Definition: bson.h:106
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
MONGO_EXPORT int mongo_create_capped_collection(mongo *conn, const char *db, const char *collection, int size, int max, bson *out)
Definition: mongo.c:3262
MONGO_EXPORT void mongo_cursor_init(mongo_cursor *cursor, mongo *conn, const char *ns)
Definition: mongo.c:3062
MONGO_EXPORT mongo_cursor * gridfile_get_chunks(gridfile *gfile, size_t start, size_t size)
Returns a mongo_cursor of size chunks starting with chunk start
Definition: mongo.c:1305
Warning: connected to a non-master node (read-only).
Definition: mongo.h:71
MONGO_EXPORT void gridfs_set_chunk_filter_funcs(gridfs_chunk_filter_func writeFilter, gridfs_chunk_filter_func readFilter, gridfs_pending_data_size_func pendingDataNeededSize)
Definition: mongo.c:523
const char * db
Definition: mongo.h:697
char host[256]
Definition: mongo.h:166
static gridfs_offset gridfile_read_from_pending_buffer(gridfile *gfile, gridfs_offset totalBytesToRead, char *buf, int *first_chunk)
Definition: mongo.c:1394
Definition: bson.h:99
static int mongo_cursor_get_more(mongo_cursor *cursor)
Definition: mongo.c:2963
static int mongo_cursor_bson_valid(mongo_cursor *cursor, const bson *bson)
Definition: mongo.c:2526
static int mongo_read_response(mongo *conn, mongo_reply **reply)
Definition: mongo.c:2066
MONGO_EXPORT const bson * mongo_cursor_bson(mongo_cursor *cursor)
Definition: mongo.c:3094
static int mongo_env_unix_socket_connect(mongo *conn, const char *sock_path)
Definition: mongo.c:1656
MONGO_EXPORT const char * mongo_write_concern_get_mode(mongo_write_concern *write_concern)
Definition: mongo.c:2866
MONGO_EXPORT void mongo_cursor_set_skip(mongo_cursor *cursor, int skip)
Definition: mongo.c:3078
MONGO_EXPORT int mongo_validate_ns(mongo *conn, const char *ns)
Definition: mongo.c:1906
MONGO_EXPORT void mongo_write_concern_dealloc(mongo_write_concern *write_concern)
Definition: mongo.c:1844
MONGO_EXPORT void mongo_destroy(mongo *conn)
Definition: mongo.c:2474
int op
Definition: mongo.h:143
struct mongo_host_port * next
Definition: mongo.h:168
bson_bool_t primary_connected
Primary node connection status.
Definition: mongo.h:185
char * remote_name
The files_id of the gridfile
Definition: mongo.c:74
MONGO_EXPORT int mongo_write_concern_get_w(mongo_write_concern *write_concern)
Definition: mongo.c:2850
Definition: bson.h:83
Definition: mongo.c:69
MONGO_EXPORT void mongo_cursor_dealloc(mongo_cursor *cursor)
Definition: mongo.c:1854
static mongo_message * mongo_message_create(size_t len, int id, int responseTo, int op)
Definition: mongo.c:2022
int rpmDigestFinal(DIGEST_CTX ctx, void *datap, size_t *lenp, int asAscii)
Return digest and destroy context.
Definition: digest.c:1000
MONGO_EXPORT int mongo_replset_connect(mongo *conn)
Definition: mongo.c:2420
const char * mode
Either "majority" or a getlasterrormode.
Definition: mongo.h:176
static const char * name
#define MONGO_DEFAULT_MAX_BSON_SIZE
Definition: mongo.h:58
Definition: mongo.h:188
bson current
This cursor's current bson object.
Definition: mongo.h:212
MONGO_EXPORT int gridfile_writer_done(gridfile *gfile)
Signal that writing of this gridfile is complete by writing any buffered chunks along with the entry ...
Definition: mongo.c:897
MONGO_EXPORT int mongo_cmd_add_user(mongo *conn, const char *db, const char *user, const char *pass)
Definition: mongo.c:3456
mongo_error_t err
Most recent driver error code.
Definition: mongo.h:199
void bson_little_endian64(void *outp, const void *inp)
Definition: bson.c:34
Warning: key contains '.
Definition: bson.h:69
MONGO_EXPORT void gridfile_get_chunk(gridfile *gfile, int n, bson *out)
Returns chunk n of GridFile.
Definition: mongo.c:1287
MONGO_EXPORT void mongo_write_concern_set_mode(mongo_write_concern *write_concern, const char *mode)
Definition: mongo.c:2892
size_t SOCKET
Definition: mongo.h:45
MONGO_EXPORT gridfs_offset gridfile_seek(gridfile *gfile, gridfs_offset offset)
Updates the position in the file (If the offset goes beyond the contentlength, the position is update...
Definition: mongo.c:1463
char * content_type
The name of the gridfile as a string
Definition: mongo.c:75
An error occured while calling connect().
Definition: mongo.h:69
static cptr_t current[2]
Definition: rpmrc.c:128
MONGO_EXPORT int mongo_client(mongo *conn, const char *host, int port)
Definition: mongo.c:2173
struct rpmmgo_s * rpmmgo
Definition: mongo.h:27
MONGO_EXPORT int mongo_write_concern_get_wtimeout(mongo_write_concern *write_concern)
Definition: mongo.c:2854
int64_t bson_date_t
Definition: bson.h:134
const char const bson const bson int int int options
Definition: mongo.h:569
#define MONGO_ERR_LEN
Definition: mongo.h:60
MONGO_EXPORT int mongo_get_server_err(mongo *conn)
Definition: mongo.c:1859
int bson_init_finished_data(bson *b, char *data, bson_bool_t ownsData)
Initialize a BSON object for reading and set its data pointer to the provided char*.
Definition: bson.c:408
static int bson_append_string_uppercase(bson *b, const char *name, const char *str, bson_bool_t upperCase)
Definition: mongo.c:644
static void gridfile_init_length(gridfile *gfile)
Definition: mongo.c:937
static void mongo_replica_set_free_list(mongo_host_port **list)
Definition: mongo.c:2231
The cursor has no more results.
Definition: mongo.h:88
MONGO_EXPORT int mongo_create_index(mongo *conn, const char *ns, const bson *key, const char *name, int options, bson *out)
Definition: mongo.c:3197
MONGO_EXPORT int mongo_reconnect(mongo *conn)
Definition: mongo.c:2436
Supplied write concern object is invalid.
Definition: mongo.h:84
static void mongo_replica_set_check_seed(mongo *conn)
Definition: mongo.c:2278
size_t(* gridfs_pending_data_size_func)(int flags)
Definition: mongo.c:97
static char * _strupr(char *str)
Definition: mongo.c:462
MONGO_EXPORT int mongo_get_op_timeout(mongo *conn)
Definition: mongo.c:1789
static int gridfs_default_chunk_filter(char **targetBuf, size_t *targetLen, const char *srcData, size_t srcLen, int flags)
Definition: mongo.c:508
mongo_cursor_destroy should free cursor.
Definition: mongo.h:98
int fsync
Same a j with journaling enabled; otherwise, call fsync.
Definition: mongo.h:175
int(* gridfs_chunk_filter_func)(char **targetBuf, size_t *targetLen, const char *srcBuf, size_t srcLen, int flags)
Definition: mongo.c:96
MONGO_EXPORT const char * mongo_get_server_err_string(mongo *conn)
Definition: mongo.c:1864
char data
Definition: mongo.h:148
MONGO_EXPORT bson_bool_t mongo_cmd_ismaster(mongo *conn, bson *realout)
Definition: mongo.c:3416
#define NI_MAXSERV
Definition: mongo.c:1588
static char * mongo_ns_to_cmd_db(const char *ns)
Definition: mongo.c:1890
int j
Definition: mongo.h:438
mongo_write_concern * write_concern
The default write concern.
Definition: mongo.h:197
MONGO_EXPORT mongo * mongo_alloc(void)
Definition: mongo.c:1770
MONGO_EXPORT void mongo_dealloc(mongo *conn)
Definition: mongo.c:1775
const char * ns
Definition: mongo.h:326
MONGO_EXPORT mongo_cursor * mongo_find(mongo *conn, const char *ns, const bson *query, const bson *fields, int limit, int skip, int options)
Definition: mongo.c:3022
static gridfs_pending_data_size_func gridfs_pending_data_size
Definition: mongo.c:521
MONGO_EXPORT int mongo_write_concern_finish(mongo_write_concern *write_concern)
Definition: mongo.c:2782
rpmioPool _rpmmgoPool
Definition: mongo.c:3558
Something is wrong with the BSON provided.
Definition: mongo.h:93