Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 154 lines (129 sloc) 4.585 kb
00d108c Jehiah Czebotar initial rev; working async find()
jehiah authored
1 # Copyright 2009-2010 10gen, Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Tools for creating `messages
16 <http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol>`_ to be sent to
17 MongoDB.
18
19 .. note:: This module is for internal use and is generally not needed by
20 application developers.
21 """
22
23 import random
24 import struct
25
26 import bson
27 from bson.son import SON
28 try:
29 from pymongo import _cbson
30 _use_c = True
31 except ImportError:
32 _use_c = False
33 from pymongo.errors import InvalidOperation
34
35
36 __ZERO = "\x00\x00\x00\x00"
37
38
39 def __last_error(args):
40 """Data to send to do a lastError.
41 """
42 cmd = SON([("getlasterror", 1)])
43 cmd.update(args)
44 return query(0, "admin.$cmd", 0, -1, cmd)
45
46
47 def __pack_message(operation, data):
48 """Takes message data and adds a message header based on the operation.
49
50 Returns the resultant message string.
51 """
52 request_id = random.randint(-2 ** 31 - 1, 2 ** 31)
53 message = struct.pack("<i", 16 + len(data))
54 message += struct.pack("<i", request_id)
55 message += __ZERO # responseTo
56 message += struct.pack("<i", operation)
57 return (request_id, message + data)
58
59
60 def insert(collection_name, docs, check_keys, safe, last_error_args):
61 """Get an **insert** message.
62 """
63 data = __ZERO
64 data += bson._make_c_string(collection_name)
65 bson_data = "".join([bson.BSON.encode(doc, check_keys) for doc in docs])
66 if not bson_data:
67 raise InvalidOperation("cannot do an empty bulk insert")
68 data += bson_data
69 if safe:
70 (_, insert_message) = __pack_message(2002, data)
71 (request_id, error_message) = __last_error(last_error_args)
72 return (request_id, insert_message + error_message)
73 else:
74 return __pack_message(2002, data)
75 if _use_c:
76 insert = _cbson._insert_message
77
78
79 def update(collection_name, upsert, multi, spec, doc, safe, last_error_args):
80 """Get an **update** message.
81 """
82 options = 0
83 if upsert:
84 options += 1
85 if multi:
86 options += 2
87
88 data = __ZERO
89 data += bson._make_c_string(collection_name)
90 data += struct.pack("<i", options)
91 data += bson.BSON.encode(spec)
92 data += bson.BSON.encode(doc)
93 if safe:
94 (_, update_message) = __pack_message(2001, data)
95 (request_id, error_message) = __last_error(last_error_args)
96 return (request_id, update_message + error_message)
97 else:
98 return __pack_message(2001, data)
99 if _use_c:
100 update = _cbson._update_message
101
102
103 def query(options, collection_name,
104 num_to_skip, num_to_return, query, field_selector=None):
105 """Get a **query** message.
106 """
107 data = struct.pack("<I", options)
108 data += bson._make_c_string(collection_name)
109 data += struct.pack("<i", num_to_skip)
110 data += struct.pack("<i", num_to_return)
111 data += bson.BSON.encode(query)
112 if field_selector is not None:
113 data += bson.BSON.encode(field_selector)
114 return __pack_message(2004, data)
115 if _use_c:
116 query = _cbson._query_message
117
118
119 def get_more(collection_name, num_to_return, cursor_id):
120 """Get a **getMore** message.
121 """
122 data = __ZERO
123 data += bson._make_c_string(collection_name)
124 data += struct.pack("<i", num_to_return)
125 data += struct.pack("<q", cursor_id)
126 return __pack_message(2005, data)
127 if _use_c:
128 get_more = _cbson._get_more_message
129
130
131 def delete(collection_name, spec, safe, last_error_args):
132 """Get a **delete** message.
133 """
134 data = __ZERO
135 data += bson._make_c_string(collection_name)
136 data += __ZERO
137 data += bson.BSON.encode(spec)
138 if safe:
139 (_, remove_message) = __pack_message(2006, data)
140 (request_id, error_message) = __last_error(last_error_args)
141 return (request_id, remove_message + error_message)
142 else:
143 return __pack_message(2006, data)
144
145
146 def kill_cursors(cursor_ids):
147 """Get a **killCursors** message.
148 """
149 data = __ZERO
150 data += struct.pack("<i", len(cursor_ids))
151 for cursor_id in cursor_ids:
152 data += struct.pack("<q", cursor_id)
153 return __pack_message(2007, data)
Something went wrong with that request. Please try again.