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