lock timeout patch - Mailing list pgsql-hackers

From Satoshi Nagayasu
Subject lock timeout patch
Date
Msg-id 40DF904D.4040208@noanet06.noanet.nttdata.co.jp
Whole thread Raw
Responses Re: lock timeout patch
List pgsql-hackers
Hello all,

I've created a lock timeout patch and it's attached.

When a transaction is blocked by another transaction because of
waiting a lock, we need a lock timeout in some cases.

Using this patch, the lock timeout is enabled with
'lock_timeout = xxxx' directive in postgresql.conf,
and if a timeout is occured, an error code (40P02)
will be returned and a client application can detect it using

  JDBC: SQLException.getSQLState()
  C:    PQresultErrorField()

I know my code need to be cleaned up,
but any comments about this patch?

--
NAGAYASU Satoshi <nagayasus@nttdata.co.jp>

Index: backend/postmaster/postmaster.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/postmaster/postmaster.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 postmaster.c
*** backend/postmaster/postmaster.c    10 Jun 2004 00:22:29 -0000    1.1.1.1
--- backend/postmaster/postmaster.c    18 Jun 2004 03:17:22 -0000
***************
*** 2418,2424 ****
       * after a time delay, so that a broken client can't hog a connection
       * indefinitely.  PreAuthDelay doesn't count against the time limit.
       */
!     if (!enable_sig_alarm(AuthenticationTimeout * 1000, false))
          elog(FATAL, "could not set timer for authorization timeout");

      /*
--- 2418,2424 ----
       * after a time delay, so that a broken client can't hog a connection
       * indefinitely.  PreAuthDelay doesn't count against the time limit.
       */
!     if (!enable_sig_alarm(AuthenticationTimeout * 1000, false, false))
          elog(FATAL, "could not set timer for authorization timeout");

      /*
***************
*** 2447,2453 ****
       * Done with authentication.  Disable timeout, and prevent
       * SIGTERM/SIGQUIT again until backend startup is complete.
       */
!     if (!disable_sig_alarm(false))
          elog(FATAL, "could not disable timer for authorization timeout");
      PG_SETMASK(&BlockSig);

--- 2447,2453 ----
       * Done with authentication.  Disable timeout, and prevent
       * SIGTERM/SIGQUIT again until backend startup is complete.
       */
!     if (!disable_sig_alarm(false, false))
          elog(FATAL, "could not disable timer for authorization timeout");
      PG_SETMASK(&BlockSig);

Index: backend/storage/lmgr/proc.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 proc.c
*** backend/storage/lmgr/proc.c    10 Jun 2004 00:22:29 -0000    1.1.1.1
--- backend/storage/lmgr/proc.c    28 Jun 2004 03:20:10 -0000
***************
*** 52,60 ****
--- 52,68 ----
  #include "storage/sinval.h"
  #include "storage/spin.h"

+ #ifdef LOCKTIMEOUT_DEBUG
+ #define PRINT_TIME(MSG, X) \
+         elog(NOTICE, "%s: %d.%03d", MSG, (X).tv_sec, ((X).tv_usec/1000))
+ #else
+ #define PRINT_TIME(MSG, X) {}
+ #endif
+
  /* GUC variables */
  int            DeadlockTimeout = 1000;
  int            StatementTimeout = 0;
+ int            LockTimeout     = 0;

  /* Pointer to this process's PGPROC struct, if any */
  PGPROC       *MyProc = NULL;
***************
*** 78,92 ****
  /* Mark these volatile because they can be changed by signal handler */
  static volatile bool statement_timeout_active = false;
  static volatile bool deadlock_timeout_active = false;

  /* statement_fin_time is valid only if statement_timeout_active is true */
  static struct timeval statement_fin_time;
!

  static void ProcKill(void);
  static void DummyProcKill(void);
  static bool CheckStatementTimeout(void);


  /*
   * Report number of semaphores needed by InitProcGlobal.
--- 86,102 ----
  /* Mark these volatile because they can be changed by signal handler */
  static volatile bool statement_timeout_active = false;
  static volatile bool deadlock_timeout_active = false;
