Обсуждение: timed PgConnection::Connect

Поиск
Список
Период
Сортировка

timed PgConnection::Connect

От
Denis A Ustimenko
Дата:
Hi, there!

I write this to put timeout parameter in PgConnection::Connect. It is really useful if you need something like that:
        try {
            write();
        }
        catch ( const DBError& e) {
            timeval timeout;
            timeout.tv_sec = reconnectTimeout;
            timeout.tv_usec = 0;

            while ( ConnectionBad()) {
                sleep( reconnectTimeout);
                Connect( conninfo.data(), &timeout);
            }
        }

this is patch for 7.2.1
*********************************************************
*** fe-connect.c.orig   Ср Авг  7 17:35:31 2002
--- fe-connect.c        Ср Авг  7 16:25:31 2002
***************
*** 173,179 ****


  static int    connectDBStart(PGconn *conn);
! static int    connectDBComplete(PGconn *conn);
  static bool PQsetenvStart(PGconn *conn);
  static PostgresPollingStatusType PQsetenvPoll(PGconn *conn);
  static PGconn *makeEmptyPGconn(void);
--- 173,179 ----


  static int    connectDBStart(PGconn *conn);
! static int    connectDBComplete(PGconn *conn, struct timeval *timeout);
  static bool PQsetenvStart(PGconn *conn);
  static PostgresPollingStatusType PQsetenvPoll(PGconn *conn);
  static PGconn *makeEmptyPGconn(void);
***************
*** 235,244 ****
  PGconn *
  PQconnectdb(const char *conninfo)
  {
        PGconn     *conn = PQconnectStart(conninfo);

        if (conn && conn->status != CONNECTION_BAD)
!               (void) connectDBComplete(conn);

        return conn;
  }
--- 235,250 ----
  PGconn *
  PQconnectdb(const char *conninfo)
  {
+       return PQconnectdbTimed( conninfo, NULL);
+ }
+
+ PGconn *
+ PQconnectdbTimed(const char *conninfo, struct timeval *timeout)
+ {
        PGconn     *conn = PQconnectStart(conninfo);

        if (conn && conn->status != CONNECTION_BAD)
!               (void) connectDBComplete(conn, timeout);

        return conn;
  }
***************
*** 513,519 ****
        else
        {
                if (connectDBStart(conn))
!                       (void) connectDBComplete(conn);
        }

        return conn;
--- 519,525 ----
        else
        {
                if (connectDBStart(conn))
!                       (void) connectDBComplete(conn, NULL);
        }

        return conn;
***************
*** 1046,1052 ****
   * Returns 1 on success, 0 on failure.
   */
  static int
