PostgreSQL Source Code: src/backend/utils/activity/pgstat.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

103

105

116

117

118

119

120

121

122

123

124

125

126#define PGSTAT_MIN_INTERVAL 1000

127

128#define PGSTAT_MAX_INTERVAL 60000

129

130#define PGSTAT_IDLE_INTERVAL 10000

131

132

133

134

135

136

137#define PGSTAT_SNAPSHOT_HASH_SIZE 512

138

139

140

141

142

143#define PGSTAT_FILE_ENTRY_END 'E'

144#define PGSTAT_FILE_ENTRY_FIXED 'F'

145#define PGSTAT_FILE_ENTRY_NAME 'N'

146#define PGSTAT_FILE_ENTRY_HASH 'S'

147

148

149

153 char status;

154 void *data;

156

157

158

159

160

161

162

163

164#define SH_PREFIX pgstat_snapshot

165#define SH_ELEMENT_TYPE PgStat_SnapshotEntry

166#define SH_KEY_TYPE PgStat_HashKey

167#define SH_KEY key

168#define SH_HASH_KEY(tb, key) \

169 pgstat_hash_hash_key(&key, sizeof(PgStat_HashKey), NULL)

170#define SH_EQUAL(tb, a, b) \

171 pgstat_cmp_hash_key(&a, &b, sizeof(PgStat_HashKey), NULL) == 0

172#define SH_SCOPE static inline

173#define SH_DEFINE

174#define SH_DECLARE

176

177

178

179

180

181

182

185

187

189

191

195

197

198

199

200

201

202

206

207

208

209

210

211

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

231

232

233

234

235

236

239

240

241

242

243

246

247

248

249

252

253

254

255

256

257

258#ifdef USE_ASSERT_CHECKING

259static bool pgstat_is_initialized = false;

260static bool pgstat_is_shutdown = false;

261#endif

262

263

264

265

266

267

268

269

270

271

272

273

274

275

278

279

280

282 .name = "database",

283

284 .fixed_amount = false,

285 .write_to_file = true,

286

287 .accessed_across_databases = true,

288

293

296 },

297

299 .name = "relation",

300

301 .fixed_amount = false,

302 .write_to_file = true,

303

308

311 },

312

314 .name = "function",

315

316 .fixed_amount = false,

317 .write_to_file = true,

318

323

325 },

326

328 .name = "replslot",

329

330 .fixed_amount = false,

331 .write_to_file = true,

332

333 .accessed_across_databases = true,

334

338

342 },

343

345 .name = "subscription",

346

347 .fixed_amount = false,

348 .write_to_file = true,

349

350 .accessed_across_databases = true,

351

356

359 },

360

362 .name = "backend",

363

364 .fixed_amount = false,

365 .write_to_file = false,

366

367 .accessed_across_databases = true,

368

372

376 },

377

378

379

381 .name = "archiver",

382

383 .fixed_amount = true,

384 .write_to_file = true,

385

390

394 },

395

397 .name = "bgwriter",

398

399 .fixed_amount = true,

400 .write_to_file = true,

401

406

410 },

411

413 .name = "checkpointer",

414

415 .fixed_amount = true,

416 .write_to_file = true,

417

418 .snapshot_ctl_off = offsetof(PgStat_Snapshot, checkpointer),

422

426 },

427

429 .name = "io",

430

431 .fixed_amount = true,

432 .write_to_file = true,

433

437 .shared_data_len = sizeof(((PgStatShared_IO *) 0)->stats),

438

444 },

445

447 .name = "slru",

448

449 .fixed_amount = true,

450 .write_to_file = true,

451

456

462 },

463

465 .name = "wal",

466

467 .fixed_amount = true,

468 .write_to_file = true,

469

474

481 },

482};

483

484

485

486

487

488

489

490

493

494

495

496

497

498

499

500

501

502

503

506{

508}

509

510

511

512

513

514

515

