@@ -137,8 +137,10 @@ static void apply_map_update(RelMapFile *map, Oid relationId, Oid fileNode,
137137static void merge_map_updates (RelMapFile * map ,const RelMapFile * updates ,
138138bool add_okay );
139139static void load_relmap_file (bool shared ,bool lock_held );
140- static void write_relmap_file (bool shared ,RelMapFile * newmap ,
141- bool write_wal ,bool send_sinval ,bool preserve_files ,
140+ static void read_relmap_file (RelMapFile * map ,char * dbpath ,bool lock_held ,
141+ int elevel );
142+ static void write_relmap_file (RelMapFile * newmap ,bool write_wal ,
143+ bool send_sinval ,bool preserve_files ,
142144Oid dbid ,Oid tsid ,const char * dbpath );
143145static void perform_relmap_update (bool shared ,const RelMapFile * updates );
144146
@@ -568,9 +570,9 @@ RelationMapFinishBootstrap(void)
568570Assert (pending_local_updates .num_mappings == 0 );
569571
570572/* Write the files; no WAL or sinval needed */
571- write_relmap_file (true, & shared_map , false, false, false,
572- InvalidOid ,GLOBALTABLESPACE_OID ,NULL );
573- write_relmap_file (false, & local_map , false, false, false,
573+ write_relmap_file (& shared_map , false, false, false,
574+ InvalidOid ,GLOBALTABLESPACE_OID ,"global" );
575+ write_relmap_file (& local_map , false, false, false,
574576MyDatabaseId ,MyDatabaseTableSpace ,DatabasePath );
575577}
576578
@@ -687,39 +689,48 @@ RestoreRelationMap(char *startAddress)
687689}
688690
689691/*
690- * load_relmap_file -- loaddata from the shared or local map file
692+ * load_relmap_file -- load the shared or local map file
691693 *
692- * Becausethe map file is essential for access to core system catalogs,
693- * failure toread it is a fatal error.
694+ * Becausethese files are essential for access to core system catalogs,
695+ * failure toload either of them is a fatal error.
694696 *
695697 * Note that the local case requires DatabasePath to be set up.
696698 */
697699static void
698700load_relmap_file (bool shared ,bool lock_held )
699701{
700- RelMapFile * map ;
702+ if (shared )
703+ read_relmap_file (& shared_map ,"global" ,lock_held ,FATAL );
704+ else
705+ read_relmap_file (& local_map ,DatabasePath ,lock_held ,FATAL );
706+ }
707+
708+ /*
709+ * read_relmap_file -- load data from any relation mapper file
710+ *
711+ * dbpath must be the relevant database path, or "global" for shared relations.
712+ *
713+ * RelationMappingLock will be acquired released unless lock_held = true.
714+ *
715+ * Errors will be reported at the indicated elevel, which should be at least
716+ * ERROR.
717+ */
718+ static void
719+ read_relmap_file (RelMapFile * map ,char * dbpath ,bool lock_held ,int elevel )
720+ {
701721char mapfilename [MAXPGPATH ];
702722pg_crc32c crc ;
703723int fd ;
704724int r ;
705725
706- if (shared )
707- {
708- snprintf (mapfilename ,sizeof (mapfilename ),"global/%s" ,
709- RELMAPPER_FILENAME );
710- map = & shared_map ;
711- }
712- else
713- {
714- snprintf (mapfilename ,sizeof (mapfilename ),"%s/%s" ,
715- DatabasePath ,RELMAPPER_FILENAME );
716- map = & local_map ;
717- }
726+ Assert (elevel >=ERROR );
718727
719- /* Read data ... */
728+ /* Open the target file. */
729+ snprintf (mapfilename ,sizeof (mapfilename ),"%s/%s" ,dbpath ,
730+ RELMAPPER_FILENAME );
720731fd = OpenTransientFile (mapfilename ,O_RDONLY |PG_BINARY );
721732if (fd < 0 )
722- ereport (FATAL ,
733+ ereport (elevel ,
723734(errcode_for_file_access (),
724735errmsg ("could not open file \"%s\": %m" ,
725736mapfilename )));
@@ -734,16 +745,17 @@ load_relmap_file(bool shared, bool lock_held)
734745if (!lock_held )
735746LWLockAcquire (RelationMappingLock ,LW_SHARED );
736747
748+ /* Now read the data. */
737749pgstat_report_wait_start (WAIT_EVENT_RELATION_MAP_READ );
738750r = read (fd ,map ,sizeof (RelMapFile ));
739751if (r != sizeof (RelMapFile ))
740752{
741753if (r < 0 )
742- ereport (FATAL ,
754+ ereport (elevel ,
743755(errcode_for_file_access (),
744756errmsg ("could not read file \"%s\": %m" ,mapfilename )));
745757else
746- ereport (FATAL ,
758+ ereport (elevel ,
747759(errcode (ERRCODE_DATA_CORRUPTED ),
748760errmsg ("could not read file \"%s\": read %d of %zu" ,
749761mapfilename ,r ,sizeof (RelMapFile ))));
@@ -754,7 +766,7 @@ load_relmap_file(bool shared, bool lock_held)
754766LWLockRelease (RelationMappingLock );
755767
756768if (CloseTransientFile (fd )!= 0 )
757- ereport (FATAL ,
769+ ereport (elevel ,
758770(errcode_for_file_access (),
759771errmsg ("could not close file \"%s\": %m" ,
760772mapfilename )));
@@ -763,7 +775,7 @@ load_relmap_file(bool shared, bool lock_held)
763775if (map -> magic != RELMAPPER_FILEMAGIC ||
764776map -> num_mappings < 0 ||
765777map -> num_mappings > MAX_MAPPINGS )
766- ereport (FATAL ,
778+ ereport (elevel ,
767779(errmsg ("relation mapping file \"%s\" contains invalid data" ,
768780mapfilename )));
769781
@@ -773,7 +785,7 @@ load_relmap_file(bool shared, bool lock_held)
773785FIN_CRC32C (crc );
774786
775787if (!EQ_CRC32C (crc ,map -> crc ))
776- ereport (FATAL ,
788+ ereport (elevel ,
777789(errmsg ("relation mapping file \"%s\" contains incorrect checksum" ,
778790mapfilename )));
779791}
@@ -795,16 +807,16 @@ load_relmap_file(bool shared, bool lock_held)
795807 *
796808 * Because this may be called during WAL replay when MyDatabaseId,
797809 * DatabasePath, etc aren't valid, we require the caller to pass in suitable
798- * values. The caller is also responsible for being sure no concurrent
799- * map update could be happening.
810+ * values. Pass dbpath as "global" for the shared map.
811+ *
812+ * The caller is also responsible for being sure no concurrent map update
813+ * could be happening.
800814 */
801815static void
802- write_relmap_file (bool shared ,RelMapFile * newmap ,
803- bool write_wal ,bool send_sinval ,bool preserve_files ,
804- Oid dbid ,Oid tsid ,const char * dbpath )
816+ write_relmap_file (RelMapFile * newmap ,bool write_wal ,bool send_sinval ,
817+ bool preserve_files ,Oid dbid ,Oid tsid ,const char * dbpath )
805818{
806819int fd ;
807- RelMapFile * realmap ;
808820char mapfilename [MAXPGPATH ];
809821
810822/*
@@ -822,19 +834,8 @@ write_relmap_file(bool shared, RelMapFile *newmap,
822834 * Open the target file. We prefer to do this before entering the
823835 * critical section, so that an open() failure need not force PANIC.
824836 */
825- if (shared )
826- {
827- snprintf (mapfilename ,sizeof (mapfilename ),"global/%s" ,
828- RELMAPPER_FILENAME );
829- realmap = & shared_map ;
830- }
831- else
832- {
833- snprintf (mapfilename ,sizeof (mapfilename ),"%s/%s" ,
834- dbpath ,RELMAPPER_FILENAME );
835- realmap = & local_map ;
836- }
837-
837+ snprintf (mapfilename ,sizeof (mapfilename ),"%s/%s" ,
838+ dbpath ,RELMAPPER_FILENAME );
838839fd = OpenTransientFile (mapfilename ,O_WRONLY |O_CREAT |PG_BINARY );
839840if (fd < 0 )
840841ereport (ERROR ,
@@ -934,16 +935,6 @@ write_relmap_file(bool shared, RelMapFile *newmap,
934935}
935936}
936937
937- /*
938- * Success, update permanent copy. During bootstrap, we might be working
939- * on the permanent copy itself, in which case skip the memcpy() to avoid
940- * invoking nominally-undefined behavior.
941- */
942- if (realmap != newmap )
943- memcpy (realmap ,newmap ,sizeof (RelMapFile ));
944- else
945- Assert (!send_sinval );/* must be bootstrapping */
946-
947938/* Critical section done */
948939if (write_wal )
949940END_CRIT_SECTION ();
@@ -990,10 +981,19 @@ perform_relmap_update(bool shared, const RelMapFile *updates)
990981merge_map_updates (& newmap ,updates ,allowSystemTableMods );
991982
992983/* Write out the updated map and do other necessary tasks */
993- write_relmap_file (shared , & newmap , true, true, true,
984+ write_relmap_file (& newmap , true, true, true,
994985 (shared ?InvalidOid :MyDatabaseId ),
995986 (shared ?GLOBALTABLESPACE_OID :MyDatabaseTableSpace ),
996- DatabasePath );
987+ (shared ?"global" :DatabasePath ));
988+
989+ /*
990+ * We succesfully wrote the updated file, so it's now safe to rely on the
991+ * new values in this process, too.
992+ */
993+ if (shared )
994+ memcpy (& shared_map ,& newmap ,sizeof (RelMapFile ));
995+ else
996+ memcpy (& local_map ,& newmap ,sizeof (RelMapFile ));
997997
998998/* Now we can release the lock */
999999LWLockRelease (RelationMappingLock );
@@ -1033,8 +1033,7 @@ relmap_redo(XLogReaderState *record)
10331033 * but grab the lock to interlock against load_relmap_file().
10341034 */
10351035LWLockAcquire (RelationMappingLock ,LW_EXCLUSIVE );
1036- write_relmap_file ((xlrec -> dbid == InvalidOid ),& newmap ,
1037- false, true, false,
1036+ write_relmap_file (& newmap , false, true, false,
10381037xlrec -> dbid ,xlrec -> tsid ,dbpath );
10391038LWLockRelease (RelationMappingLock );
10401039