|
|
818202b |
From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=A1=D0=B0=D0=BC?=
|
|
|
818202b |
=?UTF-8?q?=D1=83=D1=81=D0=B5=D0=BD=D0=BA=D0=BE?= <samusenko@msm.ru>
|
|
|
e73f7b5 |
Date: Mon, 25 Jun 2012 17:54:27 +0400
|
|
|
fa3f242 |
Subject: [PATCH] Removed all async Oracle operations - they didn't work well
|
|
|
fa3f242 |
anyway
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
|
|
|
a32049e |
diff --git a/modules/db_oracle/asynch.c b/modules/db_oracle/asynch.c
|
|
|
a32049e |
deleted file mode 100644
|
|
|
a32049e |
index d1bbe84..0000000
|
|
|
a32049e |
--- a/modules/db_oracle/asynch.c
|
|
|
a32049e |
+++ /dev/null
|
|
|
a32049e |
@@ -1,270 +0,0 @@
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * $Id$
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * Oracle module interface
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * Copyright (C) 2007,2008 TRUNK MOBILE
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * This file is part of opensips, a free SIP server.
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * opensips is free software; you can redistribute it and/or modify
|
|
|
a32049e |
- * it under the terms of the GNU General Public License as published by
|
|
|
a32049e |
- * the Free Software Foundation; either version 2 of the License, or
|
|
|
a32049e |
- * (at your option) any later version
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * opensips is distributed in the hope that it will be useful,
|
|
|
a32049e |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
a32049e |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
a32049e |
- * GNU General Public License for more details.
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * You should have received a copy of the GNU General Public License
|
|
|
a32049e |
- * along with this program; if not, write to the Free Software
|
|
|
a32049e |
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
a32049e |
- */
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * History:
|
|
|
a32049e |
- * --------
|
|
|
a32049e |
- */
|
|
|
a32049e |
-
|
|
|
a32049e |
-#include <stdlib.h>
|
|
|
a32049e |
-#include <errno.h>
|
|
|
a32049e |
-#include <sys/time.h>
|
|
|
a32049e |
-#include <oci.h>
|
|
|
a32049e |
-#include "../../dprint.h"
|
|
|
a32049e |
-#include "../../sr_module.h"
|
|
|
a32049e |
-#include "ora_con.h"
|
|
|
a32049e |
-#include "asynch.h"
|
|
|
a32049e |
-
|
|
|
a32049e |
-#define MAX_TIMEOUT_S 10
|
|
|
a32049e |
-#define MIN_TIMEOUT_MS 100
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/* Default is 3.0 second */
|
|
|
a32049e |
-static struct timeval request_tm = { .tv_sec = 3, .tv_usec = 0 };
|
|
|
a32049e |
-
|
|
|
a32049e |
-/* Default is 0.2 second */
|
|
|
a32049e |
-static struct timeval restore_tm = { .tv_sec = 0, .tv_usec = 200*1000 };
|
|
|
a32049e |
-static const struct timeval defrest_tm = { .tv_sec = 0, .tv_usec = 200*1000 };
|
|
|
a32049e |
-
|
|
|
a32049e |
-static int synch_mode;
|
|
|
a32049e |
-static int cur_asynch_mode;
|
|
|
a32049e |
-static struct timeval wtm;
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-static __inline__ int is_zero_tm(const struct timeval* tv)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- return !tv->tv_usec && !tv->tv_sec;
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * parse timeout value in syntax: nnn.mmm (sec/ms)
|
|
|
a32049e |
- */
|
|
|
a32049e |
-static int set_tv(unsigned type, const char* val, struct timeval* tv)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- char *eptr;
|
|
|
a32049e |
- unsigned long s, ms;
|
|
|
a32049e |
- double dv;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (type != STR_PARAM) {
|
|
|
a32049e |
- LM_ERR("type of parameter is no STR\n");
|
|
|
a32049e |
- return -1;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (!val || !*val) {
|
|
|
a32049e |
- LM_ERR("empty parameter\n");
|
|
|
a32049e |
- return -1;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- errno = 0;
|
|
|
a32049e |
- dv = strtod(val, &eptr);
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (*eptr) {
|
|
|
a32049e |
- LM_ERR("invalid parameter string\n");
|
|
|
a32049e |
- return -2;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- if ( errno
|
|
|
a32049e |
- || dv > (double)MAX_TIMEOUT_S
|
|
|
a32049e |
- || (dv && dv < ((double)MIN_TIMEOUT_MS)/1000))
|
|
|
a32049e |
- {
|
|
|
a32049e |
- LM_ERR("value must be between 0.%u and %u.0\n",
|
|
|
a32049e |
- MIN_TIMEOUT_MS, MAX_TIMEOUT_S);
|
|
|
a32049e |
- return -3;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- s = (unsigned)dv;
|
|
|
a32049e |
- dv -= (double)s;
|
|
|
a32049e |
- ms = (unsigned)(dv * 1000);
|
|
|
a32049e |
- tv->tv_sec = (time_t)s;
|
|
|
a32049e |
- tv->tv_usec = (suseconds_t)ms;
|
|
|
a32049e |
- return 0;
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * set operation timeout
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int set_timeout(unsigned type, const char* val)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- int rc = set_tv(type, val, &request_tm);
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (!rc) {
|
|
|
a32049e |
- synch_mode = is_zero_tm(&request_tm);
|
|
|
a32049e |
- if (!synch_mode && is_zero_tm(&restore_tm))
|
|
|
a32049e |
- restore_tm = defrest_tm;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- return rc;
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * set (re)connect timeout
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int set_reconnect(unsigned type, const char* val)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- int rc = set_tv(type, val, &restore_tm);
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (!synch_mode && is_zero_tm(&restore_tm)) {
|
|
|
a32049e |
- LM_WARN("in asyncronus mode reconnect time can't be zero. "
|
|
|
a32049e |
- "Set default value\n");
|
|
|
a32049e |
- restore_tm = defrest_tm;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- return rc;
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-static sword change_mode(ora_con_t* con)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- return OCIAttrSet(con->svchp, OCI_HTYPE_SVCCTX, NULL, 0,
|
|
|
a32049e |
- OCI_ATTR_NONBLOCKING_MODE, con->errhp);
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * start timelimited operation (if work in synch mode return SUCCESS)
|
|
|
a32049e |
- */
|
|
|
a32049e |
-sword begin_timelimit(ora_con_t* con, int connect)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- struct timeval* tv;
|
|
|
a32049e |
- sword status;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (synch_mode)
|
|
|
a32049e |
- return OCI_SUCCESS;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (connect || cur_asynch_mode) {
|
|
|
a32049e |
- ub1 mode;
|
|
|
a32049e |
-
|
|
|
a32049e |
- status = OCIAttrGet(con->svchp, OCI_HTYPE_SVCCTX, &mode, NULL,
|
|
|
a32049e |
- OCI_ATTR_NONBLOCKING_MODE, con->errhp);
|
|
|
a32049e |
- if (status != OCI_SUCCESS)
|
|
|
a32049e |
- return status;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (mode) {
|
|
|
a32049e |
- status = change_mode(con);
|
|
|
a32049e |
- if (status != OCI_SUCCESS)
|
|
|
a32049e |
- return status;
|
|
|
a32049e |
- }
|
|
|
a32049e |
- cur_asynch_mode = 0;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- status = change_mode(con);
|
|
|
a32049e |
- if (status != OCI_SUCCESS && connect >= 0)
|
|
|
a32049e |
- return status;
|
|
|
a32049e |
-
|
|
|
a32049e |
- cur_asynch_mode = 1;
|
|
|
a32049e |
-
|
|
|
a32049e |
- gettimeofday(&wtm, NULL);
|
|
|
a32049e |
- tv = &request_tm;
|
|
|
a32049e |
- if (connect)
|
|
|
a32049e |
- tv = &restore_tm;
|
|
|
a32049e |
- wtm.tv_sec += tv->tv_sec;
|
|
|
a32049e |
- wtm.tv_usec += tv->tv_usec;
|
|
|
a32049e |
- if (wtm.tv_usec >= 1000000) {
|
|
|
a32049e |
- wtm.tv_usec -= 1000000;
|
|
|
a32049e |
- ++wtm.tv_sec;
|
|
|
a32049e |
- }
|
|
|
a32049e |
-
|
|
|
a32049e |
- return OCI_SUCCESS;
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-static sword remap_status(ora_con_t* con, sword status)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- sword code;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if ( status == OCI_ERROR
|
|
|
a32049e |
- && OCIErrorGet(con->errhp, 1, NULL, &code,
|
|
|
a32049e |
- NULL, 0, OCI_HTYPE_ERROR) == OCI_SUCCESS
|
|
|
a32049e |
- && (code == 3123 /*|| code == 3127*/))
|
|
|
a32049e |
- {
|
|
|
a32049e |
- status = OCI_STILL_EXECUTING;
|
|
|
a32049e |
- }
|
|
|
a32049e |
- return status;
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * check completion of timelimited operation (if work in synch mode return 0)
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int wait_timelimit(ora_con_t* con, sword status)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- struct timeval cur;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (!cur_asynch_mode)
|
|
|
a32049e |
- return 0;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (remap_status(con, status) != OCI_STILL_EXECUTING)
|
|
|
a32049e |
- return 0;
|
|
|
a32049e |
-
|
|
|
a32049e |
- gettimeofday(&cur, NULL);
|
|
|
a32049e |
- return ( cur.tv_sec < wtm.tv_sec
|
|
|
a32049e |
- || (cur.tv_sec == wtm.tv_sec && cur.tv_usec < wtm.tv_usec));
|
|
|
a32049e |
-}
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * close current timelimited operation and disconnect if timeout occured
|
|
|
a32049e |
- * return true only if work in asynch mode and timeout detect
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int done_timelimit(ora_con_t* con, sword status)
|
|
|
a32049e |
-{
|
|
|
a32049e |
- int ret = 0;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (!cur_asynch_mode)
|
|
|
a32049e |
- return 0;
|
|
|
a32049e |
-
|
|
|
a32049e |
- if (remap_status(con, status) == OCI_STILL_EXECUTING) {
|
|
|
a32049e |
- sword code;
|
|
|
a32049e |
-
|
|
|
a32049e |
- status = OCIBreak(con->svchp, con->errhp);
|
|
|
a32049e |
- if (status != OCI_SUCCESS)
|
|
|
a32049e |
- LM_ERR("driver: %s\n",
|
|
|
a32049e |
- db_oracle_error(con, status));
|
|
|
a32049e |
-
|
|
|
a32049e |
- status = OCIReset(con->svchp, con->errhp);
|
|
|
a32049e |
- if ( status == OCI_ERROR
|
|
|
a32049e |
- && OCIErrorGet(con->errhp, 1, NULL, &code,
|
|
|
a32049e |
- NULL, 0, OCI_HTYPE_ERROR) == OCI_SUCCESS
|
|
|
a32049e |
- && code == 1013)
|
|
|
a32049e |
- {
|
|
|
a32049e |
- status = OCI_SUCCESS;
|
|
|
a32049e |
- }
|
|
|
a32049e |
- if (status != OCI_SUCCESS)
|
|
|
a32049e |
- LM_ERR("driver: %s\n",
|
|
|
a32049e |
- db_oracle_error(con, status));
|
|
|
a32049e |
- db_oracle_disconnect(con);
|
|
|
a32049e |
- ++ret;
|
|
|
a32049e |
- } else {
|
|
|
a32049e |
- status = change_mode(con);
|
|
|
a32049e |
- if (status != OCI_SUCCESS) {
|
|
|
a32049e |
- LM_ERR("driver: %s\n", db_oracle_error(con, status));
|
|
|
a32049e |
- ++ret;
|
|
|
a32049e |
- } else {
|
|
|
a32049e |
- cur_asynch_mode = 0;
|
|
|
a32049e |
- }
|
|
|
a32049e |
- }
|
|
|
a32049e |
- return ret;
|
|
|
a32049e |
-}
|
|
|
a32049e |
diff --git a/modules/db_oracle/asynch.h b/modules/db_oracle/asynch.h
|
|
|
a32049e |
deleted file mode 100644
|
|
|
a32049e |
index 9694088..0000000
|
|
|
a32049e |
--- a/modules/db_oracle/asynch.h
|
|
|
a32049e |
+++ /dev/null
|
|
|
a32049e |
@@ -1,62 +0,0 @@
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * $Id$
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * Oracle module interface
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * Copyright (C) 2007,2008 TRUNK MOBILE
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * This file is part of opensips, a free SIP server.
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * opensips is free software; you can redistribute it and/or modify
|
|
|
a32049e |
- * it under the terms of the GNU General Public License as published by
|
|
|
a32049e |
- * the Free Software Foundation; either version 2 of the License, or
|
|
|
a32049e |
- * (at your option) any later version
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * opensips is distributed in the hope that it will be useful,
|
|
|
a32049e |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
a32049e |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
a32049e |
- * GNU General Public License for more details.
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * You should have received a copy of the GNU General Public License
|
|
|
a32049e |
- * along with this program; if not, write to the Free Software
|
|
|
a32049e |
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
a32049e |
- *
|
|
|
a32049e |
- * History:
|
|
|
a32049e |
- * --------
|
|
|
a32049e |
- */
|
|
|
a32049e |
-
|
|
|
a32049e |
-#ifndef ASYNCH_H
|
|
|
a32049e |
-#define ASYNCH_H
|
|
|
a32049e |
-
|
|
|
a32049e |
-#include <oci.h>
|
|
|
a32049e |
-#include "ora_con.h"
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * parse timeout value for operation in syntax: nnn.mmm (sec/ms)
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int set_timeout(unsigned type, const char* val);
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * parse timeout value for reconnect in syntax: nnn.mmm (sec/ms)
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int set_reconnect(unsigned type, const char* val);
|
|
|
a32049e |
-
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * start timelimited operation (if work in synch mode return SUCCESS)
|
|
|
a32049e |
- */
|
|
|
a32049e |
-sword begin_timelimit(ora_con_t* con, int connect);
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * check completion of timelimited operation (if work in synch mode return 0)
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int wait_timelimit(ora_con_t* con, sword status);
|
|
|
a32049e |
-
|
|
|
a32049e |
-/*
|
|
|
a32049e |
- * close current timelimited operation and disconnect if timeout occured
|
|
|
a32049e |
- * return true only if work in asynch mode and timeout detect
|
|
|
a32049e |
- */
|
|
|
a32049e |
-int done_timelimit(ora_con_t* con, sword status);
|
|
|
a32049e |
-
|
|
|
a32049e |
-#endif /* ASYNCH_H */
|
|
|
e73f7b5 |
diff --git a/modules/db_oracle/db_oracle.c b/modules/db_oracle/db_oracle.c
|
|
|
e73f7b5 |
index 70cfe40..40c7692 100644
|
|
|
e73f7b5 |
--- a/modules/db_oracle/db_oracle.c
|
|
|
e73f7b5 |
+++ b/modules/db_oracle/db_oracle.c
|
|
|
e73f7b5 |
@@ -31,7 +31,7 @@
|
|
|
e73f7b5 |
#include "../../sr_module.h"
|
|
|
e73f7b5 |
#include "../../db/db.h"
|
|
|
e73f7b5 |
#include "dbase.h"
|
|
|
e73f7b5 |
-#include "asynch.h"
|
|
|
e73f7b5 |
+#include "timer.h"
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
static int oracle_mod_init(void);
|
|
|
e73f7b5 |
static void destroy(void);
|
|
|
e73f7b5 |
diff --git a/modules/db_oracle/dbase.c b/modules/db_oracle/dbase.c
|
|
|
e73f7b5 |
index d129e11..be2352e 100644
|
|
|
e73f7b5 |
--- a/modules/db_oracle/dbase.c
|
|
|
e73f7b5 |
+++ b/modules/db_oracle/dbase.c
|
|
|
e73f7b5 |
@@ -36,7 +36,7 @@
|
|
|
e73f7b5 |
#include "val.h"
|
|
|
e73f7b5 |
#include "ora_con.h"
|
|
|
e73f7b5 |
#include "res.h"
|
|
|
e73f7b5 |
-#include "asynch.h"
|
|
|
e73f7b5 |
+#include "timer.h"
|
|
|
e73f7b5 |
#include "dbase.h"
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
@@ -212,7 +212,6 @@ static int db_oracle_submit_query(const db_con_t* _h, const str* _s)
|
|
|
e73f7b5 |
OCIDate odt[sizeof(bind)/sizeof(bind[0])];
|
|
|
e73f7b5 |
str tmps;
|
|
|
e73f7b5 |
sword status;
|
|
|
e73f7b5 |
- int pass;
|
|
|
e73f7b5 |
ora_con_t* con = CON_ORA(_h);
|
|
|
e73f7b5 |
query_data_t* pqd = con->pqdata;
|
|
|
e73f7b5 |
size_t hc = pqd->_n + pqd->_nw;
|
|
|
e73f7b5 |
@@ -223,32 +222,16 @@ static int db_oracle_submit_query(const db_con_t* _h, const str* _s)
|
|
|
e73f7b5 |
(unsigned)hc);
|
|
|
e73f7b5 |
return -1;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- if (!pqd->_rs) {
|
|
|
e73f7b5 |
- /*
|
|
|
e73f7b5 |
- * This method is at ~25% faster as set OCI_COMMIT_ON_SUCCESS
|
|
|
e73f7b5 |
- * in StmtExecute
|
|
|
e73f7b5 |
- */
|
|
|
e73f7b5 |
- tmps.len = snprintf(st_buf, sizeof(st_buf),
|
|
|
e73f7b5 |
- "begin %.*s; commit write batch nowait; end;",
|
|
|
e73f7b5 |
- _s->len, _s->s);
|
|
|
e73f7b5 |
- if ((unsigned)tmps.len >= sizeof(st_buf))
|
|
|
e73f7b5 |
- return sql_buf_small();
|
|
|
e73f7b5 |
- tmps.s = st_buf;
|
|
|
e73f7b5 |
- _s = &tmps;
|
|
|
e73f7b5 |
- }
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
- pass = 1;
|
|
|
e73f7b5 |
- if (!con->connected) {
|
|
|
e73f7b5 |
+ if (con->connected != 2) {
|
|
|
e73f7b5 |
status = db_oracle_reconnect(con);
|
|
|
e73f7b5 |
if (status != OCI_SUCCESS) {
|
|
|
e73f7b5 |
LM_ERR("can't restore connection: %s\n", db_oracle_error(con, status));
|
|
|
e73f7b5 |
return -2;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
LM_INFO("connection restored\n");
|
|
|
e73f7b5 |
- --pass;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
-repeat:
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
stmthp = NULL;
|
|
|
e73f7b5 |
status = OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&stmthp,
|
|
|
e73f7b5 |
OCI_HTYPE_STMT, 0, NULL);
|
|
|
e73f7b5 |
@@ -291,14 +274,10 @@ bind_err:
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
- // timelimited operation
|
|
|
e73f7b5 |
- status = begin_timelimit(con, 0);
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) goto ora_err;
|
|
|
e73f7b5 |
- do status = OCIStmtExecute(con->svchp, stmthp, con->errhp,
|
|
|
e73f7b5 |
- !pqd->_rs, 0, NULL, NULL,
|
|
|
e73f7b5 |
- pqd->_rs ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT);
|
|
|
e73f7b5 |
- while (wait_timelimit(con, status));
|
|
|
e73f7b5 |
- if (done_timelimit(con, status)) goto stop_exec;
|
|
|
e73f7b5 |
+ request_timer();
|
|
|
e73f7b5 |
+ status = OCIStmtExecute(con->svchp, stmthp, con->errhp,
|
|
|
e73f7b5 |
+ !pqd->_rs, 0, NULL, NULL, pqd->_rs ? OCI_DEFAULT : OCI_COMMIT_ON_SUCCESS);
|
|
|
e73f7b5 |
+ timer_stop();
|
|
|
e73f7b5 |
switch (status) {
|
|
|
e73f7b5 |
case OCI_SUCCESS_WITH_INFO:
|
|
|
e73f7b5 |
LM_WARN("driver: %s\n", db_oracle_errorinfo(con));
|
|
|
e73f7b5 |
@@ -310,8 +289,8 @@ bind_err:
|
|
|
e73f7b5 |
OCIHandleFree(stmthp, OCI_HTYPE_STMT);
|
|
|
e73f7b5 |
return 0;
|
|
|
e73f7b5 |
default:
|
|
|
e73f7b5 |
- pass = -pass;
|
|
|
e73f7b5 |
- break;
|
|
|
e73f7b5 |
+ LM_ERR("timeout/not connected to oracle\n");
|
|
|
e73f7b5 |
+ break;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
ora_err:
|
|
|
e73f7b5 |
@@ -319,15 +298,13 @@ ora_err:
|
|
|
e73f7b5 |
stop_exec:
|
|
|
e73f7b5 |
if (stmthp)
|
|
|
e73f7b5 |
OCIHandleFree(stmthp, OCI_HTYPE_STMT);
|
|
|
e73f7b5 |
- if (pass == -1 && !con->connected) {
|
|
|
e73f7b5 |
- /* Attemtp to reconnect */
|
|
|
e73f7b5 |
- if (db_oracle_reconnect(con) == OCI_SUCCESS) {
|
|
|
e73f7b5 |
- LM_NOTICE("attempt repeat after reconnect\n");
|
|
|
e73f7b5 |
- pass = 0;
|
|
|
e73f7b5 |
- goto repeat;
|
|
|
e73f7b5 |
- }
|
|
|
e73f7b5 |
+ LM_INFO("reconnecting to oracle...\n");
|
|
|
e73f7b5 |
+ /* Attempt to reconnect */
|
|
|
e73f7b5 |
+ if (db_oracle_reconnect(con) == OCI_SUCCESS)
|
|
|
e73f7b5 |
+ LM_INFO("connection restored\n");
|
|
|
e73f7b5 |
+ else
|
|
|
e73f7b5 |
LM_ERR("connection loss\n");
|
|
|
e73f7b5 |
- }
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
return -4;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
diff --git a/modules/db_oracle/ora_con.c b/modules/db_oracle/ora_con.c
|
|
|
e73f7b5 |
index 73ced27..f03f753 100644
|
|
|
e73f7b5 |
--- a/modules/db_oracle/ora_con.c
|
|
|
e73f7b5 |
+++ b/modules/db_oracle/ora_con.c
|
|
|
e73f7b5 |
@@ -22,9 +22,10 @@
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
#include <string.h>
|
|
|
e73f7b5 |
#include <stdio.h>
|
|
|
e73f7b5 |
+#include <errno.h>
|
|
|
e73f7b5 |
#include "../../mem/mem.h"
|
|
|
e73f7b5 |
#include "../../dprint.h"
|
|
|
e73f7b5 |
-#include "asynch.h"
|
|
|
e73f7b5 |
+#include "timer.h"
|
|
|
e73f7b5 |
#include "ora_con.h"
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
/*************************************************************************/
|
|
|
e73f7b5 |
@@ -105,6 +106,12 @@ bad_param:
|
|
|
e73f7b5 |
status = OCIAttrSet(con->svchp, OCI_HTYPE_SVCCTX, con->authp, 0,
|
|
|
e73f7b5 |
OCI_ATTR_SESSION, con->errhp);
|
|
|
e73f7b5 |
if (status != OCI_SUCCESS) goto connect_err;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ if (init_ora_timer(con) != 0) {
|
|
|
e73f7b5 |
+ LM_ERR("can't start oracle timer thread\n");
|
|
|
e73f7b5 |
+ goto drop_connection;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
status = db_oracle_reconnect(con);
|
|
|
e73f7b5 |
if (status != OCI_SUCCESS) {
|
|
|
e73f7b5 |
connect_err:
|
|
|
e73f7b5 |
@@ -122,12 +129,11 @@ drop_connection:
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
// timelimited operation
|
|
|
e73f7b5 |
- status = begin_timelimit(con, 0);
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) goto connect_err;
|
|
|
e73f7b5 |
- do status = OCIServerVersion(con->svchp, con->errhp, (OraText*)buf,
|
|
|
e73f7b5 |
+ request_timer();
|
|
|
e73f7b5 |
+ status = OCIServerVersion(con->svchp, con->errhp, (OraText*)buf,
|
|
|
e73f7b5 |
(ub4)sizeof(buf), OCI_HTYPE_SVCCTX);
|
|
|
e73f7b5 |
- while (wait_timelimit(con, status));
|
|
|
e73f7b5 |
- if (done_timelimit(con, status)) goto drop_connection;
|
|
|
e73f7b5 |
+ timer_stop();
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
if (status != OCI_SUCCESS) goto connect_err;
|
|
|
e73f7b5 |
LM_INFO("server version is %s\n", buf);
|
|
|
e73f7b5 |
return con;
|
|
|
e73f7b5 |
@@ -139,6 +145,7 @@ drop_connection:
|
|
|
e73f7b5 |
*/
|
|
|
e73f7b5 |
void db_oracle_free_connection(ora_con_t* con)
|
|
|
e73f7b5 |
{
|
|
|
e73f7b5 |
+ destroy_ora_timer(con);
|
|
|
e73f7b5 |
if (!con) return;
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
if (con->connected)
|
|
|
e73f7b5 |
@@ -164,20 +171,17 @@ void db_oracle_free_connection(ora_con_t* con)
|
|
|
e73f7b5 |
void db_oracle_disconnect(ora_con_t* con)
|
|
|
e73f7b5 |
{
|
|
|
e73f7b5 |
sword status;
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- switch (con->connected) {
|
|
|
e73f7b5 |
- default:
|
|
|
e73f7b5 |
- status = OCISessionEnd(con->svchp, con->errhp, con->authp,
|
|
|
e73f7b5 |
- OCI_DEFAULT);
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS)
|
|
|
e73f7b5 |
- LM_ERR("driver: %s\n", db_oracle_error(con, status));
|
|
|
e73f7b5 |
- case 1:
|
|
|
e73f7b5 |
+ if (con->connected > 0) {
|
|
|
e73f7b5 |
+ if (con->connected > 1) {
|
|
|
e73f7b5 |
+ status = OCISessionEnd(con->svchp, con->errhp, con->authp,
|
|
|
e73f7b5 |
+ OCI_DEFAULT);
|
|
|
e73f7b5 |
+ if (status != OCI_SUCCESS)
|
|
|
e73f7b5 |
+ LM_ERR("driver: %s\n", db_oracle_error(con, status));
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
status = OCIServerDetach(con->srvhp, con->errhp, OCI_DEFAULT);
|
|
|
e73f7b5 |
if (status != OCI_SUCCESS)
|
|
|
e73f7b5 |
LM_ERR("driver: %s\n", db_oracle_error(con, status));
|
|
|
e73f7b5 |
con->connected = 0;
|
|
|
e73f7b5 |
- case 0:
|
|
|
e73f7b5 |
- break;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
@@ -192,48 +196,19 @@ sword db_oracle_reconnect(ora_con_t* con)
|
|
|
e73f7b5 |
if (con->connected)
|
|
|
e73f7b5 |
db_oracle_disconnect(con);
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
- /* timelimited operation, but OCI tcp-network does not support it :( */
|
|
|
e73f7b5 |
+ restore_timer();
|
|
|
e73f7b5 |
status = OCIServerAttach(con->srvhp, con->errhp, (OraText*)con->uri,
|
|
|
e73f7b5 |
con->uri_len, 0);
|
|
|
e73f7b5 |
+ timer_stop();
|
|
|
e73f7b5 |
if (status == OCI_SUCCESS) {
|
|
|
e73f7b5 |
++con->connected;
|
|
|
e73f7b5 |
- /*
|
|
|
e73f7b5 |
- * timelimited operation, but OCI has BUG in asynch
|
|
|
e73f7b5 |
- * implementation of OCISessionBegin :(.
|
|
|
e73f7b5 |
- *
|
|
|
e73f7b5 |
- * Next code is 'empiric hack' that work (tested) in v10/v11.
|
|
|
e73f7b5 |
- */
|
|
|
e73f7b5 |
- status = begin_timelimit(con, 1);
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) goto done;
|
|
|
e73f7b5 |
+ request_timer();
|
|
|
e73f7b5 |
status = OCISessionBegin(con->svchp, con->errhp, con->authp,
|
|
|
e73f7b5 |
OCI_CRED_RDBMS, OCI_DEFAULT);
|
|
|
e73f7b5 |
- while (wait_timelimit(con, status)) {
|
|
|
e73f7b5 |
- sword code;
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- status = OCIServerVersion(con->svchp, con->errhp, NULL,
|
|
|
e73f7b5 |
- 0, OCI_HTYPE_SVCCTX);
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- if ( status != OCI_ERROR
|
|
|
e73f7b5 |
- || OCIErrorGet(con->errhp, 1, NULL, &code, NULL, 0,
|
|
|
e73f7b5 |
- OCI_HTYPE_ERROR) != OCI_SUCCESS) break;
|
|
|
e73f7b5 |
- switch (code) {
|
|
|
e73f7b5 |
- case 24909: /* other call in progress */
|
|
|
e73f7b5 |
- status = OCI_STILL_EXECUTING;
|
|
|
e73f7b5 |
- continue;
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- case 3127: /* no new operation until active ends */
|
|
|
e73f7b5 |
- status = OCISessionBegin(con->svchp, con->errhp,
|
|
|
e73f7b5 |
- con->authp, OCI_CRED_RDBMS, OCI_DEFAULT);
|
|
|
e73f7b5 |
- default:
|
|
|
e73f7b5 |
- break;
|
|
|
e73f7b5 |
- }
|
|
|
e73f7b5 |
- break;
|
|
|
e73f7b5 |
- }
|
|
|
e73f7b5 |
- if (done_timelimit(con, status)) goto done;
|
|
|
e73f7b5 |
+ timer_stop();
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
if (status == OCI_SUCCESS)
|
|
|
e73f7b5 |
++con->connected;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
-done:
|
|
|
e73f7b5 |
return status;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
diff --git a/modules/db_oracle/ora_con.h b/modules/db_oracle/ora_con.h
|
|
|
e73f7b5 |
index 5835ffe..7267bee 100644
|
|
|
e73f7b5 |
--- a/modules/db_oracle/ora_con.h
|
|
|
e73f7b5 |
+++ b/modules/db_oracle/ora_con.h
|
|
|
e73f7b5 |
@@ -50,7 +50,8 @@ struct ora_con {
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
int connected; /* Authorized session started */
|
|
|
e73f7b5 |
int bindpos; /* Last Bind handle position */
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
+ pthread_t timer;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
query_data_t* pqdata; /* Temporary: cb data for submit_query/store_result */
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
int uri_len;
|
|
|
e73f7b5 |
diff --git a/modules/db_oracle/res.c b/modules/db_oracle/res.c
|
|
|
d9c4e87 |
index e9e6233..2c625f8 100644
|
|
|
e73f7b5 |
--- a/modules/db_oracle/res.c
|
|
|
e73f7b5 |
+++ b/modules/db_oracle/res.c
|
|
|
e73f7b5 |
@@ -32,7 +32,7 @@
|
|
|
e73f7b5 |
#include "../../dprint.h"
|
|
|
e73f7b5 |
#include "ora_con.h"
|
|
|
e73f7b5 |
#include "dbase.h"
|
|
|
e73f7b5 |
-#include "asynch.h"
|
|
|
e73f7b5 |
+#include "timer.h"
|
|
|
e73f7b5 |
#include "res.h"
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
@@ -54,6 +54,10 @@ struct dmap {
|
|
|
e73f7b5 |
};
|
|
|
e73f7b5 |
typedef struct dmap dmap_t;
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
+typedef struct ora_row {
|
|
|
e73f7b5 |
+ struct db_row hdr;
|
|
|
e73f7b5 |
+ struct ora_row* next;
|
|
|
e73f7b5 |
+} ora_row_t;
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
/*
|
|
|
e73f7b5 |
* Get and convert columns from a result. Define handlers and buffers
|
|
|
e73f7b5 |
@@ -362,66 +366,74 @@ static int convert_row(db_res_t* _res, db_row_t* _r, dmap_t* _d)
|
|
|
e73f7b5 |
*/
|
|
|
e73f7b5 |
static int get_rows(ora_con_t* con, db_res_t* _r, OCIStmt* _c, dmap_t* _d)
|
|
|
e73f7b5 |
{
|
|
|
e73f7b5 |
- ub4 rcnt;
|
|
|
e73f7b5 |
+ ub4 i = 0, rcnt = 0;
|
|
|
e73f7b5 |
sword status;
|
|
|
e73f7b5 |
unsigned n = RES_COL_N(_r);
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
+ // Since OCI have not "mysql_num_rows()", sequentialy fetch all rows into tmp area orow_list.
|
|
|
e73f7b5 |
+ // Then call db_allocate_rows() and copy tmp to db module.
|
|
|
e73f7b5 |
+ ora_row_t *orow_list = NULL, *orow_it, *orow_tail;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
memcpy(_d->len, _d->ilen, sizeof(_d->len[0]) * n);
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- // timelimited operation
|
|
|
e73f7b5 |
- status = begin_timelimit(con, 0);
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) goto ora_err;
|
|
|
e73f7b5 |
- do status = OCIStmtFetch2(_c, con->errhp, 1, OCI_FETCH_NEXT, 0,
|
|
|
e73f7b5 |
- OCI_DEFAULT);
|
|
|
e73f7b5 |
- while (wait_timelimit(con, status));
|
|
|
e73f7b5 |
- if (done_timelimit(con, status)) goto stop_load;
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) {
|
|
|
e73f7b5 |
- if (status != OCI_NO_DATA)
|
|
|
e73f7b5 |
- goto ora_err;
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- RES_ROW_N(_r) = 0;
|
|
|
e73f7b5 |
- RES_ROWS(_r) = NULL;
|
|
|
e73f7b5 |
- return 0;
|
|
|
e73f7b5 |
- }
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- status = OCIAttrGet(_c, OCI_HTYPE_STMT, &rcnt, NULL,
|
|
|
e73f7b5 |
- OCI_ATTR_CURRENT_POSITION, con->errhp);
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) goto ora_err;
|
|
|
e73f7b5 |
- if (!rcnt) {
|
|
|
e73f7b5 |
- LM_ERR("lastpos==0\n");
|
|
|
e73f7b5 |
- goto stop_load;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ request_timer();
|
|
|
e73f7b5 |
+ while ((status = OCIStmtFetch2(_c, con->errhp, 1, OCI_FETCH_NEXT, 0,
|
|
|
e73f7b5 |
+ OCI_DEFAULT)) == OCI_SUCCESS) {
|
|
|
e73f7b5 |
+ timer_stop();
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ orow_it = (ora_row_t*) pkg_malloc(sizeof(ora_row_t) + sizeof(db_val_t)*RES_COL_N(_r));
|
|
|
e73f7b5 |
+ if (orow_it == NULL) {
|
|
|
e73f7b5 |
+ LM_ERR("no private memory left\n");
|
|
|
e73f7b5 |
+ goto stop_load;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+ memset(orow_it, 0, sizeof(ora_row_t) + sizeof(db_val_t)*RES_COL_N(_r));
|
|
|
e73f7b5 |
+ orow_it->hdr.values = (db_val_t*)(orow_it+1);
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ if (orow_list == NULL)
|
|
|
e73f7b5 |
+ orow_list = orow_it;
|
|
|
e73f7b5 |
+ else
|
|
|
e73f7b5 |
+ orow_tail->next = orow_it;
|
|
|
e73f7b5 |
+ orow_tail = orow_it;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ if (convert_row(_r, &orow_it->hdr, _d) < 0) {
|
|
|
e73f7b5 |
+ LM_ERR("erroc convert row\n");
|
|
|
e73f7b5 |
+ goto stop_load;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+ memcpy(_d->len, _d->ilen, sizeof(_d->len[0]) * n);
|
|
|
e73f7b5 |
+ ++rcnt;
|
|
|
e73f7b5 |
+ request_timer();
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
+ timer_stop();
|
|
|
e73f7b5 |
+ if (status != OCI_NO_DATA)
|
|
|
e73f7b5 |
+ goto ora_err;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
RES_ROW_N(_r) = rcnt;
|
|
|
e73f7b5 |
if (db_allocate_rows( _r, rcnt)!=0) {
|
|
|
e73f7b5 |
LM_ERR("no private memory left\n");
|
|
|
e73f7b5 |
- return -1;
|
|
|
e73f7b5 |
+ goto stop_load;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- while ( 1 ) {
|
|
|
e73f7b5 |
- if (convert_row(_r, &RES_ROWS(_r)[--rcnt], _d) < 0) {
|
|
|
e73f7b5 |
- LM_ERR("error convert row\n");
|
|
|
e73f7b5 |
- goto stop_load;
|
|
|
e73f7b5 |
- }
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- if (!rcnt)
|
|
|
e73f7b5 |
- return 0;
|
|
|
e73f7b5 |
-
|
|
|
e73f7b5 |
- memcpy(_d->len, _d->ilen, sizeof(_d->len[0]) * n);
|
|
|
e73f7b5 |
- // timelimited operation
|
|
|
e73f7b5 |
- status = begin_timelimit(con, 0);
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) goto ora_err;
|
|
|
e73f7b5 |
- do status = OCIStmtFetch2(_c, con->errhp, 1, OCI_FETCH_PRIOR, 0,
|
|
|
e73f7b5 |
- OCI_DEFAULT);
|
|
|
e73f7b5 |
- while (wait_timelimit(con, status));
|
|
|
e73f7b5 |
- if (done_timelimit(con, status)) goto stop_load;
|
|
|
e73f7b5 |
- if (status != OCI_SUCCESS) break;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ for (orow_it = orow_list; orow_it; orow_it = orow_it->next) {
|
|
|
e73f7b5 |
+ memcpy(ROW_VALUES(&RES_ROWS(_r)[i]), ROW_VALUES(&orow_it->hdr), sizeof(db_val_t)*RES_COL_N(_r));
|
|
|
e73f7b5 |
+ ROW_N(&RES_ROWS(_r)[i]) = ROW_N(&orow_it->hdr);
|
|
|
e73f7b5 |
+ ++i;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ for (orow_it = orow_list; orow_it; orow_it = orow_list) {
|
|
|
e73f7b5 |
+ orow_list = orow_it->next;
|
|
|
e73f7b5 |
+ pkg_free(orow_it);
|
|
|
e73f7b5 |
+ orow_it = NULL;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
+ return 0;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
ora_err:
|
|
|
e73f7b5 |
LM_ERR("driver: %s\n", db_oracle_error(con, status));
|
|
|
e73f7b5 |
stop_load:
|
|
|
e73f7b5 |
- db_free_rows(_r);
|
|
|
e73f7b5 |
- RES_ROW_N(_r) = 0; /* TODO: skipped in db_res.c :) */
|
|
|
e73f7b5 |
+ for (orow_it = orow_list; orow_it; orow_it = orow_list) {
|
|
|
e73f7b5 |
+ orow_list = orow_it->next;
|
|
|
e73f7b5 |
+ db_free_row(&orow_it->hdr);
|
|
|
e73f7b5 |
+ pkg_free(orow_it);
|
|
|
e73f7b5 |
+ orow_it = NULL;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
return -3;
|
|
|
e73f7b5 |
}
|
|
|
e73f7b5 |
|
|
|
e73f7b5 |
diff --git a/modules/db_oracle/timer.c b/modules/db_oracle/timer.c
|
|
|
e73f7b5 |
new file mode 100644
|
|
|
e73f7b5 |
index 0000000..50484f4
|
|
|
e73f7b5 |
--- /dev/null
|
|
|
e73f7b5 |
+++ b/modules/db_oracle/timer.c
|
|
|
e73f7b5 |
@@ -0,0 +1,131 @@
|
|
|
e73f7b5 |
+#include "timer.h"
|
|
|
e73f7b5 |
+#include "../../dprint.h"
|
|
|
e73f7b5 |
+#include "../../sr_module.h"
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+#include <signal.h>
|
|
|
e73f7b5 |
+#include <stdlib.h>
|
|
|
e73f7b5 |
+#include <errno.h>
|
|
|
e73f7b5 |
+#include <sys/time.h>
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+#define MAX_TIMEOUT_S 10
|
|
|
e73f7b5 |
+#define MIN_TIMEOUT_MCS 100000
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+/* Default is 3.0 second */
|
|
|
e73f7b5 |
+struct itimerval request_tm = {{0,0}, {3,0}};
|
|
|
e73f7b5 |
+// unsigned request_tm;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+/* Default is 0.2 second */
|
|
|
e73f7b5 |
+struct itimerval restore_tm = {{0,0}, {0,200000}};
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+struct itimerval stop_tm = {{0,0}, {0,0}};
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+/* Simple error handling functions */
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+#define handle_error_en(en, msg) \
|
|
|
e73f7b5 |
+ do { LM_ERR(msg": %s\n", strerror(en)); return 1; } while (0)
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+static ora_con_t *g_con;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+static int set_tv(unsigned type, const char* val, struct timeval* tv)
|
|
|
e73f7b5 |
+{
|
|
|
e73f7b5 |
+ char *eptr;
|
|
|
e73f7b5 |
+ struct itimerval tt;
|
|
|
e73f7b5 |
+ unsigned long s, ms;
|
|
|
e73f7b5 |
+ double dv;
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ if (type != STR_PARAM) {
|
|
|
e73f7b5 |
+ LM_ERR("type of parameter is no STR\n");
|
|
|
e73f7b5 |
+ return -1;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ if (!val || !*val) {
|
|
|
e73f7b5 |
+ LM_ERR("empty parameter\n");
|
|
|
e73f7b5 |
+ return -1;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ errno = 0;
|
|
|
e73f7b5 |
+ dv = strtod(val, &eptr);
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ if (*eptr) {
|
|
|
e73f7b5 |
+ LM_ERR("invalid parameter string\n");
|
|
|
e73f7b5 |
+ return -2;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ if ( errno
|
|
|
e73f7b5 |
+ || dv > (double)MAX_TIMEOUT_S
|
|
|
e73f7b5 |
+ || (dv < ((double)MIN_TIMEOUT_MCS)/100000))
|
|
|
e73f7b5 |
+ {
|
|
|
e73f7b5 |
+ LM_ERR("value must be between 0.%.6u and %u.0\n",
|
|
|
e73f7b5 |
+ MIN_TIMEOUT_MCS, MAX_TIMEOUT_S);
|
|
|
e73f7b5 |
+ return -3;
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ s = (unsigned)dv;
|
|
|
e73f7b5 |
+ dv -= (double)s;
|
|
|
e73f7b5 |
+ ms = (unsigned)(dv * 1000000);
|
|
|
e73f7b5 |
+ tv->tv_sec = (time_t)s;
|
|
|
e73f7b5 |
+ tv->tv_usec = (suseconds_t)ms;
|
|
|
e73f7b5 |
+ return 0;
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+/*
|
|
|
e73f7b5 |
+ * set operation timeout
|
|
|
e73f7b5 |
+ */
|
|
|
e73f7b5 |
+int set_timeout(unsigned type, const char* val)
|
|
|
e73f7b5 |
+{
|
|
|
e73f7b5 |
+ return set_tv(type, val, &request_tm.it_value);
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+/*
|
|
|
e73f7b5 |
+ * set (re)connect timeout
|
|
|
e73f7b5 |
+ */
|
|
|
e73f7b5 |
+int set_reconnect(unsigned type, const char* val)
|
|
|
e73f7b5 |
+{
|
|
|
e73f7b5 |
+ return set_tv(type, val, &restore_tm.it_value);
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+void ora_alarm_handle(int sig) {
|
|
|
e73f7b5 |
+ LM_INFO("ora_alarm_handle\n");
|
|
|
e73f7b5 |
+ sword status;
|
|
|
e73f7b5 |
+ status = OCIBreak(g_con->svchp, g_con->errhp);
|
|
|
e73f7b5 |
+ if (status != OCI_SUCCESS) {
|
|
|
e73f7b5 |
+ LM_ERR("OCIBreak: %s\n", db_oracle_error(g_con, status));
|
|
|
e73f7b5 |
+ }
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+int init_ora_timer(ora_con_t* con) {
|
|
|
e73f7b5 |
+ g_con = con;
|
|
|
e73f7b5 |
+ struct sigaction sa;
|
|
|
e73f7b5 |
+ memset(&sa, 0, sizeof(sa));
|
|
|
e73f7b5 |
+ sa.sa_handler = ora_alarm_handle;
|
|
|
e73f7b5 |
+ if (sigaction(SIGALRM, &sa, NULL) < -1)
|
|
|
e73f7b5 |
+ handle_error_en(errno, "sigaction");
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+ return 0;
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+int destroy_ora_timer()
|
|
|
e73f7b5 |
+{
|
|
|
e73f7b5 |
+ timer_stop();
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+void request_timer()
|
|
|
e73f7b5 |
+{
|
|
|
e73f7b5 |
+ if (setitimer(ITIMER_REAL, &request_tm, NULL) < 0)
|
|
|
e73f7b5 |
+ LM_ERR("setitimer: %s\n", strerror(errno));
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+void restore_timer()
|
|
|
e73f7b5 |
+{
|
|
|
e73f7b5 |
+ if (setitimer(ITIMER_REAL, &restore_tm, NULL) < 0)
|
|
|
e73f7b5 |
+ LM_ERR("setitimer: %s\n", strerror(errno));
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+void timer_stop()
|
|
|
e73f7b5 |
+{
|
|
|
e73f7b5 |
+ if (setitimer(ITIMER_REAL, &stop_tm, NULL) < 0)
|
|
|
e73f7b5 |
+ LM_ERR("setitimer: %s\n", strerror(errno));
|
|
|
e73f7b5 |
+}
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
\ No newline at end of file
|
|
|
e73f7b5 |
diff --git a/modules/db_oracle/timer.h b/modules/db_oracle/timer.h
|
|
|
e73f7b5 |
new file mode 100644
|
|
|
e73f7b5 |
index 0000000..24aa4a9
|
|
|
e73f7b5 |
--- /dev/null
|
|
|
e73f7b5 |
+++ b/modules/db_oracle/timer.h
|
|
|
e73f7b5 |
@@ -0,0 +1,22 @@
|
|
|
e73f7b5 |
+#ifndef ORA_TIMER_H
|
|
|
e73f7b5 |
+#define ORA_TIMER_H
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+#include "ora_con.h"
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+/*
|
|
|
e73f7b5 |
+ * parse timeout value for operation in syntax: nnn.mmm (sec/ms)
|
|
|
e73f7b5 |
+ */
|
|
|
e73f7b5 |
+int set_timeout(unsigned type, const char* val);
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+/*
|
|
|
e73f7b5 |
+ * parse timeout value for reconnect in syntax: nnn.mmm (sec/ms)
|
|
|
e73f7b5 |
+ */
|
|
|
e73f7b5 |
+int set_reconnect(unsigned type, const char* val);
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+int init_ora_timer(ora_con_t* con);
|
|
|
e73f7b5 |
+int destroy_ora_timer();
|
|
|
e73f7b5 |
+
|
|
|
e73f7b5 |
+void request_timer();
|
|
|
e73f7b5 |
+void restore_timer();
|
|
|
e73f7b5 |
+void timer_stop();
|
|
|
e73f7b5 |
+#endif // ORA_TIMER_H
|
|
|
e73f7b5 |
\ No newline at end of file
|