518{

519 int ret;

520

521

522

524 if (ret != 0)

525 {

526 if (errno == ENOENT)

528 "didn't need to unlink permanent stats file \"%s\" - didn't exist",

530 else

533 errmsg("could not unlink permanent statistics file \"%s\": %m",

535 }

536 else

537 {

540 errmsg_internal("unlinked permanent statistics file \"%s\"",

542 }

543

544

545

546

547

549}

550

551

552

553

554

555

556

557

558

561{

564

565

566

567

568

569

570 Assert(pgstat_is_initialized && !pgstat_is_shutdown);

571

572

574

575

576

577

578

579

580 if (code == 0)

581 {

584 }

585}

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600static void

602{

603 Assert(!pgstat_is_shutdown);

605

606

607

608

609

610

611

614

616

617

620

621

624

626

627#ifdef USE_ASSERT_CHECKING

628 pgstat_is_shutdown = true;

629#endif

630}

631

632

633

634

635

636

637

640{

641 Assert(!pgstat_is_initialized);

642

644

646

647

649 {

651

652 if (kind_info == NULL || kind_info->init_backend_cb == NULL)

653 continue;

654

656 }

657

658

660

661#ifdef USE_ASSERT_CHECKING

662 pgstat_is_initialized = true;

663#endif

664}

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

693{

696 bool partial_flush;

698 bool nowait;

699

702

703

705 {

706 force = true;

708 }

709

710

712 {

713 bool do_flush = false;

714

715

717 {

719

720 if (!kind_info)

721 continue;

723 continue;

724

726 {

727 do_flush = true;

728 break;

729 }

730 }

731

732 if (!do_flush)

733 return 0;

734 }

735

736

737

738

739

740

741

743

744 if (force)

745 {

746

747

748

749

750

751

752

754 }

755 else

756 {

758

759 if (pending_since > 0 &&

761 {

762

763 force = true;

764 }

765 else if (last_flush > 0 &&

767 {

768

769 if (pending_since == 0)

770 pending_since = now;

771

773 }

774 }

775

777

778

779 nowait = !force;

780

781 partial_flush = false;

782

783

785

786

788 {

790

791 if (!kind_info)

792 continue;

794 continue;

795

797 }

798

799 last_flush = now;

800

801

802

803

804

805 if (partial_flush)

806 {

807

809

810

811 if (pending_since == 0)

812 pending_since = now;

813

815 }

816

817 pending_since = 0;

818

819 return 0;

820}

821

822

823

824

825

828{

830}

831

832

833

834

835static bool

837{

839}

840

841

842

843

844

845

846

849{

851

854 ts);

855}

856

857

858

859

860

861

862

863

864

865

868{

871

872

874

875

877

880}

881

882

883

884

885

886

887

890{

893

896 else

898}

899

900

901

902

903

904

905

906

907

908

909

910

911

912

913

916{

918

925

926

928 {

930

931

933 }

934

935

936

937

938

939

941

942

944}

945

948{

951 void *stats_data;

953

954

957

959

960

962

963 key.kind = kind;

964 key.dboid = dboid;

965 key.objid = objid;

966

967

970

971

973 {

975

977

978 if (entry)

979 return entry->data;

980

981

982

983

984

986 return NULL;

987 }

988

990

992

994 {

995

997 {

999 bool found;

1000

1003 entry->data = NULL;

1004 }

1005 return NULL;

1006 }

1007

1008

1009

1010

1011

1012

1015 else

1018

1020 memcpy(stats_data,

1024

1026 {

1028 bool found;

1029

1031 entry->data = stats_data;

1032 }

1033

1034 return stats_data;

1035}

1036

1037

1038

1039

1040

1041

1044{

1047

1049 {

1050 *have_snapshot = true;

1052 }

1053

1054 *have_snapshot = false;

1055

1056 return 0;

1057}

1058

1061{

1062

1064 return true;

1065

1067}

1068

1069

1070

1071

1072

1073

1074

1077{

1080

1083

1086 else

1088

1093}

1094

1097{

1098

1099

1100

1101

1103 {

1105

1107 continue;

1108

1111 }

1112}

1113

1116{

1119

1122 return;

1123

1126 "PgStat Snapshot",

1128

1132 NULL);

1133}

1134

1137{

1140

1141

1143

1144

1146 return;

1147

1149

1151

1153

1154

1155

1156

1159 {

1162 bool found;

1165

1166

1167

1168

1169

1170

1171

1172

1176 continue;

1177

1179 continue;

1180

1182

1185

1188

1191

1192

1193

1194

1195

1197 memcpy(entry->data,

1201 }

1203

1204

1205

1206

1208 {

1210

1211 if (!kind_info)

1212 continue;

1214 {

1216 continue;

1217 }

1218

1220 }

1221

1223}

1224

1227{

1229 int idx;

1230 bool *valid;

1231

1232

1234 {

1235 idx = kind;

1237 }

1238 else

1239 {

1242 }

1243

1246

1248 {

1249

1250 valid[idx] = false;

1251 }

1252 else if (valid[idx])

1253 {

1254

1256 return;

1257 }

1258

1260

1262

1264 valid[idx] = true;

1265}

1266

1267

1268

1269

1270

1271

1272

1273

1274

1275

1276

1277

1278

1279

1282{

1284

1285

1287

1289 {

1292 "PgStat Pending",

1294 }

1295

1297 true, created_entry);

1298

1299 if (entry_ref->pending == NULL)

1300 {

1302

1303 Assert(entrysize != (size_t) -1);

1304

1307 }

1308

1309 return entry_ref;

1310}

1311

1312

1313

1314

1315

1316

1317

1320{

1322

1324

1325 if (entry_ref == NULL || entry_ref->pending == NULL)

1326 return NULL;

1327

1328 return entry_ref;

1329}

1330

1333{

1336 void *pending_data = entry_ref->pending;

1337

1338 Assert(pending_data != NULL);

1339

1341

1344

1345 pfree(pending_data);

1346 entry_ref->pending = NULL;

1347

1349}

1350

1351

1352

1353

1356{

1357 bool have_pending = false;

1359

1360

1361

1362

1363

1364

1365

1366

1367

1368

1371

1372 while (cur)

1373 {

1379 bool did_flush;

1381

1384

1385

1387

1388 Assert(did_flush || nowait);

1389

1390

1393 else

1394 next = NULL;

1395

1396

1397 if (did_flush)

1399 else

1400 have_pending = true;

1401

1403 }

1404

1406

1407 return have_pending;

1408}

1409

1410

1411

1412

1413

1414

1415

1418{

1420 {

1422 return kind;

1423 }

1424

1425

1427 {

1429 {

1431

1434 return kind;

1435 }

1436 }

1437

1439 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

1440 errmsg("invalid statistics kind: \"%s\"", kind_str)));

1442}

1443

1444static inline bool

1446{

1448}

1449

1452{

1455

1457 {

1459

1462 return NULL;

1464 }

1465

1466 return NULL;

1467}

1468

1469

1470

1471

1472

1473

1474

1475

1476

1477

1480{

1482

1483 if (kind_info->name == NULL || strlen(kind_info->name) == 0)

1485 (errmsg("custom cumulative statistics name is invalid"),

1486 errhint("Provide a non-empty name for the custom cumulative statistics.")));

1487

1489 ereport(ERROR, (errmsg("custom cumulative statistics ID %u is out of range", kind),

1490 errhint("Provide a custom cumulative statistics ID between %u and %u.",

1492

1495 (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind),

1496 errdetail("Custom cumulative statistics must be registered while initializing modules in \"shared_preload_libraries\".")));

1497

1498

1499

1500

1502 {

1505 (errmsg("custom cumulative statistics property is invalid"),

1506 errhint("Custom cumulative statistics require a shared memory size for fixed-numbered objects.")));

1507 }

1508

1509

1510

1511

1513 {

1517 }

1518

1522 (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind),

1523 errdetail("Custom cumulative statistics \"%s\" already registered with the same ID.",

1525

1526

1528 {

1530

1532 continue;

1535 (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind),

1536 errdetail("Existing cumulative statistics with ID %u has the same name.", existing_kind)));

1537 }

