phanto          Tue Dec 16 05:29:12 2003 EDT

  Modified files:              
    /php-src/ext/oci8   oci8.c php_oci8.h 
  Log:
  @- fixed #20006, #22674 and #24531 (harald)
  @- added ZTS connection pooling support to the oci extension
  @  connections will now be pooled per process and not
  @  per thread anymore. the number of persistent and active
  @  connections is now also shown in the phpinfo() output (harald)
  
  
Index: php-src/ext/oci8/oci8.c
diff -u php-src/ext/oci8/oci8.c:1.219 php-src/ext/oci8/oci8.c:1.220
--- php-src/ext/oci8/oci8.c:1.219       Mon Dec 15 08:53:01 2003
+++ php-src/ext/oci8/oci8.c     Tue Dec 16 05:29:11 2003
@@ -18,15 +18,20 @@
    |                                                                      |
    | Collection support by Andy Sautins <[EMAIL PROTECTED]>           |
    | Temporary LOB support by David Benson <[EMAIL PROTECTED]>          |
+   | ZTS per process OCIPLogon by Harald Radi <[EMAIL PROTECTED]>        |
    +----------------------------------------------------------------------+
  */
 
-/* $Id: oci8.c,v 1.219 2003/12/15 13:53:01 tony2001 Exp $ */
+/* $Id: oci8.c,v 1.220 2003/12/16 10:29:11 phanto Exp $ */
 
 /* TODO list:
  *
  * - php.ini flags 
  *   especialliy important for things like oci_ping
+ *             allowpconns
+ *             timeout
+ *             maxlifetime
+ *             maxpconns
  * - Change return-value for OCIFetch*() (1-row read, 0-Normal end, false-error) 
  * - Error mode (print or shut up?)
  * - binding of arrays
@@ -37,7 +42,6 @@
  * - make OCIInternalDebug accept a mask of flags....
  * - have one ocifree() call.
  * - make it possible to have persistent statements?
- * - implement connection pooling in ZTS mode.
  * - failover
  * - change all the lob stuff to work without classes (optional)! 
  * - make sure that the callbacks terminate the strings with \0
@@ -60,6 +64,7 @@
 
 #include "php.h"
 #include "ext/standard/info.h"
+#include "php_ini.h"
 
 /* #define HAVE_OCI8_TEMP_LOB 1 */
 #define WITH_COLLECTIONS 1
@@ -68,6 +73,13 @@
 
 #include "php_oci8.h"
 
+/* True globals, only used by thread safe functions */
+static TsHashTable *persistent_servers;
+static TsHashTable *persistent_sessions;
+
+static long num_persistent = 0;
+static long num_links = 0;
+
 /* True globals, no need for thread safety */
 static int le_conn;
 static int le_stmt;
@@ -91,6 +103,21 @@
 
 #define SAFE_STRING(s) ((s)?(s):"")
 
+#ifdef ZTS
+MUTEX_T mx_lock;
+
+#define mutex_alloc() tsrm_mutex_alloc()
+#define mutex_free(mutex) tsrm_mutex_free(mutex)
+#define mutex_lock(mutex) tsrm_mutex_lock(mutex)
+#define mutex_unlock(mutex) tsrm_mutex_unlock(mutex)
+#define thread_id()    tsrm_thread_id()
+#else
+#define mutex_alloc()
+#define mutex_free(mutex)
+#define mutex_lock(mutex)
+#define mutex_unlock(mutex)
+#define thread_id() 1
+#endif
 
 /* dirty marcos to make sure we _never_ call oracle-functions recursivly 
  *
@@ -462,35 +489,6 @@
 };
 
 /* }}} */
-/* {{{ debug malloc/realloc/free */
-
-#define OCI_USE_EMALLOC 0              /* set this to 1 if you want to use the php 
memory manager! */
-
-#if OCI_USE_EMALLOC
-CONST dvoid *ocimalloc(dvoid *ctx, size_t size)
-{
-       dvoid *ret;
-       ret = (dvoid *)malloc(size);
-       oci_debug("ocimalloc(%d) = %08x", size,ret);
-       return ret;
-}
-
-CONST dvoid *ocirealloc(dvoid *ctx, dvoid *ptr, size_t size)
-{
-       dvoid *ret;
-       oci_debug("ocirealloc(%08x, %d)", ptr, size);
-       ret = (dvoid *)realloc(ptr, size);
-       return ptr;
-}
-
-CONST void ocifree(dvoid *ctx, dvoid *ptr)
-{
-       oci_debug("ocifree(%08x)", ptr);
-       free(ptr);
-}
-#endif
-
-/* }}} */
 /* {{{ startup, shutdown and info functions */
 
 static void php_oci_init_globals(php_oci_globals *oci_globals_p TSRMLS_DC)
