PostgreSQL Source Code git master
Loading...
Searching...
No Matches
datachecksum_state.h File Reference
Include dependency graph for datachecksum_state.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool AbsorbDataChecksumsBarrier (ProcSignalBarrierType barrier)
 
void EmitAndWaitDataChecksumsBarrier (uint32 state)
 
void DataChecksumsWorkerLauncherMain (Datum arg)
 
void DataChecksumsWorkerMain (Datum arg)
 

Function Documentation

◆ AbsorbDataChecksumsBarrier()

bool AbsorbDataChecksumsBarrier ( ProcSignalBarrierType  barrier)

Definition at line 467 of file datachecksum_state.c.

468{
470 int current = data_checksums;
471 bool found = false;
472
473 /*
474 * Translate the barrier condition to the target state, doing it here
475 * instead of in the procsignal code saves the latter from knowing about
476 * checksum states.
477 */
478 switch (barrier)
479 {
482 break;
485 break;
488 break;
491 break;
492 default:
493 elog(ERROR, "incorrect barrier \"%i\" received", barrier);
494 }
495
496 /*
497 * If the target state matches the current state then the barrier has been
498 * repeated.
499 */
500 if (current == target_state)
501 return true;
502
503 /*
504 * If the cluster is in recovery we skip the validation of current state
505 * since the replay is trusted.
506 */
507 if (RecoveryInProgress())
508 {
510 return true;
511 }
512
513 /*
514 * Find the barrier condition definition for the target state. Not finding
515 * a condition would be a grave programmer error as the states are a
516 * discrete set.
517 */
518 for (int i = 0; i < lengthof(checksum_barriers) && !found; i++)
519 {
520 if (checksum_barriers[i].from == current && checksum_barriers[i].to == target_state)
521 found = true;
522 }
523
524 /*
525 * If the relevant state criteria aren't satisfied, throw an error which
526 * will be caught by the procsignal machinery for a later retry.
527 */
528 if (!found)
531 errmsg("incorrect data checksum state %i for target state %i",
532 current, target_state));
533
535 return true;
536}
uint32_t uint32
Definition c.h:624
#define lengthof(array)
Definition c.h:873
@ PG_DATA_CHECKSUM_VERSION
Definition checksum.h:29
@ PG_DATA_CHECKSUM_INPROGRESS_OFF
Definition checksum.h:30
@ PG_DATA_CHECKSUM_INPROGRESS_ON
Definition checksum.h:31
@ PG_DATA_CHECKSUM_OFF
Definition checksum.h:28
static const ChecksumBarrierCondition checksum_barriers[9]
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
int i
Definition isn.c:77
static char * errmsg
static THREAD_BARRIER_T barrier
Definition pgbench.c:488
static int fb(int x)
@ PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF
Definition procsignal.h:55
@ PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON
Definition procsignal.h:54
@ PROCSIGNAL_BARRIER_CHECKSUM_ON
Definition procsignal.h:56
@ PROCSIGNAL_BARRIER_CHECKSUM_OFF
Definition procsignal.h:53
bool RecoveryInProgress(void)
Definition xlog.c:6836
void SetLocalDataChecksumState(uint32 data_checksum_version)
Definition xlog.c:4970
int data_checksums
Definition xlog.c:683

References barrier, checksum_barriers, data_checksums, elog, ereport, errcode(), errmsg, ERROR, fb(), i, lengthof, PG_DATA_CHECKSUM_INPROGRESS_OFF, PG_DATA_CHECKSUM_INPROGRESS_ON, PG_DATA_CHECKSUM_OFF, PG_DATA_CHECKSUM_VERSION, PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF, PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON, PROCSIGNAL_BARRIER_CHECKSUM_OFF, PROCSIGNAL_BARRIER_CHECKSUM_ON, RecoveryInProgress(), and SetLocalDataChecksumState().

Referenced by ProcessProcSignalBarrier().

◆ DataChecksumsWorkerLauncherMain()

void DataChecksumsWorkerLauncherMain ( Datum  arg)

Definition at line 1093 of file datachecksum_state.c.

