00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
00037 static const char *const PredicateLockTagTypeNames[] = {
00038 "relation",
00039 "page",
00040 "tuple"
00041 };
00042
00043
00044 typedef struct
00045 {
00046 LockData *lockData;
00047 int currIdx;
00048 PredicateLockData *predLockData;
00049 int predLockIdx;
00050 } PG_Lock_Status;
00051
00052
00053 #define NUM_LOCK_STATUS_COLUMNS 15
00054
00055
00056
00057
00058
00059
00060 static Datum
00061 VXIDGetDatum(BackendId bid, LocalTransactionId lxid)
00062 {
00063
00064
00065
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
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
00092 funcctx = SRF_FIRSTCALL_INIT();
00093
00094
00095
00096
00097 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
00098
00099
00100
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
00137
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
00170
00171
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
00189
00190
00191 if (!granted)
00192 {
00193 if (instance->waitLockMode != NoLock)
00194 {
00195
00196 mode = instance->waitLockMode;
00197
00198
00199
00200
00201
00202 mystatus->currIdx++;
00203 }
00204 else
00205 {
00206
00207
00208
00209
00210 mystatus->currIdx++;
00211 continue;
00212 }
00213 }
00214
00215
00216
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:
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
00323
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
00341
00342 MemSet(values, 0, sizeof(values));
00343 MemSet(nulls, false, sizeof(nulls));
00344
00345
00346 lockType = GET_PREDICATELOCKTARGETTAG_TYPE(*predTag);
00347
00348 values[0] = CStringGetTextDatum(PredicateLockTagTypeNames[lockType]);
00349
00350
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
00364 nulls[5] = true;
00365 nulls[6] = true;
00366 nulls[7] = true;
00367 nulls[8] = true;
00368 nulls[9] = true;
00369
00370
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
00380
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
00397
00398
00399
00400
00401
00402
00403
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
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
00432
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
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
00465
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
00482
00483
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
00501
00502
00503
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
00521
00522
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
00540
00541
00542
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
00560
00561
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
00579
00580
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
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
00615
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
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
00650
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
00668
00669
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
00688
00689
00690
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
00709
00710
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
00729
00730
00731
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
00750
00751
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
00770
00771
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
00790
00791 Datum
00792 pg_advisory_unlock_all(PG_FUNCTION_ARGS)
00793 {
00794 LockReleaseSession(USER_LOCKMETHOD);
00795
00796 PG_RETURN_VOID();
00797 }