Header And Logo

PostgreSQL
| The world's most advanced open source database.

lockfuncs.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * lockfuncs.c
00004  *      Functions for SQL access to various lock-manager capabilities.
00005  *
00006  * Copyright (c) 2002-2013, PostgreSQL Global Development Group
00007  *
00008  * IDENTIFICATION
00009  *      src/backend/utils/adt/lockfuncs.c
00010  *
00011  *-------------------------------------------------------------------------
00012  */
00013 #include "postgres.h"
00014 
00015 #include "access/htup_details.h"
00016 #include "catalog/pg_type.h"
00017 #include "funcapi.h"
00018 #include "miscadmin.h"
00019 #include "storage/predicate_internals.h"
00020 #include "utils/builtins.h"
00021 
00022 
00023 /* This must match enum LockTagType! */
00024 static const char *const LockTagTypeNames[] = {
00025     "relation",
00026     "extend",
00027     "page",
00028     "tuple",
00029     "transactionid",
00030     "virtualxid",
00031     "object",
00032     "userlock",
00033     "advisory"
00034 };
00035 
00036 /* This must match enum PredicateLockTargetType (predicate_internals.h) */
00037 static const char *const PredicateLockTagTypeNames[] = {
00038     "relation",
00039     "page",
00040     "tuple"
00041 };
00042 
00043 /* Working status for pg_lock_status */
00044 typedef struct
00045 {
00046     LockData   *lockData;       /* state data from lmgr */
00047     int         currIdx;        /* current PROCLOCK index */
00048     PredicateLockData *predLockData;    /* state data for pred locks */
00049     int         predLockIdx;    /* current index for pred lock */
00050 } PG_Lock_Status;
00051 
00052 /* Number of columns in pg_locks output */
00053 #define NUM_LOCK_STATUS_COLUMNS     15
00054 
00055 /*
00056  * VXIDGetDatum - Construct a text representation of a VXID
00057  *
00058  * This is currently only used in pg_lock_status, so we put it here.
00059  */
00060 static Datum
00061 VXIDGetDatum(BackendId bid, LocalTransactionId lxid)
00062 {
00063     /*
00064      * The representation is "<bid>/<lxid>", decimal and unsigned decimal
00065      * respectively.  Note that elog.c also knows how to format a vxid.
00066      */
00067     char        vxidstr[32];
00068 
00069     snprintf(vxidstr, sizeof(vxidstr), "%d/%u", bid, lxid);
00070 
00071     return CStringGetTextDatum(vxidstr);
00072 }
00073 
00074 
00075 /*
00076  * pg_lock_status - produce a view with one row per held or awaited lock mode
00077  */
00078 Datum
00079 pg_lock_status(PG_FUNCTION_ARGS)
00080 {
00081     FuncCallContext *funcctx;
00082     PG_Lock_Status *mystatus;
00083     LockData   *lockData;
00084     PredicateLockData *predLockData;
00085 
00086     if (SRF_IS_FIRSTCALL())
00087     {
00088         TupleDesc   tupdesc;
00089         MemoryContext oldcontext;
00090 
00091         /* create a function context for cross-call persistence */
00092         funcctx = SRF_FIRSTCALL_INIT();
00093 
00094         /*
00095          * switch to memory context appropriate for multiple function calls
00096          */
00097         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
00098 
00099         /* build tupdesc for result tuples */
00100         /* this had better match pg_locks view in system_views.sql */
00101         tupdesc = CreateTemplateTupleDesc(NUM_LOCK_STATUS_COLUMNS, false);
00102         TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype",
00103                            TEXTOID, -1, 0);
00104         TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
00105                            OIDOID, -1, 0);
00106         TupleDescInitEntry(tupdesc, (AttrNumber) 3, "relation",
00107                            OIDOID, -1, 0);
00108         TupleDescInitEntry(tupdesc, (AttrNumber) 4, "page",
00109                            INT4OID, -1, 0);
00110         TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tuple",
00111                            INT2OID, -1, 0);
00112         TupleDescInitEntry(tupdesc, (AttrNumber) 6, "virtualxid",
00113                            TEXTOID, -1, 0);
00114         TupleDescInitEntry(tupdesc, (AttrNumber) 7, "transactionid",
00115                            XIDOID, -1, 0);
00116         TupleDescInitEntry(tupdesc, (AttrNumber) 8, "classid",
00117                            OIDOID, -1, 0);
00118         TupleDescInitEntry(tupdesc, (AttrNumber) 9, "objid",
00119                            OIDOID, -1, 0);
00120         TupleDescInitEntry(tupdesc, (AttrNumber) 10, "objsubid",
00121                            INT2OID, -1, 0);
00122         TupleDescInitEntry(tupdesc, (AttrNumber) 11, "virtualtransaction",
00123                            TEXTOID, -1, 0);
00124         TupleDescInitEntry(tupdesc, (AttrNumber) 12, "pid",
00125                            INT4OID, -1, 0);
00126         TupleDescInitEntry(tupdesc, (AttrNumber) 13, "mode",
00127                            TEXTOID, -1, 0);
00128         TupleDescInitEntry(tupdesc, (AttrNumber) 14, "granted",
00129                            BOOLOID, -1, 0);
00130         TupleDescInitEntry(tupdesc, (AttrNumber) 15, "fastpath",
00131                            BOOLOID, -1, 0);
00132 
00133         funcctx->tuple_desc = BlessTupleDesc(tupdesc);
00134 
00135         /*
00136          * Collect all the locking information that we will format and send
00137          * out as a result set.
00138          */
00139         mystatus = (PG_Lock_Status *) palloc(sizeof(PG_Lock_Status));
00140         funcctx->user_fctx = (void *) mystatus;
00141 
00142         mystatus->lockData = GetLockStatusData();
00143         mystatus->currIdx = 0;
00144         mystatus->predLockData = GetPredicateLockStatusData();
00145         mystatus->predLockIdx = 0;
00146 
00147         MemoryContextSwitchTo(oldcontext);
00148     }
00149 
00150     funcctx = SRF_PERCALL_SETUP();
00151     mystatus = (PG_Lock_Status *) funcctx->user_fctx;
00152     lockData = mystatus->lockData;
00153 
00154     while (mystatus->currIdx < lockData->nelements)
00155     {
00156         bool        granted;
00157         LOCKMODE    mode = 0;
00158         const char *locktypename;
00159         char        tnbuf[32];
00160         Datum       values[NUM_LOCK_STATUS_COLUMNS];
00161         bool        nulls[NUM_LOCK_STATUS_COLUMNS];
00162         HeapTuple   tuple;
00163         Datum       result;
00164         LockInstanceData *instance;
00165 
00166         instance = &(lockData->locks[mystatus->currIdx]);
00167 
00168         /*
00169          * Look to see if there are any held lock modes in this PROCLOCK. If
00170          * so, report, and destructively modify lockData so we don't report
00171          * again.
00172          */
00173         granted = false;
00174         if (instance->holdMask)
00175         {
00176             for (mode = 0; mode < MAX_LOCKMODES; mode++)
00177             {
00178                 if (instance->holdMask & LOCKBIT_ON(mode))
00179                 {
00180                     granted = true;
00181                     instance->holdMask &= LOCKBIT_OFF(mode);
00182                     break;
00183                 }
00184             }
00185         }
00186 
00187         /*
00188          * If no (more) held modes to report, see if PROC is waiting for a
00189          * lock on this lock.
00190          */
00191         if (!granted)
00192         {
00193             if (instance->waitLockMode != NoLock)
00194             {
00195                 /* Yes, so report it with proper mode */
00196                 mode = instance->waitLockMode;
00197 
00198                 /*
00199                  * We are now done with this PROCLOCK, so advance pointer to
00200                  * continue with next one on next call.
00201                  */
00202                 mystatus->currIdx++;
00203             }
00204             else
00205             {
00206                 /*
00207                  * Okay, we've displayed all the locks associated with this
00208                  * PROCLOCK, proceed to the next one.
00209                  */
00210                 mystatus->currIdx++;
00211                 continue;
00212             }
00213         }
00214 
00215         /*
00216          * Form tuple with appropriate data.
00217          */
00218         MemSet(values, 0, sizeof(values));
00219         MemSet(nulls, false, sizeof(nulls));
00220 
00221         if (instance->locktag.locktag_type <= LOCKTAG_LAST_TYPE)
00222             locktypename = LockTagTypeNames[instance->locktag.locktag_type];
00223         else
00224         {
00225             snprintf(tnbuf, sizeof(tnbuf), "unknown %d",
00226                      (int) instance->locktag.locktag_type);
00227             locktypename = tnbuf;
00228         }
00229         values[0] = CStringGetTextDatum(locktypename);
00230 
00231         switch ((LockTagType) instance->locktag.locktag_type)
00232         {
00233             case LOCKTAG_RELATION:
00234             case LOCKTAG_RELATION_EXTEND:
00235                 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
00236                 values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
00237                 nulls[3] = true;
00238                 nulls[4] = true;
00239                 nulls[5] = true;
00240                 nulls[6] = true;
00241                 nulls[7] = true;
00242                 nulls[8] = true;
00243                 nulls[9] = true;
00244                 break;
00245             case LOCKTAG_PAGE:
00246                 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
00247                 values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
00248                 values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
00249                 nulls[4] = true;
00250                 nulls[5] = true;
00251                 nulls[6] = true;
00252                 nulls[7] = true;
00253                 nulls[8] = true;
00254                 nulls[9] = true;
00255                 break;
00256             case LOCKTAG_TUPLE:
00257                 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
00258                 values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
00259                 values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
00260                 values[4] = UInt16GetDatum(instance->locktag.locktag_field4);
00261                 nulls[5] = true;
00262                 nulls[6] = true;
00263                 nulls[7] = true;
00264                 nulls[8] = true;
00265                 nulls[9] = true;
00266                 break;
00267             case LOCKTAG_TRANSACTION:
00268                 values[6] =
00269                     TransactionIdGetDatum(instance->locktag.locktag_field1);
00270                 nulls[1] = true;
00271                 nulls[2] = true;
00272                 nulls[3] = true;
00273                 nulls[4] = true;
00274                 nulls[5] = true;
00275                 nulls[7] = true;
00276                 nulls[8] = true;
00277                 nulls[9] = true;
00278                 break;
00279             case LOCKTAG_VIRTUALTRANSACTION:
00280                 values[5] = VXIDGetDatum(instance->locktag.locktag_field1,
00281                                          instance->locktag.locktag_field2);
00282                 nulls[1] = true;
00283                 nulls[2] = true;
00284                 nulls[3] = true;
00285                 nulls[4] = true;
00286                 nulls[6] = true;
00287                 nulls[7] = true;
00288                 nulls[8] = true;
00289                 nulls[9] = true;
00290                 break;
00291             case LOCKTAG_OBJECT:
00292             case LOCKTAG_USERLOCK:
00293             case LOCKTAG_ADVISORY:
00294             default:            /* treat unknown locktags like OBJECT */
00295                 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
00296                 values[7] = ObjectIdGetDatum(instance->locktag.locktag_field2);
00297                 values[8] = ObjectIdGetDatum(instance->locktag.locktag_field3);
00298                 values[9] = Int16GetDatum(instance->locktag.locktag_field4);
00299                 nulls[2] = true;
00300                 nulls[3] = true;
00301                 nulls[4] = true;
00302                 nulls[5] = true;
00303                 nulls[6] = true;
00304                 break;
00305         }
00306 
00307         values[10] = VXIDGetDatum(instance->backend, instance->lxid);
00308         if (instance->pid != 0)
00309             values[11] = Int32GetDatum(instance->pid);
00310         else
00311             nulls[11] = true;
00312         values[12] = CStringGetTextDatum(GetLockmodeName(instance->locktag.locktag_lockmethodid, mode));
00313         values[13] = BoolGetDatum(granted);
00314         values[14] = BoolGetDatum(instance->fastpath);
00315 
00316         tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
00317         result = HeapTupleGetDatum(tuple);
00318         SRF_RETURN_NEXT(funcctx, result);
00319     }
00320 
00321     /*
00322      * Have returned all regular locks. Now start on the SIREAD predicate
00323      * locks.
00324      */
00325     predLockData = mystatus->predLockData;
00326     if (mystatus->predLockIdx < predLockData->nelements)
00327     {
00328         PredicateLockTargetType lockType;
00329 
00330         PREDICATELOCKTARGETTAG *predTag = &(predLockData->locktags[mystatus->predLockIdx]);
00331         SERIALIZABLEXACT *xact = &(predLockData->xacts[mystatus->predLockIdx]);
00332         Datum       values[NUM_LOCK_STATUS_COLUMNS];
00333         bool        nulls[NUM_LOCK_STATUS_COLUMNS];
00334         HeapTuple   tuple;
00335         Datum       result;
00336 
00337         mystatus->predLockIdx++;
00338 
00339         /*
00340          * Form tuple with appropriate data.
00341          */
00342         MemSet(values, 0, sizeof(values));
00343         MemSet(nulls, false, sizeof(nulls));
00344 
00345         /* lock type */
00346         lockType = GET_PREDICATELOCKTARGETTAG_TYPE(*predTag);
00347 
00348         values[0] = CStringGetTextDatum(PredicateLockTagTypeNames[lockType]);
00349 
00350         /* lock target */
00351         values[1] = GET_PREDICATELOCKTARGETTAG_DB(*predTag);
00352         values[2] = GET_PREDICATELOCKTARGETTAG_RELATION(*predTag);
00353         if (lockType == PREDLOCKTAG_TUPLE)
00354             values[4] = GET_PREDICATELOCKTARGETTAG_OFFSET(*predTag);
00355         else
00356             nulls[4] = true;
00357         if ((lockType == PREDLOCKTAG_TUPLE) ||
00358             (lockType == PREDLOCKTAG_PAGE))
00359             values[3] = GET_PREDICATELOCKTARGETTAG_PAGE(*predTag);
00360         else
00361             nulls[3] = true;
00362 
00363         /* these fields are targets for other types of locks */
00364         nulls[5] = true;        /* virtualxid */
00365         nulls[6] = true;        /* transactionid */
00366         nulls[7] = true;        /* classid */
00367         nulls[8] = true;        /* objid */
00368         nulls[9] = true;        /* objsubid */
00369 
00370         /* lock holder */
00371         values[10] = VXIDGetDatum(xact->vxid.backendId,
00372                                   xact->vxid.localTransactionId);
00373         if (xact->pid != 0)
00374             values[11] = Int32GetDatum(xact->pid);
00375         else
00376             nulls[11] = true;
00377 
00378         /*
00379          * Lock mode. Currently all predicate locks are SIReadLocks, which are
00380          * always held (never waiting) and have no fast path
00381          */
00382         values[12] = CStringGetTextDatum("SIReadLock");
00383         values[13] = BoolGetDatum(true);
00384         values[14] = BoolGetDatum(false);
00385 
00386         tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
00387         result = HeapTupleGetDatum(tuple);
00388         SRF_RETURN_NEXT(funcctx, result);
00389     }
00390 
00391     SRF_RETURN_DONE(funcctx);
00392 }
00393 
00394 
00395 /*
00396  * Functions for manipulating advisory locks
00397  *
00398  * We make use of the locktag fields as follows:
00399  *
00400  *  field1: MyDatabaseId ... ensures locks are local to each database
00401  *  field2: first of 2 int4 keys, or high-order half of an int8 key
00402  *  field3: second of 2 int4 keys, or low-order half of an int8 key
00403  *  field4: 1 if using an int8 key, 2 if using 2 int4 keys
00404  */
00405 #define SET_LOCKTAG_INT64(tag, key64) \
00406     SET_LOCKTAG_ADVISORY(tag, \
00407                          MyDatabaseId, \
00408                          (uint32) ((key64) >> 32), \
00409                          (uint32) (key64), \
00410                          1)
00411 #define SET_LOCKTAG_INT32(tag, key1, key2) \
00412     SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key1, key2, 2)
00413 
00414 /*
00415  * pg_advisory_lock(int8) - acquire exclusive lock on an int8 key
00416  */
00417 Datum
00418 pg_advisory_lock_int8(PG_FUNCTION_ARGS)
00419 {
00420     int64       key = PG_GETARG_INT64(0);
00421     LOCKTAG     tag;
00422 
00423     SET_LOCKTAG_INT64(tag, key);
00424 
00425     (void) LockAcquire(&tag, ExclusiveLock, true, false);
00426 
00427     PG_RETURN_VOID();
00428 }
00429 
00430 /*
00431  * pg_advisory_xact_lock(int8) - acquire xact scoped
00432  * exclusive lock on an int8 key
00433  */
00434 Datum
00435 pg_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
00436 {
00437     int64       key = PG_GETARG_INT64(0);
00438     LOCKTAG     tag;
00439 
00440     SET_LOCKTAG_INT64(tag, key);
00441 
00442     (void) LockAcquire(&tag, ExclusiveLock, false, false);
00443 
00444     PG_RETURN_VOID();
00445 }
00446 
00447 /*
00448  * pg_advisory_lock_shared(int8) - acquire share lock on an int8 key
00449  */
00450 Datum
00451 pg_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
00452 {
00453     int64       key = PG_GETARG_INT64(0);
00454     LOCKTAG     tag;
00455 
00456     SET_LOCKTAG_INT64(tag, key);
00457 
00458     (void) LockAcquire(&tag, ShareLock, true, false);
00459 
00460     PG_RETURN_VOID();
00461 }
00462 
00463 /*
00464  * pg_advisory_xact_lock_shared(int8) - acquire xact scoped
00465  * share lock on an int8 key
00466  */
00467 Datum
00468 pg_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
00469 {
00470     int64       key = PG_GETARG_INT64(0);
00471     LOCKTAG     tag;
00472 
00473     SET_LOCKTAG_INT64(tag, key);
00474 
00475     (void) LockAcquire(&tag, ShareLock, false, false);
00476 
00477     PG_RETURN_VOID();
00478 }
00479 
00480 /*
00481  * pg_try_advisory_lock(int8) - acquire exclusive lock on an int8 key, no wait
00482  *
00483  * Returns true if successful, false if lock not available
00484  */
00485 Datum
00486 pg_try_advisory_lock_int8(PG_FUNCTION_ARGS)
00487 {
00488     int64       key = PG_GETARG_INT64(0);
00489     LOCKTAG     tag;
00490     LockAcquireResult res;
00491 
00492     SET_LOCKTAG_INT64(tag, key);
00493 
00494     res = LockAcquire(&tag, ExclusiveLock, true, true);
00495 
00496     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00497 }
00498 
00499 /*
00500  * pg_try_advisory_xact_lock(int8) - acquire xact scoped
00501  * exclusive lock on an int8 key, no wait
00502  *
00503  * Returns true if successful, false if lock not available
00504  */
00505 Datum
00506 pg_try_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
00507 {
00508     int64       key = PG_GETARG_INT64(0);
00509     LOCKTAG     tag;
00510     LockAcquireResult res;
00511 
00512     SET_LOCKTAG_INT64(tag, key);
00513 
00514     res = LockAcquire(&tag, ExclusiveLock, false, true);
00515 
00516     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00517 }
00518 
00519 /*
00520  * pg_try_advisory_lock_shared(int8) - acquire share lock on an int8 key, no wait
00521  *
00522  * Returns true if successful, false if lock not available
00523  */
00524 Datum
00525 pg_try_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
00526 {
00527     int64       key = PG_GETARG_INT64(0);
00528     LOCKTAG     tag;
00529     LockAcquireResult res;
00530 
00531     SET_LOCKTAG_INT64(tag, key);
00532 
00533     res = LockAcquire(&tag, ShareLock, true, true);
00534 
00535     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00536 }
00537 
00538 /*
00539  * pg_try_advisory_xact_lock_shared(int8) - acquire xact scoped
00540  * share lock on an int8 key, no wait
00541  *
00542  * Returns true if successful, false if lock not available
00543  */
00544 Datum
00545 pg_try_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
00546 {
00547     int64       key = PG_GETARG_INT64(0);
00548     LOCKTAG     tag;
00549     LockAcquireResult res;
00550 
00551     SET_LOCKTAG_INT64(tag, key);
00552 
00553     res = LockAcquire(&tag, ShareLock, false, true);
00554 
00555     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00556 }
00557 
00558 /*
00559  * pg_advisory_unlock(int8) - release exclusive lock on an int8 key
00560  *
00561  * Returns true if successful, false if lock was not held
00562 */
00563 Datum
00564 pg_advisory_unlock_int8(PG_FUNCTION_ARGS)
00565 {
00566     int64       key = PG_GETARG_INT64(0);
00567     LOCKTAG     tag;
00568     bool        res;
00569 
00570     SET_LOCKTAG_INT64(tag, key);
00571 
00572     res = LockRelease(&tag, ExclusiveLock, true);
00573 
00574     PG_RETURN_BOOL(res);
00575 }
00576 
00577 /*
00578  * pg_advisory_unlock_shared(int8) - release share lock on an int8 key
00579  *
00580  * Returns true if successful, false if lock was not held
00581  */
00582 Datum
00583 pg_advisory_unlock_shared_int8(PG_FUNCTION_ARGS)
00584 {
00585     int64       key = PG_GETARG_INT64(0);
00586     LOCKTAG     tag;
00587     bool        res;
00588 
00589     SET_LOCKTAG_INT64(tag, key);
00590 
00591     res = LockRelease(&tag, ShareLock, true);
00592 
00593     PG_RETURN_BOOL(res);
00594 }
00595 
00596 /*
00597  * pg_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys
00598  */
00599 Datum
00600 pg_advisory_lock_int4(PG_FUNCTION_ARGS)
00601 {
00602     int32       key1 = PG_GETARG_INT32(0);
00603     int32       key2 = PG_GETARG_INT32(1);
00604     LOCKTAG     tag;
00605 
00606     SET_LOCKTAG_INT32(tag, key1, key2);
00607 
00608     (void) LockAcquire(&tag, ExclusiveLock, true, false);
00609 
00610     PG_RETURN_VOID();
00611 }
00612 
00613 /*
00614  * pg_advisory_xact_lock(int4, int4) - acquire xact scoped
00615  * exclusive lock on 2 int4 keys
00616  */
00617 Datum
00618 pg_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
00619 {
00620     int32       key1 = PG_GETARG_INT32(0);
00621     int32       key2 = PG_GETARG_INT32(1);
00622     LOCKTAG     tag;
00623 
00624     SET_LOCKTAG_INT32(tag, key1, key2);
00625 
00626     (void) LockAcquire(&tag, ExclusiveLock, false, false);
00627 
00628     PG_RETURN_VOID();
00629 }
00630 
00631 /*
00632  * pg_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys
00633  */
00634 Datum
00635 pg_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
00636 {
00637     int32       key1 = PG_GETARG_INT32(0);
00638     int32       key2 = PG_GETARG_INT32(1);
00639     LOCKTAG     tag;
00640 
00641     SET_LOCKTAG_INT32(tag, key1, key2);
00642 
00643     (void) LockAcquire(&tag, ShareLock, true, false);
00644 
00645     PG_RETURN_VOID();
00646 }
00647 
00648 /*
00649  * pg_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
00650  * share lock on 2 int4 keys
00651  */
00652 Datum
00653 pg_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
00654 {
00655     int32       key1 = PG_GETARG_INT32(0);
00656     int32       key2 = PG_GETARG_INT32(1);
00657     LOCKTAG     tag;
00658 
00659     SET_LOCKTAG_INT32(tag, key1, key2);
00660 
00661     (void) LockAcquire(&tag, ShareLock, false, false);
00662 
00663     PG_RETURN_VOID();
00664 }
00665 
00666 /*
00667  * pg_try_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys, no wait
00668  *
00669  * Returns true if successful, false if lock not available
00670  */
00671 Datum
00672 pg_try_advisory_lock_int4(PG_FUNCTION_ARGS)
00673 {
00674     int32       key1 = PG_GETARG_INT32(0);
00675     int32       key2 = PG_GETARG_INT32(1);
00676     LOCKTAG     tag;
00677     LockAcquireResult res;
00678 
00679     SET_LOCKTAG_INT32(tag, key1, key2);
00680 
00681     res = LockAcquire(&tag, ExclusiveLock, true, true);
00682 
00683     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00684 }
00685 
00686 /*
00687  * pg_try_advisory_xact_lock(int4, int4) - acquire xact scoped
00688  * exclusive lock on 2 int4 keys, no wait
00689  *
00690  * Returns true if successful, false if lock not available
00691  */
00692 Datum
00693 pg_try_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
00694 {
00695     int32       key1 = PG_GETARG_INT32(0);
00696     int32       key2 = PG_GETARG_INT32(1);
00697     LOCKTAG     tag;
00698     LockAcquireResult res;
00699 
00700     SET_LOCKTAG_INT32(tag, key1, key2);
00701 
00702     res = LockAcquire(&tag, ExclusiveLock, false, true);
00703 
00704     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00705 }
00706 
00707 /*
00708  * pg_try_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys, no wait
00709  *
00710  * Returns true if successful, false if lock not available
00711  */
00712 Datum
00713 pg_try_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
00714 {
00715     int32       key1 = PG_GETARG_INT32(0);
00716     int32       key2 = PG_GETARG_INT32(1);
00717     LOCKTAG     tag;
00718     LockAcquireResult res;
00719 
00720     SET_LOCKTAG_INT32(tag, key1, key2);
00721 
00722     res = LockAcquire(&tag, ShareLock, true, true);
00723 
00724     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00725 }
00726 
00727 /*
00728  * pg_try_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
00729  * share lock on 2 int4 keys, no wait
00730  *
00731  * Returns true if successful, false if lock not available
00732  */
00733 Datum
00734 pg_try_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
00735 {
00736     int32       key1 = PG_GETARG_INT32(0);
00737     int32       key2 = PG_GETARG_INT32(1);
00738     LOCKTAG     tag;
00739     LockAcquireResult res;
00740 
00741     SET_LOCKTAG_INT32(tag, key1, key2);
00742 
00743     res = LockAcquire(&tag, ShareLock, false, true);
00744 
00745     PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
00746 }
00747 
00748 /*
00749  * pg_advisory_unlock(int4, int4) - release exclusive lock on 2 int4 keys
00750  *
00751  * Returns true if successful, false if lock was not held
00752 */
00753 Datum
00754 pg_advisory_unlock_int4(PG_FUNCTION_ARGS)
00755 {
00756     int32       key1 = PG_GETARG_INT32(0);
00757     int32       key2 = PG_GETARG_INT32(1);
00758     LOCKTAG     tag;
00759     bool        res;
00760 
00761     SET_LOCKTAG_INT32(tag, key1, key2);
00762 
00763     res = LockRelease(&tag, ExclusiveLock, true);
00764 
00765     PG_RETURN_BOOL(res);
00766 }
00767 
00768 /*
00769  * pg_advisory_unlock_shared(int4, int4) - release share lock on 2 int4 keys
00770  *
00771  * Returns true if successful, false if lock was not held
00772  */
00773 Datum
00774 pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS)
00775 {
00776     int32       key1 = PG_GETARG_INT32(0);
00777     int32       key2 = PG_GETARG_INT32(1);
00778     LOCKTAG     tag;
00779     bool        res;
00780 
00781     SET_LOCKTAG_INT32(tag, key1, key2);
00782 
00783     res = LockRelease(&tag, ShareLock, true);
00784 
00785     PG_RETURN_BOOL(res);
00786 }
00787 
00788 /*
00789  * pg_advisory_unlock_all() - release all advisory locks
00790  */
00791 Datum
00792 pg_advisory_unlock_all(PG_FUNCTION_ARGS)
00793 {
00794     LockReleaseSession(USER_LOCKMETHOD);
00795 
00796     PG_RETURN_VOID();
00797 }