1094{
1095
1097 errmsg("background worker \"datachecksums launcher\" started"));
1098
1103
1105
1108
1109 INJECTION_POINT("datachecksumsworker-launcher-delay", NULL);
1110
1112
1114 {
1115 ereport(LOG,
1116 errmsg("background worker \"datachecksums launcher\" already running, exiting"));
1117 /* Launcher was already running, let it finish */
1119 return;
1120 }
1121
1123 launcher_running = true;
1124
1125 /* Initialize a connection to shared catalogs only */
1127
1134
1135 /*
1136 * The target state can change while we are busy enabling/disabling
1137 * checksums, if the user calls pg_disable/enable_data_checksums() before
1138 * we are finished with the previous request. In that case, we will loop
1139 * back here, to process the new request.
1140 */
1141again:
1142
1144 InvalidOid);
1145
1147 {
1148 /*
1149 * If we are asked to enable checksums in a cluster which already has
1150 * checksums enabled, exit immediately as there is nothing more to do.
1151 */
1153 goto done;
1154
1155 ereport(LOG,
1156 errmsg("enabling data checksums requested, starting data checksum calculation"));
1157
1158 /*
1159 * Set the state to inprogress-on and wait on the procsignal barrier.
1160 */
1164
1165 /*
1166 * All backends are now in inprogress-on state and are writing data
1167 * checksums. Start processing all data at rest.
1168 */
1169 if (!ProcessAllDatabases())
1170 {
1171 /*
1172 * If the target state changed during processing then it's not a
1173 * failure, so restart processing instead.
1174 */
1176 if (abort_requested)
1177 goto done;
1178 ereport(ERROR,
1180 errmsg("unable to enable data checksums in cluster"));
1181 }
1182
1183 /*
1184 * Data checksums have been set on all pages, set the state to on in
1185 * order to instruct backends to validate checksums on reading.
1186 */
1188
1189 ereport(LOG,
1190 errmsg("data checksums are now enabled"));
1191 }
1192 else if (operation == DISABLE_DATACHECKSUMS)
1193 {
1194 ereport(LOG,
1195 errmsg("disabling data checksums requested"));
1196
1200 ereport(LOG,
1201 errmsg("data checksums are now disabled"));
1202 }
1203 else
1204 Assert(false);
1205
1206done:
1207
1208 /*
1209 * This state will only be displayed for a fleeting moment, but for the
1210 * sake of correctness it is still added before ending the command.
1211 */
1214
1215 /*
1216 * All done. But before we exit, check if the target state was changed
1217 * while we were running. In that case we will have to start all over
1218 * again.
1219 */
1222 {
1228 goto again;
1229 }
1230
1231 /* Shut down progress reporting as we are done */
1233
1234 launcher_running = false;
1237}
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_end_command(void)
@ PROGRESS_COMMAND_DATACHECKSUMS
void BackgroundWorkerUnblockSignals(void)
Definition bgworker.c:949
void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags)
Definition bgworker.c:909
#define Assert(condition)
Definition c.h:943
static DataChecksumsStateStruct * DataChecksumState
static volatile sig_atomic_t launcher_running
static volatile sig_atomic_t abort_requested
static DataChecksumsWorkerOperation operation
static void launcher_cancel_handler(SIGNAL_ARGS)
#define CHECK_FOR_LAUNCHER_ABORT_REQUEST()
static bool ProcessAllDatabases(void)
@ DISABLE_DATACHECKSUMS
@ ENABLE_DATACHECKSUMS
static void launcher_exit(int code, Datum arg)
#define LOG
Definition elog.h:32
#define DEBUG1
Definition elog.h:31
#define INJECTION_POINT(name, arg)
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_EXCLUSIVE
Definition lwlock.h:104
@ B_DATACHECKSUMSWORKER_LAUNCHER
Definition miscadmin.h:373
BackendType MyBackendType
Definition miscinit.c:65
#define die(msg)
#define pqsignal
Definition port.h:548
#define PG_SIG_IGN
Definition port.h:552
#define InvalidOid
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition procsignal.c:696
#define PROGRESS_DATACHECKSUMS_PHASE_DONE
Definition progress.h:205
#define PROGRESS_DATACHECKSUMS_PHASE
Definition progress.h:192
#define PROGRESS_DATACHECKSUMS_PHASE_ENABLING
Definition progress.h:201
#define PROGRESS_DATACHECKSUMS_PHASE_DISABLING
Definition progress.h:202
void init_ps_display(const char *fixed_part)
Definition ps_status.c:286
DataChecksumsWorkerOperation launch_operation
DataChecksumsWorkerOperation operation
#define SIGUSR1
Definition win32_port.h:170
#define SIGUSR2
Definition win32_port.h:171
void SetDataChecksumsOff(void)
Definition xlog.c:4866
bool DataChecksumsNeedVerify(void)
Definition xlog.c:4733
void SetDataChecksumsOn(void)
Definition xlog.c:4802
void SetDataChecksumsOnInProgress(void)
Definition xlog.c:4749

