diff options
Diffstat (limited to 'src/mongo-wire.h')
-rw-r--r-- | src/mongo-wire.h | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/src/mongo-wire.h b/src/mongo-wire.h new file mode 100644 index 0000000..081a3e2 --- /dev/null +++ b/src/mongo-wire.h @@ -0,0 +1,433 @@ +/* mongo-wire.h - libmongo-client's MongoDB wire protocoll implementation. + * Copyright 2011, 2012 Gergely Nagy <algernon@balabit.hu> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file src/mongo-wire.h + * MongoDB Wire Protocol API public header. + */ + +#ifndef LIBMONGO_CLIENT_MONGO_WIRE_H +#define LIBMONGO_CLIENT_MONGO_WIRE_H 1 + +#include <glib.h> + +#include <bson.h> + +G_BEGIN_DECLS + +/** @defgroup mongo_wire Mongo Wire Protocol + * + * The structures and functions within this module implement the + * MongoDB wire protocol: functions to assemble various commands into + * binary blobs that can be sent over the wire. + * + * @see mongo_client + * + * @addtogroup mongo_wire + * @{ + */ + +/** @defgroup mongo_wire_packet Packets + * + * @addtogroup mongo_wire_packet + * @{ + */ + +/** Mongo packet header. + * + * Every mongo packet has a header like this. Normally, one does not + * need to touch it, though. + */ +typedef struct +{ + gint32 length; /**< Full length of the packet, including the + header. */ + gint32 id; /**< Sequence ID, used when MongoDB responds to a + command. */ + gint32 resp_to; /**< ID the response is an answer to. Only sent by + the MongoDB server, never set on client-side. */ + gint32 opcode; /**< The opcode of the command. @see + mongo_wire_opcode. <*/ +} mongo_packet_header; + +/** An opaque Mongo Packet on the wire. + * + * This structure contains the binary data that can be written + * straight to the wire. + */ +typedef struct _mongo_packet mongo_packet; + +/** Create an empty packet. + * + * Creates an empty packet to be filled in later with + * mongo_wire_packet_set_header() and mongo_packet_set_data(). + * + * @returns A newly allocated packet, or NULL on error. + */ +mongo_packet *mongo_wire_packet_new (void); + +/** Get the header data of a packet. + * + * Retrieve the mongo packet's header data. + * + * @param p is the packet which header we seek. + * @param header is a pointer to a variable which will hold the data. + * + * @note Allocating the @a header is the responsibility of the caller. + * + * @returns TRUE on success, FALSE otherwise. + */ +gboolean mongo_wire_packet_get_header (const mongo_packet *p, + mongo_packet_header *header); + +/** Set the header data of a packet. + * + * Override the mongo packet's header data. + * + * @note No sanity checks are done, use this function with great care. + * + * @param p is the packet whose header we want to override. + * @param header is the header structure to use. + * + * @returns TRUE on success, FALSE otherwise. + */ +gboolean mongo_wire_packet_set_header (mongo_packet *p, + const mongo_packet_header *header); + +/** Get the data part of a packet. + * + * Retrieve the raw binary blob of the mongo packet's data. + * + * @param p is the packet which header we seek. + * @param data is a pointer to a variable which will hold the data. + * + * @note The @a data parameter will point to an internal structure, + * which shall not be freed or written to. + * + * @returns The size of the data, or -1 on error. + */ +gint32 mongo_wire_packet_get_data (const mongo_packet *p, const guint8 **data); + +/** Set the data part of a packet. + * + * Overrides the data part of a packet, adjusting the packet length in + * the header too. + * + * @note No sanity checks are performed on the data, it is the + * caller's responsibility to supply valid information. + * + * @param p is the packet whose data is to be set. + * @param data is the data to set. + * @param size is the size of the data. + * + * @returns TRUE on success, FALSE otherwise. + */ +gboolean mongo_wire_packet_set_data (mongo_packet *p, const guint8 *data, + gint32 size); + +/** Free up a mongo packet. + * + * @param p is the packet to free. + * + * @note The packet shall not be used afterwards. + */ +void mongo_wire_packet_free (mongo_packet *p); + +/** @} */ + +/** @defgroup mongo_wire_reply Reply handling + * + * @addtogroup mongo_wire_reply + * @{ + */ + +/** Flags the server can set in replies. */ +enum + { + /** Set when get_more is called but the cursor id is invalid. */ + MONGO_REPLY_FLAG_NO_CURSOR = 0x1, + /** Set when the query failed. */ + MONGO_REPLY_FLAG_QUERY_FAIL = 0x2, + /** Set when the server suppots the AwaitData query option. + * If not set, the client should sleep a little between get_more + * calls on a tailable cursor. On Mongo >= 1.6, this flag is + * always set. + */ + MONGO_REPLY_FLAG_AWAITCAPABLE = 0x8 + }; + +/** Mongo reply packet header. + */ +#pragma pack(1) +typedef struct +{ + gint32 flags; /**< Response flags. */ + gint64 cursor_id; /**< Cursor ID, in case the client needs to do + get_more requests. */ + gint32 start; /**< Starting position of the reply within the + cursor. */ + gint32 returned; /**< Number of documents returned in the reply. */ +} mongo_reply_packet_header; +#pragma pack() + +/** Get the header of a reply packet. + * + * @param p is the packet to retrieve the reply header from. + * @param hdr is a pointer to a variable where the reply header will + * be stored. + * + * @note It is the responsibility of the caller to allocate space for + * the header. + * + * @returns TRUE on success, FALSE otherwise. + */ +gboolean mongo_wire_reply_packet_get_header (const mongo_packet *p, + mongo_reply_packet_header *hdr); + +/** Get the full data part of a reply packet. + * + * The result will include the full, unparsed data part of the reply. + * + * @param p is the packet to retrieve the data from. + * @param data is a pointer to a variable where the replys data can be + * stored. + * + * @note The @a data variable will point to an internal structure, + * which must not be freed or modified. + * + * @returns TRUE on success, FALSE otherwise. + */ +gboolean mongo_wire_reply_packet_get_data (const mongo_packet *p, + const guint8 **data); + +/** Get the Nth document from a reply packet. + * + * @param p is the packet to retrieve a document from. + * @param n is the number of the document to retrieve. + * @param doc is a pointer to a variable to hold the BSON document. + * + * @note The @a doc variable will be a newly allocated object, it is + * the responsibility of the caller to free it once it is not needed + * anymore. + * + * @returns TRUE on success, FALSE otherwise. + */ +gboolean mongo_wire_reply_packet_get_nth_document (const mongo_packet *p, + gint32 n, + bson **doc); + +/** @}*/ + +/** @defgroup mongo_wire_cmd Commands + * + * Each command has an @a id parameter, which can be used to track + * replies to various commands. It is the responsibility of the caller + * to keep track of IDs. + * + * @addtogroup mongo_wire_cmd + * @{ + */ + +/** Flags available for the update command. + * @see mongo_wire_cmd_update(). + */ +enum + { + /** When set, inserts if no matching document was found. */ + MONGO_WIRE_FLAG_UPDATE_UPSERT = 0x1, + /** When set, all matching documents will be updated, not just + the first. */ + MONGO_WIRE_FLAG_UPDATE_MULTI = 0x2 + }; + +/** Construct an update command. + * + * @param id is the sequence id. + * @param ns is the namespace, the database and collection name + * concatenated, and separated with a single dot. + * @param flags are the flags for the update command. Available flags + * are #MONGO_WIRE_FLAG_UPDATE_UPSERT and + * #MONGO_WIRE_FLAG_UPDATE_MULTI. + * @param selector is the BSON document that will act as the selector. + * @param update is the BSON document that contains the updated values. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_update (gint32 id, const gchar *ns, + gint32 flags, const bson *selector, + const bson *update); + +/** Construct an insert command. + * + * @param id is the sequence id. + * @param ns is the namespace, the database and collection name + * concatenated, and separated with a single dot. + * @tparam docs are the BSON documents to insert. One must close the + * list with a NULL value. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_insert (gint32 id, const gchar *ns, ...) + G_GNUC_NULL_TERMINATED; + +/** Construct an insert command with N documents. + * + * @param id is the sequence id. + * @param ns is the namespace, the database and collection name + * concatenated, and separated with a single dot. + * @param n is the number of documents to insert. + * @param docs is the array containing the bson documents to insert. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_insert_n (gint32 id, const gchar *ns, gint32 n, + const bson **docs); + +/** Flags available for the query command. + * @see mongo_wire_cmd_query(). + */ +enum + { + /** Set the TailableCursor flag on the query. */ + MONGO_WIRE_FLAG_QUERY_TAILABLE_CURSOR = 1 << 1, + /** Allow queries made against a replica slave. */ + MONGO_WIRE_FLAG_QUERY_SLAVE_OK = 1 << 2, + /** Disable cursor timeout. */ + MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT = 1 << 4, + /** Block if at the end of the data block, awaiting data. + * Use only with #MONGO_WIRE_FLAG_QUERY_TAILABLE_CURSOR! + */ + MONGO_WIRE_FLAG_QUERY_AWAIT_DATA = 1 << 5, + /** Stream the data down full blast in multiple packages. + * When set, the client is not allowed not to read all the data, + * unless it closes connection. + */ + MONGO_WIRE_FLAG_QUERY_EXHAUST = 1 << 6, + /** Allow partial results in a sharded environment. + * In case one or more required shards are down, with this flag + * set, partial results will be returned instead of failing. + */ + MONGO_WIRE_FLAG_QUERY_PARTIAL_RESULTS = 1 << 7 + }; + +/** Construct a query command. + * + * @param id is the sequence id. + * @param ns is the namespace, the database and collection name + * concatenated, and separated with a single dot. + * @param flags are the query options. Available flags are: + * #MONGO_WIRE_FLAG_QUERY_TAILABLE_CURSOR, + * #MONGO_WIRE_FLAG_QUERY_SLAVE_OK, + * #MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT, + * #MONGO_WIRE_FLAG_QUERY_AWAIT_DATA, #MONGO_WIRE_FLAG_QUERY_EXHAUST. + * @param skip is the number of documents to skip. + * @param ret is the number of documents to return. + * @param query is the query BSON object. + * @param sel is the (optional) selector BSON object indicating the + * fields to return. Passing NULL will return all fields. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_query (gint32 id, const gchar *ns, gint32 flags, + gint32 skip, gint32 ret, const bson *query, + const bson *sel); + +/** Construct a get more command. + * + * @param id is the sequence id. + * @param ns is the namespace, the database and collection name + * concatenated, and separated with a single dot. + * @param ret is the number of documents to return. + * @param cursor_id is the ID of the cursor to use. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_get_more (gint32 id, const gchar *ns, + gint32 ret, gint64 cursor_id); + +/** Flags available for the delete command. + */ +enum + { + /** Only remove the first match. */ + MONGO_WIRE_FLAG_DELETE_SINGLE = 0x1 + }; + +/** Construct a delete command. + * + * @param id is the sequence id. + * @param ns is the namespace, the database and collection name + * concatenated, and separated with a single dot. + * @param flags are the delete options. The only available flag is + * MONGO_WIRE_FLAG_DELETE_SINGLE. + * @param sel is the BSON object to use as a selector. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_delete (gint32 id, const gchar *ns, + gint32 flags, const bson *sel); + +/** Construct a kill cursors command. + * + * @param id is the sequence id. + * @param n is the number of cursors to delete. + * @tparam cursor_ids are the ids of the cursors to delete. + * + * @note One must supply exaclty @a n number of cursor IDs. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_kill_cursors (gint32 id, gint32 n, ...); + +/** Construct a custom command. + * + * Custom commands are queries run in the db.$cmd namespace. The + * commands themselves are queries, and as such, BSON objects. + * + * @param id is the sequence id. + * @param db is the database in which the command shall be run. + * @param flags are the query flags. See mongo_wire_cmd_query() for a + * list. + * @param command is the BSON object representing the command. + * + * @returns A newly allocated packet, or NULL on error. It is the + * responsibility of the caller to free the packet once it is not used + * anymore. + */ +mongo_packet *mongo_wire_cmd_custom (gint32 id, const gchar *db, + gint32 flags, + const bson *command); + +/** @} */ + +/** @} */ + +G_END_DECLS + +#endif |