connect_timeout parameter in libpq

Поиск
Список
Период
Сортировка
От Denis A Ustimenko
Тема connect_timeout parameter in libpq
Дата
Msg-id 20020813025411.GA8313@denis.oldham.ru
обсуждение исходный текст
Ответы Re: connect_timeout parameter in libpq  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-patches
Hi there!

I need to change current connectDBComplete() behavior ( hang if backend are not responding). Here is the patch. Please
apply.

*** fe-connect.c.orig   Чт Авг  8 12:22:46 2002
--- fe-connect.c        Пт Авг  9 14:57:18 2002
***************
*** 114,119 ****
--- 114,122 ----
        {"password", "PGPASSWORD", DefaultPassword, NULL,
        "Database-Password", "*", 20},

+         {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
+         "Connect-timeout", "", 10}, /* strlen( INT32_MAX) == 10 */
+
        {"dbname", "PGDATABASE", NULL, NULL,
        "Database-Name", "", 20},

***************
*** 307,312 ****
--- 310,317 ----
        conn->pguser = tmp ? strdup(tmp) : NULL;
        tmp = conninfo_getval(connOptions, "password");
        conn->pgpass = tmp ? strdup(tmp) : NULL;
+       tmp = conninfo_getval(connOptions, "connect_timeout");
+       conn->connect_timeout = tmp ? strdup(tmp) : NULL;
  #ifdef USE_SSL
        tmp = conninfo_getval(connOptions, "requiressl");
        conn->require_ssl = tmp ? (tmp[0] == '1' ? true : false) : false;
***************
*** 1050,1060 ****
  {
        PostgresPollingStatusType flag = PGRES_POLLING_WRITING;

        if (conn == NULL || conn->status == CONNECTION_BAD)
                return 0;

!       for (;;)
        {
                /*
                 * Wait, if necessary.  Note that the initial state (just after
                 * PQconnectStart) is to wait for the socket to select for
--- 1055,1086 ----
  {
        PostgresPollingStatusType flag = PGRES_POLLING_WRITING;

+       time_t finish_time, start_time;
+       struct timeval remains, *rp = NULL;
+
        if (conn == NULL || conn->status == CONNECTION_BAD)
                return 0;

!       if (conn->connect_timeout != NULL)
        {
+               remains.tv_sec = atoi(conn->connect_timeout);
+               if (!remains.tv_sec)
+               {
+                       conn->status = CONNECTION_BAD;
+                       return 0;
+               }
+               remains.tv_usec = 0;
+               rp = &remains;
+       }
+
+
+       while (rp == NULL || remains.tv_sec > 0)
+       {
+               if ((time_t)-1 == (start_time = time(NULL)))
+               {
+                       conn->status = CONNECTION_BAD;
+                       return 0;
+               }
                /*
                 * Wait, if necessary.  Note that the initial state (just after
                 * PQconnectStart) is to wait for the socket to select for
***************
*** 1069,1075 ****
                                return 1;               /* success! */

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

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

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

                        case PGRES_POLLING_WRITING:
!                               if (pqWaitTimed(0, 1, conn, rp))
                                {
                                        conn->status = CONNECTION_BAD;
                                        return 0;
***************
*** 1094,1100 ****
--- 1120,1135 ----
                 * Now try to advance the state machine.
                 */
                flag = PQconnectPoll(conn);
+
+                 if ((time_t)-1 == (finish_time = time(NULL)))
+                 {
+                         conn->status = CONNECTION_BAD;
+                         return 0;
+                 }
+               remains.tv_sec -= finish_time - start_time;
        }
+       conn->status = CONNECTION_BAD;
+       return 0;
  }

  /* ----------------
***************
*** 1929,1934 ****
--- 1964,1971 ----
                free(conn->pguser);
        if (conn->pgpass)
                free(conn->pgpass);
+       if (conn->connect_timeout)
+               free(conn->connect_timeout);
        /* Note that conn->Pfdebug is not ours to close or free */
        if (conn->notifyList)
                DLFreeList(conn->notifyList);
*** fe-misc.c.orig      Чт Авг  8 16:33:34 2002
--- fe-misc.c   Чт Авг  8 16:33:45 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-int.h.orig    Чт Авг  8 16:37:56 2002
--- libpq-int.h Чт Авг  8 16:37:37 2002
***************
*** 279,284 ****
--- 279,286 ----
        PQExpBufferData workBuffer; /* expansible string */

        int                     client_encoding;        /* encoding id */
+
+       char *connect_timeout;
  };

  /* String descriptions of the ExecStatusTypes.
***************
*** 324,329 ****
--- 326,332 ----
  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);


--
Regards
Denis

В списке pgsql-patches по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: Antw: Re: Patch for NetWare support
Следующее
От: Tom Lane
Дата:
Сообщение: Re: connect_timeout parameter in libpq