PostgreSQL Source Code  git master
timeline.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * timeline.c
4  * timeline-related functions.
5  *
6  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7  *
8  *-------------------------------------------------------------------------
9  */
10 #include "postgres_fe.h"
11 
12 #include "access/timeline.h"
13 #include "access/xlog_internal.h"
14 #include "pg_rewind.h"
15 
16 /*
17  * This is copy-pasted from the backend readTimeLineHistory, modified to
18  * return a malloc'd array and to work without backend functions.
19  */
20 /*
21  * Try to read a timeline's history file.
22  *
23  * If successful, return the list of component TLIs (the given TLI followed by
24  * its ancestor TLIs). If we can't find the history file, assume that the
25  * timeline has no parents, and return a list of just the specified timeline
26  * ID.
27  */
29 rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
30 {
31  char *fline;
32  TimeLineHistoryEntry *entry;
33  TimeLineHistoryEntry *entries = NULL;
34  int nlines = 0;
35  TimeLineID lasttli = 0;
36  XLogRecPtr prevend;
37  char *bufptr;
38  bool lastline = false;
39 
40  /*
41  * Parse the file...
42  */
43  prevend = InvalidXLogRecPtr;
44  bufptr = buffer;
45  while (!lastline)
46  {
47  char *ptr;
48  TimeLineID tli;
49  uint32 switchpoint_hi;
50  uint32 switchpoint_lo;
51  int nfields;
52 
53  fline = bufptr;
54  while (*bufptr && *bufptr != '\n')
55  bufptr++;
56  if (!(*bufptr))
57  lastline = true;
58  else
59  *bufptr++ = '\0';
60 
61  /* skip leading whitespace and check for # comment */
62  for (ptr = fline; *ptr; ptr++)
63  {
64  if (!isspace((unsigned char) *ptr))
65  break;
66  }
67  if (*ptr == '\0' || *ptr == '#')
68  continue;
69 
70  nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo);
71 
72  if (nfields < 1)
73  {
74  /* expect a numeric timeline ID as first field of line */
75  pg_log_error("syntax error in history file: %s", fline);
76  pg_log_error_detail("Expected a numeric timeline ID.");
77  exit(1);
78  }
79  if (nfields != 3)
80  {
81  pg_log_error("syntax error in history file: %s", fline);
82  pg_log_error_detail("Expected a write-ahead log switchpoint location.");
83  exit(1);
84  }
85  if (entries && tli <= lasttli)
86  {
87  pg_log_error("invalid data in history file: %s", fline);
88  pg_log_error_detail("Timeline IDs must be in increasing sequence.");
89  exit(1);
90  }
91 
92  lasttli = tli;
93 
94  nlines++;
95  entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry));
96 
97  entry = &entries[nlines - 1];
98  entry->tli = tli;
99  entry->begin = prevend;
100  entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
101  prevend = entry->end;
102 
103  /* we ignore the remainder of each line */
104  }
105 
106  if (entries && targetTLI <= lasttli)
107  {
108  pg_log_error("invalid data in history file");
109  pg_log_error_detail("Timeline IDs must be less than child timeline's ID.");
110  exit(1);
111  }
112 
113  /*
114  * Create one more entry for the "tip" of the timeline, which has no entry
115  * in the history file.
116  */
117  nlines++;
118  if (entries)
119  entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry));
120  else
121  entries = pg_malloc(1 * sizeof(TimeLineHistoryEntry));
122 
123  entry = &entries[nlines - 1];
124  entry->tli = targetTLI;
125  entry->begin = prevend;
126  entry->end = InvalidXLogRecPtr;
127 
128  *nentries = nlines;
129  return entries;
130 }
TimeLineHistoryEntry * rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
Definition: timeline.c:29
unsigned int uint32
Definition: c.h:495
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
exit(1)
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_detail(...)
Definition: logging.h:109
XLogRecPtr begin
Definition: timeline.h:28
TimeLineID tli
Definition: timeline.h:27
XLogRecPtr end
Definition: timeline.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
uint32 TimeLineID
Definition: xlogdefs.h:59