Read is symmetric to write. It gets the page in which the start of the log record resides. It checks whether the log record starts with the magic number. If not, it checks the byte against logrecord::LOG_END. If this matches, an EOF is signaled and global_shm_log_ptr->sl_nextlsn is set to the LSN supplied. (Thus, a side effect of the analysis pass of restart recovery would be to determine the end of the log.) If this test also failed, the LSN does not point to the start of a log record. An error indication is returned.
The log record header is then examined. It may happen that the log record header is split across pages. In this case, the next page is read to get the remaining portion of the header. The header contains the length of the entire log record. This is used to determine the number of pages that must be read to get the whole log record. The appropriate number of pages are read to assemble the entire log record. If the physical end of the log is reached, read wraps back to the physical beginning of the log to continue the read.
Note that write always goes through the log tail to the log file whereas read never touches the log tail. This is required so that an arbitrary read does not corrupt the log tail. However, this poses a problem during restart recovery. The recovery manager will read log records till the end of the log is reached. New log records are then written. Unfortunately, if the end of the log occurred in the middle of a page, the log tail is not initialized with the contents of the page and, hence, the next flush of the log tail will corrupt the log. The open constructor handles this by reading the page of the log into the log tail when it detects end of log.