@@ -498,12 +496,6 @@
        OCI(shutdown)   = 0;
        OCI(in_call)    = 0;
 
-       OCI(user) = malloc(sizeof(HashTable));
-       zend_hash_init(OCI(user), 13, NULL, NULL, 1);
-
-       OCI(server) = malloc(sizeof(HashTable));
-       zend_hash_init(OCI(server), 13, NULL, NULL, 1); 
-
        CALL_OCI(OCIEnvInit(
                                &OCI(pEnv), 
                                OCI_DEFAULT, 
@@ -518,6 +510,27 @@
                                NULL));
 }
 
+static int _sessions_pcleanup(zend_llist *session_list TSRMLS_DC)
+{
+       zend_llist_destroy(session_list);
+
+       return 1;
+}
+
+static int _session_pcleanup(oci_session *session TSRMLS_DC)
+{
+       _oci_close_session(session);
+
+       return 1;
+}
+
+static int _server_pcleanup(oci_server *server TSRMLS_DC)
+{
+       _oci_close_server(server);
+
+       return 1;
+}
+
 PHP_MINIT_FUNCTION(oci)
 {
        zend_class_entry oci_lob_class_entry;
@@ -543,11 +556,14 @@
 
 #endif
 
-#if OCI_USE_EMALLOC
-       OCIInitialize(PHP_OCI_INIT_MODE, NULL, ocimalloc, ocirealloc, ocifree);
-#else
+       mx_lock = mutex_alloc();
+
+       persistent_servers = malloc(sizeof(TsHashTable));
+       persistent_sessions = malloc(sizeof(TsHashTable));
+       zend_ts_hash_init(persistent_servers, 13, NULL, (dtor_func_t) 
_server_pcleanup, 1); 
+       zend_ts_hash_init(persistent_sessions, 13, NULL, (dtor_func_t) 
_sessions_pcleanup, 1); 
+
        OCIInitialize(PHP_OCI_INIT_MODE, NULL, NULL, NULL, NULL);
-#endif
 
 #ifdef ZTS
        ts_allocate_id(&oci_globals_id, sizeof(php_oci_globals), (ts_allocate_ctor) 
php_oci_init_globals, NULL);
@@ -642,11 +658,6 @@
 
 PHP_RINIT_FUNCTION(oci)
 {
-       /* XXX NYI
-       OCI(num_links) = 
-               OCI(num_persistent);
-       */
-
        OCI(debug_mode) = 0; /* start "fresh" */
 /*     OCI(in_call) = 0; i don't think we want this! */
 
@@ -655,34 +666,19 @@
        return SUCCESS;
 }
 
-static int _session_pcleanup(oci_session *session TSRMLS_DC)
-{
-       _oci_close_session(session);
-
-       return 1;
-}
-
-static int _server_pcleanup(oci_server *server TSRMLS_DC)
-{
-       _oci_close_server(server);
-
-       return 1;
-}
-
 PHP_MSHUTDOWN_FUNCTION(oci)
 {
        OCI(shutdown) = 1;
 
        oci_debug("START php_mshutdown_oci");
 
-       zend_hash_apply(OCI(user), (apply_func_t)_session_pcleanup TSRMLS_CC);
-       zend_hash_apply(OCI(server), (apply_func_t)_server_pcleanup TSRMLS_CC);
+       zend_ts_hash_destroy(persistent_sessions);
+       zend_ts_hash_destroy(persistent_servers);
 
-       zend_hash_destroy(OCI(user));
-       zend_hash_destroy(OCI(server));
+       free(persistent_sessions);
+       free(persistent_servers);
 
-       free(OCI(user));
-       free(OCI(server));
+       mutex_free(mx_lock);
 
        CALL_OCI(OCIHandleFree(
                                (dvoid *)OCI(pEnv), 
@@ -700,8 +696,8 @@
 #if 0
        /* XXX free all statements, rollback all outstanding transactions */
 
-       zend_hash_apply(OCI(user), (apply_func_t) _session_cleanup TSRMLS_CC);
-       zend_hash_apply(OCI(server), (apply_func_t) _server_cleanup TSRMLS_CC);
+       zend_ts_hash_apply(persistent_sessions, (apply_func_t) _session_cleanup 
TSRMLS_CC);
+       zend_ts_hash_apply(persistent_servers, (apply_func_t) _server_cleanup 
TSRMLS_CC);
 #endif
 
        oci_debug("END   php_rshutdown_oci");
@@ -712,10 +708,17 @@
 
 PHP_MINFO_FUNCTION(oci)
 {
+       char buf[32];
 
        php_info_print_table_start();
        php_info_print_table_row(2, "OCI8 Support", "enabled");
-       php_info_print_table_row(2, "Revision", "$Revision: 1.219 $");
+       php_info_print_table_row(2, "Revision", "$Revision: 1.220 $");
+
+       sprintf(buf, "%ld", num_persistent);
+       php_info_print_table_row(2, "Active Persistent Links", buf);
+       sprintf(buf, "%ld", num_links);
+       php_info_print_table_row(2, "Active Links", buf);
+
 #ifndef PHP_WIN32
        php_info_print_table_row(2, "Oracle Version", PHP_OCI8_VERSION );
        php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DIR );
@@ -910,9 +913,8 @@
                                        (ub4) OCI_HTYPE_SVCCTX));
        }
 
-       if (connection->session && connection->session->exclusive) {
-               /* exclusive connection created via OCINLogon() close their 
-                  associated session when destructed */
+       if (connection->session) {
+               /* close associated session when destructed */
                zend_list_delete(connection->session->num);
        }
 
@@ -1003,8 +1005,11 @@
 _oci_session_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
        oci_session *session = (oci_session *)rsrc->ptr;
-       if (session->persistent)
+       if (session->persistent) {
+               /* clear thread assignment */
+               session->thread = 0;
                return;
+       }
 
        _oci_close_session(session);
 }
@@ -2120,7 +2125,7 @@
        ub4 siz = 0;
        ub4 readlen = 0;
        ub4 loblen = 0;
-       int bytes = 0;
+       ub4 bytes = 0;
        char *buf;
        TSRMLS_FETCH();
 
@@ -2172,7 +2177,7 @@
                return -1;
        }
 