References abort_requested, Assert, B_DATACHECKSUMSWORKER_LAUNCHER, BackgroundWorkerInitializeConnectionByOid(), BackgroundWorkerUnblockSignals(), CHECK_FOR_LAUNCHER_ABORT_REQUEST, DataChecksumsStateStruct::cost_delay, DataChecksumsStateStruct::cost_limit, DataChecksumsNeedVerify(), DataChecksumState, DEBUG1, die, DISABLE_DATACHECKSUMS, ENABLE_DATACHECKSUMS, ereport, errcode(), errmsg, ERROR, fb(), init_ps_display(), INJECTION_POINT, InvalidOid, DataChecksumsStateStruct::launch_cost_delay, DataChecksumsStateStruct::launch_cost_limit, DataChecksumsStateStruct::launch_operation, launcher_cancel_handler(), launcher_exit(), DataChecksumsStateStruct::launcher_running, launcher_running, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyBackendType, on_shmem_exit(), DataChecksumsStateStruct::operation, operation, PG_SIG_IGN, pgstat_progress_end_command(), pgstat_progress_start_command(), pgstat_progress_update_param(), pqsignal, ProcessAllDatabases(), procsignal_sigusr1_handler(), PROGRESS_COMMAND_DATACHECKSUMS, PROGRESS_DATACHECKSUMS_PHASE, PROGRESS_DATACHECKSUMS_PHASE_DISABLING, PROGRESS_DATACHECKSUMS_PHASE_DONE, PROGRESS_DATACHECKSUMS_PHASE_ENABLING, SetDataChecksumsOff(), SetDataChecksumsOn(), SetDataChecksumsOnInProgress(), SIGUSR1, and SIGUSR2.

◆ DataChecksumsWorkerMain()

void DataChecksumsWorkerMain ( Datum  arg)

Definition at line 1544 of file datachecksum_state.c.

