PostgreSQL Source Code: src/backend/storage/lmgr/predicate.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
199
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233#define TargetTagIsCoveredBy(covered_target, covering_target) \
234 ((GET_PREDICATELOCKTARGETTAG_RELATION(covered_target) == \
235 GET_PREDICATELOCKTARGETTAG_RELATION(covering_target)) \
236 && (GET_PREDICATELOCKTARGETTAG_OFFSET(covering_target) == \
237 InvalidOffsetNumber) \
238 && (((GET_PREDICATELOCKTARGETTAG_OFFSET(covered_target) != \
239 InvalidOffsetNumber) \
240 && (GET_PREDICATELOCKTARGETTAG_PAGE(covering_target) == \
241 GET_PREDICATELOCKTARGETTAG_PAGE(covered_target))) \
242 || ((GET_PREDICATELOCKTARGETTAG_PAGE(covering_target) == \
243 InvalidBlockNumber) \
244 && (GET_PREDICATELOCKTARGETTAG_PAGE(covered_target) \
245 != InvalidBlockNumber))) \
246 && (GET_PREDICATELOCKTARGETTAG_DB(covered_target) == \
247 GET_PREDICATELOCKTARGETTAG_DB(covering_target)))
248
249
250
251
252
253
254
255
256#define PredicateLockHashPartition(hashcode) \
257 ((hashcode) % NUM_PREDICATELOCK_PARTITIONS)
258#define PredicateLockHashPartitionLock(hashcode) \
259 (&MainLWLockArray[PREDICATELOCK_MANAGER_LWLOCK_OFFSET + \
260 PredicateLockHashPartition(hashcode)].lock)
261#define PredicateLockHashPartitionLockByIndex(i) \
262 (&MainLWLockArray[PREDICATELOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
263
264#define NPREDICATELOCKTARGETENTS() \
265 mul_size(max_predicate_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))
266
267#define SxactIsOnFinishedList(sxact) (!dlist_node_is_detached(&(sxact)->finishedLink))
268
269
270
271
272
273
274
275
276
277#define SxactIsCommitted(sxact) (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0)
278#define SxactIsPrepared(sxact) (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
279#define SxactIsRolledBack(sxact) (((sxact)->flags & SXACT_FLAG_ROLLED_BACK) != 0)
280#define SxactIsDoomed(sxact) (((sxact)->flags & SXACT_FLAG_DOOMED) != 0)
281#define SxactIsReadOnly(sxact) (((sxact)->flags & SXACT_FLAG_READ_ONLY) != 0)
282#define SxactHasSummaryConflictIn(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0)
283#define SxactHasSummaryConflictOut(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_OUT) != 0)
284
285
286
287
288
289#define SxactHasConflictOut(sxact) (((sxact)->flags & SXACT_FLAG_CONFLICT_OUT) != 0)
290#define SxactIsDeferrableWaiting(sxact) (((sxact)->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0)
291#define SxactIsROSafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 0)
292#define SxactIsROUnsafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0)
293#define SxactIsPartiallyReleased(sxact) (((sxact)->flags & SXACT_FLAG_PARTIALLY_RELEASED) != 0)
294
295
296
297
298
299
300
301
302
303#define PredicateLockTargetTagHashCode(predicatelocktargettag) \
304 get_hash_value(PredicateLockTargetHash, predicatelocktargettag)
305
306
307
308
309
310
311
312
313
314
315
316#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash) \
317 ((targethash) ^ ((uint32) PointerGetDatum((predicatelocktag)->myXact)) \
318 << LOG2_NUM_PREDICATELOCK_PARTITIONS)
319
320
321
322
323
325
326#define SerialSlruCtl (&SerialSlruCtlData)
327
328#define SERIAL_PAGESIZE BLCKSZ
329#define SERIAL_ENTRYSIZE sizeof(SerCommitSeqNo)
330#define SERIAL_ENTRIESPERPAGE (SERIAL_PAGESIZE / SERIAL_ENTRYSIZE)
331
332
333
334
335#define SERIAL_MAX_PAGE (MaxTransactionId / SERIAL_ENTRIESPERPAGE)
336
337#define SerialNextPage(page) (((page) >= SERIAL_MAX_PAGE) ? 0 : (page) + 1)
338
339#define SerialValue(slotno, xid) (*((SerCommitSeqNo *) \
340 (SerialSlruCtl->shared->page_buffer[slotno] + \
341 ((((uint32) (xid)) % SERIAL_ENTRIESPERPAGE) * SERIAL_ENTRYSIZE))))
342
343#define SerialPage(xid) (((uint32) (xid)) / SERIAL_ENTRIESPERPAGE)
344
346{
351
353
355
356
357
358
359
360
361
363
364
365
366
367
368
369
370
374
375
376
377
378
379
380
381
382
383
385
386
387
388
389
391
392
393
394
395
400
401
402
403
404
405
409
410
411
412
413
415
416
417
418
419
420
423
424
425
426
427
428
429
430
432
433
434
437
443
449
455 int sourcepid);
463 uint32 targettaghash);
469 uint32 targettaghash,
474 bool removeOld);
477 bool transfer);
481 bool summarize);
489
490
491
492
493
494
495
496
497static inline bool
499{
502}
503
504
505
506
507
508
509
510
511
512
513
514
515static inline bool
517{
518
520 return false;
521
522
523
524
525
526
527
528
530 return false;
531
532
533
534
535
536
537
538
539
540
541
543 {
545 return false;
546 }
547
548
550 return false;
551
552 return true;
553}
554
555
556
557
558
559static inline bool
561{
562
564 return false;
565
566
568 return false;
569
570 return true;
571}
572
573
574
575
576
577
578
579
580
583{
585
587 return NULL;
588
592 return sxact;
593}
594
595static void
597{
599
602}
603
604
605
606
607
608
609static bool
611{
613
614 Assert(reader != writer);
615
616
621 return false;
622
623
624
625
626
627
628
630 {
633
634 if (conflict->sxactIn == writer)
635 return true;
636 }
637
638
639 return false;
640}
641
642static void
644{
646
647 Assert(reader != writer);
649
652 (errcode(ERRCODE_OUT_OF_MEMORY),
653 errmsg("not enough elements in RWConflictPool to record a read/write conflict"),
654 errhint("You might need to run fewer transactions at a time or increase \"max_connections\".")));
655
658
660 conflict->sxactIn = writer;
663}
664
665static void
668{
670
671 Assert(roXact != activeXact);
674
677 (errcode(ERRCODE_OUT_OF_MEMORY),
678 errmsg("not enough elements in RWConflictPool to record a potential read/write conflict"),
679 errhint("You might need to run fewer transactions at a time or increase \"max_connections\".")));
680
683
684 conflict->sxactOut = activeXact;
685 conflict->sxactIn = roXact;
688}
689
690static void
692{
696}
697
698static void
700{
702
705
707
708
709
710
711
713 {
716
719
721 }
722}
723
724
725
726
727
728
729
730static bool
732{
735
740
743}
744
745#ifdef USE_ASSERT_CHECKING
746static void
747SerialPagePrecedesLogicallyUnitTests(void)
748{
750 offset = per_page / 2;
751 int64 newestPage,
752 oldestPage,
754 targetPage;
756 oldestXact;
757
758
760 newestXact = newestPage * per_page + offset;
761 Assert(newestXact / per_page == newestPage);
762 oldestXact = newestXact + 1;
763 oldestXact -= 1U << 31;
764 oldestPage = oldestXact / per_page;
765
766
767
768
769
770
771
772
773
774
776 targetPage = oldestPage;
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
794 targetPage = newestPage;
796#if 0
798#endif
799}
800#endif
801
802
803
804
805static void
807{
808 bool found;
809
810
811
812
816 LWTRANCHE_SERIAL_BUFFER, LWTRANCHE_SERIAL_SLRU,
818#ifdef USE_ASSERT_CHECKING
819 SerialPagePrecedesLogicallyUnitTests();
820#endif
822
823
824
825
828
830 if (!found)
831 {
832
833
834
840 }
841}
842
843
844
845
846bool
848{
850}
851
852
853
854
855
856
857static void
859{
861 int64 targetPage;
862 int slotno;
863 int64 firstZeroPage;
864 bool isNewPage;
866
868
871
872
873
874
875
876
878
879
880
881
882
883
884
887 {
889 return;
890 }
891
892
893
894
895
896
897
899 {
901 isNewPage = true;
902 }
903 else
904 {
907 targetPage);
908 }
909
913 if (isNewPage)
915
916 if (isNewPage)
917 {
918
919 for (;;)
920 {
924 if (firstZeroPage == targetPage)
925 break;
928 }
929 }
930 else
931 {
934 }
935
936 SerialValue(slotno, xid) = minConflictCommitSeqNo;
937 SerialSlruCtl->shared->page_dirty[slotno] = true;
938
941}
942
943
944
945
946
947
950{
954 int slotno;
955
957
962
964 return 0;
965
967
970 return 0;
971
972
973
974
975
980 return val;
981}
982
983
984
985
986
987
988
989static void
991{
993
994
995
996
997
998
999
1001 {
1005 return;
1006 }
1007
1008
1009
1010
1011
1012
1013
1015 {
1019 {
1021 }
1023 return;
1024 }
1025
1028
1030
1032}
1033
1034
1035
1036
1037
1038
1039
1040void
1042{
1043 int64 truncateCutoffPage;
1044
1046
1047
1049 {
1051 return;
1052 }
1053
1055 {
1057
1059
1060
1061
1062
1063
1064
1065
1066
1068 {
1069
1070 truncateCutoffPage = tailPage;
1071 }
1072 else
1074 }
1075 else
1076 {
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1108 }
1109
1111
1112
1113
1114
1115
1116
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1130}
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144void
1146{
1148 int64 max_table_size;
1149 Size requestSize;
1150 bool found;
1151
1152#ifndef EXEC_BACKEND
1154#endif
1155
1156
1157
1158
1159
1161
1162
1163
1164
1165
1169
1171 max_table_size,
1172 max_table_size,
1173 &info,
1176
1177
1178
1179
1180
1181
1182
1184 {
1188 }
1189
1190
1193
1194
1195
1196
1197
1202
1203
1204 max_table_size *= 2;
1205
1207 max_table_size,
1208 max_table_size,
1209 &info,
1212
1213
1214
1215
1216
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227 max_table_size *= 10;
1228
1232
1234 requestSize,
1235 &found);
1237 if (!found)
1238 {
1239 int i;
1240
1241
1242 memset(PredXact, 0, requestSize);
1243
1254
1255 for (i = 0; i < max_table_size; i++)
1256 {
1258 LWTRANCHE_PER_XACT_PREDICATE_LIST);
1260 }
1277 }
1278
1280
1281
1282
1283
1284
1287
1289 max_table_size,
1290 max_table_size,
1291 &info,
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306 max_table_size *= 5;
1307
1311
1313 requestSize,
1314 &found);
1316 if (!found)
1317 {
1318 int i;
1319
1320
1322
1326
1327 for (i = 0; i < max_table_size; i++)
1328 {
1331 }
1332 }
1333
1334
1335
1336
1337
1341 &found);
1343 if (!found)
1345
1346
1347
1348
1349
1351}
1352
1353
1354
1355
1358{
1359 Size size = 0;
1360 long max_table_size;
1361
1362
1366
1367
1368 max_table_size *= 2;
1371
1372
1373
1374
1375
1376 size = add_size(size, size / 10);
1377
1378
1380 max_table_size *= 10;
1384
1385
1388
1389
1390 max_table_size *= 5;
1394
1395
1397
1398
1401
1402 return size;
1403}
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1420{
1423
1425
1426
1428
1430}
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1446{
1448 int i;
1449 int els,
1450 el;
1453
1455
1456
1457
1458
1459
1463
1464
1466 data->nelements = els;
1469
1470
1471
1473
1474 el = 0;
1475
1477 {
1480 el++;
1481 }
1482
1484
1485
1489
1490 return data;
1491}
1492
1493
1494
1495
1496
1497
1498
1499
1500static void
1502{
1504
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1518 {
1520 return;
1521 }
1522
1523
1524
1525
1526
1530
1531
1535
1536
1538
1540}
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1557{
1559
1561
1562 while (true)
1563 {
1564
1565
1566
1567
1568
1569
1572
1574 return snapshot;
1575
1577
1578
1579
1580
1581
1585 {
1589 }
1591
1593 {
1595 break;
1596 }
1597
1599
1600
1603 errmsg_internal("deferrable snapshot was unsafe; trying a new one")));
1605 }
1606
1607
1608
1609
1612
1613 return snapshot;
1614}
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625int
1627{
1628 int num_written = 0;
1631
1633
1634
1636 {
1639
1640 if (sxact->pid == blocked_pid)
1641 {
1642 blocking_sxact = sxact;
1643 break;
1644 }
1645 }
1646
1647
1649 {
1650
1652 {
1655
1657
1658 if (num_written >= output_size)
1659 break;
1660 }
1661 }
1662
1664
1665 return num_written;
1666}
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1681{
1683
1684
1685
1686
1687
1688
1689
1692 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1693 errmsg("cannot use serializable mode in a hot standby"),
1694 errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1695 errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1696
1697
1698
1699
1700
1701
1704
1707}
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719void
1722 int sourcepid)
1723{
1725
1726
1727
1728
1729
1730
1731
1732
1733
1735 return;
1736
1737
1738
1739
1740
1741
1742
1745 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1746 errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1747
1749 sourcepid);
1750}
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1764 int sourcepid)
1765{
1769 *othersxact;
1770
1771
1773
1775
1776
1777
1778
1779
1780
1782 elog(ERROR, "cannot establish serializable snapshot during a parallel operation");
1783
1785 Assert(proc != NULL);
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800#ifdef TEST_SUMMARIZE_SERIAL
1802#endif
1804 do
1805 {
1807
1808 if (!sxact)
1809 {
1813 }
1814 } while (!sxact);
1815
1816
1817 if (!sourcevxid)
1820 {
1824 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1825 errmsg("could not import the requested snapshot"),
1826 errdetail("The source process with PID %d is not running anymore.",
1827 sourcepid)));
1828 }
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1843 {
1846 return snapshot;
1847 }
1848
1849
1850 sxact->vxid = vxid;
1859 sxact->xmin = snapshot->xmin;
1864 sxact->flags = 0;
1866 {
1868
1870
1871
1872
1873
1874
1875
1876
1878 {
1880
1884 {
1886 }
1887 }
1888
1889
1890
1891
1892
1893
1894
1896 {
1899 return snapshot;
1900 }
1901 }
1902 else
1903 {
1907 }
1908
1909
1911 {
1916 }
1918 {
1921 }
1922 else
1923 {
1925 }
1926
1928 MyXactDidWrite = false;
1929
1931
1933
1934 return snapshot;
1935}
1936
1937static void
1939{
1941
1942
1948 &hash_ctl,
1950}
1951
1952
1953
1954
1955
1956void
1958{
1961 bool found;
1962
1963
1964
1965
1966
1968 return;
1969
1970
1972
1974
1975
1977
1979
1980 sxidtag.xid = xid;
1982 &sxidtag,
1985
1986
1989}
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005bool
2007{
2009 uint32 targettaghash;
2010 LWLock *partitionLock;
2012
2015 relation->rd_id,
2016 blkno);
2017
2023 &targettag, targettaghash,
2026
2027 return (target != NULL);
2028}
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042static bool
2044{
2046
2047
2049 targettag,
2051
2052 if (!lock)
2053 return false;
2054
2055
2056
2057
2058
2059 return lock->held;
2060}
2061
2062
2063
2064
2065
2066
2067
2068
2069static bool
2072{
2074 {
2076
2077 return false;
2078
2080
2084
2085 return true;
2086
2088
2093 return true;
2094 }
2095
2096
2098 return false;
2099}
2100
2101
2102
2103
2104
2105
2106
2107
2108static bool
2110{
2112 parenttag;
2113
2114 targettag = *newtargettag;
2115
2116
2118 {
2119 targettag = parenttag;
2121 return true;
2122 }
2123
2124
2125 return false;
2126}
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137static void
2139{
2140 bool found;
2141
2143
2144 if (!lockheld)
2151 if (!lockheld)
2153}
2154
2155
2156
2157
2158static void
2160{
2161 bool found;
2162
2164
2165 if (!lockheld)
2172 if (!lockheld)
2174}
2175
2176
2177
2178
2179
2180static void
2182{
2184
2186
2187
2189 return;
2190
2191
2193 &target->tag,
2194 targettaghash,
2196 Assert(rmtarget == target);
2197}
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211static void
2213{
2217
2222
2224 {
2228
2230
2231 oldlocktag = predlock->tag;
2233 oldtarget = oldlocktag.myTarget;
2234 oldtargettag = oldtarget->tag;
2235
2237 {
2238 uint32 oldtargettaghash;
2239 LWLock *partitionLock;
2241
2244
2246
2251 &oldlocktag,
2253 oldtargettaghash),
2255 Assert(rmpredlock == predlock);
2256
2258
2260
2262 }
2263 }
2267}
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286static int
2288{
2290 {
2296
2299
2301
2302
2303
2304
2305
2307 return 0;
2308 }
2309
2310
2312 return 0;
2313}
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323static bool
2325{
2327 nexttag,
2328 promotiontag;
2330 bool found,
2331 promote;
2332
2333 promote = false;
2334
2335 targettag = *reqtag;
2336
2337
2339 {
2340 targettag = nexttag;
2342 &targettag,
2344 &found);
2345 if (!found)
2346 {
2347 parentlock->held = false;
2349 }
2350 else
2352
2355 {
2356
2357
2358
2359
2360
2361
2362 promotiontag = targettag;
2363 promote = true;
2364 }
2365 }
2366
2367 if (promote)
2368 {
2369
2371 return true;
2372 }
2373 else
2374 return false;
2375}
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388static void
2390{
2392 nexttag;
2393
2394 parenttag = *targettag;
2395
2397 {
2398 uint32 targettaghash;
2401
2402 parenttag = nexttag;
2406 &parenttag, targettaghash,
2408
2409
2410
2411
2412
2413
2414 if (parentlock == NULL)
2415 continue;
2416
2418
2419
2420
2421
2422
2423
2425 {
2428 }
2429
2430 if ((parentlock->childLocks == 0) && (!parentlock->held))
2431 {
2434 &parenttag, targettaghash,
2436 Assert(rmlock == parentlock);
2437 }
2438 }
2439}
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450static void
2452 uint32 targettaghash,
2454{
2458 LWLock *partitionLock;
2459 bool found;
2460
2462
2467
2468
2471 targettag, targettaghash,
2473 if (!target)
2475 (errcode(ERRCODE_OUT_OF_MEMORY),
2476 errmsg("out of shared memory"),
2477 errhint("You might need to increase \"%s\".", "max_pred_locks_per_transaction")));
2478 if (!found)
2480
2481
2483 locktag.myXact = sxact;
2488 if (!lock)
2490 (errcode(ERRCODE_OUT_OF_MEMORY),
2491 errmsg("out of shared memory"),
2492 errhint("You might need to increase \"%s\".", "max_pred_locks_per_transaction")));
2493
2494 if (!found)
2495 {
2499 }
2500
2505}
2506
2507
2508
2509
2510
2511
2512
2513
2514static void
2516{
2517 uint32 targettaghash;
2518 bool found;
2520
2521
2523 return;
2524
2526 return;
2527
2528
2530
2531
2534 targettag, targettaghash,
2536 locallock->held = true;
2537 if (!found)
2539
2540
2542
2543
2544
2545
2546
2547
2549 {
2550
2551
2552
2553
2554
2555 }
2556 else
2557 {
2558
2561 }
2562}
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573void
2575{
2577
2579 return;
2580
2583 relation->rd_id);
2585}
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596void
2598{
2600
2602 return;
2603
2606 relation->rd_id,
2607 blkno);
2609}
2610
2611
2612
2613
2614
2615
2616
2617
2618void
2621{
2623
2625 return;
2626
2627
2628
2629
2630 if (relation->rd_index == NULL)
2631 {
2632
2634 return;
2635 }
2636
2637
2638
2639
2640
2641
2642
2645 relation->rd_id);
2647 return;
2648
2651 relation->rd_id,
2655}
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666static void
2668{
2670
2674
2676
2678 {
2681 bool found;
2682
2685
2688 &predlock->tag,
2690 targettaghash),
2693 }
2695
2696
2698}
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727static bool
2730 bool removeOld)
2731{
2732 uint32 oldtargettaghash;
2733 LWLock *oldpartitionLock;
2735 uint32 newtargettaghash;
2736 LWLock *newpartitionLock;
2737 bool found;
2738 bool outOfShmem = false;
2739
2742
2747
2748 if (removeOld)
2749 {
2750
2751
2752
2753
2755 }
2756
2757
2758
2759
2760
2761
2762 if (oldpartitionLock < newpartitionLock)
2763 {
2767 }
2768 else if (oldpartitionLock > newpartitionLock)
2769 {
2773 }
2774 else
2776
2777
2778
2779
2780
2781
2782
2784 &oldtargettag,
2785 oldtargettaghash,
2787
2788 if (oldtarget)
2789 {
2793
2795 &newtargettag,
2796 newtargettaghash,
2798
2799 if (!newtarget)
2800 {
2801
2802 outOfShmem = true;
2803 goto exit;
2804 }
2805
2806
2807 if (!found)
2809
2810 newpredlocktag.myTarget = newtarget;
2811
2812
2813
2814
2815
2817
2819 {
2824
2826
2827 if (removeOld)
2828 {
2831
2834 &oldpredlock->tag,
2836 oldtargettaghash),
2839 }
2840
2843 &newpredlocktag,
2845 newtargettaghash),
2847 &found);
2848 if (!newpredlock)
2849 {
2850
2853 outOfShmem = true;
2854 goto exit;
2855 }
2856 if (!found)
2857 {
2862 newpredlock->commitSeqNo = oldCommitSeqNo;
2863 }
2864 else
2865 {
2866 if (newpredlock->commitSeqNo < oldCommitSeqNo)
2867 newpredlock->commitSeqNo = oldCommitSeqNo;
2868 }
2869
2873 }
2875
2876 if (removeOld)
2877 {
2880 }
2881 }
2882
2883
2884exit:
2885
2886 if (oldpartitionLock < newpartitionLock)
2887 {
2890 }
2891 else if (oldpartitionLock > newpartitionLock)
2892 {
2895 }
2896 else
2898
2899 if (removeOld)
2900 {
2901
2902 Assert(!outOfShmem);
2903
2904
2906 }
2907
2908 return !outOfShmem;
2909}
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934static void
2936{
2940 Oid dbId;
2941 Oid relId;
2942 Oid heapId;
2943 int i;
2944 bool isIndex;
2945 bool found;
2946 uint32 heaptargettaghash;
2947
2948
2949
2950
2951
2952
2953
2955 return;
2956
2958 return;
2959
2961 relId = relation->rd_id;
2962 if (relation->rd_index == NULL)
2963 {
2964 isIndex = false;
2965 heapId = relId;
2966 }
2967 else
2968 {
2969 isIndex = true;
2970 heapId = relation->rd_index->indrelid;
2971 }
2973 Assert(transfer || !isIndex);
2974
2975
2976
2977 heaptargettaghash = 0;
2978 heaptarget = NULL;
2979
2980
2985
2986
2987
2988
2989
2990 if (transfer)
2992
2993
2995
2997 {
2999
3000
3001
3002
3004 continue;
3006 continue;
3007 if (transfer && !isIndex
3009 continue;
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022 if (transfer && heaptarget == NULL)
3023 {
3025
3029 &heaptargettag,
3030 heaptargettaghash,
3032 if (!found)
3034 }
3035
3036
3037
3038
3039
3041 {
3047
3048
3049
3050
3051
3052 oldCommitSeqNo = oldpredlock->commitSeqNo;
3053 oldXact = oldpredlock->tag.myXact;
3054
3056
3057
3058
3059
3060
3062 &oldpredlock->tag,
3065
3066 if (transfer)
3067 {
3069
3070 newpredlocktag.myTarget = heaptarget;
3071 newpredlocktag.myXact = oldXact;
3074 &newpredlocktag,
3076 heaptargettaghash),
3078 &found);
3079 if (!found)
3080 {
3085 newpredlock->commitSeqNo = oldCommitSeqNo;
3086 }
3087 else
3088 {
3089 if (newpredlock->commitSeqNo < oldCommitSeqNo)
3090 newpredlock->commitSeqNo = oldCommitSeqNo;
3091 }
3092
3096 }
3097 }
3098
3100 &found);
3102 }
3103
3104
3105 if (transfer)
3107
3108
3113}
3114
3115
3116
3117
3118
3119
3120void
3122{
3124}
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141void
3144{
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3160 return;
3161
3163 return;
3164
3165 Assert(oldblkno != newblkno);
3168
3171 relation->rd_id,
3172 oldblkno);
3175 relation->rd_id,
3176 newblkno);
3177
3179
3180
3181
3182
3183
3185 newtargettag,
3186 false);
3187
3189 {
3190
3191
3192
3193
3194
3195
3197 &newtargettag);
3199
3200
3201
3202
3203
3204
3205
3206
3207
3209 newtargettag,
3210 true);
3212 }
3213
3215}
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226void
3229{
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3242}
3243
3244
3245
3246
3247
3248static void
3250{
3252
3254
3257
3259 {
3262
3266 {
3271 {
3274 }
3278 }
3279 }
3280
3282}
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309void
3311{
3312 bool partiallyReleasing = false;
3313 bool needToClear;
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326 bool topLevelIsDeclaredReadOnly;
3327
3328
3329 Assert(!(isCommit && isReadOnlySafe));
3330
3331
3332 if (!isReadOnlySafe)
3333 {
3334
3335
3336
3337
3338
3340 {
3342 return;
3343 }
3344
3345
3346
3347
3348
3350
3351
3352
3353
3354
3355
3356
3358 {
3363 }
3364 }
3365
3367 {
3369 return;
3370 }
3371
3373
3374
3375
3376
3377
3379 isCommit = false;
3380
3381
3382
3383
3384
3385
3386
3388 {
3389
3390
3391
3392
3395
3396
3397
3398
3399
3400
3401
3403 {
3406 return;
3407 }
3408 else
3409 {
3411 partiallyReleasing = true;
3412
3413 }
3414 }
3420
3421
3423
3424
3426
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3441
3442
3443
3444
3445
3446 if (isCommit)
3447 {
3450
3453 }
3454 else
3455 {
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3470
3471
3472
3473
3474
3475
3476
3478 }
3479
3480 if (!topLevelIsDeclaredReadOnly)
3481 {
3484 {
3485
3486
3487
3488
3489
3490
3491
3492
3493
3495 }
3496 }
3497 else
3498 {
3499
3500
3501
3502
3503
3505 {
3508
3511
3513 }
3514 }
3515
3516
3517 if (isCommit
3520 {
3521
3522
3523
3524
3528 }
3529
3530
3531
3532
3533
3534
3536 {
3539
3540 if (isCommit
3543 {
3548 }
3549
3550 if (!isCommit
3554 }
3555
3556
3557
3558
3559
3561 {
3564
3565 if (!isCommit
3569 }
3570
3571 if (!topLevelIsDeclaredReadOnly)
3572 {
3573
3574
3575
3576
3577
3578
3580 {
3583
3584 roXact = possibleUnsafeConflict->sxactIn;
3587
3588
3589 if (isCommit
3594 {
3595
3596
3597
3598
3600 }
3601 else
3602 {
3604
3605
3606
3607
3608
3609
3612 }
3613
3614
3615
3616
3617
3621 }
3622 }
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634 needToClear = false;
3635 if ((partiallyReleasing ||
3639 {
3642 {
3644 needToClear = true;
3645 }
3646 }
3647
3649
3651
3652
3653 if (isCommit)
3656
3657
3658
3659
3660
3661
3662
3663 if (!isCommit)
3666 false);
3667
3669
3670 if (needToClear)
3672
3674}
3675
3676static void
3678{
3681
3682
3684 {
3687 }
3688}
3689
3690
3691
3692
3693
3694static void
3696{
3698
3699
3700
3701
3702
3706 {
3709
3713 {
3714
3715
3716
3717
3722 }
3725 {
3726
3727
3728
3729
3730
3732
3734 {
3735
3738 }
3739 else
3740 {
3741
3742
3743
3744
3745
3747 }
3748
3751 }
3752 else
3753 {
3754
3755 break;
3756 }
3757 }
3759
3760
3761
3762
3765 {
3768 bool canDoPartialCleanup;
3769
3775
3776
3777
3778
3779
3780 if (canDoPartialCleanup)
3781 {
3785 uint32 targettaghash;
3786 LWLock *partitionLock;
3787
3788 tag = predlock->tag;
3790 targettag = target->tag;
3793
3795
3798
3801 targettaghash),
3804
3806 }
3807 }
3808
3811}
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832static void
3834 bool summarize)
3835{
3838
3839 Assert(sxact != NULL);
3843
3844
3845
3846
3847
3852 {
3858 uint32 targettaghash;
3859 LWLock *partitionLock;
3860
3861 tag = predlock->tag;
3863 targettag = target->tag;
3866
3868
3870
3873 targettaghash),
3875 if (summarize)
3876 {
3877 bool found;
3878
3879
3883 targettaghash),
3885 if (!predlock)
3887 (errcode(ERRCODE_OUT_OF_MEMORY),
3888 errmsg("out of shared memory"),
3889 errhint("You might need to increase \"%s\".", "max_pred_locks_per_transaction")));
3890 if (found)
3891 {
3896 }
3897 else
3898 {
3904 }
3905 }
3906 else
3908
3910 }
3911
3912
3913
3914
3915
3917
3921
3924
3925
3926 if (!partial)
3927 {
3929 {
3932
3933 if (summarize)
3936 }
3937 }
3938
3939
3941 {
3944
3945 if (summarize)
3948 }
3949
3950
3951 if (!partial)
3952 {
3956 }
3957
3959}
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969static bool
3971{
3973
3976
3978
3980 return false;
3981
3983 return true;
3984
3986}
3987
3988bool
3990{
3992 return false;
3993
3994
3996 {
3999 errmsg("could not serialize access due to read/write dependencies among transactions"),
4000 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4001 errhint("The transaction might succeed if retried.")));
4002 }
4003
4004 return true;
4005}
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020void
4022{
4026
4028 return;
4029
4030
4032 {
4035 errmsg("could not serialize access due to read/write dependencies among transactions"),
4036 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
4037 errhint("The transaction might succeed if retried.")));
4038 }
4040
4042 return;
4043
4044
4045
4046
4047 sxidtag.xid = xid;
4051 if (!sxid)
4052 {
4053
4054
4055
4056
4058
4060 if (conflictCommitSeqNo != 0)
4061 {
4064 || conflictCommitSeqNo
4068 errmsg("could not serialize access due to read/write dependencies among transactions"),
4069 errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4070 errhint("The transaction might succeed if retried.")));
4071
4076 errmsg("could not serialize access due to read/write dependencies among transactions"),
4077 errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4078 errhint("The transaction might succeed if retried.")));
4079
4081 }
4082
4083
4085 return;
4086 }
4087 sxact = sxid->myXact;
4090 {
4091
4093 return;
4094 }
4095
4096
4097
4098
4099
4100
4101
4103 {
4105 {
4108 return;
4109 }
4110 else
4111 {
4115 errmsg("could not serialize access due to read/write dependencies among transactions"),
4116 errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4117 errhint("The transaction might succeed if retried.")));
4118 }
4119 }
4120
4121
4122
4123
4124
4125
4131 {
4132
4134 return;
4135 }
4136
4138 {
4139
4141 return;
4142 }
4143
4145 {
4146
4148 return;
4149 }
4150
4151
4152
4153
4154
4157}
4158
4159
4160
4161
4162
4163static void
4165{
4166 uint32 targettaghash;
4167 LWLock *partitionLock;
4172
4174
4175
4176
4177
4183 targettag, targettaghash,
4185 if (!target)
4186 {
4187
4189 return;
4190 }
4191
4192
4193
4194
4195
4197
4199 {
4203
4205 {
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4218 {
4219 mypredlock = predlock;
4220 mypredlocktag = predlock->tag;
4221 }
4222 }
4228 {
4231
4232
4233
4234
4235
4241 {
4243 }
4244
4247 }
4248 }
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260 if (mypredlock != NULL)
4261 {
4262 uint32 predlockhashcode;
4264
4270
4271
4272
4273
4274
4275
4277 (&mypredlocktag, targettaghash);
4280 &mypredlocktag,
4281 predlockhashcode,
4283 if (rmpredlock != NULL)
4284 {
4285 Assert(rmpredlock == mypredlock);
4286
4289
4292 &mypredlocktag,
4293 predlockhashcode,
4295 Assert(rmpredlock == mypredlock);
4296
4298 }
4299
4305
4306 if (rmpredlock != NULL)
4307 {
4308
4309
4310
4311
4312
4314 targettag, targettaghash,
4316
4318 }
4319 }
4320}
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333void
4335{
4337
4339 return;
4340
4341
4345 errmsg("could not serialize access due to read/write dependencies among transactions"),
4346 errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4347 errhint("The transaction might succeed if retried.")));
4348
4349
4350
4351
4352
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364 if (tid != NULL)
4365 {
4368 relation->rd_id,
4372 }
4373
4375 {
4378 relation->rd_id,
4379 blkno);
4381 }
4382
4385 relation->rd_id);
4387}
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416void
4418{
4421 Oid dbId;
4422 Oid heapId;
4423 int i;
4424
4425
4426
4427
4428
4429
4430
4432 return;
4433
4435 return;
4436
4437
4438
4439
4440
4442
4443 Assert(relation->rd_index == NULL);
4444
4446 heapId = relation->rd_id;
4447
4452
4453
4455
4457 {
4459
4460
4461
4462
4464 continue;
4466 continue;
4467
4468
4469
4470
4472 {
4475
4478 {
4480 }
4481 }
4482 }
4483
4484
4489}
4490
4491
4492
4493
4494
4495
4496
4497
4498static void
4500{
4501 Assert(reader != writer);
4502
4503
4505
4506
4511 else
4513}
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533static void
4536{
4537 bool failure;
4538
4540
4541 failure = false;
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4556 failure = true;
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4578 failure = true;
4579 else if (!failure)
4580 {
4582
4584 {
4588
4596 {
4597 failure = true;
4598 break;
4599 }
4600 }
4601 }
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4617 {
4619 {
4620 failure = true;
4621 }
4622 else
4623 {
4625
4626
4627
4628
4629
4631 {
4635
4641 {
4642 failure = true;
4643 break;
4644 }
4645 }
4646 }
4647 }
4648
4649 if (failure)
4650 {
4651
4652
4653
4654
4655
4656
4657
4658
4660 {
4664 errmsg("could not serialize access due to read/write dependencies among transactions"),
4665 errdetail_internal("Reason code: Canceled on identification as a pivot, during write."),
4666 errhint("The transaction might succeed if retried.")));
4667 }
4669 {
4671
4672
4676 errmsg("could not serialize access due to read/write dependencies among transactions"),
4677 errdetail_internal("Reason code: Canceled on conflict out to pivot %u, during read.", writer->topXid),
4678 errhint("The transaction might succeed if retried.")));
4679 }
4681 }
4682}
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700void
4702{
4704
4706 return;
4707
4709
4711
4712
4713
4714
4715
4716
4719 {
4723 errmsg("could not serialize access due to read/write dependencies among transactions"),
4724 errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4725 errhint("The transaction might succeed if retried.")));
4726 }
4727
4729 {
4732
4735 {
4737
4739 {
4742
4747 {
4748
4749
4750
4751
4752
4753
4755 {
4759 errmsg("could not serialize access due to read/write dependencies among transactions"),
4760 errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4761 errhint("The transaction might succeed if retried.")));
4762 }
4764 break;
4765 }
4766 }
4767 }
4768 }
4769
4772
4774}
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787void
4789{
4795
4799
4801 return;
4802
4803
4807
4808
4809
4810
4811
4812
4813
4814
4816 &record, sizeof(record));
4817
4818
4819
4820
4821
4822
4823
4824
4826
4827
4828
4829
4830
4831
4833
4835 {
4838
4841
4843 &record, sizeof(record));
4844 }
4845
4847}
4848
4849
4850
4851
4852
4853
4854
4855
4856void
4858{
4860 return;
4861
4863
4866
4869
4872}
4873
4874
4875
4876
4877
4878
4879void
4881{
4884
4886
4891
4892
4893 if (sxid == NULL)
4894 return;
4895
4896
4898 MyXactDidWrite = true;
4899
4901}
4902
4903
4904
4905
4906void
4909{
4912
4914
4916
4919
4921 {
4922
4927 bool found;
4928
4930
4933 if (!sxact)
4935 (errcode(ERRCODE_OUT_OF_MEMORY),
4936 errmsg("out of shared memory")));
4937
4938
4941 sxact->pid = 0;
4943
4944
4948
4950
4951
4952
4953
4954
4955
4957
4960
4961 sxact->topXid = xid;
4962 sxact->xmin = xactRecord->xmin;
4966 {
4970 }
4971
4972
4973
4974
4975
4976
4981
4982
4983 sxidtag.xid = xid;
4985 &sxidtag,
4987 Assert(sxid != NULL);
4989 sxid->myXact = sxact;
4990
4991
4992
4993
4994
4995
4996
4997
5000 {
5004 }
5006 {
5009 }
5010
5012 }
5014 {
5015
5020 uint32 targettaghash;
5021
5024
5026 sxidtag.xid = xid;
5030
5031 Assert(sxid != NULL);
5032 sxact = sxid->myXact;
5034
5036 }
5037}
5038
5039
5040
5041
5042
5043
5046{
5048}
5049
5050
5051
5052
5053void
5055{
5056
5058
5062}
bool ParallelContextActive(void)
#define InvalidBlockNumber
static bool BlockNumberIsValid(BlockNumber blockNumber)
#define unconstify(underlying_type, expr)
#define PG_USED_FOR_ASSERTS_ONLY
uint32 LocalTransactionId
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Size hash_estimate_size(int64 num_entries, Size entrysize)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
void hash_destroy(HTAB *hashp)
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
void * hash_seq_search(HASH_SEQ_STATUS *status)
int64 hash_get_num_entries(HTAB *hashp)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errmsg_internal(const char *fmt,...)
int errdetail_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define palloc_object(type)
#define palloc_array(type, count)
Assert(PointerIsAligned(start, uint64))
static dlist_node * dlist_pop_head_node(dlist_head *head)
#define dlist_foreach(iter, lhead)
static void dlist_init(dlist_head *head)
#define dlist_head_element(type, membername, lhead)
static void dlist_delete_thoroughly(dlist_node *node)
static void dlist_delete(dlist_node *node)
#define dlist_foreach_modify(iter, lhead)
static bool dlist_is_empty(const dlist_head *head)
static void dlist_push_tail(dlist_head *head, dlist_node *node)
static void dlist_node_init(dlist_node *node)
#define dlist_container(type, membername, ptr)
#define IsParallelWorker()
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
#define SetInvalidVirtualTransactionId(vxid)
bool LWLockHeldByMe(LWLock *lock)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
void LWLockInitialize(LWLock *lock, int tranche_id)
#define NUM_PREDICATELOCK_PARTITIONS
#define SLRU_PAGES_PER_SEGMENT
static bool pg_lfind32(uint32 key, const uint32 *base, uint32 nelem)
static rewind_source * source
#define ERRCODE_T_R_SERIALIZATION_FAILURE
PredicateLockData * GetPredicateLockStatusData(void)
void CheckPointPredicate(void)
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
static void DecrementParentLocks(const PREDICATELOCKTARGETTAG *targettag)
static HTAB * PredicateLockHash
static void SetPossibleUnsafeConflict(SERIALIZABLEXACT *roXact, SERIALIZABLEXACT *activeXact)
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
static void SetNewSxactGlobalXmin(void)
void CheckForSerializableConflictIn(Relation relation, const ItemPointerData *tid, BlockNumber blkno)
static void ReleasePredXact(SERIALIZABLEXACT *sxact)
void SetSerializableTransactionSnapshot(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
static bool PredicateLockingNeededForRelation(Relation relation)
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
static Snapshot GetSafeSnapshot(Snapshot origSnapshot)
#define SxactIsCommitted(sxact)
static SerialControl serialControl
void PredicateLockPage(Relation relation, BlockNumber blkno, Snapshot snapshot)
#define SxactIsROUnsafe(sxact)
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
static LWLock * ScratchPartitionLock
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
#define SxactIsDeferrableWaiting(sxact)
static void ReleasePredicateLocksLocal(void)
static HTAB * LocalPredicateLockHash
int max_predicate_locks_per_page
struct SerialControlData * SerialControl
static PredXactList PredXact
static void SetRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
int GetSafeSnapshotBlockingPids(int blocked_pid, int *output, int output_size)
static uint32 ScratchTargetTagHash
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
static uint32 predicatelock_hash(const void *key, Size keysize)
void CheckForSerializableConflictOut(Relation relation, TransactionId xid, Snapshot snapshot)
#define SxactIsReadOnly(sxact)
#define SerialNextPage(page)
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
bool PageIsPredicateLocked(Relation relation, BlockNumber blkno)
static SlruCtlData SerialSlruCtlData
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
static void SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
static void ClearOldPredicateLocks(void)
#define SxactHasSummaryConflictIn(sxact)
static SERIALIZABLEXACT * CreatePredXact(void)
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
static void RestoreScratchTarget(bool lockheld)
#define SerialValue(slotno, xid)
static void DeleteChildTargetLocks(const PREDICATELOCKTARGETTAG *newtargettag)
static void DeleteLockTarget(PREDICATELOCKTARGET *target, uint32 targettaghash)
void PredicateLockTwoPhaseFinish(FullTransactionId fxid, bool isCommit)
void predicatelock_twophase_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
static SERIALIZABLEXACT * OldCommittedSxact
#define SxactHasConflictOut(sxact)
static bool MyXactDidWrite
static int MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag)
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
static void SerialInit(void)
void CheckTableForSerializableConflictIn(Relation relation)
#define SxactIsPrepared(sxact)
void AttachSerializableXact(SerializableXactHandle handle)
struct SerialControlData SerialControlData
SerializableXactHandle ShareSerializableXact(void)
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
static void RemoveScratchTarget(bool lockheld)
#define SxactIsOnFinishedList(sxact)
#define SxactIsPartiallyReleased(sxact)
static void SerialSetActiveSerXmin(TransactionId xid)
static dlist_head * FinishedSerializableTransactions
static bool SerializationNeededForWrite(Relation relation)
static HTAB * SerializableXidHash
static bool CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag)
void PredicateLockPageCombine(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
static bool SerialPagePrecedesLogically(int64 page1, int64 page2)
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
int max_predicate_locks_per_relation
#define SxactIsROSafe(sxact)
void PreCommit_CheckForSerializationFailure(void)
void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe)
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
static const PREDICATELOCKTARGETTAG ScratchTargetTag
#define PredicateLockHashPartitionLockByIndex(i)
static void OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
static bool CoarserLockCovers(const PREDICATELOCKTARGETTAG *newtargettag)
void PredicateLockRelation(Relation relation, Snapshot snapshot)
static SERIALIZABLEXACT * MySerializableXact
void PredicateLockShmemInit(void)
void PredicateLockTID(Relation relation, const ItemPointerData *tid, Snapshot snapshot, TransactionId tuple_xid)
Size PredicateLockShmemSize(void)
#define SxactIsDoomed(sxact)
#define NPREDICATELOCKTARGETENTS()
static SerCommitSeqNo SerialGetMinConflictCommitSeqNo(TransactionId xid)
static void SummarizeOldestCommittedSxact(void)
bool check_serial_buffers(int *newval, void **extra, GucSource source)
void PostPrepare_PredicateLocks(FullTransactionId fxid)
#define TargetTagIsCoveredBy(covered_target, covering_target)
static RWConflictPoolHeader RWConflictPool
static void ReleaseRWConflict(RWConflict conflict)
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
void AtPrepare_PredicateLocks(void)
void RegisterPredicateLockingXid(TransactionId xid)
#define PredicateLockHashPartitionLock(hashcode)
#define SERIAL_ENTRIESPERPAGE
static bool XidIsConcurrent(TransactionId xid)
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
static HTAB * PredicateLockTargetHash
bool CheckForSerializableConflictOutNeeded(Relation relation, Snapshot snapshot)
#define SxactIsRolledBack(sxact)
static SERIALIZABLEXACT * SavedSerializableXact
#define SxactHasSummaryConflictOut(sxact)
void TransferPredicateLocksToHeapRelation(Relation relation)
static void CreateLocalPredicateLockHash(void)
int max_predicate_locks_per_xact
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
void * SerializableXactHandle
#define RWConflictDataSize
#define SXACT_FLAG_DEFERRABLE_WAITING
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
@ TWOPHASEPREDICATERECORD_XACT
@ TWOPHASEPREDICATERECORD_LOCK
#define FirstNormalSerCommitSeqNo
#define InvalidSerCommitSeqNo
struct PREDICATELOCKTAG PREDICATELOCKTAG
#define SXACT_FLAG_CONFLICT_OUT
#define PredXactListDataSize
#define SXACT_FLAG_READ_ONLY
#define SXACT_FLAG_DOOMED
struct LOCALPREDICATELOCK LOCALPREDICATELOCK
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
#define RWConflictPoolHeaderDataSize
struct SERIALIZABLEXIDTAG SERIALIZABLEXIDTAG
#define InvalidSerializableXact
struct PREDICATELOCKTARGET PREDICATELOCKTARGET
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define RecoverySerCommitSeqNo
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
struct SERIALIZABLEXID SERIALIZABLEXID
struct RWConflictData * RWConflict
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
#define SXACT_FLAG_ROLLED_BACK
#define SXACT_FLAG_COMMITTED
#define SXACT_FLAG_RO_UNSAFE
#define SXACT_FLAG_PREPARED
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SXACT_FLAG_PARTIALLY_RELEASED
#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag)
#define SXACT_FLAG_RO_SAFE
struct PREDICATELOCK PREDICATELOCK
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag)
Snapshot GetSnapshotData(Snapshot snapshot)
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
#define INVALID_PROC_NUMBER
#define RelationUsesLocalBuffers(relation)
bool ShmemAddrIsValid(const void *addr)
Size add_size(Size s1, Size s2)
Size mul_size(Size s1, Size s2)
HTAB * ShmemInitHash(const char *name, int64 init_size, int64 max_size, HASHCTL *infoP, int hash_flags)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, const char *subdir, int buffer_tranche_id, int bank_tranche_id, SyncRequestHandler sync_handler, bool long_segment_names)
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno, TransactionId xid)
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, TransactionId xid)
int SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
Size SimpleLruShmemSize(int nslots, int nlsns)
bool check_slru_buffers(const char *name, int *newval)
static LWLock * SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
#define SlruPagePrecedesUnitTests(ctl, per_page)
Snapshot GetTransactionSnapshot(void)
#define IsMVCCSnapshot(snapshot)
void ProcSendSignal(ProcNumber procNumber)
void ProcWaitForSignal(uint32 wait_event_info)
SERIALIZABLEXACT * myXact
PREDICATELOCKTARGET * myTarget
PREDICATELOCKTARGETTAG tag
dlist_head predicateLocks
SerCommitSeqNo commitSeqNo
SERIALIZABLEXACT * element
SerCommitSeqNo LastSxactCommitSeqNo
SerCommitSeqNo CanPartialClearThrough
SERIALIZABLEXACT * OldCommittedSxact
SerCommitSeqNo HavePartialClearedThrough
TransactionId SxactGlobalXmin
SERIALIZABLEXACT * sxactIn
SERIALIZABLEXACT * sxactOut
RelFileLocator rd_locator
VirtualTransactionId vxid
LWLock perXactPredicateListLock
SerCommitSeqNo lastCommitBeforeSnapshot
dlist_head possibleUnsafeConflicts
union SERIALIZABLEXACT::@128 SeqNo
SerCommitSeqNo prepareSeqNo
dlist_head predicateLocks
SerCommitSeqNo commitSeqNo
TransactionId finishedBefore
SerCommitSeqNo earliestOutConflictCommit
SERIALIZABLEXACT * myXact
FullTransactionId nextXid
PREDICATELOCKTARGETTAG target
TwoPhasePredicateRecordType type
union TwoPhasePredicateRecord::@129 data
TwoPhasePredicateLockRecord lockRecord
TwoPhasePredicateXactRecord xactRecord
LocalTransactionId localTransactionId
static bool TransactionIdFollows(TransactionId id1, TransactionId id2)
#define FirstUnpinnedObjectId
#define InvalidTransactionId
static bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
static bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
#define TransactionIdEquals(id1, id2)
#define XidFromFullTransactionId(x)
#define FirstNormalTransactionId
#define TransactionIdIsValid(xid)
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
#define TWOPHASE_RM_PREDICATELOCK_ID
TransamVariablesData * TransamVariables
TransactionId GetTopTransactionIdIfAny(void)
bool IsSubTransaction(void)
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
bool IsInParallelMode(void)
#define IsolationIsSerializable()
bool RecoveryInProgress(void)