1538

1539

1542 (errmsg("registered custom cumulative statistics \"%s\" with ID %u",

1543 kind_info->name, kind)));

1544}

1545

1546

1547

1548

1549

1550

1551#ifdef USE_ASSERT_CHECKING

1552void

1554{

1555 Assert(pgstat_is_initialized && !pgstat_is_shutdown);

1556}

1557#endif

1558

1559

1560

1561

1562

1563

1564

1565

1568{

1569 int rc;

1570

1571 rc = fwrite(ptr, len, 1, fpout);

1572

1573

1574 (void) rc;

1575}

1577#define write_chunk_s(fpout, ptr) write_chunk(fpout, ptr, sizeof(*ptr))

1578

1579

1580

1581

1582

1585{

1586 FILE *fpout;

1587 int32 format_id;

1592

1594

1595

1597

1598

1600

1601 elog(DEBUG2, "writing stats file \"%s\"", statfile);

1602

1603

1604

1605

1607 if (fpout == NULL)

1608 {

1611 errmsg("could not open temporary statistics file \"%s\": %m",

1612 tmpfile)));

1613 return;

1614 }

1615

1616

1617

1618

1621

1622

1624 {

1625 char *ptr;

1627

1629 continue;

1630

1633

1634

1636 continue;

1637

1641 else

1643

1647 }