+ static volatile bool lock_timeout_active = false;

  /* statement_fin_time is valid only if statement_timeout_active is true */
  static struct timeval statement_fin_time;
! static struct timeval lock_fin_time;

  static void ProcKill(void);
  static void DummyProcKill(void);
  static bool CheckStatementTimeout(void);

+ static LOCK *prevWaitLock = NULL;

  /*
   * Report number of semaphores needed by InitProcGlobal.
***************
*** 244,249 ****
--- 254,261 ----
      MyProc->waitHolder = NULL;
      SHMQueueInit(&(MyProc->procHolders));

+     prevWaitLock = NULL;
+
      /*
       * Arrange to clean up at backend exit.
       */
***************
*** 307,312 ****
--- 319,326 ----
      MyProc->waitHolder = NULL;
      SHMQueueInit(&(MyProc->procHolders));

+     prevWaitLock = NULL;
+
      /*
       * Arrange to clean up at process exit.
       */
***************
*** 338,344 ****
      waitingForLock = false;

      /* Turn off the deadlock timer, if it's still running (see ProcSleep) */
!     disable_sig_alarm(false);

      /* Unlink myself from the wait queue, if on it (might not be anymore!) */
      LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
--- 352,358 ----
      waitingForLock = false;

      /* Turn off the deadlock timer, if it's still running (see ProcSleep) */
!     disable_sig_alarm(false, false);

      /* Unlink myself from the wait queue, if on it (might not be anymore!) */
      LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
***************
*** 627,632 ****
--- 641,648 ----

      MyProc->errType = STATUS_OK;    /* initialize result for success */

+     prevWaitLock = MyProc->waitLock;
+
      /*
       * If we detected deadlock, give up without waiting.  This must agree
       * with CheckDeadLock's recovery code, except that we shouldn't
***************
*** 661,667 ****
       * By delaying the check until we've waited for a bit, we can avoid
       * running the rather expensive deadlock-check code in most cases.
       */
!     if (!enable_sig_alarm(DeadlockTimeout, false))
          elog(FATAL, "could not set timer for process wakeup");

      /*
--- 677,683 ----
       * By delaying the check until we've waited for a bit, we can avoid
       * running the rather expensive deadlock-check code in most cases.
       */
!     if (!enable_sig_alarm(DeadlockTimeout, false, false))
          elog(FATAL, "could not set timer for process wakeup");

      /*
***************
*** 683,689 ****
      /*
       * Disable the timer, if it's still running
       */
!     if (!disable_sig_alarm(false))
          elog(FATAL, "could not disable timer for process wakeup");

      /*
--- 699,705 ----
      /*
       * Disable the timer, if it's still running
       */
!     if (!disable_sig_alarm(false, false))
          elog(FATAL, "could not disable timer for process wakeup");

      /*
***************
*** 738,743 ****
--- 754,761 ----
      proc->waitHolder = NULL;
      proc->errType = errType;

+     prevWaitLock = NULL;
+
      /* And awaken it */
      PGSemaphoreUnlock(&proc->sem);

***************
*** 885,890 ****
--- 903,911 ----
       * RemoveFromWaitQueue took care of waking up any such processes.
       */
      LWLockRelease(LockMgrLock);
+
+     deadlock_timeout_active = false;
+     prevWaitLock = NULL;
  }


***************
*** 930,936 ****
          PGSemaphoreUnlock(&proc->sem);
  }

-
  /*****************************************************************************
   * SIGALRM interrupt support
   *
--- 951,956 ----
***************
*** 949,955 ****
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! enable_sig_alarm(int delayms, bool is_statement_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
--- 969,975 ----
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! enable_sig_alarm(int delayms, bool is_statement_timeout, bool is_lock_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
***************
*** 963,970 ****
      bigtime_t    time_interval;
  #endif

      /* Compute target timeout time if we will need it */
