|
|
本帖最后由 yulihua49 于 2021-1-19 12:06 编辑
PROC多线程非常困难,OCI多线程相对容易。
还有一个可能是你自己的环境没弄好,不是OCI的问题。
必须每个线程使用自己的context。
- /*---------------------------------------------------------------------------
- * sqlo_server_attach
- *--------------------------------------------------------------------------*/
- int
- DEFUN(sqlo_server_attach, (dbhp, tnsname),
- sqlo_db_handle_t * dbhp AND
- const char * tnsname )
- {
- sqlo_db_struct_ptr_t dbp;
-
- if (dbhp)
- *dbhp = -1;
- TRACE(2, fprintf(_get_trace_fp(NULL), "sqlo_server_attach starts\n" ););
- if (!(dbp = _db_add())) {
- TRACE(3, fprintf(_get_trace_fp(NULL),
- "sqlo_server_attach: Could not alloacte a dbp\n"); );
- return SQLO_ERROR;
- }
- TRACE(3, fprintf(_get_trace_fp(dbp), "sqlo_server_attach: allocated dbh=%u\n",
- dbp->dbh); );
- /* if tnsname contains a connect string we split it */
- if (strchr(tnsname, [url=mailto:]'@'[/url]) || strchr(tnsname, '/') ) {
- enum {MAX_BUFLEN = 1023};
- char uid[MAX_BUFLEN + 1];
- char pwd[MAX_BUFLEN + 1];
- char dbname[MAX_BUFLEN + 1];
- if (SQLO_SUCCESS != sqlo_split_cstring(tnsname, uid, pwd, dbname, MAX_BUFLEN))
- return SQLO_ERROR;
- dbp->tnsname = strdup(dbname);
-
- } else {
- dbp->tnsname = strdup(tnsname);
- }
- dbp->status = SQLO_SUCCESS;
- dbp->exec_flags = OCI_DEFAULT;
- dbp->errmsg[0] = '\0';
- /* We return the handle even on error, so sql_geterror can return
- * the stored message
- */
- if (dbhp)
- *dbhp = (int) dbp->dbh;
- /*
- We must use OCIEnvCreate instead of OCIInitialize / OCIEnvInit (see Oracle OCI
- Programmer's Guide 8.1.6 pg 15-91 - 15-93). If during the first call to OCIEnvCreate
- an OCI_THREADED parameter is specified then this parameter will apply all along.
- CAFL says fb doesn't have the earlier manual...which says to use
- ocienvinit to create the handle. The real question is whether to pass
- OCI_NO_MUTEX to it, which would probably be right here where there is one
- environment handle per connection, or OCI_DEFAULT. I have no guts.
- */
- /* There are roumors that OCIEnvCreate is not thread safe. I'm not sure that this
- * is true, but to be on the safe side, I protect it by a lock
- */
- EXEC_WHEN_THREADING(_env_lock(););
- #ifdef HAVE_OCIENVCREATE
- dbp->status = OCIEnvCreate( &dbp->envhp,
- _oci_init_mode,
- NULL, NULL, NULL, NULL, 0, NULL
- ) ;
- CHECK_OCI_STATUS(dbp, dbp->status, "sqlo_server_attach", "OCIEnvCreate" );
- #else
- dbp->status = OCIEnvInit( (dvoid *)&dbp->envhp,
- _oci_init_mode,
- 0, (dvoid **)0
- );
- CHECK_OCI_STATUS(dbp, dbp->status, "sqlo_server_attach", "OCIEnvInit" );
- #endif
- EXEC_WHEN_THREADING( _env_unlock(); );
- /* release allocated resources */
- if (OCI_SUCCESS != dbp->status) {
- _db_release( dbp );
- return ( dbp->status );
- }
- /* Alloc the service context handle */
- dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
- (dvoid **)&dbp->svchp,
- OCI_HTYPE_SVCCTX,
- 0,
- (dvoid **) 0
- );
- CHECK_OCI_STATUS(dbp, dbp->status,
- "sqlo_server_attach", "OCIEnvHandleAlloc(svchp)" );
- /* release allocated resources */
- if (OCI_SUCCESS != dbp->status) {
- _db_release( dbp );
- return (dbp->status);
- }
- /* Alloc the error handle */
- dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
- (dvoid **)&dbp->errhp,
- OCI_HTYPE_ERROR,
- 0, (dvoid **) 0
- );
- CHECK_OCI_STATUS(dbp, dbp->status, "sqlo_server_attach",
- "OCIHandleAlloc(errhp)" );
-
- /* release allocated resources */
- if (OCI_SUCCESS != dbp->status) {
- _db_release( dbp );
- return ( dbp->status );
- }
- /* Alloc the server handle */
- dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
- (dvoid **)&dbp->srvhp,
- OCI_HTYPE_SERVER,
- 0,
- (dvoid **) 0
- );
-
- CHECK_OCI_STATUS(dbp, dbp->status,
- "sqlo_server_attach", "OCIHandleAlloc(srvhp)" );
- /* release allocated resources */
- if (OCI_SUCCESS != dbp->status) {
- _db_release(dbp);
- return (dbp->status);
- }
- /* Create a server context */
- dbp->status = OCIServerAttach( dbp->srvhp,
- dbp->errhp,
- (text *)dbp->tnsname,
- strlen(dbp->tnsname),
- OCI_DEFAULT
- );
- CHECK_OCI_STATUS(dbp, dbp->status,
- "sqlo_server_attach", "OCISeverAttach(tnsname)");
- /* release allocated resources */
- if (OCI_SUCCESS != dbp->status) {
- _db_release( dbp );
- return ( dbp->status );
- }
- /* Set the server context in the service context */
- dbp->status = OCIAttrSet( (dvoid *)dbp->svchp,
- OCI_HTYPE_SVCCTX,
- (dvoid *)dbp->srvhp,
- (ub4) 0,
- OCI_ATTR_SERVER,
- dbp->errhp
- );
- CHECK_OCI_STATUS(dbp, dbp->status,
- "sqlo_server_attach", "OCIAttrSet(server->service)" );
-
- /* release allocated resources */
- if (OCI_SUCCESS != dbp->status) {
- _db_release( dbp );
- return ( dbp->status );
- }
- /* Allocate a authentication handle */
- dbp->status = OCIHandleAlloc( (dvoid *)dbp->envhp,
- (dvoid **)&dbp->authp,
- OCI_HTYPE_SESSION,
- 0,
- (dvoid **) 0
- );
- CHECK_OCI_STATUS( dbp, dbp->status,
- "sqlo_server_attach", "OCIHandleAlloc(authp)" );
- if (SQLO_SUCCESS == dbp->status) {
- TRACE(2,fprintf( _get_trace_fp(dbp), "sqlo_server_attach[%d]: attached\n", *dbhp); );
- } else {
- /* release allocated resources */
- TRACE(2,fprintf( _get_trace_fp(dbp), "sqlo_server_attach[%d]: failed\n", *dbhp); );
- _db_release( dbp );
- return ( dbp->status );
- }
-
- dbp->used = TRUE;
- dbp->attached = TRUE;
- return ( dbp->status );
- }
复制代码
这是他的打开环境函数,可以看到里边线程加锁的动作。
- /* There are roumors that OCIEnvCreate is not thread safe. I'm not sure that this
- * is true, but to be on the safe side, I protect it by a lock
- */
这东西是线程独享,就是说,每个线程一个或多个,不能一个连接各线程用。
多线程时,我是建立连接池,每个线程各自从池里取连接。
程序发不了,说是有不良信息。QQ讨论吧。
|
|