-       while (readlen > 0 && bytes < *len && siz < loblen) {  //paranoia
+       while (readlen > 0 && bytes < *len && siz < loblen) {  /* paranoia */
                CALL_OCI_RETURN(connection->error, OCILobRead(
                                        connection->pServiceContext, 
                                        connection->pError, 
@@ -2420,8 +2425,9 @@
 
 static oci_session *_oci_open_session(oci_server* server,char *username,char 
*password,int persistent,int exclusive,char *charset)
 {
-       oci_session *session = 0, *psession = 0;
-       OCISvcCtx *svchp = 0;
+       zend_llist *session_list;
+       oci_session *session = NULL;
+       OCISvcCtx *svchp = NULL;
        smart_str hashed_details = {0};
 #ifdef HAVE_OCI_9_2
        ub2 charsetid = 0;
@@ -2475,7 +2481,27 @@
        smart_str_0(&hashed_details);
 
        if (! exclusive) {
-               zend_hash_find(OCI(user), hashed_details.c, hashed_details.len+1, 
(void **) &session);
+               if (zend_ts_hash_find(persistent_sessions, hashed_details.c, 
hashed_details.len+1, &session_list) != SUCCESS) {
+                       zend_llist tmp;
+                       /* first session, set up a session list */
+                       zend_llist_init(&tmp, sizeof(oci_session), (llist_dtor_func_t) 
_session_pcleanup, 1);
+                       zend_ts_hash_update(persistent_sessions, hashed_details.c, 
hashed_details.len+1, &tmp, sizeof(zend_llist), &session_list);
+               } else {
+                       mutex_lock(mx_lock);
+
+                       /* session list found, search for an idle session or an 
already opened session by the current thread */
+                       session = zend_llist_get_first(session_list);
+                       while ((session != NULL) && session->thread && 
(session->thread != thread_id())) {
+                               session = zend_llist_get_next(session_list);
+                       }
+
+                       if (session != NULL) {
+                               /* mark session as busy */
+                               session->thread = thread_id();
+                       }
+
+                       mutex_unlock(mx_lock);
+               }
 
                if (session) {
                        if (session->is_open) {
@@ -2491,16 +2517,17 @@
                }
        }
 
-       session = calloc(1,sizeof(oci_session));
+       session = ecalloc(1,sizeof(oci_session));
 
        if (! session) {
                goto CLEANUP;
        }
 
        session->persistent = persistent;
-       session->hashed_details = hashed_details.c;
        session->server = server;
        session->exclusive = exclusive;
+       session->sessions_list = session_list;
+       session->thread = thread_id();
 
 #ifdef HAVE_OCI_9_2
 
@@ -2627,25 +2654,22 @@
                                (dvoid *) svchp, 
                                (ub4) OCI_HTYPE_SVCCTX));
 
-       if (exclusive) {
-               psession = session;
-       } else {
-               zend_hash_update(OCI(user),
-                                                session->hashed_details,
-                                                strlen(session->hashed_details)+1, 
-                                                (void *)session,
-                                                sizeof(oci_session),
-                                                (void**)&psession);
-       }
-
-       psession->num = zend_list_insert(psession,le_session);
-       psession->is_open = 1;
+       session->num = zend_list_insert(session, le_session);
+       session->is_open = 1;
 
-       oci_debug("_oci_open_session new sess=%d user=%s",psession->num,username);
+       mutex_lock(mx_lock);
+               num_links++;
+               if (! exclusive) {
+                       zend_llist_add_element(session_list, session);
+                       efree(session);
+                       session = (oci_session*) session_list->tail->data;
+                       num_persistent++;
+               }
+       mutex_unlock(mx_lock);
 
-       if (! exclusive) free(session);
+       oci_debug("_oci_open_session new sess=%d user=%s",session->num,username);
 
-       return psession;
+       return session;
 
 CLEANUP:
        oci_debug("_oci_open_session: FAILURE -> CLEANUP called");
@@ -2659,11 +2683,15 @@
 /* {{{ _oci_close_session()
  */
 
+static int _session_compare(oci_session *sess1, oci_session *sess2)
+{
+       return sess1->num = sess2->num;
+}
+
 static void
 _oci_close_session(oci_session *session)
 {
        OCISvcCtx *svchp;
-       char *hashed_details;
        TSRMLS_FETCH();
 
        if (! session) {
@@ -2735,13 +2763,17 @@
                                        (ub4) OCI_HTYPE_SESSION));
        }
 
-       hashed_details = session->hashed_details;
+       mutex_lock(mx_lock);
+               num_links--;
+               if (! OCI(shutdown) && session->persistent) {
+                       zend_llist_del_element(session->sessions_list, session, 
_session_compare);
+                       num_persistent--;
+               }
+       mutex_unlock(mx_lock);
 
-       if (! OCI(shutdown)) {
-               zend_hash_del(OCI(user), hashed_details, strlen(hashed_details)+1);
+       if (session->exclusive) {
+               efree(session);
        }
-
-       free(hashed_details);
 }
 
 /* }}} */
@@ -2750,7 +2782,7 @@
 
 static oci_server *_oci_open_server(char *dbname,int persistent)
 { 
-       oci_server *server, *pserver = 0;
+       oci_server *server, *pserver = NULL;
        TSRMLS_FETCH();
 
        /* 
@@ -2762,7 +2794,8 @@
           but only as pesistent requested connections will be kept between requests!
        */
 
-       zend_hash_find(OCI(server), dbname, strlen(dbname)+1, (void **) &pserver);
+       /* TODO either keep servers global or don't reuse them at all */
+       zend_ts_hash_find(persistent_servers, dbname, strlen(dbname)+1, (void **) 
&pserver);
 
        if (pserver) {
                /* XXX ini-flag */
@@ -2784,7 +2817,7 @@
                }
        }
        
-       server = calloc(1,sizeof(oci_server));
+       server = ecalloc(1,sizeof(oci_server));
 
        server->persistent = persistent;
        server->dbname = strdup(SAFE_STRING(dbname));
@@ -2808,7 +2841,7 @@
                goto CLEANUP;
        }
        
-       zend_hash_update(OCI(server),
+       zend_ts_hash_update(persistent_servers,
                                         server->dbname,
                                         strlen(server->dbname)+1, 
                                         (void *)server,
@@ -2820,7 +2853,7 @@
 
        oci_debug("_oci_open_server new conn=%d dname=%s",server->num,server->dbname);
 
-       free(server);
+       efree(server);
 
        return pserver;
 
@@ -2909,7 +2942,7 @@
        dbname = server->dbname;
 
        if (! OCI(shutdown)) {
-               zend_hash_del(OCI(server),dbname,strlen(dbname)+1);
+               zend_ts_hash_del(persistent_servers, dbname, strlen(dbname)+1);
        }
 
        free(dbname);
@@ -2977,7 +3010,7 @@
                persistent = 0;
        } else {
                /* if our server-context is not persistent we can't */
-               persistent = server->persistent; 
+               persistent = (server->persistent) ? persistent : 0;
        }
 
        session = 
_oci_open_session(server,username,password,persistent,exclusive,charset);
@@ -3620,7 +3653,6 @@
        zval *id;
        oci_descriptor *descr;
        int inx;
-       int len;
 
        if ((id = getThis()) != 0) {
                if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
@@ -3642,7 +3674,6 @@
        zval *id;
        oci_descriptor *descr;
        int inx;
-       int len;
 
        if ((id = getThis()) != 0) {
                if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
@@ -3704,7 +3735,7 @@
                                }
                }
                        else {
-                               //OCI_SEEK_SET by default
+                               /* OCI_SEEK_SET by default */
                                descr->lob_current_position = Z_LVAL_PP(arg1);
                        }
                        RETURN_TRUE;
@@ -3825,7 +3856,7 @@
                        descr->lob_size = descr->lob_current_position;
                }
                
-               //marking buffer as used
+               /* marking buffer as used */
                if (descr->buffering == 1) {
                        descr->buffering = 2;
                }
@@ -3954,7 +3985,7 @@
                }
 
                if (trim_length < 0) {
-                       //negative length is not allowed
+                       /* negative length is not allowed */
                        RETURN_FALSE;
                }
                
@@ -4095,12 +4126,12 @@
                }
 
                if (descr->buffering == 0) {
-                       //buffering wasn't enabled, there is nothing to flush
+                       /* buffering wasn't enabled, there is nothing to flush */
                        RETURN_FALSE;
                }
                else if (descr->buffering == 1) {
-                       //buffering is enabled, but not used yet
-                       //dunno why, but OCI returns error in this case, so I think we 
should suppress it
+                       /* buffering is enabled, but not used yet
+                          dunno why, but OCI returns error in this case, so I think 
we should suppress it */
                        RETURN_TRUE;
                }
                
