1717
1818static void transfer_single_new_db (pageCnvCtx * pageConverter ,
1919FileNameMap * maps ,int size );
20- static void transfer_relfile (pageCnvCtx * pageConverter ,
21- const char * fromfile ,const char * tofile ,
22- const char * nspname ,const char * relname );
20+ static void transfer_relfile (pageCnvCtx * pageConverter ,FileNameMap * map ,
21+ const char * suffix );
2322
2423
2524/*
@@ -131,123 +130,33 @@ static void
131130transfer_single_new_db (pageCnvCtx * pageConverter ,
132131FileNameMap * maps ,int size )
133132{
134- char old_dir [MAXPGPATH ];
135- char file_pattern [MAXPGPATH ];
136- char * * namelist = NULL ;
137- int numFiles = 0 ;
138133int mapnum ;
139- int fileno ;
140- bool vm_crashsafe_change = false;
141-
142- old_dir [ 0 ] = '\0' ;
143-
144- /* Do not copy non-crashsafe vm files for binaries that assume crashsafety */
134+ bool vm_crashsafe_match = true ;
135+
136+ /*
137+ * Do the old and new cluster disagree on the crash-safetiness of the vm
138+ * files? If so, do not copy them.
139+ */
145140if (old_cluster .controldata .cat_ver < VISIBILITY_MAP_CRASHSAFE_CAT_VER &&
146141new_cluster .controldata .cat_ver >=VISIBILITY_MAP_CRASHSAFE_CAT_VER )
147- vm_crashsafe_change = true ;
142+ vm_crashsafe_match = false ;
148143
149144for (mapnum = 0 ;mapnum < size ;mapnum ++ )
150145{
151- char old_file [MAXPGPATH ];
152- char new_file [MAXPGPATH ];
153-
154- /* Changed tablespaces? Need a new directory scan? */
155- if (strcmp (maps [mapnum ].old_dir ,old_dir )!= 0 )
156- {
157- if (numFiles > 0 )
158- {
159- for (fileno = 0 ;fileno < numFiles ;fileno ++ )
160- pg_free (namelist [fileno ]);
161- pg_free (namelist );
162- }
163-
164- snprintf (old_dir ,sizeof (old_dir ),"%s" ,maps [mapnum ].old_dir );
165- numFiles = load_directory (old_dir ,& namelist );
166- }
167-
168- /* Copying files might take some time, so give feedback. */
169-
170- snprintf (old_file ,sizeof (old_file ),"%s/%u" ,maps [mapnum ].old_dir ,
171- maps [mapnum ].old_relfilenode );
172- snprintf (new_file ,sizeof (new_file ),"%s/%u" ,maps [mapnum ].new_dir ,
173- maps [mapnum ].new_relfilenode );
174- pg_log (PG_REPORT ,OVERWRITE_MESSAGE ,old_file );
175-
176- /*
177- * Copy/link the relation's primary file (segment 0 of main fork)
178- * to the new cluster
179- */
180- unlink (new_file );
181- transfer_relfile (pageConverter ,old_file ,new_file ,
182- maps [mapnum ].nspname ,maps [mapnum ].relname );
146+ /* transfer primary file */
147+ transfer_relfile (pageConverter ,& maps [mapnum ],"" );
183148
184149/* fsm/vm files added in PG 8.4 */
185150if (GET_MAJOR_VERSION (old_cluster .major_version ) >=804 )
186151{
187152/*
188153 * Copy/link any fsm and vm files, if they exist
189154 */
190- snprintf (file_pattern ,sizeof (file_pattern ),"%u_" ,
191- maps [mapnum ].old_relfilenode );
192-
193- for (fileno = 0 ;fileno < numFiles ;fileno ++ )
194- {
195- char * vm_offset = strstr (namelist [fileno ],"_vm" );
196- bool is_vm_file = false;
197-
198- /* Is a visibility map file? (name ends with _vm) */
199- if (vm_offset && strlen (vm_offset )== strlen ("_vm" ))
200- is_vm_file = true;
201-
202- if (strncmp (namelist [fileno ],file_pattern ,
203- strlen (file_pattern ))== 0 &&
204- (!is_vm_file || !vm_crashsafe_change ))
205- {
206- snprintf (old_file ,sizeof (old_file ),"%s/%s" ,maps [mapnum ].old_dir ,
207- namelist [fileno ]);
208- snprintf (new_file ,sizeof (new_file ),"%s/%u%s" ,maps [mapnum ].new_dir ,
209- maps [mapnum ].new_relfilenode ,strchr (namelist [fileno ],'_' ));
210-
211- unlink (new_file );
212- transfer_relfile (pageConverter ,old_file ,new_file ,
213- maps [mapnum ].nspname ,maps [mapnum ].relname );
214- }
215- }
216- }
217-
218- /*
219- * Now copy/link any related segments as well. Remember, PG breaks
220- * large files into 1GB segments, the first segment has no extension,
221- * subsequent segments are named relfilenode.1, relfilenode.2,
222- * relfilenode.3, ... 'fsm' and 'vm' files use underscores so are not
223- * copied.
224- */
225- snprintf (file_pattern ,sizeof (file_pattern ),"%u." ,
226- maps [mapnum ].old_relfilenode );
227-
228- for (fileno = 0 ;fileno < numFiles ;fileno ++ )
229- {
230- if (strncmp (namelist [fileno ],file_pattern ,
231- strlen (file_pattern ))== 0 )
232- {
233- snprintf (old_file ,sizeof (old_file ),"%s/%s" ,maps [mapnum ].old_dir ,
234- namelist [fileno ]);
235- snprintf (new_file ,sizeof (new_file ),"%s/%u%s" ,maps [mapnum ].new_dir ,
236- maps [mapnum ].new_relfilenode ,strchr (namelist [fileno ],'.' ));
237-
238- unlink (new_file );
239- transfer_relfile (pageConverter ,old_file ,new_file ,
240- maps [mapnum ].nspname ,maps [mapnum ].relname );
241- }
155+ transfer_relfile (pageConverter ,& maps [mapnum ],"_fsm" );
156+ if (vm_crashsafe_match )
157+ transfer_relfile (pageConverter ,& maps [mapnum ],"_vm" );
242158}
243159}
244-
245- if (numFiles > 0 )
246- {
247- for (fileno = 0 ;fileno < numFiles ;fileno ++ )
248- pg_free (namelist [fileno ]);
249- pg_free (namelist );
250- }
251160}
252161
253162
@@ -257,31 +166,78 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
257166 * Copy or link file from old cluster to new one.
258167 */
259168static void
260- transfer_relfile (pageCnvCtx * pageConverter ,const char * old_file ,
261- const char * new_file , const char * nspname , const char * relname )
169+ transfer_relfile (pageCnvCtx * pageConverter ,FileNameMap * map ,
170+ const char * type_suffix )
262171{
263172const char * msg ;
264-
265- if ((user_opts .transfer_mode == TRANSFER_MODE_LINK )&& (pageConverter != NULL ))
266- pg_log (PG_FATAL ,"This upgrade requires page-by-page conversion, "
267- "you must use copy mode instead of link mode.\n" );
268-
269- if (user_opts .transfer_mode == TRANSFER_MODE_COPY )
173+ char old_file [MAXPGPATH ];
174+ char new_file [MAXPGPATH ];
175+ int fd ;
176+ int segno ;
177+ char extent_suffix [65 ];
178+
179+ /*
180+ * Now copy/link any related segments as well. Remember, PG breaks
181+ * large files into 1GB segments, the first segment has no extension,
182+ * subsequent segments are named relfilenode.1, relfilenode.2,
183+ * relfilenode.3.
184+ * copied.
185+ */
186+ for (segno = 0 ;;segno ++ )
270187{
271- pg_log (PG_VERBOSE ,"copying \"%s\" to \"%s\"\n" ,old_file ,new_file );
188+ if (segno == 0 )
189+ extent_suffix [0 ]= '\0' ;
190+ else
191+ snprintf (extent_suffix ,sizeof (extent_suffix ),".%d" ,segno );
192+
193+ snprintf (old_file ,sizeof (old_file ),"%s/%u%s%s" ,map -> old_dir ,
194+ map -> old_relfilenode ,type_suffix ,extent_suffix );
195+ snprintf (new_file ,sizeof (new_file ),"%s/%u%s%s" ,map -> new_dir ,
196+ map -> new_relfilenode ,type_suffix ,extent_suffix );
197+
198+ /* Is it an extent, fsm, or vm file? */
199+ if (type_suffix [0 ]!= '\0' || segno != 0 )
200+ {
201+ /* Did file open fail? */
202+ if ((fd = open (old_file ,O_RDONLY ))== -1 )
203+ {
204+ /* File does not exist? That's OK, just return */
205+ if (errno == ENOENT )
206+ return ;
207+ else
208+ pg_log (PG_FATAL ,"non-existant file error while copying relation \"%s.%s\" (\"%s\" to \"%s\")\n" ,
209+ map -> nspname ,map -> relname ,old_file ,new_file );
210+ }
211+ close (fd );
212+ }
272213
273- if ((msg = copyAndUpdateFile (pageConverter ,old_file ,new_file , true))!= NULL )
274- pg_log (PG_FATAL ,"error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" ,
275- nspname ,relname ,old_file ,new_file ,msg );
276- }
277- else
278- {
279- pg_log (PG_VERBOSE ,"linking \"%s\" to \"%s\"\n" ,old_file ,new_file );
214+ unlink (new_file );
215+
216+ /* Copying files might take some time, so give feedback. */
217+ pg_log (PG_REPORT ,OVERWRITE_MESSAGE ,old_file );
218+
219+ if ((user_opts .transfer_mode == TRANSFER_MODE_LINK )&& (pageConverter != NULL ))
220+ pg_log (PG_FATAL ,"This upgrade requires page-by-page conversion, "
221+ "you must use copy mode instead of link mode.\n" );
222+
223+ if (user_opts .transfer_mode == TRANSFER_MODE_COPY )
224+ {
225+ pg_log (PG_VERBOSE ,"copying \"%s\" to \"%s\"\n" ,old_file ,new_file );
226+
227+ if ((msg = copyAndUpdateFile (pageConverter ,old_file ,new_file , true))!= NULL )
228+ pg_log (PG_FATAL ,"error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" ,
229+ map -> nspname ,map -> relname ,old_file ,new_file ,msg );
230+ }
231+ else
232+ {
233+ pg_log (PG_VERBOSE ,"linking \"%s\" to \"%s\"\n" ,old_file ,new_file );
234+
235+ if ((msg = linkAndUpdateFile (pageConverter ,old_file ,new_file ))!= NULL )
236+ pg_log (PG_FATAL ,
237+ "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" ,
238+ map -> nspname ,map -> relname ,old_file ,new_file ,msg );
239+ }
240+ }
280241
281- if ((msg = linkAndUpdateFile (pageConverter ,old_file ,new_file ))!= NULL )
282- pg_log (PG_FATAL ,
283- "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" ,
284- nspname ,relname ,old_file ,new_file ,msg );
285- }
286242return ;
287243}