1648

1649

1650

1651

1654 {

1657

1659

1660

1661

1662

1663

1664

1665

1666

1667

1668

1670 if (ps->dropped)

1671 continue;

1672

1673

1674

1675

1676

1678 {

1679 elog(WARNING, "found unknown stats entry %u/%u/%" PRIu64,

1680 ps->key.kind, ps->key.dboid,

1681 ps->key.objid);

1682 continue;

1683 }

1684

1686

1688

1689

1691

1692

1694 continue;

1695

1697 {

1698

1701 }

1702 else

1703 {

1704

1706

1708

1712 }

1713

1714

1718 }

1720

1721

1722

1723

1724

1725

1727

1728 if (ferror(fpout))

1729 {

1732 errmsg("could not write temporary statistics file \"%s\": %m",

1733 tmpfile)));

1735 unlink(tmpfile);

1736 }

1737 else if (FreeFile(fpout) < 0)

1738 {

1741 errmsg("could not close temporary statistics file \"%s\": %m",

1742 tmpfile)));

1743 unlink(tmpfile);

1744 }

1746 {

1747

1748 unlink(tmpfile);

1749 }

1750}

1751

1752

1755{

1756 return fread(ptr, 1, len, fpin) == len;

1757}

1759#define read_chunk_s(fpin, ptr) read_chunk(fpin, ptr, sizeof(*ptr))

1760

1761

1762

1763

1764

1765

1766

1769{

1770 FILE *fpin;

1771 int32 format_id;

1772 bool found;

1775

1776

1778

1779 elog(DEBUG2, "reading stats file \"%s\"", statfile);

1780

1781

1782

1783

1784

1785

1786

1787

1788

1789

1791 {

1792 if (errno != ENOENT)

1795 errmsg("could not open statistics file \"%s\": %m",

1796 statfile)));

1798 return;

1799 }

1800

1801

1802

1803

1805 {

1806 elog(WARNING, "could not read format ID");

1808 }

1809

1811 {

1812 elog(WARNING, "found incorrect format ID %d (expected %d)",

1815 }

1816

1817

1818

1819

1820

1821 for (;;)

1822 {

1823 int t = fgetc(fpin);

1824

1825 switch (t)

1826 {

1828 {

1831 char *ptr;

1832

1833

1835 {

1836 elog(WARNING, "could not read stats kind for entry of type %c", t);

1838 }

1839

1841 {

1842 elog(WARNING, "invalid stats kind %u for entry of type %c",

1843 kind, t);

1845 }

1846

1848 if (!info)

1849 {

1850 elog(WARNING, "could not find information of kind %u for entry of type %c",

1851 kind, t);

1853 }

1854

1856 {

1857 elog(WARNING, "invalid fixed_amount in stats kind %u for entry of type %c",

1858 kind, t);

1860 }

1861

1862

1866 else

1867 {

1869

1872 }

1873

1875 {

1876 elog(WARNING, "could not read data of stats kind %u for entry of type %c with size %u",

1879 }

1880

1881 break;

1882 }

1885 {

1889

1891

1893 {

1894

1896 {

1897 elog(WARNING, "could not read key for entry of type %c", t);

1899 }

1900

1902 {

1903 elog(WARNING, "invalid stats kind for entry %u/%u/%" PRIu64 " of type %c",

1904 key.kind, key.dboid,

1905 key.objid, t);

1907 }

1908

1910 {

1911 elog(WARNING, "could not find information of kind for entry %u/%u/%" PRIu64 " of type %c",

1912 key.kind, key.dboid,

1913 key.objid, t);

1915 }

1916 }

1917 else

1918 {

1919

1923

1925 {

1926 elog(WARNING, "could not read stats kind for entry of type %c", t);

1928 }

1930 {

1931 elog(WARNING, "could not read name of stats kind %u for entry of type %c",

1932 kind, t);

1934 }

1936 {

1937 elog(WARNING, "invalid stats kind %u for entry of type %c",

1938 kind, t);

1940 }

1941

1943 if (!kind_info)

1944 {

1945 elog(WARNING, "could not find information of kind %u for entry of type %c",

1946 kind, t);

1948 }

1949

1951 {

1952 elog(WARNING, "invalid from_serialized_name in stats kind %u for entry of type %c",

1953 kind, t);

1955 }

1956

1958 {

1959

1961 {

1962 elog(WARNING, "could not seek \"%s\" of stats kind %u for entry of type %c",

1965 }

1966

1967 continue;

1968 }

1969

1971 }

1972

1973

1974

1975

1976

1977

1979

1980

1981 if (found)

1982 {

1984 elog(WARNING, "found duplicate stats entry %u/%u/%" PRIu64 " of type %c",

1985 key.kind, key.dboid,

1986 key.objid, t);

1988 }

1989

1992

1996 {

1997 elog(WARNING, "could not read data for entry %u/%u/%" PRIu64 " of type %c",

1998 key.kind, key.dboid,

1999 key.objid, t);

2001 }

2002

2003 break;

2004 }

2006

2007

2008

2009

2010

2011 if (fgetc(fpin) != EOF)

2012 {

2013 elog(WARNING, "could not read end-of-file");

2015 }

2016

2017 goto done;

2018

2019 default:

2020 elog(WARNING, "could not read entry of type %c", t);

2022 }

2023 }

2024

2025done:

2027

2028 elog(DEBUG2, "removing permanent stats file \"%s\"", statfile);

2029 unlink(statfile);

2030

2031 return;

2032

2035 (errmsg("corrupted statistics file \"%s\"", statfile)));

2036

2038

2039 goto done;

2040}

2041

2042

2043

2044

2045

2048{

2050

2051

2053 {

2055

2057 continue;

2058

2060 }

2061

2062

2064}

2065

2066

2067

2068

2071{

2072

2073

2074

2075

2076

2079}

Datum idx(PG_FUNCTION_ARGS)

static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)

bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)

TimestampTz GetCurrentTimestamp(void)

Datum now(PG_FUNCTION_ARGS)

void pgstat_clear_backend_activity_snapshot(void)

#define OidIsValid(objectId)

void * dsa_get_address(dsa_area *area, dsa_pointer dp)

void dshash_release_lock(dshash_table *hash_table, void *entry)

void dshash_seq_init(dshash_seq_status *status, dshash_table *hash_table, bool exclusive)

void dshash_seq_term(dshash_seq_status *status)

void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)

void * dshash_seq_next(dshash_seq_status *status)

int errmsg_internal(const char *fmt,...)

int errcode_for_file_access(void)

int errdetail(const char *fmt,...)

int errhint(const char *fmt,...)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

int durable_rename(const char *oldfile, const char *newfile, int elevel)

FILE * AllocateFile(const char *name, const char *mode)

bool IsPostmasterEnvironment

Assert(PointerIsAligned(start, uint64))

static void dlist_init(dlist_head *head)

static bool dlist_has_next(const dlist_head *head, const dlist_node *node)

static dlist_node * dlist_next_node(dlist_head *head, dlist_node *node)

static void dlist_delete(dlist_node *node)

static dlist_node * dlist_head_node(dlist_head *head)

static bool dlist_is_empty(const dlist_head *head)

static void dlist_push_tail(dlist_head *head, dlist_node *node)

#define DLIST_STATIC_INIT(name)

#define dlist_container(type, membername, ptr)

void before_shmem_exit(pg_on_exit_callback function, Datum arg)

bool LWLockAcquire(LWLock *lock, LWLockMode mode)

void LWLockRelease(LWLock *lock)

void * MemoryContextAlloc(MemoryContext context, Size size)

void * MemoryContextAllocZero(MemoryContext context, Size size)

void pfree(void *pointer)

MemoryContext TopMemoryContext

void MemoryContextDelete(MemoryContext context)

#define AllocSetContextCreate

#define ALLOCSET_SMALL_SIZES

#define CHECK_FOR_INTERRUPTS()

BackendType MyBackendType

bool process_shared_preload_libraries_in_progress

void pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid)

static bool pgStatForceNextFlush

int pgstat_fetch_consistency

#define PGSTAT_MIN_INTERVAL

void pgstat_snapshot_fixed(PgStat_Kind kind)

static void pgstat_prep_snapshot(void)

static const PgStat_KindInfo ** pgstat_kind_custom_infos

