00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <string.h>
00024 #include <stdio.h>
00025 #include "../../mem/mem.h"
00026 #include "../../dprint.h"
00027 #include "asynch.h"
00028 #include "ora_con.h"
00029
00030
00031
00032
00033
00034
00035 ora_con_t* db_oracle_new_connection(const struct db_id* id)
00036 {
00037 ora_con_t* con;
00038 char buf[512];
00039 size_t uri_len;
00040 sword status;
00041
00042 if (!id || !id->username || !*id->username || !id->password ||
00043 !*id->password || !id->database || !*id->database)
00044 {
00045 bad_param:
00046 LM_ERR("invalid parameter value\n");
00047 return NULL;
00048 }
00049
00050
00051 if (!id->host || !*id->host) {
00052 if (id->port) goto bad_param;
00053 uri_len = snprintf(buf, sizeof(buf), "%s", id->database);
00054 } else if (id->port) {
00055 uri_len = snprintf(buf, sizeof(buf), "%s:%u/%s",
00056 id->host, id->port, id->database);
00057 } else {
00058 uri_len = snprintf(buf, sizeof(buf), "%s/%s",
00059 id->host, id->database);
00060 }
00061 if (uri_len >= sizeof(buf)) goto bad_param;
00062 LM_DBG("opening connection: oracle://xxxx:xxxx@%s\n", buf);
00063
00064 con = (ora_con_t*)pkg_malloc(sizeof(*con) + uri_len+1);
00065 if (!con) {
00066 LM_ERR("no private memory left\n");
00067 return NULL;
00068 }
00069
00070 memset(con, 0, sizeof(*con));
00071 con->hdr.ref = 1;
00072 con->hdr.id = (struct db_id*)id;
00073 con->uri_len = uri_len;
00074 memcpy(con->uri, buf, uri_len+1);
00075
00076 if ( OCIEnvCreate(&con->envhp,
00077 OCI_DEFAULT | OCI_NEW_LENGTH_SEMANTICS,
00078 NULL, NULL, NULL, NULL, 0, NULL) != OCI_SUCCESS
00079 || OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&con->errhp,
00080 OCI_HTYPE_ERROR, 0, NULL) != OCI_SUCCESS
00081 || OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&con->srvhp,
00082 OCI_HTYPE_SERVER, 0, NULL) != OCI_SUCCESS
00083 || OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&con->svchp,
00084 OCI_HTYPE_SVCCTX, 0, NULL) != OCI_SUCCESS
00085 || OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&con->authp,
00086 OCI_HTYPE_SESSION, 0, NULL) != OCI_SUCCESS)
00087 {
00088
00089 LM_ERR("no oracle memory left\n");
00090 db_oracle_free_connection(con);
00091 return NULL;
00092 }
00093
00094 status = OCIAttrSet(con->svchp, OCI_HTYPE_SVCCTX, con->srvhp, 0,
00095 OCI_ATTR_SERVER, con->errhp);
00096 if (status != OCI_SUCCESS) goto connect_err;
00097 status = OCIAttrSet(con->authp, OCI_HTYPE_SESSION,
00098 id->username, (ub4)strlen(id->username),
00099 OCI_ATTR_USERNAME, con->errhp);
00100 if (status != OCI_SUCCESS) goto connect_err;
00101 status = OCIAttrSet(con->authp, OCI_HTYPE_SESSION,
00102 id->password, (ub4)strlen(id->password),
00103 OCI_ATTR_PASSWORD, con->errhp);
00104 if (status != OCI_SUCCESS) goto connect_err;
00105 status = OCIAttrSet(con->svchp, OCI_HTYPE_SVCCTX, con->authp, 0,
00106 OCI_ATTR_SESSION, con->errhp);
00107 if (status != OCI_SUCCESS) goto connect_err;
00108 status = db_oracle_reconnect(con);
00109 if (status != OCI_SUCCESS) {
00110 connect_err:
00111 if ( (status != OCI_ERROR && status != OCI_SUCCESS_WITH_INFO)
00112 || OCIErrorGet(con->errhp, 1, NULL, &status, (OraText*)buf,
00113 sizeof(buf), OCI_HTYPE_ERROR) != OCI_SUCCESS)
00114 {
00115 LM_ERR("internal driver error\n");
00116 } else {
00117 LM_ERR("driver: %s\n", buf);
00118 }
00119 drop_connection:
00120 db_oracle_free_connection(con);
00121 return NULL;
00122 }
00123
00124
00125 status = begin_timelimit(con, 0);
00126 if (status != OCI_SUCCESS) goto connect_err;
00127 do status = OCIServerVersion(con->svchp, con->errhp, (OraText*)buf,
00128 (ub4)sizeof(buf), OCI_HTYPE_SVCCTX);
00129 while (wait_timelimit(con, status));
00130 if (done_timelimit(con, status)) goto drop_connection;
00131 if (status != OCI_SUCCESS) goto connect_err;
00132 LM_INFO("server version is %s\n", buf);
00133 return con;
00134 }
00135
00136
00137
00138
00139
00140 void db_oracle_free_connection(ora_con_t* con)
00141 {
00142 if (!con) return;
00143
00144 if (con->connected)
00145 db_oracle_disconnect(con);
00146 if (con->svchp)
00147 OCIHandleFree(con->svchp, OCI_HTYPE_SVCCTX);
00148 if (con->authp)
00149 OCIHandleFree(con->authp, OCI_HTYPE_SESSION);
00150 if (con->srvhp)
00151 OCIHandleFree(con->srvhp, OCI_HTYPE_SERVER);
00152 if (con->errhp)
00153 OCIHandleFree(con->errhp, OCI_HTYPE_ERROR);
00154 if (con->envhp)
00155 OCIHandleFree(con->envhp, OCI_HTYPE_ENV);
00156 free_db_id(con->hdr.id);
00157 pkg_free(con);
00158 }
00159
00160
00161
00162
00163
00164 void db_oracle_disconnect(ora_con_t* con)
00165 {
00166 sword status;
00167
00168 switch (con->connected) {
00169 default:
00170 status = OCISessionEnd(con->svchp, con->errhp, con->authp,
00171 OCI_DEFAULT);
00172 if (status != OCI_SUCCESS)
00173 LM_ERR("driver: %s\n", db_oracle_error(con, status));
00174 case 1:
00175 status = OCIServerDetach(con->srvhp, con->errhp, OCI_DEFAULT);
00176 if (status != OCI_SUCCESS)
00177 LM_ERR("driver: %s\n", db_oracle_error(con, status));
00178 con->connected = 0;
00179 case 0:
00180 break;
00181 }
00182 }
00183
00184
00185
00186
00187
00188 sword db_oracle_reconnect(ora_con_t* con)
00189 {
00190 sword status;
00191
00192 if (con->connected)
00193 db_oracle_disconnect(con);
00194
00195
00196 status = OCIServerAttach(con->srvhp, con->errhp, (OraText*)con->uri,
00197 con->uri_len, 0);
00198 if (status == OCI_SUCCESS) {
00199 ++con->connected;
00200
00201
00202
00203
00204
00205
00206 status = begin_timelimit(con, 1);
00207 if (status != OCI_SUCCESS) goto done;
00208 status = OCISessionBegin(con->svchp, con->errhp, con->authp,
00209 OCI_CRED_RDBMS, OCI_DEFAULT);
00210 while (wait_timelimit(con, status)) {
00211 sword code;
00212
00213 status = OCIServerVersion(con->svchp, con->errhp, NULL,
00214 0, OCI_HTYPE_SVCCTX);
00215
00216 if ( status != OCI_ERROR
00217 || OCIErrorGet(con->errhp, 1, NULL, &code, NULL, 0,
00218 OCI_HTYPE_ERROR) != OCI_SUCCESS) break;
00219 switch (code) {
00220 case 24909:
00221 status = OCI_STILL_EXECUTING;
00222 continue;
00223
00224 case 3127:
00225 status = OCISessionBegin(con->svchp, con->errhp,
00226 con->authp, OCI_CRED_RDBMS, OCI_DEFAULT);
00227 default:
00228 break;
00229 }
00230 break;
00231 }
00232 if (done_timelimit(con, status)) goto done;
00233
00234 if (status == OCI_SUCCESS)
00235 ++con->connected;
00236 }
00237 done:
00238 return status;
00239 }