!     if (is_statement_timeout || statement_timeout_active)
      {
          gettimeofday(&fin_time, NULL);
          fin_time.tv_sec += delayms / 1000;
--- 983,999 ----
      bigtime_t    time_interval;
  #endif

+ #ifdef LOCKTIMEOUT_DEBUG
+     elog(NOTICE, "enable_sig_alarm: is_statement_timeout=%d, "
+          "is_lock_timeout=%d\n",
+          is_statement_timeout,
+          is_lock_timeout);
+     elog(NOTICE, "enable_sig_alarm: LockTimeout=%d", LockTimeout);
+ #endif
+
      /* Compute target timeout time if we will need it */
!     if (is_statement_timeout || statement_timeout_active ||
!         is_lock_timeout || lock_timeout_active )
      {
          gettimeofday(&fin_time, NULL);
          fin_time.tv_sec += delayms / 1000;
***************
*** 974,979 ****
--- 1003,1009 ----
              fin_time.tv_sec++;
              fin_time.tv_usec -= 1000000;
          }
+         PRINT_TIME("enable_sig_alarm", fin_time);
      }

      if (is_statement_timeout)
***************
*** 983,1012 ****
          statement_fin_time = fin_time;
          statement_timeout_active = true;
      }
!     else if (statement_timeout_active)
      {
!         /*
!          * Begin deadlock timeout with statement-level timeout active
!          *
!          * Here, we want to interrupt at the closer of the two timeout times.
!          * If fin_time >= statement_fin_time then we need not touch the
!          * existing timer setting; else set up to interrupt at the
!          * deadlock timeout time.
!          *
!          * NOTE: in this case it is possible that this routine will be
!          * interrupted by the previously-set timer alarm.  This is okay
!          * because the signal handler will do only what it should do
!          * according to the state variables.  The deadlock checker may get
!          * run earlier than normal, but that does no harm.
!          */
!         deadlock_timeout_active = true;
!         if (fin_time.tv_sec > statement_fin_time.tv_sec ||
!             (fin_time.tv_sec == statement_fin_time.tv_sec &&
!              fin_time.tv_usec >= statement_fin_time.tv_usec))
!             return true;
      }
      else
      {
          /* Begin deadlock timeout with no statement-level timeout */
          deadlock_timeout_active = true;
      }
--- 1013,1066 ----
          statement_fin_time = fin_time;
          statement_timeout_active = true;
      }
!     else if ( is_lock_timeout )
      {
!         Assert(!lock_timeout_active);
!         lock_fin_time = fin_time;
!         lock_timeout_active = true;
!         prevWaitLock = MyProc->waitLock;
      }
      else
      {
+         /*
+          * If is_statement_timeout and is_lock_timeout are false,
+          * delayms means a timeout time to detect deadlock.
+          */
+         if (statement_timeout_active)
+         {
+             /*
+              * Begin deadlock timeout with statement-level timeout active
+              *
+              * Here, we want to interrupt at the closer of the two timeout times.
+              * If fin_time >= statement_fin_time then we need not touch the
+              * existing timer setting; else set up to interrupt at the
+              * deadlock timeout time.
+              *
+              * NOTE: in this case it is possible that this routine will be
+              * interrupted by the previously-set timer alarm.  This is okay
+              * because the signal handler will do only what it should do
+              * according to the state variables.  The deadlock checker may get
+              * run earlier than normal, but that does no harm.
+              */
+             deadlock_timeout_active = true;
+             if (fin_time.tv_sec > statement_fin_time.tv_sec ||
+                 (fin_time.tv_sec == statement_fin_time.tv_sec &&
+                  fin_time.tv_usec >= statement_fin_time.tv_usec))
+                 return true;
+         }
+         if (lock_timeout_active)
+         {
+             /*
+              * If the lock timeout has been already set, and it is shorter
+              * than me, there is no need to set another one.
+              * The shortest timer has to be set.
+              */
+             deadlock_timeout_active = true;
+             if (fin_time.tv_sec > lock_fin_time.tv_sec ||
+                 (fin_time.tv_sec == lock_fin_time.tv_sec &&
+                  fin_time.tv_usec >= lock_fin_time.tv_usec))
+                 return true;
+         }
          /* Begin deadlock timeout with no statement-level timeout */
          deadlock_timeout_active = true;
      }