static void pgstat_build_snapshot_fixed(PgStat_Kind kind)

#define PGSTAT_SNAPSHOT_HASH_SIZE

#define PGSTAT_FILE_ENTRY_END

void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref)

void pgstat_reset_counters(void)

PgStat_EntryRef * pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *created_entry)

static void pgstat_build_snapshot(void)

void pgstat_initialize(void)

static void pgstat_write_statsfile(void)

long pgstat_report_stat(bool force)

static void pgstat_read_statsfile(void)

static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]

void pgstat_reset_of_kind(PgStat_Kind kind)

static bool pgstat_flush_pending_entries(bool nowait)

void pgstat_before_server_shutdown(int code, Datum arg)

const PgStat_KindInfo * pgstat_get_kind_info(PgStat_Kind kind)

static void pgstat_reset_after_failure(void)

void assign_stats_fetch_consistency(int newval, void *extra)

void pgstat_force_next_flush(void)

static bool pgstat_is_kind_valid(PgStat_Kind kind)

void pgstat_clear_snapshot(void)

TimestampTz pgstat_get_stat_snapshot_timestamp(bool *have_snapshot)

bool pgstat_have_entry(PgStat_Kind kind, Oid dboid, uint64 objid)

static MemoryContext pgStatPendingContext

static dlist_head pgStatPending

#define PGSTAT_FILE_ENTRY_HASH

static void pgstat_init_snapshot_fixed(void)

PgStat_EntryRef * pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid)

static void write_chunk(FILE *fpout, void *ptr, size_t len)

void pgstat_restore_stats(void)

void * pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid)

#define write_chunk_s(fpout, ptr)

struct PgStat_SnapshotEntry PgStat_SnapshotEntry

#define PGSTAT_MAX_INTERVAL

#define PGSTAT_FILE_ENTRY_FIXED

static bool read_chunk(FILE *fpin, void *ptr, size_t len)

#define read_chunk_s(fpin, ptr)

#define PGSTAT_IDLE_INTERVAL

#define PGSTAT_FILE_ENTRY_NAME

void pgstat_register_kind(PgStat_Kind kind, const PgStat_KindInfo *kind_info)

PgStat_LocalState pgStatLocal

void pgstat_discard_stats(void)

static bool match_db_entries(PgStatShared_HashEntry *entry, Datum match_data)

static bool force_stats_snapshot_clear

PgStat_Kind pgstat_get_kind_from_str(char *kind_str)

static void pgstat_shutdown_hook(int code, Datum arg)

@ PGSTAT_FETCH_CONSISTENCY_NONE

@ PGSTAT_FETCH_CONSISTENCY_CACHE

@ PGSTAT_FETCH_CONSISTENCY_SNAPSHOT

#define PGSTAT_STAT_PERMANENT_FILENAME

#define PGSTAT_STAT_PERMANENT_TMPFILE

#define PGSTAT_FILE_FORMAT_ID

void pgstat_archiver_init_shmem_cb(void *stats)

void pgstat_archiver_reset_all_cb(TimestampTz ts)

void pgstat_archiver_snapshot_cb(void)

bool pgstat_backend_have_pending_cb(void)

void pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)

bool pgstat_backend_flush_cb(bool nowait)

void pgstat_bgwriter_reset_all_cb(TimestampTz ts)

void pgstat_bgwriter_init_shmem_cb(void *stats)

void pgstat_bgwriter_snapshot_cb(void)

void pgstat_checkpointer_snapshot_cb(void)

void pgstat_checkpointer_init_shmem_cb(void *stats)

void pgstat_checkpointer_reset_all_cb(TimestampTz ts)

void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)

void pgstat_update_dbstats(TimestampTz ts)

void pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts)

void pgstat_report_disconnect(Oid dboid)

bool pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)

bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)

struct PgStatShared_Function PgStatShared_Function

static void * pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry)

struct PgStatShared_Subscription PgStatShared_Subscription

#define pgstat_assert_is_up()

struct PgStatShared_Relation PgStatShared_Relation

struct PgStatShared_Database PgStatShared_Database

static size_t pgstat_get_entry_len(PgStat_Kind kind)

struct PgStatShared_Backend PgStatShared_Backend

struct PgStatShared_ReplSlot PgStatShared_ReplSlot

bool pgstat_io_have_pending_cb(void)

