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)