00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "access/subtrans.h"
00019 #include "access/transam.h"
00020 #include "access/xact.h"
00021 #include "catalog/catalog.h"
00022 #include "miscadmin.h"
00023 #include "storage/lmgr.h"
00024 #include "storage/procarray.h"
00025 #include "utils/inval.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034 void
00035 RelationInitLockInfo(Relation relation)
00036 {
00037 Assert(RelationIsValid(relation));
00038 Assert(OidIsValid(RelationGetRelid(relation)));
00039
00040 relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
00041
00042 if (relation->rd_rel->relisshared)
00043 relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
00044 else
00045 relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
00046 }
00047
00048
00049
00050
00051
00052 static inline void
00053 SetLocktagRelationOid(LOCKTAG *tag, Oid relid)
00054 {
00055 Oid dbid;
00056
00057 if (IsSharedRelation(relid))
00058 dbid = InvalidOid;
00059 else
00060 dbid = MyDatabaseId;
00061
00062 SET_LOCKTAG_RELATION(*tag, dbid, relid);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071 void
00072 LockRelationOid(Oid relid, LOCKMODE lockmode)
00073 {
00074 LOCKTAG tag;
00075 LockAcquireResult res;
00076
00077 SetLocktagRelationOid(&tag, relid);
00078
00079 res = LockAcquire(&tag, lockmode, false, false);
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 if (res != LOCKACQUIRE_ALREADY_HELD)
00092 AcceptInvalidationMessages();
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 bool
00105 ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
00106 {
00107 LOCKTAG tag;
00108 LockAcquireResult res;
00109
00110 SetLocktagRelationOid(&tag, relid);
00111
00112 res = LockAcquire(&tag, lockmode, false, true);
00113
00114 if (res == LOCKACQUIRE_NOT_AVAIL)
00115 return false;
00116
00117
00118
00119
00120
00121 if (res != LOCKACQUIRE_ALREADY_HELD)
00122 AcceptInvalidationMessages();
00123
00124 return true;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133 void
00134 UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
00135 {
00136 LOCKTAG tag;
00137
00138 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
00139
00140 LockRelease(&tag, lockmode, false);
00141 }
00142
00143
00144
00145
00146
00147
00148 void
00149 UnlockRelationOid(Oid relid, LOCKMODE lockmode)
00150 {
00151 LOCKTAG tag;
00152
00153 SetLocktagRelationOid(&tag, relid);
00154
00155 LockRelease(&tag, lockmode, false);
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165 void
00166 LockRelation(Relation relation, LOCKMODE lockmode)
00167 {
00168 LOCKTAG tag;
00169 LockAcquireResult res;
00170
00171 SET_LOCKTAG_RELATION(tag,
00172 relation->rd_lockInfo.lockRelId.dbId,
00173 relation->rd_lockInfo.lockRelId.relId);
00174
00175 res = LockAcquire(&tag, lockmode, false, false);
00176
00177
00178
00179
00180
00181 if (res != LOCKACQUIRE_ALREADY_HELD)
00182 AcceptInvalidationMessages();
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192 bool
00193 ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
00194 {
00195 LOCKTAG tag;
00196 LockAcquireResult res;
00197
00198 SET_LOCKTAG_RELATION(tag,
00199 relation->rd_lockInfo.lockRelId.dbId,
00200 relation->rd_lockInfo.lockRelId.relId);
00201
00202 res = LockAcquire(&tag, lockmode, false, true);
00203
00204 if (res == LOCKACQUIRE_NOT_AVAIL)
00205 return false;
00206
00207
00208
00209
00210
00211 if (res != LOCKACQUIRE_ALREADY_HELD)
00212 AcceptInvalidationMessages();
00213
00214 return true;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 void
00224 UnlockRelation(Relation relation, LOCKMODE lockmode)
00225 {
00226 LOCKTAG tag;
00227
00228 SET_LOCKTAG_RELATION(tag,
00229 relation->rd_lockInfo.lockRelId.dbId,
00230 relation->rd_lockInfo.lockRelId.relId);
00231
00232 LockRelease(&tag, lockmode, false);
00233 }
00234
00235
00236
00237
00238
00239
00240
00241 bool
00242 LockHasWaitersRelation(Relation relation, LOCKMODE lockmode)
00243 {
00244 LOCKTAG tag;
00245
00246 SET_LOCKTAG_RELATION(tag,
00247 relation->rd_lockInfo.lockRelId.dbId,
00248 relation->rd_lockInfo.lockRelId.relId);
00249
00250 return LockHasWaiters(&tag, lockmode, false);
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 void
00266 LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
00267 {
00268 LOCKTAG tag;
00269
00270 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
00271
00272 (void) LockAcquire(&tag, lockmode, true, false);
00273 }
00274
00275
00276
00277
00278 void
00279 UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
00280 {
00281 LOCKTAG tag;
00282
00283 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
00284
00285 LockRelease(&tag, lockmode, true);
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 void
00299 LockRelationForExtension(Relation relation, LOCKMODE lockmode)
00300 {
00301 LOCKTAG tag;
00302
00303 SET_LOCKTAG_RELATION_EXTEND(tag,
00304 relation->rd_lockInfo.lockRelId.dbId,
00305 relation->rd_lockInfo.lockRelId.relId);
00306
00307 (void) LockAcquire(&tag, lockmode, false, false);
00308 }
00309
00310
00311
00312
00313 void
00314 UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
00315 {
00316 LOCKTAG tag;
00317
00318 SET_LOCKTAG_RELATION_EXTEND(tag,
00319 relation->rd_lockInfo.lockRelId.dbId,
00320 relation->rd_lockInfo.lockRelId.relId);
00321
00322 LockRelease(&tag, lockmode, false);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331 void
00332 LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
00333 {
00334 LOCKTAG tag;
00335
00336 SET_LOCKTAG_PAGE(tag,
00337 relation->rd_lockInfo.lockRelId.dbId,
00338 relation->rd_lockInfo.lockRelId.relId,
00339 blkno);
00340
00341 (void) LockAcquire(&tag, lockmode, false, false);
00342 }
00343
00344
00345
00346
00347
00348
00349
00350 bool
00351 ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
00352 {
00353 LOCKTAG tag;
00354
00355 SET_LOCKTAG_PAGE(tag,
00356 relation->rd_lockInfo.lockRelId.dbId,
00357 relation->rd_lockInfo.lockRelId.relId,
00358 blkno);
00359
00360 return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
00361 }
00362
00363
00364
00365
00366 void
00367 UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
00368 {
00369 LOCKTAG tag;
00370
00371 SET_LOCKTAG_PAGE(tag,
00372 relation->rd_lockInfo.lockRelId.dbId,
00373 relation->rd_lockInfo.lockRelId.relId,
00374 blkno);
00375
00376 LockRelease(&tag, lockmode, false);
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386 void
00387 LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
00388 {
00389 LOCKTAG tag;
00390
00391 SET_LOCKTAG_TUPLE(tag,
00392 relation->rd_lockInfo.lockRelId.dbId,
00393 relation->rd_lockInfo.lockRelId.relId,
00394 ItemPointerGetBlockNumber(tid),
00395 ItemPointerGetOffsetNumber(tid));
00396
00397 (void) LockAcquire(&tag, lockmode, false, false);
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 bool
00407 ConditionalLockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
00408 {
00409 LOCKTAG tag;
00410
00411 SET_LOCKTAG_TUPLE(tag,
00412 relation->rd_lockInfo.lockRelId.dbId,
00413 relation->rd_lockInfo.lockRelId.relId,
00414 ItemPointerGetBlockNumber(tid),
00415 ItemPointerGetOffsetNumber(tid));
00416
00417 return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
00418 }
00419
00420
00421
00422
00423 void
00424 UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
00425 {
00426 LOCKTAG tag;
00427
00428 SET_LOCKTAG_TUPLE(tag,
00429 relation->rd_lockInfo.lockRelId.dbId,
00430 relation->rd_lockInfo.lockRelId.relId,
00431 ItemPointerGetBlockNumber(tid),
00432 ItemPointerGetOffsetNumber(tid));
00433
00434 LockRelease(&tag, lockmode, false);
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444 void
00445 XactLockTableInsert(TransactionId xid)
00446 {
00447 LOCKTAG tag;
00448
00449 SET_LOCKTAG_TRANSACTION(tag, xid);
00450
00451 (void) LockAcquire(&tag, ExclusiveLock, false, false);
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461 void
00462 XactLockTableDelete(TransactionId xid)
00463 {
00464 LOCKTAG tag;
00465
00466 SET_LOCKTAG_TRANSACTION(tag, xid);
00467
00468 LockRelease(&tag, ExclusiveLock, false);
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 void
00484 XactLockTableWait(TransactionId xid)
00485 {
00486 LOCKTAG tag;
00487
00488 for (;;)
00489 {
00490 Assert(TransactionIdIsValid(xid));
00491 Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
00492
00493 SET_LOCKTAG_TRANSACTION(tag, xid);
00494
00495 (void) LockAcquire(&tag, ShareLock, false, false);
00496
00497 LockRelease(&tag, ShareLock, false);
00498
00499 if (!TransactionIdIsInProgress(xid))
00500 break;
00501 xid = SubTransGetParent(xid);
00502 }
00503 }
00504
00505
00506
00507
00508
00509
00510
00511 bool
00512 ConditionalXactLockTableWait(TransactionId xid)
00513 {
00514 LOCKTAG tag;
00515
00516 for (;;)
00517 {
00518 Assert(TransactionIdIsValid(xid));
00519 Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
00520
00521 SET_LOCKTAG_TRANSACTION(tag, xid);
00522
00523 if (LockAcquire(&tag, ShareLock, false, true) == LOCKACQUIRE_NOT_AVAIL)
00524 return false;
00525
00526 LockRelease(&tag, ShareLock, false);
00527
00528 if (!TransactionIdIsInProgress(xid))
00529 break;
00530 xid = SubTransGetParent(xid);
00531 }
00532
00533 return true;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 void
00545 LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
00546 LOCKMODE lockmode)
00547 {
00548 LOCKTAG tag;
00549
00550 SET_LOCKTAG_OBJECT(tag,
00551 MyDatabaseId,
00552 classid,
00553 objid,
00554 objsubid);
00555
00556 (void) LockAcquire(&tag, lockmode, false, false);
00557
00558
00559 AcceptInvalidationMessages();
00560 }
00561
00562
00563
00564
00565 void
00566 UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
00567 LOCKMODE lockmode)
00568 {
00569 LOCKTAG tag;
00570
00571 SET_LOCKTAG_OBJECT(tag,
00572 MyDatabaseId,
00573 classid,
00574 objid,
00575 objsubid);
00576
00577 LockRelease(&tag, lockmode, false);
00578 }
00579
00580
00581
00582
00583
00584
00585 void
00586 LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
00587 LOCKMODE lockmode)
00588 {
00589 LOCKTAG tag;
00590
00591 SET_LOCKTAG_OBJECT(tag,
00592 InvalidOid,
00593 classid,
00594 objid,
00595 objsubid);
00596
00597 (void) LockAcquire(&tag, lockmode, false, false);
00598
00599
00600 AcceptInvalidationMessages();
00601 }
00602
00603
00604
00605
00606 void
00607 UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
00608 LOCKMODE lockmode)
00609 {
00610 LOCKTAG tag;
00611
00612 SET_LOCKTAG_OBJECT(tag,
00613 InvalidOid,
00614 classid,
00615 objid,
00616 objsubid);
00617
00618 LockRelease(&tag, lockmode, false);
00619 }
00620
00621
00622
00623
00624
00625
00626
00627 void
00628 LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
00629 LOCKMODE lockmode)
00630 {
00631 LOCKTAG tag;
00632
00633 SET_LOCKTAG_OBJECT(tag,
00634 InvalidOid,
00635 classid,
00636 objid,
00637 objsubid);
00638
00639 (void) LockAcquire(&tag, lockmode, true, false);
00640 }
00641
00642
00643
00644
00645 void
00646 UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
00647 LOCKMODE lockmode)
00648 {
00649 LOCKTAG tag;
00650
00651 SET_LOCKTAG_OBJECT(tag,
00652 InvalidOid,
00653 classid,
00654 objid,
00655 objsubid);
00656
00657 LockRelease(&tag, lockmode, true);
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 void
00669 DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
00670 {
00671 switch ((LockTagType) tag->locktag_type)
00672 {
00673 case LOCKTAG_RELATION:
00674 appendStringInfo(buf,
00675 _("relation %u of database %u"),
00676 tag->locktag_field2,
00677 tag->locktag_field1);
00678 break;
00679 case LOCKTAG_RELATION_EXTEND:
00680 appendStringInfo(buf,
00681 _("extension of relation %u of database %u"),
00682 tag->locktag_field2,
00683 tag->locktag_field1);
00684 break;
00685 case LOCKTAG_PAGE:
00686 appendStringInfo(buf,
00687 _("page %u of relation %u of database %u"),
00688 tag->locktag_field3,
00689 tag->locktag_field2,
00690 tag->locktag_field1);
00691 break;
00692 case LOCKTAG_TUPLE:
00693 appendStringInfo(buf,
00694 _("tuple (%u,%u) of relation %u of database %u"),
00695 tag->locktag_field3,
00696 tag->locktag_field4,
00697 tag->locktag_field2,
00698 tag->locktag_field1);
00699 break;
00700 case LOCKTAG_TRANSACTION:
00701 appendStringInfo(buf,
00702 _("transaction %u"),
00703 tag->locktag_field1);
00704 break;
00705 case LOCKTAG_VIRTUALTRANSACTION:
00706 appendStringInfo(buf,
00707 _("virtual transaction %d/%u"),
00708 tag->locktag_field1,
00709 tag->locktag_field2);
00710 break;
00711 case LOCKTAG_OBJECT:
00712 appendStringInfo(buf,
00713 _("object %u of class %u of database %u"),
00714 tag->locktag_field3,
00715 tag->locktag_field2,
00716 tag->locktag_field1);
00717 break;
00718 case LOCKTAG_USERLOCK:
00719
00720 appendStringInfo(buf,
00721 _("user lock [%u,%u,%u]"),
00722 tag->locktag_field1,
00723 tag->locktag_field2,
00724 tag->locktag_field3);
00725 break;
00726 case LOCKTAG_ADVISORY:
00727 appendStringInfo(buf,
00728 _("advisory lock [%u,%u,%u,%u]"),
00729 tag->locktag_field1,
00730 tag->locktag_field2,
00731 tag->locktag_field3,
00732 tag->locktag_field4);
00733 break;
00734 default:
00735 appendStringInfo(buf,
00736 _("unrecognized locktag type %d"),
00737 (int) tag->locktag_type);
00738 break;
00739 }
00740 }