Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 345 lines (278 sloc) 10.898 kb
76f30d4 @kchodorow cleaning
kchodorow authored
1 // php_mongo.c
2 /**
820dd82 @kchodorow now that it's august, time to update the copyright
kchodorow authored
3 * Copyright 2009-2011 10gen, Inc.
76f30d4 @kchodorow cleaning
kchodorow authored
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <php.h>
23
24 #include <zend_exceptions.h>
25 #include <php_ini.h>
26 #include <ext/standard/info.h>
27
28 #include "php_mongo.h"
29
30 #include "mongo.h"
31 #include "cursor.h"
32 #include "mongo_types.h"
33
34 #include "util/pool.h"
35 #include "util/server.h"
36 #include "util/rs.h"
37 #include "util/log.h"
38
039b4a9 @kchodorow fixed duplicate symbol PHP-255
kchodorow authored
39 extern zend_object_handlers mongo_default_handlers,
76f30d4 @kchodorow cleaning
kchodorow authored
40 mongo_id_handlers;
41
42 /** Classes */
a3e8dbd @kchodorow add connection info to cursor exception whenever possible PHP-211
kchodorow authored
43 extern zend_class_entry *mongo_ce_CursorException;
44
45 zend_class_entry *mongo_ce_ConnectionException,
76f30d4 @kchodorow cleaning
kchodorow authored
46 *mongo_ce_CursorTOException,
47 *mongo_ce_GridFSException,
48 *mongo_ce_Exception,
49 *mongo_ce_MaxKey,
50 *mongo_ce_MinKey;
51
52 /** Resources */
53 int le_pconnection,
54 le_pserver,
55 le_prs,
56 le_cursor_list;
57
58 static void mongo_init_MongoExceptions(TSRMLS_D);
59
60 ZEND_DECLARE_MODULE_GLOBALS(mongo)
61
62 #if ZEND_MODULE_API_NO >= 20060613
63 // 5.2+ globals
64 static PHP_GINIT_FUNCTION(mongo);
65 #else
66 // 5.1- globals
67 static void mongo_init_globals(zend_mongo_globals* g TSRMLS_DC);
68 #endif /* ZEND_MODULE_API_NO >= 20060613 */
69
70 #if WIN32
71 extern HANDLE cursor_mutex;
72 extern HANDLE io_mutex;
73 extern HANDLE pool_mutex;
74 #endif
75
76 zend_function_entry mongo_functions[] = {
77 PHP_FE(bson_encode, NULL)
78 PHP_FE(bson_decode, NULL)
79 { NULL, NULL, NULL }
80 };
81
82 /* {{{ mongo_module_entry
83 */
84 zend_module_entry mongo_module_entry = {
85 #if ZEND_MODULE_API_NO >= 20010901
86 STANDARD_MODULE_HEADER,
87 #endif
88 PHP_MONGO_EXTNAME,
89 mongo_functions,
90 PHP_MINIT(mongo),
91 PHP_MSHUTDOWN(mongo),
92 PHP_RINIT(mongo),
93 NULL,
94 PHP_MINFO(mongo),
95 PHP_MONGO_VERSION,
96 #if ZEND_MODULE_API_NO >= 20060613
97 PHP_MODULE_GLOBALS(mongo),
98 PHP_GINIT(mongo),
99 NULL,
100 NULL,
101 STANDARD_MODULE_PROPERTIES_EX
102 #else
103 STANDARD_MODULE_PROPERTIES
104 #endif
105 };
106 /* }}} */
107
108 #ifdef COMPILE_DL_MONGO
109 ZEND_GET_MODULE(mongo)
110 #endif
111
112
113 /* {{{ PHP_INI */
114 // these must be in the same order as mongo_globals are declared or it will segfault on 64-bit machines!
115 PHP_INI_BEGIN()
116 STD_PHP_INI_ENTRY("mongo.auto_reconnect", "1", PHP_INI_ALL, OnUpdateLong, auto_reconnect, zend_mongo_globals, mongo_globals)
117 STD_PHP_INI_ENTRY("mongo.allow_persistent", "1", PHP_INI_ALL, OnUpdateLong, allow_persistent, zend_mongo_globals, mongo_globals)
118 STD_PHP_INI_ENTRY("mongo.default_host", "localhost", PHP_INI_ALL, OnUpdateString, default_host, zend_mongo_globals, mongo_globals)
119 STD_PHP_INI_ENTRY("mongo.default_port", "27017", PHP_INI_ALL, OnUpdateLong, default_port, zend_mongo_globals, mongo_globals)
120 STD_PHP_INI_ENTRY("mongo.chunk_size", "262144", PHP_INI_ALL, OnUpdateLong, chunk_size, zend_mongo_globals, mongo_globals)
121 STD_PHP_INI_ENTRY("mongo.cmd", "$", PHP_INI_ALL, OnUpdateStringUnempty, cmd_char, zend_mongo_globals, mongo_globals)
122 STD_PHP_INI_ENTRY("mongo.utf8", "1", PHP_INI_ALL, OnUpdateLong, utf8, zend_mongo_globals, mongo_globals)
123 STD_PHP_INI_ENTRY("mongo.native_long", "0", PHP_INI_ALL, OnUpdateLong, native_long, zend_mongo_globals, mongo_globals)
124 STD_PHP_INI_ENTRY("mongo.long_as_object", "0", PHP_INI_ALL, OnUpdateLong, long_as_object, zend_mongo_globals, mongo_globals)
125 STD_PHP_INI_ENTRY("mongo.allow_empty_keys", "0", PHP_INI_ALL, OnUpdateLong, allow_empty_keys, zend_mongo_globals, mongo_globals)
126 STD_PHP_INI_ENTRY("mongo.no_id", "0", PHP_INI_SYSTEM, OnUpdateLong, no_id, zend_mongo_globals, mongo_globals)
127 PHP_INI_END()
128 /* }}} */
129
130
131 /* {{{ PHP_MINIT_FUNCTION
132 */
133 PHP_MINIT_FUNCTION(mongo) {
134 zend_class_entry max_key, min_key;
135
136 #if ZEND_MODULE_API_NO < 20060613
137 ZEND_INIT_MODULE_GLOBALS(mongo, mongo_init_globals, NULL);
138 #endif /* ZEND_MODULE_API_NO < 20060613 */
139
140 REGISTER_INI_ENTRIES();
141
142 le_pconnection = zend_register_list_destructors_ex(NULL, mongo_util_pool_shutdown, PHP_CONNECTION_RES_NAME, module_number);
143 le_pserver = zend_register_list_destructors_ex(NULL, mongo_util_server_shutdown, PHP_SERVER_RES_NAME, module_number);
144 le_prs = zend_register_list_destructors_ex(NULL, mongo_util_rs_shutdown, PHP_RS_RES_NAME, module_number);
145 le_cursor_list = zend_register_list_destructors_ex(NULL, php_mongo_cursor_list_pfree, PHP_CURSOR_LIST_RES_NAME, module_number);
146
147 mongo_init_Mongo(TSRMLS_C);
148 mongo_init_MongoDB(TSRMLS_C);
149 mongo_init_MongoCollection(TSRMLS_C);
150 mongo_init_MongoCursor(TSRMLS_C);
151
152 mongo_init_MongoGridFS(TSRMLS_C);
153 mongo_init_MongoGridFSFile(TSRMLS_C);
154 mongo_init_MongoGridFSCursor(TSRMLS_C);
155
156 mongo_init_MongoId(TSRMLS_C);
157 mongo_init_MongoCode(TSRMLS_C);
158 mongo_init_MongoRegex(TSRMLS_C);
159 mongo_init_MongoDate(TSRMLS_C);
160 mongo_init_MongoBinData(TSRMLS_C);
161 mongo_init_MongoDBRef(TSRMLS_C);
162
163 mongo_init_MongoExceptions(TSRMLS_C);
164
165 mongo_init_MongoTimestamp(TSRMLS_C);
166 mongo_init_MongoInt32(TSRMLS_C);
167 mongo_init_MongoInt64(TSRMLS_C);
168
169 mongo_init_MongoLog(TSRMLS_C);
3577888 @kchodorow create pool class
kchodorow authored
170 mongo_init_MongoPool(TSRMLS_C);
76f30d4 @kchodorow cleaning
kchodorow authored
171
172 /*
173 * MongoMaxKey and MongoMinKey are completely non-interactive: they have no
174 * method, fields, or constants.
175 */
176 INIT_CLASS_ENTRY(max_key, "MongoMaxKey", NULL);
177 mongo_ce_MaxKey = zend_register_internal_class(&max_key TSRMLS_CC);
178 INIT_CLASS_ENTRY(min_key, "MongoMinKey", NULL);
179 mongo_ce_MinKey = zend_register_internal_class(&min_key TSRMLS_CC);
180
181
182 // make mongo objects uncloneable
183 memcpy(&mongo_default_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
184 mongo_default_handlers.clone_obj = NULL;
185
186 // add compare_objects for MongoId
187 memcpy(&mongo_id_handlers, &mongo_default_handlers, sizeof(zend_object_handlers));
188 mongo_id_handlers.compare_objects = php_mongo_compare_ids;
189
190 // start random number generator
191 srand(time(0));
192
193 #ifdef WIN32
194 cursor_mutex = CreateMutex(NULL, FALSE, NULL);
195 pool_mutex = CreateMutex(NULL, FALSE, NULL);
196 io_mutex = CreateMutex(NULL, FALSE, NULL);
197 if (cursor_mutex == NULL || pool_mutex == NULL || io_mutex == NULL) {
198 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Windows couldn't create a mutex: %s", GetLastError());
199 return FAILURE;
200 }
201 #endif
202
203 return SUCCESS;
204 }
205
206
207 #if ZEND_MODULE_API_NO >= 20060613
208 /* {{{ PHP_GINIT_FUNCTION
209 */
210 static PHP_GINIT_FUNCTION(mongo)
211 #else
212 /* {{{ mongo_init_globals
213 */
214 static void mongo_init_globals(zend_mongo_globals *mongo_globals TSRMLS_DC)
215 #endif /* ZEND_MODULE_API_NO >= 20060613 */
216 {
217 // on windows, the max length is 256. linux doesn't have a limit, but it will
218 // fill in the first 256 chars of hostname even if the actual hostname is
219 // longer. if you can't get a unique character in the first 256 chars of your
220 // hostname, you're doing it wrong.
221 int len, win_max = 256;
222 char *hostname, host_start[256];
223 register ulong hash;
224
225 mongo_globals->auto_reconnect = 1;
226 mongo_globals->default_host = "localhost";
227 mongo_globals->default_port = 27017;
228 mongo_globals->request_id = 3;
229 mongo_globals->chunk_size = DEFAULT_CHUNK_SIZE;
230 mongo_globals->cmd_char = "$";
231 mongo_globals->utf8 = 1;
232
233 mongo_globals->inc = 0;
234 mongo_globals->response_num = 0;
235 mongo_globals->errmsg = 0;
236
237 mongo_globals->max_send_size = 64 * 1024 * 1024;
238 mongo_globals->pool_size = -1;
239
240 hostname = host_start;
241 // from the gnu manual:
242 // gethostname stores the beginning of the host name in name even if the
243 // host name won't entirely fit. For some purposes, a truncated host name
244 // is good enough. If it is, you can ignore the error code.
245 // so we'll ignore the error code.
246 // returns 0-terminated hostname.
247 gethostname(hostname, win_max);
248 len = strlen(hostname);
249
250 hash = 5381;
251
252 /* from zend_hash.h */
253 /* variant with the hash unrolled eight times */
254 for (; len >= 8; len -= 8) {
255 hash = ((hash << 5) + hash) + *hostname++;
256 hash = ((hash << 5) + hash) + *hostname++;
257 hash = ((hash << 5) + hash) + *hostname++;
258 hash = ((hash << 5) + hash) + *hostname++;
259 hash = ((hash << 5) + hash) + *hostname++;
260 hash = ((hash << 5) + hash) + *hostname++;
261 hash = ((hash << 5) + hash) + *hostname++;
262 hash = ((hash << 5) + hash) + *hostname++;
263 }
264
265 switch (len) {
266 case 7: hash = ((hash << 5) + hash) + *hostname++; /* fallthrough... */
267 case 6: hash = ((hash << 5) + hash) + *hostname++; /* fallthrough... */
268 case 5: hash = ((hash << 5) + hash) + *hostname++; /* fallthrough... */
269 case 4: hash = ((hash << 5) + hash) + *hostname++; /* fallthrough... */
270 case 3: hash = ((hash << 5) + hash) + *hostname++; /* fallthrough... */
271 case 2: hash = ((hash << 5) + hash) + *hostname++; /* fallthrough... */
272 case 1: hash = ((hash << 5) + hash) + *hostname++; break;
273 case 0: break;
274 }
275
276 mongo_globals->machine = hash;
277
278 mongo_globals->ts_inc = 0;
279 }
280 /* }}} */
281
282
283 /* {{{ PHP_MSHUTDOWN_FUNCTION
284 */
285 PHP_MSHUTDOWN_FUNCTION(mongo) {
286 UNREGISTER_INI_ENTRIES();
287
288 #if WIN32
289 // 0 is failure
290 if (CloseHandle(cursor_mutex) == 0 || CloseHandle(pool_mutex) == 0 || CloseHandle(io_mutex) == 0) {
291 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Windows couldn't destroy a mutex: %s", GetLastError());
292 return FAILURE;
293 }
294 #endif
295
296 return SUCCESS;
297 }
298 /* }}} */
299
300
301 /* {{{ PHP_RINIT_FUNCTION
302 */
303 PHP_RINIT_FUNCTION(mongo) {
304 return SUCCESS;
305 }
306 /* }}} */
307
308
309 /* {{{ PHP_MINFO_FUNCTION
310 */
311 PHP_MINFO_FUNCTION(mongo) {
312 php_info_print_table_start();
313
314 php_info_print_table_header(2, "MongoDB Support", "enabled");
315 php_info_print_table_row(2, "Version", PHP_MONGO_VERSION);
316
317 php_info_print_table_end();
318
319 DISPLAY_INI_ENTRIES();
320 }
321 /* }}} */
322
323 static void mongo_init_MongoExceptions(TSRMLS_D) {
a3e8dbd @kchodorow add connection info to cursor exception whenever possible PHP-211
kchodorow authored
324 zend_class_entry e, conn, e2, ctoe;
76f30d4 @kchodorow cleaning
kchodorow authored
325
326 INIT_CLASS_ENTRY(e, "MongoException", NULL);
327
328 #if ZEND_MODULE_API_NO >= 20060613
329 mongo_ce_Exception = zend_register_internal_class_ex(&e, (zend_class_entry*)zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
330 #else
331 mongo_ce_Exception = zend_register_internal_class_ex(&e, (zend_class_entry*)zend_exception_get_default(), NULL TSRMLS_CC);
332 #endif /* ZEND_MODULE_API_NO >= 20060613 */
333
a3e8dbd @kchodorow add connection info to cursor exception whenever possible PHP-211
kchodorow authored
334 mongo_init_CursorExceptions(TSRMLS_C);
76f30d4 @kchodorow cleaning
kchodorow authored
335
336 INIT_CLASS_ENTRY(ctoe, "MongoCursorTimeoutException", NULL);
337 mongo_ce_CursorTOException = zend_register_internal_class_ex(&ctoe, mongo_ce_CursorException, NULL TSRMLS_CC);
338
339 INIT_CLASS_ENTRY(conn, "MongoConnectionException", NULL);
340 mongo_ce_ConnectionException = zend_register_internal_class_ex(&conn, mongo_ce_Exception, NULL TSRMLS_CC);
341
342 INIT_CLASS_ENTRY(e2, "MongoGridFSException", NULL);
343 mongo_ce_GridFSException = zend_register_internal_class_ex(&e2, mongo_ce_Exception, NULL TSRMLS_CC);
344 }
Something went wrong with that request. Please try again.