39
39
#include <Zend/zend_exceptions.h>
40
40
#include <ext/spl/spl_iterators.h>
41
41
#include <ext/spl/spl_exceptions.h>
42
+ #include <ext/standard/php_var.h>
43
+
44
+ #if PHP_VERSION_ID >= 70000
45
+ # include <Zend/zend_smart_str.h>
46
+ #else
47
+ # include <ext/standard/php_smart_str.h>
48
+ #endif
49
+
42
50
/* Stream wrapper */
43
51
#include <main/php_streams.h>
44
52
#include <main/php_network.h>
@@ -1378,6 +1386,84 @@ static void php_phongo_free_ssl_opt(mongoc_ssl_opt_t *ssl_opt)
1378
1386
efree (ssl_opt );
1379
1387
}
1380
1388
1389
+ /* Creates a hash for a client by concatenating the URI string with serialized
1390
+ * options arrays. On success, a persistent string is returned (i.e. pefree()
1391
+ * should be used to free it) and hash_len will be set to the string's length.
1392
+ * On error, an exception will have been thrown and NULL will be returned. */
1393
+ static char * php_phongo_manager_make_client_hash (const char * uri_string , zval * options , zval * driverOptions , size_t * hash_len TSRMLS_DC )
1394
+ {
1395
+ char * hash = NULL ;
1396
+ smart_str var_buf = {0 };
1397
+ php_serialize_data_t var_hash ;
1398
+
1399
+ #if PHP_VERSION_ID >= 70000
1400
+ zval args ;
1401
+
1402
+ array_init_size (& args , 3 );
1403
+ ADD_ASSOC_STRING (& args , "uri" , (char * ) uri_string );
1404
+
1405
+ if (options ) {
1406
+ ADD_ASSOC_ZVAL_EX (& args , "options" , options );
1407
+ Z_ADDREF_P (options );
1408
+ } else {
1409
+ ADD_ASSOC_NULL_EX (& args , "options" );
1410
+ }
1411
+
1412
+ if (driverOptions ) {
1413
+ ADD_ASSOC_ZVAL_EX (& args , "driverOptions" , driverOptions );
1414
+ Z_ADDREF_P (driverOptions );
1415
+ } else {
1416
+ ADD_ASSOC_NULL_EX (& args , "driverOptions" );
1417
+ }
1418
+
1419
+ PHP_VAR_SERIALIZE_INIT (var_hash );
1420
+ php_var_serialize (& var_buf , & args , & var_hash );
1421
+ PHP_VAR_SERIALIZE_DESTROY (var_hash );
1422
+
1423
+ if (!EG (exception )) {
1424
+ * hash_len = ZSTR_LEN (var_buf .s );
1425
+ hash = pestrndup (ZSTR_VAL (var_buf .s ), * hash_len , 1 );
1426
+ }
1427
+
1428
+ zval_ptr_dtor (& args );
1429
+ #else
1430
+ zval * args ;
1431
+
1432
+ MAKE_STD_ZVAL (args );
1433
+ array_init_size (args , 3 );
1434
+ ADD_ASSOC_STRING (args , "uri" , (char * ) uri_string );
1435
+
1436
+ if (options ) {
1437
+ ADD_ASSOC_ZVAL_EX (args , "options" , options );
1438
+ Z_ADDREF_P (options );
1439
+ } else {
1440
+ ADD_ASSOC_NULL_EX (args , "options" );
1441
+ }
1442
+
1443
+ if (driverOptions ) {
1444
+ ADD_ASSOC_ZVAL_EX (args , "driverOptions" , driverOptions );
1445
+ Z_ADDREF_P (driverOptions );
1446
+ } else {
1447
+ ADD_ASSOC_NULL_EX (args , "driverOptions" );
1448
+ }
1449
+
1450
+ PHP_VAR_SERIALIZE_INIT (var_hash );
1451
+ php_var_serialize (& var_buf , & args , & var_hash TSRMLS_CC );
1452
+ PHP_VAR_SERIALIZE_DESTROY (var_hash );
1453
+
1454
+ if (!EG (exception )) {
1455
+ * hash_len = var_buf .len ;
1456
+ hash = pestrndup (var_buf .c , * hash_len , 1 );
1457
+ }
1458
+
1459
+ zval_ptr_dtor (& args );
1460
+ #endif
1461
+
1462
+ smart_str_free (& var_buf );
1463
+
1464
+ return hash ;
1465
+ }
1466
+
1381
1467
static mongoc_client_t * php_phongo_make_mongo_client (const mongoc_uri_t * uri , mongoc_ssl_opt_t * ssl_opt TSRMLS_DC ) /* {{{ */
1382
1468
{
1383
1469
const char * mongoc_version , * bson_version ;
@@ -1419,10 +1505,38 @@ static mongoc_client_t *php_phongo_make_mongo_client(const mongoc_uri_t *uri, mo
1419
1505
1420
1506
void phongo_manager_init (php_phongo_manager_t * manager , const char * uri_string , zval * options , zval * driverOptions TSRMLS_DC ) /* {{{ */
1421
1507
{
1508
+ char * hash = NULL ;
1509
+ size_t hash_len = 0 ;
1422
1510
bson_t bson_options = BSON_INITIALIZER ;
1423
1511
mongoc_uri_t * uri = NULL ;
1424
1512
mongoc_ssl_opt_t * ssl_opt = NULL ;
1425
1513
1514
+ #if PHP_VERSION_ID >= 70000
1515
+ zval * client_ptr ;
1516
+ zval new_client_ptr ;
1517
+ #else
1518
+ mongoc_client_t * * client_ptr ;
1519
+ #endif
1520
+
1521
+ if (!(hash = php_phongo_manager_make_client_hash (uri_string , options , driverOptions , & hash_len TSRMLS_CC ))) {
1522
+ /* Exception should already have been thrown and there is nothing to free */
1523
+ return ;
1524
+ }
1525
+
1526
+ #if PHP_VERSION_ID >= 70000
1527
+ if ((client_ptr = zend_hash_str_find (& MONGODB_G (clients ), hash , hash_len )) && Z_TYPE_P (client_ptr ) == IS_PTR ) {
1528
+ MONGOC_DEBUG ("Found client for hash: %s\n" , hash );
1529
+ manager -> client = (mongoc_client_t * )Z_PTR_P (client_ptr );
1530
+ goto cleanup ;
1531
+ }
1532
+ #else
1533
+ if (zend_hash_find (& MONGODB_G (clients ), hash , hash_len + 1 , (void * * ) & client_ptr ) == SUCCESS ) {
1534
+ MONGOC_DEBUG ("Found client for hash: %s\n" , hash );
1535
+ manager -> client = * client_ptr ;
1536
+ goto cleanup ;
1537
+ }
1538
+ #endif
1539
+
1426
1540
if (options ) {
1427
1541
phongo_zval_to_bson (options , PHONGO_BSON_NONE , & bson_options , NULL TSRMLS_CC );
1428
1542
}
@@ -1455,9 +1569,22 @@ void phongo_manager_init(php_phongo_manager_t *manager, const char *uri_string,
1455
1569
1456
1570
if (!manager -> client ) {
1457
1571
phongo_throw_exception (PHONGO_ERROR_RUNTIME TSRMLS_CC , "Failed to create Manager from URI: '%s'" , uri_string );
1572
+ goto cleanup ;
1458
1573
}
1459
1574
1575
+ MONGOC_DEBUG ("Created client hash: %s\n" , hash );
1576
+ #if PHP_VERSION_ID >= 70000
1577
+ ZVAL_PTR (& new_client_ptr , manager -> client );
1578
+ zend_hash_str_update (& MONGODB_G (clients ), hash , hash_len , & new_client_ptr );
1579
+ #else
1580
+ zend_hash_update (& MONGODB_G (clients ), hash , hash_len + 1 , & manager -> client , sizeof (mongoc_client_t * ), NULL );
1581
+ #endif
1582
+
1460
1583
cleanup :
1584
+ if (hash ) {
1585
+ pefree (hash , 1 );
1586
+ }
1587
+
1461
1588
bson_destroy (& bson_options );
1462
1589
1463
1590
if (uri ) {
@@ -1723,22 +1850,22 @@ zend_object_iterator *php_phongo_cursor_get_iterator(zend_class_entry *ce, zval
1723
1850
/* {{{ Memory allocation wrappers */
1724
1851
static void * php_phongo_malloc (size_t num_bytes ) /* {{{ */
1725
1852
{
1726
- return emalloc (num_bytes );
1853
+ return pemalloc (num_bytes , 1 );
1727
1854
} /* }}} */
1728
1855
1729
1856
static void * php_phongo_calloc (size_t num_members , size_t num_bytes ) /* {{{ */
1730
1857
{
1731
- return ecalloc (num_members , num_bytes );
1858
+ return pecalloc (num_members , num_bytes , 1 );
1732
1859
} /* }}} */
1733
1860
1734
1861
static void * php_phongo_realloc (void * mem , size_t num_bytes ) { /* {{{ */
1735
- return erealloc (mem , num_bytes );
1862
+ return perealloc (mem , num_bytes , 1 );
1736
1863
} /* }}} */
1737
1864
1738
1865
static void php_phongo_free (void * mem ) /* {{{ */
1739
1866
{
1740
1867
if (mem ) {
1741
- efree (mem );
1868
+ pefree (mem , 1 );
1742
1869
}
1743
1870
} /* }}} */
1744
1871
@@ -1869,6 +1996,18 @@ PHP_GINIT_FUNCTION(mongodb)
1869
1996
}
1870
1997
/* }}} */
1871
1998
1999
+ #if PHP_VERSION_ID >= 70000
2000
+ static void php_phongo_client_dtor (zval * zv )
2001
+ {
2002
+ mongoc_client_destroy ((mongoc_client_t * ) Z_PTR_P (zv ));
2003
+ }
2004
+ #else
2005
+ static void php_phongo_client_dtor (void * client )
2006
+ {
2007
+ mongoc_client_destroy (* ((mongoc_client_t * * ) client ));
2008
+ }
2009
+ #endif
2010
+
1872
2011
/* {{{ PHP_MINIT_FUNCTION */
1873
2012
PHP_MINIT_FUNCTION (mongodb )
1874
2013
{
@@ -1890,6 +2029,9 @@ PHP_MINIT_FUNCTION(mongodb)
1890
2029
/* Initialize libbson */
1891
2030
bson_mem_set_vtable (& MONGODB_G (bsonMemVTable ));
1892
2031
2032
+ /* Initialize HashTable for persistent clients */
2033
+ zend_hash_init (& MONGODB_G (clients ), 0 , NULL , php_phongo_client_dtor , 1 );
2034
+
1893
2035
/* Prep default object handlers to be used when we register the classes */
1894
2036
memcpy (& phongo_std_object_handlers , zend_get_std_object_handlers (), sizeof (zend_object_handlers ));
1895
2037
phongo_std_object_handlers .clone_obj = NULL ;
@@ -1956,6 +2098,10 @@ PHP_MSHUTDOWN_FUNCTION(mongodb)
1956
2098
{
1957
2099
(void )type ; /* We don't care if we are loaded via dl() or extension= */
1958
2100
2101
+ /* Destroy HashTable for persistent clients. The HashTable destructor will
2102
+ * destroy any mongoc_client_t objects contained within. */
2103
+ zend_hash_destroy (& MONGODB_G (clients ));
2104
+
1959
2105
bson_mem_restore_vtable ();
1960
2106
/* Cleanup after libmongoc */
1961
2107
mongoc_cleanup ();
0 commit comments