00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 """Tools for creating `messages
00016 <http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol>`_ to be sent to
00017 MongoDB.
00018
00019 .. note:: This module is for internal use and is generally not needed by
00020 application developers.
00021
00022 .. versionadded:: 1.1.2
00023 """
00024
00025 import random
00026 import struct
00027
00028 import bson
00029 from bson.son import SON
00030 try:
00031 from pymongo import _cbson
00032 _use_c = True
00033 except ImportError:
00034 _use_c = False
00035 from pymongo.errors import InvalidOperation
00036
00037
00038 __ZERO = "\x00\x00\x00\x00"
00039
00040
00041 def __last_error(args):
00042 """Data to send to do a lastError.
00043 """
00044 cmd = SON([("getlasterror", 1)])
00045 cmd.update(args)
00046 return query(0, "admin.$cmd", 0, -1, cmd)
00047
00048
00049 def __pack_message(operation, data):
00050 """Takes message data and adds a message header based on the operation.
00051
00052 Returns the resultant message string.
00053 """
00054 request_id = random.randint(-2 ** 31 - 1, 2 ** 31)
00055 message = struct.pack("<i", 16 + len(data))
00056 message += struct.pack("<i", request_id)
00057 message += __ZERO
00058 message += struct.pack("<i", operation)
00059 return (request_id, message + data)
00060
00061
00062 def insert(collection_name, docs, check_keys, safe, last_error_args):
00063 """Get an **insert** message.
00064 """
00065 max_bson_size = 0
00066 data = __ZERO
00067 data += bson._make_c_string(collection_name)
00068 bson_data = ""
00069 for doc in docs:
00070 encoded = bson.BSON.encode(doc, check_keys)
00071 bson_data += encoded
00072 max_bson_size = max(len(encoded), max_bson_size)
00073 if not bson_data:
00074 raise InvalidOperation("cannot do an empty bulk insert")
00075 data += bson_data
00076 if safe:
00077 (_, insert_message) = __pack_message(2002, data)
00078 (request_id, error_message, _) = __last_error(last_error_args)
00079 return (request_id, insert_message + error_message, max_bson_size)
00080 else:
00081 (request_id, insert_message) = __pack_message(2002, data)
00082 return (request_id, insert_message, max_bson_size)
00083 if _use_c:
00084 insert = _cbson._insert_message
00085
00086
00087 def update(collection_name, upsert, multi, spec, doc, safe, last_error_args):
00088 """Get an **update** message.
00089 """
00090 options = 0
00091 if upsert:
00092 options += 1
00093 if multi:
00094 options += 2
00095
00096 data = __ZERO
00097 data += bson._make_c_string(collection_name)
00098 data += struct.pack("<i", options)
00099 data += bson.BSON.encode(spec)
00100 encoded = bson.BSON.encode(doc)
00101 data += encoded
00102 if safe:
00103 (_, update_message) = __pack_message(2001, data)
00104 (request_id, error_message, _) = __last_error(last_error_args)
00105 return (request_id, update_message + error_message, len(encoded))
00106 else:
00107 (request_id, update_message) = __pack_message(2001, data)
00108 return (request_id, update_message, len(encoded))
00109 if _use_c:
00110 update = _cbson._update_message
00111
00112
00113 def query(options, collection_name,
00114 num_to_skip, num_to_return, query, field_selector=None):
00115 """Get a **query** message.
00116 """
00117 data = struct.pack("<I", options)
00118 data += bson._make_c_string(collection_name)
00119 data += struct.pack("<i", num_to_skip)
00120 data += struct.pack("<i", num_to_return)
00121 encoded = bson.BSON.encode(query)
00122 data += encoded
00123 max_bson_size = len(encoded)
00124 if field_selector is not None:
00125 encoded = bson.BSON.encode(field_selector)
00126 data += encoded
00127 max_bson_size = max(len(encoded), max_bson_size)
00128 (request_id, query_message) = __pack_message(2004, data)
00129 return (request_id, query_message, max_bson_size)
00130 if _use_c:
00131 query = _cbson._query_message
00132
00133
00134 def get_more(collection_name, num_to_return, cursor_id):
00135 """Get a **getMore** message.
00136 """
00137 data = __ZERO
00138 data += bson._make_c_string(collection_name)
00139 data += struct.pack("<i", num_to_return)
00140 data += struct.pack("<q", cursor_id)
00141 return __pack_message(2005, data)
00142 if _use_c:
00143 get_more = _cbson._get_more_message
00144
00145
00146 def delete(collection_name, spec, safe, last_error_args):
00147 """Get a **delete** message.
00148 """
00149 data = __ZERO
00150 data += bson._make_c_string(collection_name)
00151 data += __ZERO
00152 encoded = bson.BSON.encode(spec)
00153 data += encoded
00154 if safe:
00155 (_, remove_message) = __pack_message(2006, data)
00156 (request_id, error_message, _) = __last_error(last_error_args)
00157 return (request_id, remove_message + error_message, len(encoded))
00158 else:
00159 (request_id, remove_message) = __pack_message(2006, data)
00160 return (request_id, remove_message, len(encoded))
00161
00162
00163 def kill_cursors(cursor_ids):
00164 """Get a **killCursors** message.
00165 """
00166 data = __ZERO
00167 data += struct.pack("<i", len(cursor_ids))
00168 for cursor_id in cursor_ids:
00169 data += struct.pack("<q", cursor_id)
00170 return __pack_message(2007, data)