为错误检查和配置信息读取控制文件。我们已经检查了控制文件的CRC,需要的CRC run-time test支持设施已经加载。postmaster在启动过程中会进行测试CRC,子进程会继承该函数指针,不需要重复进行测试。

LocalProcessControlFile(false)

LocalProcessControlFile函数会读取控制文件,设置respective GUC。该函数是在启动过程中调用,包括在crash recovery cycle(除了bootstrap模式,因为这个模式下还没有生产控制文件)。这时还没有建立共享内存,所以需要将控制文件的内容放置本地被称中,并在XLOGShmemInit函数中拷贝到共享内存中。

void LocalProcessControlFile(bool reset) {
Assert(reset || ControlFile == NULL);
ControlFile = palloc(sizeof(ControlFileData));
ReadControlFile();
}

执行过程

  1. 打开控制文件,读取控制文件
static void ReadControlFile(void) {
pg_crc32c crc;
int fd;
static char wal_segsz_str[20];
int r;

/* Read data... */
fd = BasicOpenFile(XLOG_CONTROL_FILE, O_RDWR | PG_BINARY); // 打开文件
if (fd < 0) ereport(PANIC,(errcode_for_file_access(),errmsg("could not open file \"%s\": %m", XLOG_CONTROL_FILE)));

pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_READ); // 将WAIT_EVENT_CONTROL_FILE_READ事件设置到MyProc->wait_event_info中
r = read(fd, ControlFile, sizeof(ControlFileData));
if (r != sizeof(ControlFileData)) {
if (r < 0) ereport(PANIC,(errcode_for_file_access(), errmsg("could not read file \"%s\": %m",XLOG_CONTROL_FILE)));
else ereport(PANIC,(errcode(ERRCODE_DATA_CORRUPTED),errmsg("could not read file \"%s\": read %d of %zu", XLOG_CONTROL_FILE, r, sizeof(ControlFileData))));
}
pgstat_report_wait_end();
close(fd);
  1. 检查控制文件:版本,CRC,兼容性检查
  2. 设置respective GUC:wal_segment_size、data_checksums
= ControlFile->xlog_seg_size;
if (!IsValidWalSegSize(wal_segment_size)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),errmsg_plural("WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte","WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes",wal_segment_size,wal_segment_size)));

snprintf(wal_segsz_str, sizeof(wal_segsz_str), "%d", wal_segment_size);
SetConfigOption("wal_segment_size", wal_segsz_str, PGC_INTERNAL,PGC_S_OVERRIDE);

/* check and update variables dependent on wal_segment_size */
if (ConvertToXSegs(min_wal_size_mb, wal_segment_size) < 2)
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),errmsg("\"min_wal_size\" must be at least twice \"wal_segment_size\"")));
if (ConvertToXSegs(max_wal_size_mb, wal_segment_size) < 2)
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),errmsg("\"max_wal_size\" must be at least twice \"wal_segment_size\"")));


UsableBytesInSegment =(wal_segment_size / XLOG_BLCKSZ * UsableBytesInPage) - (SizeOfXLogLongPHD - SizeOfXLogShortPHD);

CalculateCheckpointSegments();

/* Make the initdb settings visible as GUC variables, too */
SetConfigOption("data_checksums", DataChecksumsEnabled() ? "yes" : "no", PGC_INTERNAL, PGC_S_OVERRIDE);