@@ -4212,11 +4243,10 @@
 
 PHP_FUNCTION(ocigetbufferinglob)
 {
-       zval *id, **flag;
+       zval *id;
        OCILobLocator *mylob;
        oci_descriptor *descr;
        int inx;
-       ub4 curloblen;
 
        if ((id = getThis()) != 0) {
                if ((inx = _oci_get_ocidesc(id,&descr TSRMLS_CC)) == 0) {
@@ -4333,7 +4363,6 @@
        oci_connection *connection;
        oci_descriptor *first_descr,*second_descr;
        int inx;
-       ub4 first_curloblen,second_curloblen;
        boolean is_equal;
 
                if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
Index: php-src/ext/oci8/php_oci8.h
diff -u php-src/ext/oci8/php_oci8.h:1.30 php-src/ext/oci8/php_oci8.h:1.31
--- php-src/ext/oci8/php_oci8.h:1.30    Mon Dec 15 08:53:01 2003
+++ php-src/ext/oci8/php_oci8.h Tue Dec 16 05:29:11 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: php_oci8.h,v 1.30 2003/12/15 13:53:01 tony2001 Exp $ */
+/* $Id: php_oci8.h,v 1.31 2003/12/16 10:29:11 phanto Exp $ */
 
 #if HAVE_OCI8
 # ifndef PHP_OCI8_H
@@ -68,10 +68,15 @@
 
 typedef struct {
        int num;
-       int persistent;
-       int is_open;
-       int exclusive;
-       char *hashed_details;
+       zend_bool persistent;
+       zend_bool is_open;
+       zend_bool exclusive;
+#if ZTS
+       THREAD_T thread;
+#else
+       zend_bool thread;
+#endif
+       zend_llist *sessions_list;
        oci_server *server;
        OCISession *pSession;
        OCIEnv *pEnv;                           /* sessions own environment */
@@ -185,13 +190,8 @@
     long allow_persistent;
     long max_persistent;
     long max_links;
-    long num_persistent;
-    long num_links;
        */
 
-    HashTable *server;
-       HashTable *user;
-
     OCIEnv *pEnv;
 
        int in_call;

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to