Remember by posting about a working informix driver for 3.x?

Well -- I guess I have an almost working Informix driver.

The driver loads, connects, and works fine until I let it idle for a while
and an idle handle gets closed. I get the following two lines in the log:

Notice: Done running scheduled proc acs_messaging_process_queue.
Notice: dbinit: closing idle handle in pool 'noacs_eoffice'

Once this happens, my next attempt to access the informix db pool fails.

The handle passed to OpenDb is bogus so handle->datasource is null or filled
with random garbage. My suspision is that CloseDb is freeing something
that it shouldn't but it's not obvious to me. (I only dable in C code).

I'm hoping someone resolved a similar problem when porting a AOS 2.x driver
to 3.x. Here are the OpenDb and CloseDb functions. any help would be greatly
appreciated.

---

/* OpenDb
*******************************************************************************
** Open a connection & initialise handle.
**
** Note that we don't use the `define_locked_fun' macro here, as at this
** point the uninitialised handle doesn't have a mutex to use!
*/

static int OpenDb(Ns_DbHandle *handle)
{
  EXEC SQL BEGIN DECLARE SECTION;
  char *dbname;
  string *conn_name;
  EXEC SQL END DECLARE SECTION;

  static long gensym_counter = 0; /* Protected by gensym_mutex. */
  int conn_id;
  struct ius_state *ius_stuff;

  Ns_Log(Notice, "Open");

  if( !handle ) {
      Ns_Log(Error, "Null handle.");
      return (NS_ERROR);
      }

  Ns_Log(Notice,
         "Connecting to datasource '%s' as user '%s' with password '%s'.",
         denull(handle->datasource),
         denull(handle->user),
         denull(handle->password));

  if( !handle->datasource ) {
      Ns_Log(Error, "No datasource.");
      return NS_ERROR;
      }

  dbname = strchr(handle->datasource, ':');
  if( !dbname ) {
      Ns_Log(Error, "Datasource doesn't contain a colon.");
      return NS_ERROR;
      }
  dbname++; /* Skip the colon. */

  /* Connections need SQL names. We just gensym them up using conn_id
  ** for a counter; we wrap at 2^31. The gensym op must be protected with
  ** a mutex.
  */
  Ns_LockMutex(&gensym_mutex);
  gensym_counter = (gensym_counter+1) & 0x3FFFFFFF;
  conn_id = gensym_counter;
  Ns_UnlockMutex(&gensym_mutex);

  ius_stuff = Alloc(struct ius_state);

  conn_name = ius_stuff->cname;
  sprintf(conn_name, "ns%d", conn_id);

  /* CONCURRENT TRANSACTION clause enables cross-thread transactions. */
  EXEC SQL connect to :dbname as :conn_name with concurrent transaction;
  handle->connection = (void*) ius_stuff;

  /* Free cursors and their statements when they are closed. */
  EXEC SQL set autofree;

  /* Tell the database to allow SQL string literals to contain
  ** newline chars. What bunch of brain-dead pinheads designed
  ** this system?
  */
  /* Commented out because it was causing an error (probably obsolete
  **
  ** EXEC SQL EXECUTE PROCEDURE IFX_ALLOW_NEWLINE('t');
  */

  /* Make the connection dormant so it's not associated
  ** with a particular thread.
  */
  EXEC SQL set connection :conn_name dormant;

  /* Success. */
  Ns_InitializeMutex(&ius_stuff->mutex);
  handle->connected    = 1;
  handle->fetchingRows = 0;
  ius_stuff->rowbuf = NULL;
  return NS_OK;

  /* Failure. Clean up and return. */
sql_err:
  report_xcptn(handle);
  Free(ius_stuff);
  handle->connection = NULL;
  return NS_ERROR;
  }



/* CloseDb
*******************************************************************************
** Close a connection and free up related resources.
**
** Note that we don't use `define_locked_fun', as we don't have a connection
** to disconnect after the core function has done its job.
*/

static int CloseDb(Ns_DbHandle *handle)
{
  struct ius_state *state;
  EXEC SQL BEGIN DECLARE SECTION;
  string *conn_name;
  EXEC SQL END DECLARE SECTION;
  int set_dormant = 0;          /* Advises sql_err error handler. */

  Ns_Log(Notice, "CloseDb");

  if( !handle ) {                               /* Error checks */
      Ns_Log(Error, "CloseDb -- Null handle.");
      return NS_ERROR;
      }

  if( !handle->connected || !handle->connection ) {
        Ns_Log(Error, "CloseDb -- handle not connected.");
        return NS_ERROR;
        }

  state = (struct ius_state*) handle->connection;
  conn_name = state->cname;

  Ns_LockMutex(& state->mutex);                 /* Lock.                 */
  EXEC SQL set connection :conn_name;           /* Connect.              */
  set_dormant = 1;
  EXEC SQL disconnect :conn_name;               /* Close the connection. */
  set_dormant = 0;

  handle->connected = 0;                        /* Clear out handle.     */
  if( handle->datasource ) { Free(handle->datasource); handle->datasource =
NULL; }
  if( handle->user )       { Free(handle->user);       handle->user       =
NULL; }
  if( handle->password )   { Free(handle->password);   handle->password   =
NULL; }

  Ns_UnlockMutex(& state->mutex);               /* Unlock & free state. */
  Ns_DestroyMutex(& state->mutex);
  free_rowbuf(handle);
  Free(state);  handle->connection = NULL;

  return NS_OK;

sql_err:
  report_xcptn(handle);
  if( set_dormant ) {
      EXEC SQL set connection :conn_name dormant;
      }
  Ns_UnlockMutex(& state->mutex);       /* Unlock. */
  return NS_ERROR;
  }

---

------
Keith Paskett                        [EMAIL PROTECTED]
Space Dynamics Laboratory            PGP or GPG encrypted mail preferred
1695 North Research Parkway          435-797-4195
Logan, Utah 84341

Reply via email to