@@ -54,164 +54,6 @@ bool InRecovery = false;
54
54
/* Are we in Hot Standby mode? Only valid in startup process, see xlogutils.h */
55
55
HotStandbyState standbyState = STANDBY_DISABLED ;
56
56
57
-
58
- /*
59
- * If a create database WAL record is being replayed more than once during
60
- * crash recovery on a standby, it is possible that either the tablespace
61
- * directory or the template database directory is missing. This happens when
62
- * the directories are removed by replay of subsequent drop records. Note
63
- * that this problem happens only on standby and not on master. On master, a
64
- * checkpoint is created at the end of create database operation. On standby,
65
- * however, such a strategy (creating restart points during replay) is not
66
- * viable because it will slow down WAL replay.
67
- *
68
- * The alternative is to track references to each missing directory
69
- * encountered when performing crash recovery in the following hash table.
70
- * Similar to invalid page table above, the expectation is that each missing
71
- * directory entry should be matched with a drop database or drop tablespace
72
- * WAL record by the end of crash recovery.
73
- */
74
- typedef struct xl_missing_dir_key
75
- {
76
- Oid spcNode ;
77
- Oid dbNode ;
78
- } xl_missing_dir_key ;
79
-
80
- typedef struct xl_missing_dir
81
- {
82
- xl_missing_dir_key key ;
83
- char path [MAXPGPATH ];
84
- } xl_missing_dir ;
85
-
86
- static HTAB * missing_dir_tab = NULL ;
87
-
88
-
89
- /*
90
- * Keep track of a directory that wasn't found while replaying database
91
- * creation records. These should match up with tablespace removal records
92
- * later in the WAL stream; we verify that before reaching consistency.
93
- */
94
- void
95
- XLogRememberMissingDir (Oid spcNode , Oid dbNode , char * path )
96
- {
97
- xl_missing_dir_key key ;
98
- bool found ;
99
- xl_missing_dir * entry ;
100
-
101
- /*
102
- * Database OID may be invalid but tablespace OID must be valid. If
103
- * dbNode is InvalidOid, we are logging a missing tablespace directory,
104
- * otherwise we are logging a missing database directory.
105
- */
106
- Assert (OidIsValid (spcNode ));
107
-
108
- if (missing_dir_tab == NULL )
109
- {
110
- /* create hash table when first needed */
111
- HASHCTL ctl ;
112
-
113
- memset (& ctl , 0 , sizeof (ctl ));
114
- ctl .keysize = sizeof (xl_missing_dir_key );
115
- ctl .entrysize = sizeof (xl_missing_dir );
116
-
117
- missing_dir_tab = hash_create ("XLOG missing directory table" ,
118
- 100 ,
119
- & ctl ,
120
- HASH_ELEM | HASH_BLOBS );
121
- }
122
-
123
- key .spcNode = spcNode ;
124
- key .dbNode = dbNode ;
125
-
126
- entry = hash_search (missing_dir_tab , & key , HASH_ENTER , & found );
127
-
128
- if (found )
129
- {
130
- if (dbNode == InvalidOid )
131
- elog (DEBUG1 , "missing directory %s (tablespace %u) already exists: %s" ,
132
- path , spcNode , entry -> path );
133
- else
134
- elog (DEBUG1 , "missing directory %s (tablespace %u database %u) already exists: %s" ,
135
- path , spcNode , dbNode , entry -> path );
136
- }
137
- else
138
- {
139
- strlcpy (entry -> path , path , sizeof (entry -> path ));
140
- if (dbNode == InvalidOid )
141
- elog (DEBUG1 , "logged missing dir %s (tablespace %u)" ,
142
- path , spcNode );
143
- else
144
- elog (DEBUG1 , "logged missing dir %s (tablespace %u database %u)" ,
145
- path , spcNode , dbNode );
146
- }
147
- }
148
-
149
- /*
150
- * Remove an entry from the list of directories not found. This is to be done
151
- * when the matching tablespace removal WAL record is found.
152
- */
153
- void
154
- XLogForgetMissingDir (Oid spcNode , Oid dbNode )
155
- {
156
- xl_missing_dir_key key ;
157
-
158
- key .spcNode = spcNode ;
159
- key .dbNode = dbNode ;
160
-
161
- /* Database OID may be invalid but tablespace OID must be valid. */
162
- Assert (OidIsValid (spcNode ));
163
-
164
- if (missing_dir_tab == NULL )
165
- return ;
166
-
167
- if (hash_search (missing_dir_tab , & key , HASH_REMOVE , NULL ) != NULL )
168
- {
169
- if (dbNode == InvalidOid )
170
- {
171
- elog (DEBUG2 , "forgot missing dir (tablespace %u)" , spcNode );
172
- }
173
- else
174
- {
175
- char * path = GetDatabasePath (dbNode , spcNode );
176
-
177
- elog (DEBUG2 , "forgot missing dir %s (tablespace %u database %u)" ,
178
- path , spcNode , dbNode );
179
- pfree (path );
180
- }
181
- }
182
- }
183
-
184
- /*
185
- * This is called at the end of crash recovery, before entering archive
186
- * recovery on a standby. PANIC if the hash table is not empty.
187
- */
188
- void
189
- XLogCheckMissingDirs (void )
190
- {
191
- HASH_SEQ_STATUS status ;
192
- xl_missing_dir * hentry ;
193
- bool foundone = false;
194
-
195
- if (missing_dir_tab == NULL )
196
- return ; /* nothing to do */
197
-
198
- hash_seq_init (& status , missing_dir_tab );
199
-
200
- while ((hentry = (xl_missing_dir * ) hash_seq_search (& status )) != NULL )
201
- {
202
- elog (WARNING , "missing directory \"%s\" tablespace %u database %u" ,
203
- hentry -> path , hentry -> key .spcNode , hentry -> key .dbNode );
204
- foundone = true;
205
- }
206
-
207
- if (foundone )
208
- elog (PANIC , "WAL contains references to missing directories" );
209
-
210
- hash_destroy (missing_dir_tab );
211
- missing_dir_tab = NULL ;
212
- }
213
-
214
-
215
57
/*
216
58
* During XLOG replay, we may see XLOG records for incremental updates of
217
59
* pages that no longer exist, because their relation was later dropped or
@@ -237,6 +79,7 @@ typedef struct xl_invalid_page
237
79
238
80
static HTAB * invalid_page_tab = NULL ;
239
81
82
+
240
83
/* Report a reference to an invalid page */
241
84
static void
242
85
report_invalid_page (int elevel , RelFileNode node , ForkNumber forkno ,
0 commit comments