***************
*** 1016,1021 ****
--- 1070,1086 ----
      MemSet(&timeval, 0, sizeof(struct itimerval));
      timeval.it_value.tv_sec = delayms / 1000;
      timeval.it_value.tv_usec = (delayms % 1000) * 1000;
+     {
+         PRINT_TIME("enable_sig_alarm", timeval.it_value);
+ #ifdef LOCKTIMEOUT_DEBUG
+         elog(NOTICE, "enable_sig_alarm: deadlock_timeout_active=%d, "
+              "statement_timeout_active=%d, "
+              "lock_timeout_active=%d\n",
+              deadlock_timeout_active,
+              statement_timeout_active,
+              lock_timeout_active);
+ #endif
+     }
      if (setitimer(ITIMER_REAL, &timeval, NULL))
          return false;
  #else
***************
*** 1025,1030 ****
--- 1090,1098 ----
          return false;
  #endif
  #endif
+
+     PRINT_TIME("enable_sig_alarm: lock_fin_time", lock_fin_time);
+
      return true;
  }

***************
*** 1036,1042 ****
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! disable_sig_alarm(bool is_statement_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
--- 1104,1110 ----
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! disable_sig_alarm(bool is_statement_timeout, bool is_lock_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
***************
*** 1049,1055 ****
       *
       * We will re-enable the interrupt if necessary in CheckStatementTimeout.
       */
!     if (statement_timeout_active || deadlock_timeout_active)
      {
  #ifndef __BEOS__
          struct itimerval timeval;
--- 1117,1124 ----
       *
       * We will re-enable the interrupt if necessary in CheckStatementTimeout.
       */
!     if (statement_timeout_active || deadlock_timeout_active ||
!         lock_timeout_active )
      {
  #ifndef __BEOS__
          struct itimerval timeval;
***************
*** 1057,1070 ****
          MemSet(&timeval, 0, sizeof(struct itimerval));
          if (setitimer(ITIMER_REAL, &timeval, NULL))
          {
!             statement_timeout_active = deadlock_timeout_active = false;
              return false;
          }
  #else
          /* BeOS doesn't have setitimer, but has set_alarm */
          if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
          {
!             statement_timeout_active = deadlock_timeout_active = false;
              return false;
          }
  #endif
--- 1126,1143 ----
          MemSet(&timeval, 0, sizeof(struct itimerval));
          if (setitimer(ITIMER_REAL, &timeval, NULL))
          {
!             statement_timeout_active = deadlock_timeout_active
!                     = lock_timeout_active = false;
!             prevWaitLock = NULL;
              return false;
          }
  #else
          /* BeOS doesn't have setitimer, but has set_alarm */
          if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
          {
!             statement_timeout_active = deadlock_timeout_active
!                     = lock_timeout_active = false;
!             prevWaitLock = NULL;
              return false;
          }
  #endif
***************
*** 1076,1081 ****
--- 1149,1159 ----
      /* Cancel or reschedule statement timeout */
      if (is_statement_timeout)
          statement_timeout_active = false;
+     else if (is_lock_timeout)
+     {
+         lock_timeout_active = false;
+         prevWaitLock = NULL;
+     }
      else if (statement_timeout_active)
      {
          if (!CheckStatementTimeout())
***************
*** 1086,1091 ****
--- 1164,1196 ----
  }


+ static struct timeval *
+ GetShorterTimer(struct timeval *r, struct timeval t1, struct timeval t2)
+ {
+     if ( t1.tv_sec<t2.tv_sec )
+     {
+         r->tv_sec = t1.tv_sec;
+         r->tv_usec = t1.tv_usec;
+     }
+     else if ( t1.tv_sec>t2.tv_sec )
+     {
+         r->tv_sec = t2.tv_sec;
+         r->tv_usec = t2.tv_usec;
+     }
+     else if ( t1.tv_usec<t2.tv_usec )
+     {
+         r->tv_sec = t1.tv_sec;
+         r->tv_usec = t1.tv_usec;
+     }
+     else
+     {
+         r->tv_sec = t2.tv_sec;
+         r->tv_usec = t2.tv_usec;
+     }
+     return r;
+ }
+
+
  /*
   * Check for statement timeout.  If the timeout time has come,
   * trigger a query-cancel interrupt; if not, reschedule the SIGALRM
***************
*** 1121,1128 ****
          struct itimerval timeval;

          MemSet(&timeval, 0, sizeof(struct itimerval));
!         timeval.it_value.tv_sec = statement_fin_time.tv_sec - now.tv_sec;
!         timeval.it_value.tv_usec = statement_fin_time.tv_usec - now.tv_usec;
          if (timeval.it_value.tv_usec < 0)
          {
              timeval.it_value.tv_sec--;
--- 1226,1242 ----
          struct itimerval timeval;

          MemSet(&timeval, 0, sizeof(struct itimerval));
!
!         if ( statement_timeout_active && lock_timeout_active )
!             GetShorterTimer(&(timeval.it_value), statement_fin_time,lock_fin_time);
!         else if ( statement_timeout_active )
!             timeval.it_value = statement_fin_time;
!         else if ( lock_timeout_active )
!             timeval.it_value = lock_fin_time;
!
!         timeval.it_value.tv_sec -= now.tv_sec;
!         timeval.it_value.tv_usec -= now.tv_usec;
!
          if (timeval.it_value.tv_usec < 0)
          {
              timeval.it_value.tv_sec--;
***************
*** 1131,1136 ****
--- 1245,1251 ----
          if (setitimer(ITIMER_REAL, &timeval, NULL))
              return false;
  #else
+ #warning *** LOCKTIMEOUT NOT IMPLEMENTED!!! ***
          /* BeOS doesn't have setitimer, but has set_alarm */
          bigtime_t    time_interval;

***************
*** 1146,1151 ****
--- 1261,1346 ----
      return true;
  }

+ static bool
+ CheckLockTimeout(void)
+ {
+     struct timeval now;
+
+     if (!lock_timeout_active)
+         return true;            /* do nothing if not active */
+
+     gettimeofday(&now, NULL);
+
+     PRINT_TIME("CheckLockTimeout: now", now);
+     PRINT_TIME("CheckLockTimeout: lock_fin_time", lock_fin_time);
+
+     if (now.tv_sec > lock_fin_time.tv_sec ||
+         (now.tv_sec == lock_fin_time.tv_sec &&
+          now.tv_usec >= lock_fin_time.tv_usec))
+
+     elog(DEBUG1, "MyProc.lwWaiting=%d, MyProc.lwExclusive=%d", MyProc->lwWaiting,
+          MyProc->lwWaiting);
+     elog(DEBUG1, "MyProc.waitLock=%p", MyProc->waitLock);
+
+     /*
+      * Still waiting a same lock.
+      */
+     if ( MyProc->waitLock && MyProc->waitLock==prevWaitLock )
+     {
+         /* Time to die */
+         lock_timeout_active = false;
+         prevWaitLock = NULL;
+
+         ereport(ERROR, (errcode(ERRCODE_T_R_LOCKTIMEOUT_DETECTED),
+                 errmsg("the current transaction is going to be rolled-back because of lock timeout.")));
+     }
+     else
+     {
+         /* Not time yet, so (re)schedule the interrupt */
+ #ifdef WIN32
+ #warning add win32 timer
+ #else
+ #ifndef __BEOS__
+         struct itimerval timeval;
+
+         MemSet(&timeval, 0, sizeof(struct itimerval));
+
+         if ( statement_timeout_active && lock_timeout_active )
+             GetShorterTimer(&(timeval.it_value), statement_fin_time,lock_fin_time);
+         else if ( statement_timeout_active )
+             timeval.it_value = statement_fin_time;
+         else if ( lock_timeout_active )
+             timeval.it_value = lock_fin_time;
+
+         PRINT_TIME("CheckLockTimeout: timeval.it_value", timeval.it_value);
+         timeval.it_value.tv_sec -= now.tv_sec;
+         timeval.it_value.tv_usec -= now.tv_usec;
+         PRINT_TIME("CheckLockTimeout: timeval.it_value", timeval.it_value);
+
+         if (timeval.it_value.tv_usec < 0)
+         {
+             timeval.it_value.tv_sec--;
+             timeval.it_value.tv_usec += 1000000;
+         }
+         if (setitimer(ITIMER_REAL, &timeval, NULL))
+             return false;
+ #else
+ #warning *** NOT IMPLEMENTED!!! ***
+         /* BeOS doesn't have setitimer, but has set_alarm */
+         bigtime_t    time_interval;
+
+         time_interval =
+             (lock_fin_time.tv_sec - now.tv_sec) * 1000000 +
+             (lock_fin_time.tv_usec - now.tv_usec);
+         if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
+             return false;
+ #endif
+ #endif
+     }
+
+     return true;
+ }
+

  /*
   * Signal handler for SIGALRM
***************
*** 1160,1173 ****
  {
      int            save_errno = errno;

      if (deadlock_timeout_active)
      {
-         deadlock_timeout_active = false;
          CheckDeadLock();
      }

      if (statement_timeout_active)
          (void) CheckStatementTimeout();

      errno = save_errno;
  }
--- 1355,1382 ----
  {
      int            save_errno = errno;

+ //    elog(NOTICE, "handle_sig_alarm: deadlock_timeout_active=%d, statement_timeout_active=%d,
lock_timeout_active=%d",deadlock_timeout_active, statement_timeout_active, lock_timeout_active); 
+
+     PRINT_TIME("handle_sig_alarm: lock_fin_time", lock_fin_time);
+
      if (deadlock_timeout_active)
      {
          CheckDeadLock();
      }

+     PRINT_TIME("handle_sig_alarm: lock_fin_time", lock_fin_time);
+
      if (statement_timeout_active)
+     {
          (void) CheckStatementTimeout();
+     }
+
+     PRINT_TIME("handle_sig_alarm: lock_fin_time", lock_fin_time);
+
+     if (lock_timeout_active)
+     {
+         (void) CheckLockTimeout();
+     }

      errno = save_errno;
  }
Index: backend/tcop/postgres.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/tcop/postgres.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 postgres.c
*** backend/tcop/postgres.c    10 Jun 2004 00:22:29 -0000    1.1.1.1
--- backend/tcop/postgres.c    18 Jun 2004 03:16:32 -0000
***************
*** 1734,1740 ****

          /* Set statement timeout running, if any */
          if (StatementTimeout > 0)
!             enable_sig_alarm(StatementTimeout, true);

          xact_started = true;
      }
--- 1734,1742 ----

          /* Set statement timeout running, if any */
          if (StatementTimeout > 0)
!             enable_sig_alarm(StatementTimeout, true, false);
!         if (LockTimeout > 0)
!             enable_sig_alarm(LockTimeout, false, true);

          xact_started = true;
      }
***************
*** 1749,1755 ****
          DeferredTriggerEndQuery();

          /* Cancel any active statement timeout before committing */
!         disable_sig_alarm(true);

          /* Now commit the command */
          ereport(DEBUG3,
--- 1751,1757 ----
          DeferredTriggerEndQuery();

          /* Cancel any active statement timeout before committing */
!         disable_sig_alarm(true, true);

          /* Now commit the command */
          ereport(DEBUG3,
***************
*** 2704,2710 ****
          QueryCancelPending = false;
          InterruptHoldoffCount = 1;
          CritSectionCount = 0;    /* should be unnecessary, but... */
!         disable_sig_alarm(true);
          QueryCancelPending = false;        /* again in case timeout occurred */
          DisableNotifyInterrupt();
          debug_query_string = NULL;
--- 2706,2712 ----
          QueryCancelPending = false;
          InterruptHoldoffCount = 1;
          CritSectionCount = 0;    /* should be unnecessary, but... */
!         disable_sig_alarm(true, true);
          QueryCancelPending = false;        /* again in case timeout occurred */
          DisableNotifyInterrupt();
          debug_query_string = NULL;
Index: backend/utils/misc/guc.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 guc.c
*** backend/utils/misc/guc.c    10 Jun 2004 00:22:33 -0000    1.1.1.1
--- backend/utils/misc/guc.c    28 Jun 2004 01:30:20 -0000
***************
*** 910,917 ****
              NULL
          },
          &DeadlockTimeout,
!         1000, 0, INT_MAX, NULL, NULL
      },

  #ifdef HAVE_SYSLOG
      {
--- 910,927 ----
              NULL
          },
          &DeadlockTimeout,
!         5000, 0, INT_MAX, NULL, NULL
      },
