NO WAIT ... - Mailing list pgsql-patches

From Hans-Jürgen Schönig
Subject NO WAIT ...
Date
Msg-id 40339D67.90208@cybertec.at
Whole thread Raw
Responses Re: NO WAIT ...  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
hi everyone ...

i have attached a patch implementing NO WAIT with the help of a GUC
variable.
documentation should be included as well.
it works nicely for me.

test=# begin;
BEGIN
test=# show wait_for_locks;
  wait_for_locks
----------------
  row share
(1 row)

test=# lock table x in exclusive mode;
LOCK TABLE
test=# commit;
COMMIT
test=# begin;
BEGIN
test=# -- somebody else has locked the table ...
test=# lock table x in exclusive mode;
ERROR:  LockAcquire failed



[hs@fedora pgsql]$ difforig > nowait.patch
./doc/src/sgml/runtime.sgml
./src/backend/storage/lmgr/lock.c
./src/backend/utils/misc/guc.c
./src/backend/utils/misc/postgresql.conf.sample
./src/bin/psql/tab-complete.c
./src/include/storage/lock.h
./src/include/utils/guc.h


i hope this patch is ok.
if there are any modifications needed just drop me a line.

maybe i will have some spare time to implement "SELECT FOR UPDATE
NOWAIT" (SQL version). maybe this extension would make sense as well
because many people porting from oracle to pg would like that.

     cheers,

         Hans

--
Cybertec Geschwinde u Schoenig
Schoengrabern 134, A-2020 Hollabrunn, Austria
Tel: +43/2952/30706 or +43/664/233 90 75
www.cybertec.at, www.postgresql.at, kernel.cybertec.at

*** ./doc/src/sgml/runtime.sgml.orig    2004-02-17 12:06:23.000000000 +0100
--- ./doc/src/sgml/runtime.sgml    2004-02-17 13:10:26.000000000 +0100
***************
*** 2555,2560 ****
--- 2555,2578 ----
        </listitem>
       </varlistentry>

+      <varlistentry>
+       <term><varname>wait_for_locks</varname> (<type>string</type>)</term>
+       <listitem>
+        <para>
+         By default an SQL statement has to wait until the desired locks for
+     processing the command can be acquired. In some cases this is not
+     the best thing to do. Therefore it is possible to tell PostgreSQL
+     which locks it is worth waiting for.  The following kinds of locks /
+     settings are supported: all, access share, row share, row exclusive,
+     share update exclusive, share, share row exclusive, exclusive,
+     access exclusive. <quote>all</> is the default setting and means that
+     PostgreSQL will wait for all locks. If <quote>share</> is specified
+     PostgreSQL will not wait for locks which are higher or equal to a
+     share lock.
+        </para>
+       </listitem>
+      </varlistentry>
+
       </variablelist>
     </sect2>

*** ./src/backend/storage/lmgr/lock.c.orig    2004-02-17 09:45:04.000000000 +0100
--- ./src/backend/storage/lmgr/lock.c    2004-02-17 11:33:13.000000000 +0100
***************
*** 36,41 ****
--- 36,42 ----
  #include "access/xact.h"
  #include "miscadmin.h"
  #include "storage/proc.h"
+ #include "utils/guc.h"
  #include "utils/memutils.h"
  #include "utils/ps_status.h"

***************
*** 435,440 ****
--- 436,455 ----
               locktag->objId.blkno, lock_mode_names[lockmode]);
  #endif

+     /* check if NO WAIT has been enabled
+        the basic strategy is very simple: if the user has selected "all"
+        PostgreSQL will act normally. However, if a certain lock level has
+        been defined PostgreSQL won't wait for locks which are higher than
+        the specified level */
+     if    (Wait_for_locks != 0)
+     {
+         /* now we have to adjust dontWait */
+         if    (lockmode >= Wait_for_locks)
+         {
+             dontWait = true;
+         }
+     }
+
      /* ???????? This must be changed when short term locks will be used */
      locktag->lockmethodid = lockmethodid;

*** ./src/backend/utils/misc/guc.c.orig    2004-02-17 09:48:34.000000000 +0100
--- ./src/backend/utils/misc/guc.c    2004-02-17 14:42:10.000000000 +0100
***************
*** 47,52 ****
--- 47,53 ----
  #include "storage/fd.h"
  #include "storage/freespace.h"
  #include "storage/lock.h"
+ #include "storage/lmgr.h"
  #include "storage/proc.h"
  #include "tcop/tcopprot.h"
  #include "utils/array.h"
***************
*** 85,90 ****
--- 86,93 ----

  static const char *assign_defaultxactisolevel(const char *newval,
                             bool doit, GucSource source);