1545{
1546 Oid dboid;
1549 BufferAccessStrategy strategy;
1550 bool aborted = false;
1552 bool process_shared;
1553#ifdef USE_INJECTION_POINTS
1554 bool retried = false;
1555#endif
1556
1558
1560
1563
1565
1568
1571 {
1573 return;
1574 }
1577
1580
1581 /* worker will have a separate entry in pg_stat_progress_data_checksums */
1583 InvalidOid);
1584
1585 /*
1586 * Get a list of all temp tables present as we start in this database. We
1587 * need to wait until they are all gone before we exit. For the list of
1588 * relations to enable checksums in, check if shared catalogs have been
1589 * processed already.
1590 */
1594 {
1596 return;
1597 }
1599
1600 /*
1601 * Enable vacuum cost delay, if any. While this process isn't doing any
1602 * vacuuming, we are re-using the infrastructure that vacuum cost delay
1603 * provides rather than inventing something bespoke. This is an internal
1604 * implementation detail and care should be taken to avoid it bleeding
1605 * through to the user to avoid confusion.
1606 *
1607 * VacuumUpdateCosts() propagates the values to the variables actually
1608 * read by vacuum_delay_point().
1609 */
1615
1616 /*
1617 * Create and set the vacuum strategy as our buffer strategy.
1618 */
1619 strategy = GetAccessStrategy(BAS_VACUUM);
1620
1622
1623 /* Update the total number of relations to be processed in this DB. */
1624 {
1625 const int index[] = {
1628 };
1629
1630 int64 vals[2];
1631
1632 vals[0] = list_length(RelationList);
1633 vals[1] = 0;
1634
1636 }
1637
1638 /* Process the relations */
1639 rels_done = 0;
1640 foreach_oid(reloid, RelationList)
1641 {
1642 bool costs_updated = false;
1643
1644 if (!ProcessSingleRelationByOid(reloid, strategy))
1645 {
1646 aborted = true;
1647 break;
1648 }
1649
1651 ++rels_done);
1654
1655 if (abort_requested)
1656 break;
1657
1658 /*
1659 * Check if the cost settings changed during runtime and if so, update
1660 * to reflect the new values and signal that the access strategy needs
1661 * to be refreshed.
1662 */
1665 {
1667 break;
1668 }
1671 {
1672 costs_updated = true;
1676
1679 }
1680 else
1681 costs_updated = false;
1683
1684 if (costs_updated)
1685 {
1686 FreeAccessStrategy(strategy);
1687 strategy = GetAccessStrategy(BAS_VACUUM);
1688 }
1689 }
1690
1692 FreeAccessStrategy(strategy);
1693
1694 if (aborted || abort_requested)
1695 {
1701 errmsg("data checksum processing aborted in database OID %u",
1702 dboid));
1703 return;
1704 }
1705
1706 /* The worker is about to wait for temporary tables to go away. */
1709
1710 /*
1711 * Wait for all temp tables that existed when we started to go away. This
1712 * is necessary since we cannot "reach" them to enable checksums. Any temp
1713 * tables created after we started will already have checksums in them
1714 * (due to the "inprogress-on" state), so no need to wait for those.
1715 */
1716 for (;;)
1717 {
1719 int numleft;
1720 char activity[64];
1721
1722 CurrentTempTables = BuildRelationList(true, false);
1723 numleft = 0;
1725 {
1727 numleft++;
1728 }
1730
1731#ifdef USE_INJECTION_POINTS
1732 if (IS_INJECTION_POINT_ATTACHED("datachecksumsworker-fake-temptable-wait"))
1733 {
1734 /* Make sure to just cause one retry */
1735 if (!retried && numleft == 0)
1736 {
1737 numleft = 1;
1738 retried = true;
1739
1740 INJECTION_POINT_CACHED("datachecksumsworker-fake-temptable-wait", NULL);
1741 }
1742 }
1743#endif
1744
1745 if (numleft == 0)
1746 break;
1747
1748 /*
1749 * At least one temp table is left to wait for, indicate in pgstat
1750 * activity and progress reporting.
1751 */
1753 sizeof(activity),
1754 "Waiting for %d temp tables to be removed", numleft);
1756
1757 /* Retry every 3 seconds */
1761 3000,
1763
1766
1767 if (aborted || abort_requested)
1768 {
1773 ereport(LOG,
1774 errmsg("data checksum processing aborted in database OID %u",
1775 dboid));
1776 return;
1777 }
1778 }
1779
1781
1782 /* worker done */
1784
1789}
void VacuumUpdateCosts(void)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
void pgstat_report_activity(BackendState state, const char *cmd_str)
@ STATE_RUNNING
#define BGWORKER_BYPASS_ALLOWCONN
Definition bgworker.h:166
@ BAS_VACUUM
Definition bufmgr.h:40
int64_t int64
Definition c.h:621
#define CHECK_FOR_WORKER_ABORT_REQUEST()
static bool ProcessSingleRelationByOid(Oid relationId, BufferAccessStrategy strategy)
@ DATACHECKSUMSWORKER_ABORTED
@ DATACHECKSUMSWORKER_SUCCESSFUL
static uint64 worker_invocation
static List * BuildRelationList(bool temp_relations, bool include_shared)
Datum arg
Definition elog.c:1323
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition freelist.c:426
void FreeAccessStrategy(BufferAccessStrategy strategy)
Definition freelist.c:608
int VacuumCostLimit
Definition globals.c:157
int VacuumCostBalance
Definition globals.c:160
struct Latch * MyLatch
Definition globals.c:65
double VacuumCostDelay
Definition globals.c:158
#define IS_INJECTION_POINT_ATTACHED(name)
#define INJECTION_POINT_CACHED(name, arg)
void ResetLatch(Latch *latch)
Definition latch.c:374
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition latch.c:172
void list_free(List *list)
Definition list.c:1546
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
@ LW_SHARED
Definition lwlock.h:105
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
@ B_DATACHECKSUMSWORKER_WORKER
Definition miscadmin.h:374
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define foreach_oid(var, lst)
Definition pg_list.h:503
#define snprintf
Definition port.h:261
static uint64 DatumGetUInt64(Datum X)
Definition postgres.h:436
unsigned int Oid
#define PROGRESS_DATACHECKSUMS_RELS_TOTAL
Definition progress.h:195
#define PROGRESS_DATACHECKSUMS_PHASE_WAITING_TEMPREL
Definition progress.h:203
#define PROGRESS_DATACHECKSUMS_RELS_DONE
Definition progress.h:196
DataChecksumsWorkerResult worker_result
Definition pg_list.h:54
Definition type.h:97
#define WL_TIMEOUT
#define WL_EXIT_ON_PM_DEATH
#define WL_LATCH_SET