+
+     {
+         {"lock_timeout", PGC_SIGHUP, LOCK_MANAGEMENT,
+             gettext_noop("The time in milliseconds to wait on lock before detecting timeout."),
+             NULL
+         },
+         &LockTimeout,
+         0, 0, INT_MAX, NULL, NULL
+     },
+

  #ifdef HAVE_SYSLOG
      {
Index: include/storage/proc.h
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/include/storage/proc.h,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 proc.h
*** include/storage/proc.h    10 Jun 2004 00:22:34 -0000    1.1.1.1
--- include/storage/proc.h    15 Jun 2004 08:20:34 -0000
***************
*** 88,93 ****
--- 88,94 ----

  /* configurable options */
  extern int    DeadlockTimeout;
+ extern int    LockTimeout;
  extern int    StatementTimeout;


***************
*** 111,118 ****
  extern void ProcCancelWaitForSignal(void);
  extern void ProcSendSignal(BackendId procId);

! extern bool enable_sig_alarm(int delayms, bool is_statement_timeout);
! extern bool disable_sig_alarm(bool is_statement_timeout);
  extern void handle_sig_alarm(SIGNAL_ARGS);

  #endif   /* PROC_H */
--- 112,120 ----
  extern void ProcCancelWaitForSignal(void);
  extern void ProcSendSignal(BackendId procId);

! extern bool enable_sig_alarm(int delayms, bool is_statement_timeout,
!                              bool is_lock_timeout);
! extern bool disable_sig_alarm(bool is_statement_timeout, bool is_lock_timeout);
  extern void handle_sig_alarm(SIGNAL_ARGS);

  #endif   /* PROC_H */
Index: include/utils/errcodes.h
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/include/utils/errcodes.h,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 errcodes.h
*** include/utils/errcodes.h    10 Jun 2004 00:22:34 -0000    1.1.1.1
--- include/utils/errcodes.h    18 Jun 2004 06:29:09 -0000
***************
*** 203,208 ****
--- 203,211 ----
  #define ERRCODE_T_R_SERIALIZATION_FAILURE    MAKE_SQLSTATE('4','0', '0','0','1')
  #define ERRCODE_T_R_STATEMENT_COMPLETION_UNKNOWN    MAKE_SQLSTATE('4','0', '0','0','3')
  #define ERRCODE_T_R_DEADLOCK_DETECTED        MAKE_SQLSTATE('4','0', 'P','0','1')
+ #ifdef LOCKTIMEOUT
+  #define ERRCODE_T_R_LOCKTIMEOUT_DETECTED        MAKE_SQLSTATE('4','0', 'P','0','2')
+ #endif

  /* Class 42 - Syntax Error or Access Rule Violation */
  #define ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION        MAKE_SQLSTATE('4','2', '0','0','0')

pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: Fixing pg_dump
Next
From: Christopher Kings-Lynne
Date:
Subject: Re: Fixing pg_dump