+ static const char *assign_wait_for_locks(const char *newval,
+                            bool doit, GucSource source);
  static const char *assign_log_min_messages(const char *newval,
                          bool doit, GucSource source);
  static const char *assign_client_min_messages(const char *newval,
***************
*** 132,137 ****
--- 135,141 ----
  int            client_min_messages = NOTICE;

  int            log_min_duration_statement = -1;
+ int            Wait_for_locks = 0;


  /*
***************
*** 149,154 ****
--- 153,159 ----
  static char *client_encoding_string;
  static char *datestyle_string;
  static char *default_iso_level_string;
+ static char *wait_for_locks_string;
  static char *locale_collate;
  static char *locale_ctype;
  static char *regex_flavor_string;
***************
*** 1515,1521 ****
          &default_iso_level_string,
          "read committed", assign_defaultxactisolevel, NULL
      },
!
      {
          {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
              gettext_noop("Sets the path for dynamically loadable modules."),
--- 1520,1537 ----
          &default_iso_level_string,
          "read committed", assign_defaultxactisolevel, NULL
      },
!     {
!         {"wait_for_locks", PGC_USERSET, CLIENT_CONN_STATEMENT,
!             gettext_noop("Tells PostgreSQL whether to wait for locks or not."),
!             gettext_noop("Allowed settings: "
!                  "\"all\", \"access share\", \"row share\", "
!                  "\"row exclusive\", \"share update exclusive\", "
!                  "\"share\", \"share row exclusive\", "
!                  "\"exclusive\", \"access exclusive\".")
!         },
!         &wait_for_locks_string,
!         "all", assign_wait_for_locks, NULL
!     },
      {
          {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
              gettext_noop("Sets the path for dynamically loadable modules."),
***************
*** 4457,4462 ****
--- 4473,4533 ----
  #endif


+ /* in this function we will check if the string in the config-file
+    contains a correct lock level */
+ static const char *
+ assign_wait_for_locks(const char *newval, bool doit, GucSource source)
+ {
+     if (strcasecmp(newval, "all") == 0)
+     {
+         if (doit)
+             Wait_for_locks = NoLock;
+     }
+     else if (strcasecmp(newval, "access share") == 0)
+     {
+         if (doit)
+             Wait_for_locks = AccessShareLock;
+     }
+     else if (strcasecmp(newval, "row share") == 0)
+     {
+         if (doit)
+             Wait_for_locks = RowShareLock;
+     }
+     else if (strcasecmp(newval, "row exclusive") == 0)
+     {
+         if (doit)
+             Wait_for_locks = RowExclusiveLock;
+     }
+     else if (strcasecmp(newval, "share update exclusive") == 0)
+     {
+         if (doit)
+             Wait_for_locks = ShareUpdateExclusiveLock;
+     }
+     else if (strcasecmp(newval, "share") == 0)
+     {
+         if (doit)
+             Wait_for_locks = ShareLock;
+     }
+     else if (strcasecmp(newval, "share row exclusive") == 0)
+     {
+         if (doit)
+             Wait_for_locks = ShareRowExclusiveLock;
+     }
+     else if (strcasecmp(newval, "exclusive") == 0)
+     {
+         if (doit)
+             Wait_for_locks = ExclusiveLock;
+     }
+     else if (strcasecmp(newval, "access exclusive") == 0)
+     {
+         if (doit)
+             Wait_for_locks = AccessExclusiveLock;
+     }
+     else
+         return NULL;
+     return newval;
+ }
+
  static const char *
  assign_defaultxactisolevel(const char *newval, bool doit, GucSource source)
  {
*** ./src/backend/utils/misc/postgresql.conf.sample.orig    2004-02-17 11:02:35.000000000 +0100
--- ./src/backend/utils/misc/postgresql.conf.sample    2004-02-17 13:38:14.000000000 +0100
***************
*** 248,253 ****
--- 248,257 ----
  # LOCK MANAGEMENT
  #---------------------------------------------------------------------------

+ #wait_for_locks = 'all'        # allowed settings: all, access share,
+                 #  row share, row exclusive, share update
+                 #  exclusive, share, share row exclusive,
+                 #  exclusive, access exclusive
  #deadlock_timeout = 1000    # in milliseconds
  #max_locks_per_transaction = 64    # min 10, ~260*max_connections bytes each

*** ./src/bin/psql/tab-complete.c.orig    2004-02-17 11:51:19.000000000 +0100
--- ./src/bin/psql/tab-complete.c    2004-02-17 11:51:54.000000000 +0100
***************
*** 567,572 ****
--- 567,573 ----
          "unix_socket_directory",
          "unix_socket_group",
          "unix_socket_permissions",
+         "wait_for_locks",
          "wal_buffers",
          "wal_debug",
          "wal_sync_method",
*** ./src/include/storage/lock.h.orig    2004-02-17 10:12:37.000000000 +0100
--- ./src/include/storage/lock.h    2004-02-17 10:16:51.000000000 +0100
***************
*** 32,37 ****
--- 32,45 ----

  extern int    max_locks_per_xact;

+
+ /* PostgreSQL supports NO WAIT via GUC variables
+    therefore we need information telling us whether we want to wait for locks or
+    not. In addition to that we want to tell the system for which locks we want
+    to wait */
+ extern int  Wait_for_locks;
+
+
  #ifdef LOCK_DEBUG
  extern int    Trace_lock_oidmin;
  extern bool Trace_locks;
*** ./src/include/utils/guc.h.orig    2004-02-17 10:35:02.000000000 +0100
--- ./src/include/utils/guc.h    2004-02-17 10:35:29.000000000 +0100
***************
*** 126,131 ****
--- 126,132 ----
  extern int    log_min_messages;
  extern int    client_min_messages;
  extern int    log_min_duration_statement;
+ extern int    Wait_for_locks;


  extern void SetConfigOption(const char *name, const char *value,

pgsql-patches by date:

Previous
From: Tom Lane
Date:
Subject: Re: Doing psql's lexing with flex
Next
From: Peter Eisentraut
Date:
Subject: Re: Doing psql's lexing with flex