References abort_requested, arg, B_DATACHECKSUMSWORKER_WORKER, BackgroundWorkerInitializeConnectionByOid(), BackgroundWorkerUnblockSignals(), BAS_VACUUM, BGWORKER_BYPASS_ALLOWCONN, BuildRelationList(), CHECK_FOR_INTERRUPTS, CHECK_FOR_WORKER_ABORT_REQUEST, DataChecksumsStateStruct::cost_delay, DataChecksumsStateStruct::cost_limit, DataChecksumsStateStruct::database_oid, DataChecksumState, DATACHECKSUMSWORKER_ABORTED, DATACHECKSUMSWORKER_SUCCESSFUL, DatumGetUInt64(), DEBUG1, die, ENABLE_DATACHECKSUMS, ereport, errmsg, fb(), foreach_oid, FreeAccessStrategy(), GetAccessStrategy(), init_ps_display(), INJECTION_POINT_CACHED, InvalidOid, IS_INJECTION_POINT_ATTACHED, DataChecksumsStateStruct::launch_cost_delay, DataChecksumsStateStruct::launch_cost_limit, list_free(), list_length(), list_member_oid(), LOG, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MyBackendType, MyLatch, NIL, operation, pgstat_progress_end_command(), pgstat_progress_start_command(), pgstat_progress_update_multi_param(), pgstat_progress_update_param(), pgstat_report_activity(), pqsignal, DataChecksumsStateStruct::process_shared_catalogs, ProcessSingleRelationByOid(), procsignal_sigusr1_handler(), PROGRESS_COMMAND_DATACHECKSUMS, PROGRESS_DATACHECKSUMS_PHASE, PROGRESS_DATACHECKSUMS_PHASE_WAITING_TEMPREL, PROGRESS_DATACHECKSUMS_RELS_DONE, PROGRESS_DATACHECKSUMS_RELS_TOTAL, ResetLatch(), SIGUSR1, snprintf, STATE_RUNNING, VacuumCostBalance, VacuumCostDelay, VacuumCostLimit, VacuumUpdateCosts(), WaitLatch(), WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, WL_TIMEOUT, DataChecksumsStateStruct::worker_invocation, worker_invocation, and DataChecksumsStateStruct::worker_result.

◆ EmitAndWaitDataChecksumsBarrier()

void EmitAndWaitDataChecksumsBarrier ( uint32  state)

Definition at line 426 of file datachecksum_state.c.

427{
429
430 switch (state)
431 {
435 break;
436
440 break;
441
445 break;
446
450 break;
451
452 default:
453 Assert(false);
454 }
455}
uint64_t uint64
Definition c.h:625
void WaitForProcSignalBarrier(uint64 generation)
Definition procsignal.c:436
uint64 EmitProcSignalBarrier(ProcSignalBarrierType type)
Definition procsignal.c:368

References Assert, barrier, EmitProcSignalBarrier(), PG_DATA_CHECKSUM_INPROGRESS_OFF, PG_DATA_CHECKSUM_INPROGRESS_ON, PG_DATA_CHECKSUM_OFF, PG_DATA_CHECKSUM_VERSION, PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_OFF, PROCSIGNAL_BARRIER_CHECKSUM_INPROGRESS_ON, PROCSIGNAL_BARRIER_CHECKSUM_OFF, PROCSIGNAL_BARRIER_CHECKSUM_ON, and WaitForProcSignalBarrier().

Referenced by StartupXLOG(), xlog2_redo(), and xlog_redo().