! connectDBComplete(PGconn *conn)
  {
        PostgresPollingStatusType flag = PGRES_POLLING_WRITING;

--- 1052,1058 ----
   * Returns 1 on success, 0 on failure.
   */
  static int
! connectDBComplete(PGconn *conn, struct timeval *timeout)
  {
        PostgresPollingStatusType flag = PGRES_POLLING_WRITING;

***************
*** 1069,1075 ****
                                return 1;               /* success! */

                        case PGRES_POLLING_READING:
!                               if (pqWait(1, 0, conn))
                                {
                                        conn->status = CONNECTION_BAD;
                                        return 0;
--- 1075,1081 ----
                                return 1;               /* success! */

                        case PGRES_POLLING_READING:
!                               if (pqWaitTimed(1, 0, conn, timeout))
                                {
                                        conn->status = CONNECTION_BAD;
                                        return 0;
***************
*** 1077,1083 ****
                                break;

                        case PGRES_POLLING_WRITING:
!                               if (pqWait(0, 1, conn))
                                {
                                        conn->status = CONNECTION_BAD;
                                        return 0;
--- 1083,1089 ----
                                break;

                        case PGRES_POLLING_WRITING:
!                               if (pqWaitTimed(0, 1, conn, timeout))
                                {
                                        conn->status = CONNECTION_BAD;
                                        return 0;
***************
*** 2026,2032 ****
                closePGconn(conn);

                if (connectDBStart(conn))
!                       (void) connectDBComplete(conn);
        }
  }

--- 2032,2038 ----
                closePGconn(conn);

                if (connectDBStart(conn))
!                       (void) connectDBComplete(conn, NULL);
        }
  }
******************************************************************
*** fe-misc.c.orig      Ср Авг  7 17:35:08 2002
--- fe-misc.c   Ср Авг  7 16:04:19 2002
***************
*** 748,753 ****
--- 748,759 ----
  int
  pqWait(int forRead, int forWrite, PGconn *conn)
  {
+       return pqWaitTimed( forRead, forWrite, conn, (struct timeval *) NULL);
+ }
+
+ int
+ pqWaitTimed(int forRead, int forWrite, PGconn *conn, struct timeval *timeout)
+ {
        fd_set          input_mask;
        fd_set          output_mask;
        fd_set          except_mask;
***************
*** 770,777 ****
                if (forWrite)
                        FD_SET(conn->sock, &output_mask);
                FD_SET(conn->sock, &except_mask);
!               if (select(conn->sock + 1, &input_mask, &output_mask, &except_mask,
!                                  (struct timeval *) NULL) < 0)
                {
                        if (SOCK_ERRNO == EINTR)
                                goto retry;
--- 776,783 ----
                if (forWrite)
                        FD_SET(conn->sock, &output_mask);
                FD_SET(conn->sock, &except_mask);
!               if (select(conn->sock + 1, &input_mask, &output_mask,
!                             &except_mask, timeout) < 0)
                {
                        if (SOCK_ERRNO == EINTR)
                                goto retry;
******************************************************************
*** libpq-fe.h.orig     Ср Авг  7 17:36:03 2002
--- libpq-fe.h  Ср Авг  7 16:20:54 2002
***************
*** 185,190 ****
--- 185,191 ----

  /* Synchronous (blocking) */
  extern PGconn *PQconnectdb(const char *conninfo);
+ extern PGconn *PQconnectdbTimed(const char *conninfo, struct timeval *timeout);
  extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
                         const char *pgoptions, const char *pgtty,
                         const char *dbName,
******************************************************************
*** libpq-int.h.orig    Ср Авг  7 17:36:46 2002
--- libpq-int.h Ср Авг  7 15:55:26 2002
***************
*** 324,329 ****
--- 324,330 ----
  extern int    pqReadData(PGconn *conn);
  extern int    pqFlush(PGconn *conn);
  extern int    pqWait(int forRead, int forWrite, PGconn *conn);
+ extern int    pqWaitTimed(int forRead, int forWrite, PGconn *conn, struct timeval* timeout);
  extern int    pqReadReady(PGconn *conn);
  extern int    pqWriteReady(PGconn *conn);

******************************************************************
*** ../libpq++/pgconnection.cc.orig     Ср Авг  7 17:38:01 2002
--- ../libpq++/pgconnection.cc  Ср Авг  7 16:35:24 2002
***************
*** 68,83 ****
    }
  }

-
  // PgConnection::connect
  // establish a connection to a backend
! ConnStatusType PgConnection::Connect(const char conninfo[])
  {
    // if the connection is open, close it first
    CloseConnection();

    // Connect to the database
!   pgConn = PQconnectdb(conninfo);

    // Now we have a connection we must close (even if it's bad!)
    pgCloseConnection = true;
--- 68,82 ----
    }
  }

  // PgConnection::connect
  // establish a connection to a backend
! ConnStatusType PgConnection::Connect(const char conninfo[], timeval const *const timeout)
  {
    // if the connection is open, close it first
    CloseConnection();

    // Connect to the database
!   pgConn = PQconnectdbTimed(conninfo, const_cast<timeval *const timeout>(timeout));

    // Now we have a connection we must close (even if it's bad!)
    pgCloseConnection = true;
******************************************************************
*** ../libpq++/pgconnection.h.orig      Ср Авг  7 17:38:11 2002
--- ../libpq++/pgconnection.h   Ср Авг  7 16:32:47 2002
***************
*** 81,87 ****
     PGnotify* Notifies();

  protected:
!    ConnStatusType Connect(const char* conninfo);
     void CloseConnection();
     static PGSTD string IntToString(int);
     // Default constructor is only available to subclasses
--- 81,87 ----
     PGnotify* Notifies();

  protected:
!    ConnStatusType Connect(const char* conninfo, timeval const *const timeout = NULL);
     void CloseConnection();
     static PGSTD string IntToString(int);
     // Default constructor is only available to subclasses


--
Regards
Denis

Re: timed PgConnection::Connect

От
Tom Lane
Дата:
Denis A Ustimenko <denis@oldham.ru> writes:
> I write this to put timeout parameter in PgConnection::Connect.

This patch seems really messy.  In the first place, the timeout isn't on
total connection delay, but on individual waits of which there will be
several.  I'd think that's not really what you want.  In the second
place, I'd expect a timeout to be specified as a new optional parameter
in connection strings, not as an ad-hoc additional parameter in the API.

            regards, tom lane

Re: timed PgConnection::Connect

От
Denis A Ustimenko
Дата:
Hi!

Here is rewrited version. Time out can be specified as "connect_timeout" parameter. API hadn't changed.

On Wed, Aug 07, 2002 at 09:52:05AM -0400, Tom Lane wrote:
> Denis A Ustimenko <denis@oldham.ru> writes:
> > I write this to put timeout parameter in PgConnection::Connect.
>
> This patch seems really messy.  In the first place, the timeout isn't on
> total connection delay, but on individual waits of which there will be
> several.  I'd think that's not really what you want.  In the second
> place, I'd expect a timeout to be specified as a new optional parameter
> in connection strings, not as an ad-hoc additional parameter in the API.
>
>             regards, tom lane

--
Regards
Denis

Вложения