bool pgstat_io_flush_cb(bool nowait)

void pgstat_io_reset_all_cb(TimestampTz ts)

void pgstat_io_snapshot_cb(void)

void pgstat_io_init_shmem_cb(void *stats)

#define PGSTAT_KIND_CUSTOM_MAX

#define PGSTAT_KIND_ARCHIVER

static bool pgstat_is_kind_builtin(PgStat_Kind kind)

static bool pgstat_is_kind_custom(PgStat_Kind kind)

#define PGSTAT_KIND_BGWRITER

#define PGSTAT_KIND_CUSTOM_MIN

#define PGSTAT_KIND_REPLSLOT

#define PGSTAT_KIND_FUNCTION

#define PGSTAT_KIND_BUILTIN_MAX

#define PGSTAT_KIND_CUSTOM_SIZE

#define PGSTAT_KIND_DATABASE

#define PGSTAT_KIND_INVALID

#define PGSTAT_KIND_RELATION

#define PGSTAT_KIND_CHECKPOINTER

#define PGSTAT_KIND_BUILTIN_SIZE

#define PGSTAT_KIND_SUBSCRIPTION

#define PGSTAT_KIND_BACKEND

#define PGSTAT_KIND_BUILTIN_MIN

bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)

void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref)

bool pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat_HashKey *key)

void pgstat_replslot_to_serialized_name_cb(const PgStat_HashKey *key, const PgStatShared_Common *header, NameData *name)

void pgstat_replslot_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)

void pgstat_reset_entries_of_kind(PgStat_Kind kind, TimestampTz ts)

void pgstat_request_entry_refs_gc(void)

PgStat_EntryRef * pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry)

bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait)

void pgstat_attach_shmem(void)

bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, uint64 objid)

void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, uint64 objid, TimestampTz ts)

PgStatShared_Common * pgstat_init_entry(PgStat_Kind kind, PgStatShared_HashEntry *shhashent)

void pgstat_reset_matching_entries(bool(*do_reset)(PgStatShared_HashEntry *, Datum), Datum match_data, TimestampTz ts)

void pgstat_drop_all_entries(void)

void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)

void pgstat_detach_shmem(void)

void pgstat_slru_snapshot_cb(void)

bool pgstat_slru_flush_cb(bool nowait)

void pgstat_slru_reset_all_cb(TimestampTz ts)

void pgstat_slru_init_shmem_cb(void *stats)

bool pgstat_slru_have_pending_cb(void)

bool pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)

void pgstat_subscription_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)

void pgstat_wal_reset_all_cb(TimestampTz ts)

void pgstat_wal_init_shmem_cb(void *stats)

void pgstat_wal_init_backend_cb(void)

bool pgstat_wal_flush_cb(bool nowait)

bool pgstat_wal_have_pending_cb(void)

void pgstat_wal_snapshot_cb(void)

int pg_strcasecmp(const char *s1, const char *s2)

static Oid DatumGetObjectId(Datum X)

static Datum ObjectIdGetDatum(Oid X)

pg_atomic_uint32 refcount

PgStatShared_Common * shared_stats

PgStatShared_HashEntry * shared_entry

bool accessed_across_databases

bool(* flush_static_cb)(bool nowait)

void(* to_serialized_name)(const PgStat_HashKey *key, const PgStatShared_Common *header, NameData *name)

bool(* from_serialized_name)(const NameData *name, PgStat_HashKey *key)

bool(* have_static_pending_cb)(void)

bool(* flush_pending_cb)(PgStat_EntryRef *sr, bool nowait)

void(* reset_all_cb)(TimestampTz ts)

void(* init_backend_cb)(void)

void(* delete_pending_cb)(PgStat_EntryRef *sr)

void(* snapshot_cb)(void)

dshash_table * shared_hash

PgStat_ShmemControl * shmem

void * custom_data[PGSTAT_KIND_CUSTOM_SIZE]

void * custom_data[PGSTAT_KIND_CUSTOM_SIZE]

TimestampTz snapshot_timestamp

bool custom_valid[PGSTAT_KIND_CUSTOM_SIZE]

PgStat_FetchConsistency mode

struct pgstat_snapshot_hash * stats

bool fixed_valid[PGSTAT_KIND_BUILTIN_SIZE]

bool IsTransactionOrTransactionBlock(void)

TimestampTz GetCurrentTransactionStopTimestamp(void)