libmongo-client 0.1.4
|
00001 /* mongo-sync.c - libmongo-client synchronous wrapper API 00002 * Copyright 2011 Gergely Nagy <algernon@balabit.hu> 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00021 #include "config.h" 00022 #include "mongo.h" 00023 #include "libmongo-private.h" 00024 00025 #include <stdlib.h> 00026 #include <errno.h> 00027 #include <string.h> 00028 #include <unistd.h> 00029 00030 mongo_sync_connection * 00031 mongo_sync_connect (const gchar *host, gint port, 00032 gboolean slaveok) 00033 { 00034 mongo_sync_connection *s; 00035 mongo_connection *c; 00036 00037 c = mongo_connect (host, port); 00038 if (!c) 00039 return NULL; 00040 s = g_realloc (c, sizeof (mongo_sync_connection)); 00041 00042 s->slaveok = slaveok; 00043 s->safe_mode = FALSE; 00044 s->auto_reconnect = FALSE; 00045 s->rs.seeds = g_list_append (NULL, g_strdup_printf ("%s:%d", host, port)); 00046 s->rs.hosts = NULL; 00047 s->rs.primary = NULL; 00048 s->last_error = NULL; 00049 s->max_insert_size = MONGO_SYNC_DEFAULT_MAX_INSERT_SIZE; 00050 00051 return s; 00052 } 00053 00054 gboolean 00055 mongo_sync_conn_seed_add (mongo_sync_connection *conn, 00056 const gchar *host, gint port) 00057 { 00058 if (!conn) 00059 { 00060 errno = ENOTCONN; 00061 return FALSE; 00062 } 00063 if (!host || port < 0) 00064 { 00065 errno = EINVAL; 00066 return FALSE; 00067 } 00068 00069 conn->rs.seeds = g_list_append (conn->rs.seeds, 00070 g_strdup_printf ("%s:%d", host, port)); 00071 return TRUE; 00072 } 00073 00074 static void 00075 _mongo_sync_connect_replace (mongo_sync_connection *old, 00076 mongo_sync_connection *new) 00077 { 00078 GList *l; 00079 00080 if (!old || !new) 00081 return; 00082 00083 g_free (old->rs.primary); 00084 00085 /* Delete the host list. */ 00086 l = old->rs.hosts; 00087 while (l) 00088 { 00089 g_free (l->data); 00090 l = g_list_delete_link (l, l); 00091 } 00092 old->rs.hosts = NULL; 00093 00094 if (old->super.fd) 00095 close (old->super.fd); 00096 00097 old->super.fd = new->super.fd; 00098 old->super.request_id = -1; 00099 old->slaveok = new->slaveok; 00100 old->rs.primary = NULL; 00101 g_free (old->last_error); 00102 old->last_error = NULL; 00103 00104 /* Free the replicaset struct in the new connection. These aren't 00105 copied, in order to avoid infinite loops. */ 00106 l = new->rs.hosts; 00107 while (l) 00108 { 00109 g_free (l->data); 00110 l = g_list_delete_link (l, l); 00111 } 00112 l = new->rs.seeds; 00113 while (l) 00114 { 00115 g_free (l->data); 00116 l = g_list_delete_link (l, l); 00117 } 00118 g_free (new->rs.primary); 00119 g_free (new->last_error); 00120 g_free (new); 00121 } 00122 00123 mongo_sync_connection * 00124 mongo_sync_reconnect (mongo_sync_connection *conn, 00125 gboolean force_master) 00126 { 00127 gboolean ping = FALSE; 00128 guint i; 00129 mongo_sync_connection *nc; 00130 gchar *host; 00131 gint port; 00132 00133 if (!conn) 00134 { 00135 errno = ENOTCONN; 00136 return NULL; 00137 } 00138 00139 ping = mongo_sync_cmd_ping (conn); 00140 00141 if (ping) 00142 { 00143 if (!force_master) 00144 return conn; 00145 if (force_master && mongo_sync_cmd_is_master (conn)) 00146 return conn; 00147 00148 /* Force refresh the host list. */ 00149 mongo_sync_cmd_is_master (conn); 00150 } 00151 00152 /* We either didn't ping, or we're not master, and have to 00153 * reconnect. 00154 * 00155 * First, check if we have a primary, and if we can connect there. 00156 */ 00157 00158 if (conn->rs.primary) 00159 { 00160 if (mongo_util_parse_addr (conn->rs.primary, &host, &port)) 00161 { 00162 nc = mongo_sync_connect (host, port, conn->slaveok); 00163 g_free (host); 00164 if (nc) 00165 { 00166 int e; 00167 00168 /* We can call ourselves here, since connect does not set 00169 conn->rs, thus, we won't end up in an infinite loop. */ 00170 nc = mongo_sync_reconnect (nc, force_master); 00171 e = errno; 00172 _mongo_sync_connect_replace (conn, nc); 00173 errno = e; 00174 return conn; 00175 } 00176 } 00177 } 00178 00179 /* No primary found, or we couldn't connect, try the rest of the 00180 hosts. */ 00181 00182 for (i = 0; i < g_list_length (conn->rs.hosts); i++) 00183 { 00184 gchar *addr = (gchar *)g_list_nth_data (conn->rs.hosts, i); 00185 int e; 00186 00187 if (!mongo_util_parse_addr (addr, &host, &port)) 00188 continue; 00189 00190 nc = mongo_sync_connect (host, port, conn->slaveok); 00191 g_free (host); 00192 if (!nc) 00193 continue; 00194 00195 nc = mongo_sync_reconnect (nc, force_master); 00196 e = errno; 00197 _mongo_sync_connect_replace (conn, nc); 00198 errno = e; 00199 return conn; 00200 } 00201 00202 /* And if that failed too, try the seeds. */ 00203 00204 for (i = 0; i < g_list_length (conn->rs.seeds); i++) 00205 { 00206 gchar *addr = (gchar *)g_list_nth_data (conn->rs.seeds, i); 00207 int e; 00208 00209 if (!mongo_util_parse_addr (addr, &host, &port)) 00210 continue; 00211 00212 nc = mongo_sync_connect (host, port, conn->slaveok); 00213 g_free (host); 00214 if (!nc) 00215 continue; 00216 00217 nc = mongo_sync_reconnect (nc, force_master); 00218 e = errno; 00219 _mongo_sync_connect_replace (conn, nc); 00220 errno = e; 00221 return conn; 00222 } 00223 00224 errno = EHOSTUNREACH; 00225 return NULL; 00226 } 00227 00228 void 00229 mongo_sync_disconnect (mongo_sync_connection *conn) 00230 { 00231 GList *l; 00232 00233 if (!conn) 00234 return; 00235 00236 g_free (conn->rs.primary); 00237 g_free (conn->last_error); 00238 00239 /* Delete the host list. */ 00240 l = conn->rs.hosts; 00241 while (l) 00242 { 00243 g_free (l->data); 00244 l = g_list_delete_link (l, l); 00245 } 00246 00247 /* Delete the seed list. */ 00248 l = conn->rs.seeds; 00249 while (l) 00250 { 00251 g_free (l->data); 00252 l = g_list_delete_link (l, l); 00253 } 00254 00255 mongo_disconnect ((mongo_connection *)conn); 00256 } 00257 00258 gint32 00259 mongo_sync_conn_get_max_insert_size (mongo_sync_connection *conn) 00260 { 00261 if (!conn) 00262 { 00263 errno = ENOTCONN; 00264 return -1; 00265 } 00266 return conn->max_insert_size; 00267 } 00268 00269 gboolean 00270 mongo_sync_conn_set_max_insert_size (mongo_sync_connection *conn, 00271 gint32 max_size) 00272 { 00273 if (!conn) 00274 { 00275 errno = ENOTCONN; 00276 return FALSE; 00277 } 00278 if (max_size <= 0) 00279 { 00280 errno = ERANGE; 00281 return FALSE; 00282 } 00283 00284 errno = 0; 00285 conn->max_insert_size = max_size; 00286 return TRUE; 00287 } 00288 00289 gboolean 00290 mongo_sync_conn_get_safe_mode (const mongo_sync_connection *conn) 00291 { 00292 if (!conn) 00293 { 00294 errno = ENOTCONN; 00295 return FALSE; 00296 } 00297 00298 errno = 0; 00299 return conn->safe_mode; 00300 } 00301 00302 gboolean 00303 mongo_sync_conn_set_safe_mode (mongo_sync_connection *conn, 00304 gboolean safe_mode) 00305 { 00306 if (!conn) 00307 { 00308 errno = ENOTCONN; 00309 return FALSE; 00310 } 00311 00312 errno = 0; 00313 conn->safe_mode = safe_mode; 00314 return TRUE; 00315 } 00316 00317 gboolean 00318 mongo_sync_conn_get_auto_reconnect (const mongo_sync_connection *conn) 00319 { 00320 if (!conn) 00321 { 00322 errno = ENOTCONN; 00323 return FALSE; 00324 } 00325 00326 errno = 0; 00327 return conn->auto_reconnect; 00328 } 00329 00330 gboolean 00331 mongo_sync_conn_set_auto_reconnect (mongo_sync_connection *conn, 00332 gboolean auto_reconnect) 00333 { 00334 if (!conn) 00335 { 00336 errno = ENOTCONN; 00337 return FALSE; 00338 } 00339 00340 conn->auto_reconnect = auto_reconnect; 00341 return TRUE; 00342 } 00343 00344 gboolean 00345 mongo_sync_conn_get_slaveok (const mongo_sync_connection *conn) 00346 { 00347 if (!conn) 00348 { 00349 errno = ENOTCONN; 00350 return FALSE; 00351 } 00352 00353 errno = 0; 00354 return conn->slaveok; 00355 } 00356 00357 gboolean 00358 mongo_sync_conn_set_slaveok (mongo_sync_connection *conn, 00359 gboolean slaveok) 00360 { 00361 if (!conn) 00362 { 00363 errno = ENOTCONN; 00364 return FALSE; 00365 } 00366 00367 errno = 0; 00368 conn->slaveok = slaveok; 00369 return TRUE; 00370 } 00371 00372 #define _SLAVE_FLAG(c) ((c->slaveok) ? MONGO_WIRE_FLAG_QUERY_SLAVE_OK : 0) 00373 00374 static inline gboolean 00375 _mongo_cmd_ensure_conn (mongo_sync_connection *conn, 00376 gboolean force_master) 00377 { 00378 if (!conn) 00379 { 00380 errno = ENOTCONN; 00381 return FALSE; 00382 } 00383 00384 if (force_master || !conn->slaveok) 00385 { 00386 errno = 0; 00387 if (!mongo_sync_cmd_is_master (conn)) 00388 { 00389 if (errno == EPROTO) 00390 return FALSE; 00391 if (!conn->auto_reconnect) 00392 { 00393 errno = ENOTCONN; 00394 return FALSE; 00395 } 00396 if (!mongo_sync_reconnect (conn, TRUE)) 00397 return FALSE; 00398 } 00399 return TRUE; 00400 } 00401 00402 errno = 0; 00403 if (!mongo_sync_cmd_ping (conn)) 00404 { 00405 if (errno == EPROTO) 00406 return FALSE; 00407 if (!conn->auto_reconnect) 00408 { 00409 errno = ENOTCONN; 00410 return FALSE; 00411 } 00412 if (!mongo_sync_reconnect (conn, FALSE)) 00413 { 00414 errno = ENOTCONN; 00415 return FALSE; 00416 } 00417 } 00418 errno = 0; 00419 return TRUE; 00420 } 00421 00422 static inline gboolean 00423 _mongo_cmd_verify_slaveok (mongo_sync_connection *conn) 00424 { 00425 if (!conn) 00426 { 00427 errno = ENOTCONN; 00428 return FALSE; 00429 } 00430 00431 if (conn->slaveok || !conn->safe_mode) 00432 return TRUE; 00433 00434 errno = 0; 00435 if (!mongo_sync_cmd_is_master (conn)) 00436 { 00437 if (errno == EPROTO) 00438 return FALSE; 00439 if (!conn->auto_reconnect) 00440 { 00441 errno = ENOTCONN; 00442 return FALSE; 00443 } 00444 if (!mongo_sync_reconnect (conn, TRUE)) 00445 return FALSE; 00446 } 00447 return TRUE; 00448 } 00449 00450 static inline gboolean 00451 _mongo_sync_packet_send (mongo_sync_connection *conn, 00452 mongo_packet *p, 00453 gboolean force_master, 00454 gboolean auto_reconnect) 00455 { 00456 gboolean out = FALSE; 00457 00458 if (force_master) 00459 if (!_mongo_cmd_ensure_conn (conn, force_master)) 00460 return FALSE; 00461 00462 for (;;) 00463 { 00464 if (!mongo_packet_send ((mongo_connection *)conn, p)) 00465 { 00466 int e = errno; 00467 00468 if (!auto_reconnect || (conn && !conn->auto_reconnect)) 00469 { 00470 mongo_wire_packet_free (p); 00471 errno = e; 00472 return FALSE; 00473 } 00474 00475 if (out || !mongo_sync_reconnect (conn, force_master)) 00476 { 00477 mongo_wire_packet_free (p); 00478 errno = e; 00479 return FALSE; 00480 } 00481 00482 out = TRUE; 00483 continue; 00484 } 00485 break; 00486 } 00487 mongo_wire_packet_free (p); 00488 return TRUE; 00489 } 00490 00491 static inline mongo_packet * 00492 _mongo_sync_packet_recv (mongo_sync_connection *conn, gint32 rid, gint32 flags) 00493 { 00494 mongo_packet *p; 00495 mongo_packet_header h; 00496 mongo_reply_packet_header rh; 00497 00498 p = mongo_packet_recv ((mongo_connection *)conn); 00499 if (!p) 00500 return NULL; 00501 00502 if (!mongo_wire_packet_get_header_raw (p, &h)) 00503 { 00504 int e = errno; 00505 00506 mongo_wire_packet_free (p); 00507 errno = e; 00508 return NULL; 00509 } 00510 00511 if (h.resp_to != rid) 00512 { 00513 mongo_wire_packet_free (p); 00514 errno = EPROTO; 00515 return NULL; 00516 } 00517 00518 if (!mongo_wire_reply_packet_get_header (p, &rh)) 00519 { 00520 int e = errno; 00521 00522 mongo_wire_packet_free (p); 00523 errno = e; 00524 return NULL; 00525 } 00526 00527 if (rh.flags & flags) 00528 { 00529 mongo_wire_packet_free (p); 00530 errno = EPROTO; 00531 return NULL; 00532 } 00533 00534 if (rh.returned == 0) 00535 { 00536 mongo_wire_packet_free (p); 00537 errno = ENOENT; 00538 return NULL; 00539 } 00540 00541 return p; 00542 } 00543 00544 static gboolean 00545 _mongo_sync_check_ok (bson *b) 00546 { 00547 bson_cursor *c; 00548 gdouble d; 00549 00550 c = bson_find (b, "ok"); 00551 if (!c) 00552 { 00553 errno = ENOENT; 00554 return FALSE; 00555 } 00556 00557 if (!bson_cursor_get_double (c, &d)) 00558 { 00559 bson_cursor_free (c); 00560 errno = EINVAL; 00561 return FALSE; 00562 } 00563 bson_cursor_free (c); 00564 errno = (d == 1) ? 0 : EPROTO; 00565 return (d == 1); 00566 } 00567 00568 static gboolean 00569 _mongo_sync_get_error (const bson *rep, gchar **error) 00570 { 00571 bson_cursor *c; 00572 00573 if (!error) 00574 return FALSE; 00575 00576 c = bson_find (rep, "err"); 00577 if (!c) 00578 { 00579 c = bson_find (rep, "errmsg"); 00580 if (!c) 00581 { 00582 errno = EPROTO; 00583 return FALSE; 00584 } 00585 } 00586 if (bson_cursor_type (c) == BSON_TYPE_NONE || 00587 bson_cursor_type (c) == BSON_TYPE_NULL) 00588 { 00589 *error = NULL; 00590 bson_cursor_free (c); 00591 return TRUE; 00592 } 00593 else if (bson_cursor_type (c) == BSON_TYPE_STRING) 00594 { 00595 const gchar *err; 00596 00597 bson_cursor_get_string (c, &err); 00598 *error = g_strdup (err); 00599 bson_cursor_free (c); 00600 return TRUE; 00601 } 00602 errno = EPROTO; 00603 return FALSE; 00604 } 00605 00606 static mongo_packet * 00607 _mongo_sync_packet_check_error (mongo_sync_connection *conn, mongo_packet *p, 00608 gboolean check_ok) 00609 { 00610 bson *b; 00611 gboolean error; 00612 00613 if (!p) 00614 return NULL; 00615 00616 if (!mongo_wire_reply_packet_get_nth_document (p, 1, &b)) 00617 { 00618 mongo_wire_packet_free (p); 00619 errno = EPROTO; 00620 return NULL; 00621 } 00622 bson_finish (b); 00623 00624 if (check_ok) 00625 { 00626 if (!_mongo_sync_check_ok (b)) 00627 { 00628 int e = errno; 00629 00630 g_free (conn->last_error); 00631 conn->last_error = NULL; 00632 _mongo_sync_get_error (b, &conn->last_error); 00633 bson_free (b); 00634 mongo_wire_packet_free (p); 00635 errno = e; 00636 return NULL; 00637 } 00638 bson_free (b); 00639 return p; 00640 } 00641 00642 g_free (conn->last_error); 00643 conn->last_error = NULL; 00644 error = _mongo_sync_get_error (b, &conn->last_error); 00645 bson_free (b); 00646 00647 if (error) 00648 { 00649 mongo_wire_packet_free (p); 00650 return NULL; 00651 } 00652 return p; 00653 } 00654 00655 static inline gboolean 00656 _mongo_sync_cmd_verify_result (mongo_sync_connection *conn, 00657 const gchar *ns) 00658 { 00659 gchar *error, *db, *tmp; 00660 gboolean res; 00661 00662 if (!conn || !ns) 00663 return FALSE; 00664 if (!conn->safe_mode) 00665 return TRUE; 00666 00667 tmp = g_strstr_len (ns, -1, "."); 00668 if (tmp) 00669 db = g_strndup (ns, tmp - ns); 00670 else 00671 db = g_strdup (ns); 00672 00673 mongo_sync_cmd_get_last_error (conn, db, &error); 00674 g_free (db); 00675 res = (error) ? FALSE : TRUE; 00676 g_free (error); 00677 00678 return res; 00679 } 00680 00681 gboolean 00682 mongo_sync_cmd_update (mongo_sync_connection *conn, 00683 const gchar *ns, 00684 gint32 flags, const bson *selector, 00685 const bson *update) 00686 { 00687 mongo_packet *p; 00688 gint32 rid; 00689 00690 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 00691 00692 p = mongo_wire_cmd_update (rid, ns, flags, selector, update); 00693 if (!p) 00694 return FALSE; 00695 00696 if (!_mongo_sync_packet_send (conn, p, TRUE, TRUE)) 00697 return FALSE; 00698 00699 return _mongo_sync_cmd_verify_result (conn, ns); 00700 } 00701 00702 gboolean 00703 mongo_sync_cmd_insert_n (mongo_sync_connection *conn, 00704 const gchar *ns, gint32 n, 00705 const bson **docs) 00706 { 00707 mongo_packet *p; 00708 gint32 rid; 00709 gint32 pos = 0, c, i = 0; 00710 gint32 size = 0; 00711 00712 if (!conn) 00713 { 00714 errno = ENOTCONN; 00715 return FALSE; 00716 } 00717 00718 if (!ns || !docs) 00719 { 00720 errno = EINVAL; 00721 return FALSE; 00722 } 00723 if (n <= 0) 00724 { 00725 errno = EINVAL; 00726 return FALSE; 00727 } 00728 00729 for (i = 0; i < n; i++) 00730 { 00731 if (bson_size (docs[i]) >= conn->max_insert_size) 00732 { 00733 errno = EMSGSIZE; 00734 return FALSE; 00735 } 00736 } 00737 00738 do 00739 { 00740 i = pos; 00741 c = 0; 00742 00743 while (i < n && size < conn->max_insert_size) 00744 { 00745 size += bson_size (docs[i++]); 00746 c++; 00747 } 00748 size = 0; 00749 if (i < n) 00750 c--; 00751 00752 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 00753 00754 p = mongo_wire_cmd_insert_n (rid, ns, c, &docs[pos]); 00755 if (!p) 00756 return FALSE; 00757 00758 if (!_mongo_sync_packet_send (conn, p, TRUE, TRUE)) 00759 return FALSE; 00760 00761 if (!_mongo_sync_cmd_verify_result (conn, ns)) 00762 return FALSE; 00763 00764 pos += c; 00765 } while (pos < n); 00766 00767 return TRUE; 00768 } 00769 00770 gboolean 00771 mongo_sync_cmd_insert (mongo_sync_connection *conn, 00772 const gchar *ns, ...) 00773 { 00774 gboolean b; 00775 bson **docs, *d; 00776 gint32 n = 0; 00777 va_list ap; 00778 00779 if (!conn) 00780 { 00781 errno = ENOTCONN; 00782 return FALSE; 00783 } 00784 00785 if (!ns) 00786 { 00787 errno = EINVAL; 00788 return FALSE; 00789 } 00790 00791 docs = (bson **)g_new0 (bson *, 1); 00792 00793 va_start (ap, ns); 00794 while ((d = (bson *)va_arg (ap, gpointer))) 00795 { 00796 if (bson_size (d) < 0) 00797 { 00798 g_free (docs); 00799 errno = EINVAL; 00800 return FALSE; 00801 } 00802 00803 docs = (bson **)g_renew (bson *, docs, n + 1); 00804 docs[n++] = d; 00805 } 00806 va_end (ap); 00807 00808 b = mongo_sync_cmd_insert_n (conn, ns, n, (const bson **)docs); 00809 g_free (docs); 00810 return b; 00811 } 00812 00813 mongo_packet * 00814 mongo_sync_cmd_query (mongo_sync_connection *conn, 00815 const gchar *ns, gint32 flags, 00816 gint32 skip, gint32 ret, 00817 const bson *query, const bson *sel) 00818 { 00819 mongo_packet *p; 00820 gint32 rid; 00821 00822 if (!_mongo_cmd_verify_slaveok (conn)) 00823 return FALSE; 00824 00825 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 00826 00827 p = mongo_wire_cmd_query (rid, ns, flags | _SLAVE_FLAG (conn), 00828 skip, ret, query, sel); 00829 if (!p) 00830 return NULL; 00831 00832 if (!_mongo_sync_packet_send (conn, p, 00833 !((conn && conn->slaveok) || 00834 (flags & MONGO_WIRE_FLAG_QUERY_SLAVE_OK)), 00835 TRUE)) 00836 return NULL; 00837 00838 p = _mongo_sync_packet_recv (conn, rid, MONGO_REPLY_FLAG_QUERY_FAIL); 00839 return _mongo_sync_packet_check_error (conn, p, FALSE); 00840 } 00841 00842 mongo_packet * 00843 mongo_sync_cmd_get_more (mongo_sync_connection *conn, 00844 const gchar *ns, 00845 gint32 ret, gint64 cursor_id) 00846 { 00847 mongo_packet *p; 00848 gint32 rid; 00849 00850 if (!_mongo_cmd_verify_slaveok (conn)) 00851 return FALSE; 00852 00853 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 00854 00855 p = mongo_wire_cmd_get_more (rid, ns, ret, cursor_id); 00856 if (!p) 00857 return NULL; 00858 00859 if (!_mongo_sync_packet_send (conn, p, FALSE, TRUE)) 00860 return FALSE; 00861 00862 p = _mongo_sync_packet_recv (conn, rid, MONGO_REPLY_FLAG_NO_CURSOR); 00863 return _mongo_sync_packet_check_error (conn, p, FALSE); 00864 } 00865 00866 gboolean 00867 mongo_sync_cmd_delete (mongo_sync_connection *conn, const gchar *ns, 00868 gint32 flags, const bson *sel) 00869 { 00870 mongo_packet *p; 00871 gint32 rid; 00872 00873 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 00874 00875 p = mongo_wire_cmd_delete (rid, ns, flags, sel); 00876 if (!p) 00877 return FALSE; 00878 00879 return _mongo_sync_packet_send (conn, p, TRUE, TRUE); 00880 } 00881 00882 gboolean 00883 mongo_sync_cmd_kill_cursors (mongo_sync_connection *conn, 00884 gint32 n, ...) 00885 { 00886 mongo_packet *p; 00887 gint32 rid; 00888 va_list ap; 00889 00890 if (n <= 0) 00891 { 00892 errno = EINVAL; 00893 return FALSE; 00894 } 00895 00896 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 00897 00898 va_start (ap, n); 00899 p = mongo_wire_cmd_kill_cursors_va (rid, n, ap); 00900 if (!p) 00901 { 00902 int e = errno; 00903 00904 va_end (ap); 00905 errno = e; 00906 return FALSE; 00907 } 00908 va_end (ap); 00909 00910 return _mongo_sync_packet_send (conn, p, FALSE, TRUE); 00911 } 00912 00913 static mongo_packet * 00914 _mongo_sync_cmd_custom (mongo_sync_connection *conn, 00915 const gchar *db, 00916 const bson *command, 00917 gboolean check_conn, 00918 gboolean force_master) 00919 { 00920 mongo_packet *p; 00921 gint32 rid; 00922 00923 if (!conn) 00924 { 00925 errno = ENOTCONN; 00926 return NULL; 00927 } 00928 00929 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 00930 00931 p = mongo_wire_cmd_custom (rid, db, _SLAVE_FLAG (conn), command); 00932 if (!p) 00933 return NULL; 00934 00935 if (!_mongo_sync_packet_send (conn, p, force_master, check_conn)) 00936 return NULL; 00937 00938 p = _mongo_sync_packet_recv (conn, rid, MONGO_REPLY_FLAG_QUERY_FAIL); 00939 return _mongo_sync_packet_check_error (conn, p, TRUE); 00940 } 00941 00942 mongo_packet * 00943 mongo_sync_cmd_custom (mongo_sync_connection *conn, 00944 const gchar *db, 00945 const bson *command) 00946 { 00947 return _mongo_sync_cmd_custom (conn, db, command, TRUE, FALSE); 00948 } 00949 00950 gdouble 00951 mongo_sync_cmd_count (mongo_sync_connection *conn, 00952 const gchar *db, const gchar *coll, 00953 const bson *query) 00954 { 00955 mongo_packet *p; 00956 bson *cmd; 00957 bson_cursor *c; 00958 gdouble d; 00959 00960 cmd = bson_new_sized (bson_size (query) + 32); 00961 bson_append_string (cmd, "count", coll, -1); 00962 if (query) 00963 bson_append_document (cmd, "query", query); 00964 bson_finish (cmd); 00965 00966 p = _mongo_sync_cmd_custom (conn, db, cmd, TRUE, FALSE); 00967 if (!p) 00968 { 00969 int e = errno; 00970 00971 bson_free (cmd); 00972 errno = e; 00973 return -1; 00974 } 00975 bson_free (cmd); 00976 00977 if (!mongo_wire_reply_packet_get_nth_document (p, 1, &cmd)) 00978 { 00979 int e = errno; 00980 00981 mongo_wire_packet_free (p); 00982 errno = e; 00983 return -1; 00984 } 00985 mongo_wire_packet_free (p); 00986 bson_finish (cmd); 00987 00988 c = bson_find (cmd, "n"); 00989 if (!c) 00990 { 00991 bson_free (cmd); 00992 errno = ENOENT; 00993 return -1; 00994 } 00995 if (!bson_cursor_get_double (c, &d)) 00996 { 00997 bson_free (cmd); 00998 bson_cursor_free (c); 00999 errno = EINVAL; 01000 return -1; 01001 } 01002 bson_cursor_free (c); 01003 bson_free (cmd); 01004 01005 return d; 01006 } 01007 01008 gboolean 01009 mongo_sync_cmd_create (mongo_sync_connection *conn, 01010 const gchar *db, const gchar *coll, 01011 gint flags, ...) 01012 { 01013 mongo_packet *p; 01014 bson *cmd; 01015 01016 if (!conn) 01017 { 01018 errno = ENOTCONN; 01019 return FALSE; 01020 } 01021 if (!db || !coll) 01022 { 01023 errno = EINVAL; 01024 return FALSE; 01025 } 01026 01027 cmd = bson_new_sized (128); 01028 bson_append_string (cmd, "create", coll, -1); 01029 if (flags & MONGO_COLLECTION_AUTO_INDEX_ID) 01030 bson_append_boolean (cmd, "autoIndexId", TRUE); 01031 if (flags & MONGO_COLLECTION_CAPPED || 01032 flags & MONGO_COLLECTION_CAPPED_MAX || 01033 flags & MONGO_COLLECTION_SIZED) 01034 { 01035 va_list ap; 01036 gint64 i; 01037 01038 if (flags & MONGO_COLLECTION_CAPPED || 01039 flags & MONGO_COLLECTION_CAPPED_MAX) 01040 bson_append_boolean (cmd, "capped", TRUE); 01041 01042 va_start (ap, flags); 01043 i = (gint64)va_arg (ap, gint64); 01044 if (i <= 0) 01045 { 01046 bson_free (cmd); 01047 errno = ERANGE; 01048 return FALSE; 01049 } 01050 bson_append_int64 (cmd, "size", i); 01051 01052 if (flags & MONGO_COLLECTION_CAPPED_MAX) 01053 { 01054 i = (gint64)va_arg (ap, gint64); 01055 if (i <= 0) 01056 { 01057 bson_free (cmd); 01058 errno = ERANGE; 01059 return FALSE; 01060 } 01061 bson_append_int64 (cmd, "max", i); 01062 } 01063 va_end (ap); 01064 } 01065 bson_finish (cmd); 01066 01067 p = _mongo_sync_cmd_custom (conn, db, cmd, TRUE, TRUE); 01068 if (!p) 01069 { 01070 int e = errno; 01071 01072 bson_free (cmd); 01073 errno = e; 01074 return FALSE; 01075 } 01076 bson_free (cmd); 01077 mongo_wire_packet_free (p); 01078 01079 return TRUE; 01080 } 01081 01082 bson * 01083 mongo_sync_cmd_exists (mongo_sync_connection *conn, 01084 const gchar *db, const gchar *coll) 01085 { 01086 bson *cmd, *r; 01087 mongo_packet *p; 01088 gchar *ns, *sys; 01089 gint32 rid; 01090 01091 if (!conn) 01092 { 01093 errno = ENOTCONN; 01094 return NULL; 01095 } 01096 if (!db || !coll) 01097 { 01098 errno = EINVAL; 01099 return NULL; 01100 } 01101 01102 rid = mongo_connection_get_requestid ((mongo_connection *)conn) + 1; 01103 01104 ns = g_strconcat (db, ".", coll, NULL); 01105 cmd = bson_new_sized (128); 01106 bson_append_string (cmd, "name", ns, -1); 01107 bson_finish (cmd); 01108 g_free (ns); 01109 01110 sys = g_strconcat (db, ".system.namespaces", NULL); 01111 01112 p = mongo_wire_cmd_query (rid, sys, _SLAVE_FLAG (conn), 0, 1, cmd, NULL); 01113 if (!p) 01114 { 01115 int e = errno; 01116 01117 bson_free (cmd); 01118 g_free (sys); 01119 01120 errno = e; 01121 return NULL; 01122 } 01123 g_free (sys); 01124 bson_free (cmd); 01125 01126 if (!_mongo_sync_packet_send (conn, p, !conn->slaveok, TRUE)) 01127 return NULL; 01128 01129 p = _mongo_sync_packet_recv (conn, rid, MONGO_REPLY_FLAG_QUERY_FAIL); 01130 if (!p) 01131 return NULL; 01132 01133 p = _mongo_sync_packet_check_error (conn, p, FALSE); 01134 if (!p) 01135 return NULL; 01136 01137 if (!mongo_wire_reply_packet_get_nth_document (p, 1, &r)) 01138 { 01139 int e = errno; 01140 01141 mongo_wire_packet_free (p); 01142 errno = e; 01143 return NULL; 01144 } 01145 mongo_wire_packet_free (p); 01146 bson_finish (r); 01147 01148 return r; 01149 } 01150 01151 gboolean 01152 mongo_sync_cmd_drop (mongo_sync_connection *conn, 01153 const gchar *db, const gchar *coll) 01154 { 01155 mongo_packet *p; 01156 bson *cmd; 01157 01158 cmd = bson_new_sized (64); 01159 bson_append_string (cmd, "drop", coll, -1); 01160 bson_finish (cmd); 01161 01162 p = _mongo_sync_cmd_custom (conn, db, cmd, TRUE, TRUE); 01163 if (!p) 01164 { 01165 int e = errno; 01166 01167 bson_free (cmd); 01168 errno = e; 01169 return FALSE; 01170 } 01171 bson_free (cmd); 01172 mongo_wire_packet_free (p); 01173 01174 return TRUE; 01175 } 01176 01177 gboolean 01178 mongo_sync_cmd_get_last_error (mongo_sync_connection *conn, 01179 const gchar *db, gchar **error) 01180 { 01181 mongo_packet *p; 01182 bson *cmd; 01183 01184 if (!conn) 01185 { 01186 errno = ENOTCONN; 01187 return FALSE; 01188 } 01189 if (!error) 01190 { 01191 errno = EINVAL; 01192 return FALSE; 01193 } 01194 01195 cmd = bson_new_sized (64); 01196 bson_append_int32 (cmd, "getlasterror", 1); 01197 bson_finish (cmd); 01198 01199 p = _mongo_sync_cmd_custom (conn, db, cmd, FALSE, FALSE); 01200 if (!p) 01201 { 01202 int e = errno; 01203 01204 bson_free (cmd); 01205 errno = e; 01206 return FALSE; 01207 } 01208 bson_free (cmd); 01209 01210 if (!mongo_wire_reply_packet_get_nth_document (p, 1, &cmd)) 01211 { 01212 int e = errno; 01213 01214 mongo_wire_packet_free (p); 01215 errno = e; 01216 return FALSE; 01217 } 01218 mongo_wire_packet_free (p); 01219 bson_finish (cmd); 01220 01221 if (!_mongo_sync_get_error (cmd, error)) 01222 { 01223 int e = errno; 01224 01225 bson_free (cmd); 01226 errno = e; 01227 return FALSE; 01228 } 01229 bson_free (cmd); 01230 01231 if (*error == NULL) 01232 *error = g_strdup (conn->last_error); 01233 else 01234 { 01235 g_free (conn->last_error); 01236 conn->last_error = NULL; 01237 } 01238 01239 return TRUE; 01240 } 01241 01242 gboolean 01243 mongo_sync_cmd_reset_error (mongo_sync_connection *conn, 01244 const gchar *db) 01245 { 01246 mongo_packet *p; 01247 bson *cmd; 01248 01249 if (conn) 01250 { 01251 g_free (conn->last_error); 01252 conn->last_error = NULL; 01253 } 01254 01255 cmd = bson_new_sized (32); 01256 bson_append_int32 (cmd, "reseterror", 1); 01257 bson_finish (cmd); 01258 01259 p = _mongo_sync_cmd_custom (conn, db, cmd, FALSE, FALSE); 01260 if (!p) 01261 { 01262 int e = errno; 01263 01264 bson_free (cmd); 01265 errno = e; 01266 return FALSE; 01267 } 01268 bson_free (cmd); 01269 mongo_wire_packet_free (p); 01270 return TRUE; 01271 } 01272 01273 gboolean 01274 mongo_sync_cmd_is_master (mongo_sync_connection *conn) 01275 { 01276 bson *cmd, *res, *hosts; 01277 mongo_packet *p; 01278 bson_cursor *c; 01279 gboolean b; 01280 GList *l; 01281 01282 cmd = bson_new_sized (32); 01283 bson_append_int32 (cmd, "ismaster", 1); 01284 bson_finish (cmd); 01285 01286 p = _mongo_sync_cmd_custom (conn, "system", cmd, FALSE, FALSE); 01287 if (!p) 01288 { 01289 int e = errno; 01290 01291 bson_free (cmd); 01292 errno = e; 01293 return FALSE; 01294 } 01295 bson_free (cmd); 01296 01297 if (!mongo_wire_reply_packet_get_nth_document (p, 1, &res)) 01298 { 01299 int e = errno; 01300 01301 mongo_wire_packet_free (p); 01302 errno = e; 01303 return FALSE; 01304 } 01305 mongo_wire_packet_free (p); 01306 bson_finish (res); 01307 01308 c = bson_find (res, "ismaster"); 01309 if (!bson_cursor_get_boolean (c, &b)) 01310 { 01311 bson_cursor_free (c); 01312 bson_free (res); 01313 errno = EPROTO; 01314 return FALSE; 01315 } 01316 bson_cursor_free (c); 01317 01318 if (!b) 01319 { 01320 const gchar *s; 01321 01322 /* We're not the master, so we should have a 'primary' key in 01323 the response. */ 01324 c = bson_find (res, "primary"); 01325 if (bson_cursor_get_string (c, &s)) 01326 { 01327 g_free (conn->rs.primary); 01328 conn->rs.primary = g_strdup (s); 01329 } 01330 bson_cursor_free (c); 01331 } 01332 01333 /* Find all the members of the set, and cache them. */ 01334 c = bson_find (res, "hosts"); 01335 if (!c) 01336 { 01337 bson_free (res); 01338 errno = 0; 01339 return b; 01340 } 01341 01342 if (!bson_cursor_get_array (c, &hosts)) 01343 { 01344 bson_cursor_free (c); 01345 bson_free (res); 01346 errno = 0; 01347 return b; 01348 } 01349 bson_cursor_free (c); 01350 bson_finish (hosts); 01351 01352 /* Delete the old host list. */ 01353 l = conn->rs.hosts; 01354 while (l) 01355 { 01356 g_free (l->data); 01357 l = g_list_delete_link (l, l); 01358 } 01359 conn->rs.hosts = NULL; 01360 01361 c = bson_cursor_new (hosts); 01362 while (bson_cursor_next (c)) 01363 { 01364 const gchar *s; 01365 01366 if (bson_cursor_get_string (c, &s)) 01367 conn->rs.hosts = g_list_append (conn->rs.hosts, g_strdup (s)); 01368 } 01369 bson_cursor_free (c); 01370 bson_free (hosts); 01371 01372 c = bson_find (res, "passives"); 01373 if (bson_cursor_get_array (c, &hosts)) 01374 { 01375 bson_cursor_free (c); 01376 bson_finish (hosts); 01377 01378 c = bson_cursor_new (hosts); 01379 while (bson_cursor_next (c)) 01380 { 01381 const gchar *s; 01382 01383 if (bson_cursor_get_string (c, &s)) 01384 conn->rs.hosts = g_list_append (conn->rs.hosts, g_strdup (s)); 01385 } 01386 bson_free (hosts); 01387 } 01388 bson_cursor_free (c); 01389 01390 bson_free (res); 01391 errno = 0; 01392 return b; 01393 } 01394 01395 gboolean 01396 mongo_sync_cmd_ping (mongo_sync_connection *conn) 01397 { 01398 bson *cmd; 01399 mongo_packet *p; 01400 01401 cmd = bson_new_sized (32); 01402 bson_append_int32 (cmd, "ping", 1); 01403 bson_finish (cmd); 01404 01405 p = _mongo_sync_cmd_custom (conn, "system", cmd, FALSE, FALSE); 01406 if (!p) 01407 { 01408 int e = errno; 01409 01410 bson_free (cmd); 01411 errno = e; 01412 return FALSE; 01413 } 01414 bson_free (cmd); 01415 mongo_wire_packet_free (p); 01416 01417 errno = 0; 01418 return TRUE; 01419 } 01420 01421 static gchar * 01422 _pass_digest (const gchar *user, const gchar *pw) 01423 { 01424 GChecksum *chk; 01425 gchar *digest; 01426 01427 chk = g_checksum_new (G_CHECKSUM_MD5); 01428 g_checksum_update (chk, (const guchar *)user, -1); 01429 g_checksum_update (chk, (const guchar *)":mongo:", 7); 01430 g_checksum_update (chk, (const guchar *)pw, -1); 01431 digest = g_strdup (g_checksum_get_string (chk)); 01432 g_checksum_free (chk); 01433 01434 return digest; 01435 } 01436 01437 gboolean 01438 mongo_sync_cmd_user_add (mongo_sync_connection *conn, 01439 const gchar *db, 01440 const gchar *user, 01441 const gchar *pw) 01442 { 01443 bson *s, *u; 01444 gchar *userns; 01445 gchar *hex_digest; 01446 01447 if (!db || !user || !pw) 01448 { 01449 errno = EINVAL; 01450 return FALSE; 01451 } 01452 01453 userns = g_strconcat (db, ".system.users", NULL); 01454 01455 hex_digest = _pass_digest (user, pw); 01456 01457 s = bson_build (BSON_TYPE_STRING, "user", user, -1, 01458 BSON_TYPE_NONE); 01459 bson_finish (s); 01460 u = bson_build_full (BSON_TYPE_DOCUMENT, "$set", TRUE, 01461 bson_build (BSON_TYPE_STRING, "pwd", hex_digest, -1, 01462 BSON_TYPE_NONE), 01463 BSON_TYPE_NONE); 01464 bson_finish (u); 01465 g_free (hex_digest); 01466 01467 if (!mongo_sync_cmd_update (conn, userns, MONGO_WIRE_FLAG_UPDATE_UPSERT, 01468 s, u)) 01469 { 01470 int e = errno; 01471 01472 bson_free (s); 01473 bson_free (u); 01474 g_free (userns); 01475 errno = e; 01476 return FALSE; 01477 } 01478 bson_free (s); 01479 bson_free (u); 01480 g_free (userns); 01481 01482 return TRUE; 01483 } 01484 01485 gboolean 01486 mongo_sync_cmd_user_remove (mongo_sync_connection *conn, 01487 const gchar *db, 01488 const gchar *user) 01489 { 01490 bson *s; 01491 gchar *userns; 01492 01493 if (!db || !user) 01494 { 01495 errno = EINVAL; 01496 return FALSE; 01497 } 01498 01499 userns = g_strconcat (db, ".system.users", NULL); 01500 01501 s = bson_build (BSON_TYPE_STRING, "user", user, -1, 01502 BSON_TYPE_NONE); 01503 bson_finish (s); 01504 01505 if (!mongo_sync_cmd_delete (conn, userns, 0, s)) 01506 { 01507 int e = errno; 01508 01509 bson_free (s); 01510 g_free (userns); 01511 errno = e; 01512 return FALSE; 01513 } 01514 bson_free (s); 01515 g_free (userns); 01516 01517 return TRUE; 01518 } 01519 01520 gboolean 01521 mongo_sync_cmd_authenticate (mongo_sync_connection *conn, 01522 const gchar *db, 01523 const gchar *user, 01524 const gchar *pw) 01525 { 01526 bson *b; 01527 mongo_packet *p; 01528 const gchar *s; 01529 gchar *nonce; 01530 bson_cursor *c; 01531 01532 GChecksum *chk; 01533 gchar *hex_digest; 01534 const gchar *digest; 01535 01536 if (!db || !user || !pw) 01537 { 01538 errno = EINVAL; 01539 return FALSE; 01540 } 01541 01542 /* Obtain nonce */ 01543 b = bson_new_sized (32); 01544 bson_append_int32 (b, "getnonce", 1); 01545 bson_finish (b); 01546 01547 p = mongo_sync_cmd_custom (conn, db, b); 01548 if (!p) 01549 { 01550 int e = errno; 01551 01552 bson_free (b); 01553 errno = e; 01554 return FALSE; 01555 } 01556 bson_free (b); 01557 01558 if (!mongo_wire_reply_packet_get_nth_document (p, 1, &b)) 01559 { 01560 int e = errno; 01561 01562 mongo_wire_packet_free (p); 01563 errno = e; 01564 return FALSE; 01565 } 01566 mongo_wire_packet_free (p); 01567 bson_finish (b); 01568 01569 c = bson_find (b, "nonce"); 01570 if (!c) 01571 { 01572 bson_free (b); 01573 errno = EPROTO; 01574 return FALSE; 01575 } 01576 if (!bson_cursor_get_string (c, &s)) 01577 { 01578 bson_free (b); 01579 errno = EPROTO; 01580 return FALSE; 01581 } 01582 nonce = g_strdup (s); 01583 bson_cursor_free (c); 01584 bson_free (b); 01585 01586 /* Generate the password digest. */ 01587 hex_digest = _pass_digest (user, pw); 01588 01589 /* Generate the key */ 01590 chk = g_checksum_new (G_CHECKSUM_MD5); 01591 g_checksum_update (chk, (const guchar *)nonce, -1); 01592 g_checksum_update (chk, (const guchar *)user, -1); 01593 g_checksum_update (chk, (const guchar *)hex_digest, -1); 01594 g_free (hex_digest); 01595 01596 digest = g_checksum_get_string (chk); 01597 01598 /* Run the authenticate command. */ 01599 b = bson_build (BSON_TYPE_INT32, "authenticate", 1, 01600 BSON_TYPE_STRING, "user", user, -1, 01601 BSON_TYPE_STRING, "nonce", nonce, -1, 01602 BSON_TYPE_STRING, "key", digest, -1, 01603 BSON_TYPE_NONE); 01604 bson_finish (b); 01605 g_free (nonce); 01606 g_checksum_free (chk); 01607 01608 p = mongo_sync_cmd_custom (conn, db, b); 01609 if (!p) 01610 { 01611 int e = errno; 01612 01613 bson_free (b); 01614 errno = e; 01615 return FALSE; 01616 } 01617 bson_free (b); 01618 mongo_wire_packet_free (p); 01619 01620 return TRUE; 01621 } 01622 01623 static GString * 01624 _mongo_index_gen_name (const bson *key) 01625 { 01626 bson_cursor *c; 01627 GString *name; 01628 01629 name = g_string_new ("_"); 01630 c = bson_cursor_new (key); 01631 while (bson_cursor_next (c)) 01632 { 01633 gint64 v = 0; 01634 01635 g_string_append (name, bson_cursor_key (c)); 01636 g_string_append_c (name, '_'); 01637 01638 switch (bson_cursor_type (c)) 01639 { 01640 case BSON_TYPE_BOOLEAN: 01641 { 01642 gboolean vb; 01643 01644 bson_cursor_get_boolean (c, &vb); 01645 v = vb; 01646 break; 01647 } 01648 case BSON_TYPE_INT32: 01649 { 01650 gint32 vi; 01651 01652 bson_cursor_get_int32 (c, &vi); 01653 v = vi; 01654 break; 01655 } 01656 case BSON_TYPE_INT64: 01657 { 01658 gint64 vl; 01659 01660 bson_cursor_get_int64 (c, &vl); 01661 v = vl; 01662 break; 01663 } 01664 case BSON_TYPE_DOUBLE: 01665 { 01666 gdouble vd; 01667 01668 bson_cursor_get_double (c, &vd); 01669 v = (gint64)vd; 01670 break; 01671 } 01672 default: 01673 break; 01674 } 01675 if (v != 0) 01676 g_string_append_printf (name, "%" G_GINT64_FORMAT "_", v); 01677 } 01678 bson_cursor_free (c); 01679 01680 return name; 01681 } 01682 01683 gboolean 01684 mongo_sync_cmd_index_create (mongo_sync_connection *conn, 01685 const gchar *ns, 01686 const bson *key, 01687 gint options) 01688 { 01689 GString *name; 01690 gchar *idxns, *t; 01691 bson *cmd; 01692 01693 if (!conn) 01694 { 01695 errno = ENOTCONN; 01696 return FALSE; 01697 } 01698 if (!ns || !key) 01699 { 01700 errno = EINVAL; 01701 return FALSE; 01702 } 01703 if (strchr (ns, '.') == NULL) 01704 { 01705 errno = EINVAL; 01706 return FALSE; 01707 } 01708 01709 name = _mongo_index_gen_name (key); 01710 01711 cmd = bson_new_sized (bson_size (key) + name->len + 128); 01712 bson_append_document (cmd, "key", key); 01713 bson_append_string (cmd, "ns", ns, -1); 01714 bson_append_string (cmd, "name", name->str, name->len); 01715 if (options & MONGO_INDEX_UNIQUE) 01716 bson_append_boolean (cmd, "unique", TRUE); 01717 if (options & MONGO_INDEX_DROP_DUPS) 01718 bson_append_boolean (cmd, "dropDups", TRUE); 01719 if (options & MONGO_INDEX_BACKGROUND) 01720 bson_append_boolean (cmd, "background", TRUE); 01721 if (options & MONGO_INDEX_SPARSE) 01722 bson_append_boolean (cmd, "sparse", TRUE); 01723 bson_finish (cmd); 01724 g_string_free (name, TRUE); 01725 01726 t = g_strdup (ns); 01727 *(strchr (t, '.')) = '\0'; 01728 idxns = g_strconcat (t, ".system.indexes", NULL); 01729 g_free (t); 01730 01731 if (!mongo_sync_cmd_insert_n (conn, idxns, 1, (const bson **)&cmd)) 01732 { 01733 int e = errno; 01734 01735 bson_free (cmd); 01736 g_free (idxns); 01737 errno = e; 01738 return FALSE; 01739 } 01740 bson_free (cmd); 01741 g_free (idxns); 01742 01743 return TRUE; 01744 } 01745 01746 static gboolean 01747 _mongo_sync_cmd_index_drop (mongo_sync_connection *conn, 01748 const gchar *full_ns, 01749 const gchar *index_name) 01750 { 01751 bson *cmd; 01752 gchar *db, *ns; 01753 mongo_packet *p; 01754 01755 if (!conn) 01756 { 01757 errno = ENOTCONN; 01758 return FALSE; 01759 } 01760 if (!full_ns || !index_name) 01761 { 01762 errno = EINVAL; 01763 return FALSE; 01764 } 01765 ns = strchr (full_ns, '.'); 01766 if (ns == NULL) 01767 { 01768 errno = EINVAL; 01769 return FALSE; 01770 } 01771 ns++; 01772 01773 cmd = bson_new_sized (256 + strlen (index_name)); 01774 bson_append_string (cmd, "deleteIndexes", ns, -1); 01775 bson_append_string (cmd, "index", index_name, -1); 01776 bson_finish (cmd); 01777 01778 db = g_strndup (full_ns, ns - full_ns - 1); 01779 p = mongo_sync_cmd_custom (conn, db, cmd); 01780 if (!p) 01781 { 01782 int e = errno; 01783 01784 bson_free (cmd); 01785 g_free (db); 01786 errno = e; 01787 return FALSE; 01788 } 01789 mongo_wire_packet_free (p); 01790 g_free (db); 01791 bson_free (cmd); 01792 01793 return TRUE; 01794 } 01795 01796 gboolean 01797 mongo_sync_cmd_index_drop (mongo_sync_connection *conn, 01798 const gchar *ns, 01799 const bson *key) 01800 { 01801 GString *name; 01802 gboolean b; 01803 01804 if (!key) 01805 { 01806 errno = EINVAL; 01807 return FALSE; 01808 } 01809 01810 name = _mongo_index_gen_name (key); 01811 01812 b = _mongo_sync_cmd_index_drop (conn, ns, name->str); 01813 g_string_free (name, TRUE); 01814 return b; 01815 } 01816 01817 gboolean 01818 mongo_sync_cmd_index_drop_all (mongo_sync_connection *conn, 01819 const gchar *ns) 01820 { 01821 return _mongo_sync_cmd_index_drop (conn, ns, "*"); 01822 }