@@ -137,8 +137,10 @@ static void apply_map_update(RelMapFile *map, Oid relationId, Oid fileNode,
137
137
static void merge_map_updates (RelMapFile * map , const RelMapFile * updates ,
138
138
bool add_okay );
139
139
static 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 ,
142
144
Oid dbid , Oid tsid , const char * dbpath );
143
145
static void perform_relmap_update (bool shared , const RelMapFile * updates );
144
146
@@ -568,9 +570,9 @@ RelationMapFinishBootstrap(void)
568
570
Assert (pending_local_updates .num_mappings == 0 );
569
571
570
572
/* 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,
574
576
MyDatabaseId , MyDatabaseTableSpace , DatabasePath );
575
577
}
576
578
@@ -687,39 +689,48 @@ RestoreRelationMap(char *startAddress)
687
689
}
688
690
689
691
/*
690
- * load_relmap_file -- load data from the shared or local map file
692
+ * load_relmap_file -- load the shared or local map file
691
693
*
692
- * Because the map file is essential for access to core system catalogs,
693
- * failure to read it is a fatal error.
694
+ * Because these files are essential for access to core system catalogs,
695
+ * failure to load either of them is a fatal error.
694
696
*
695
697
* Note that the local case requires DatabasePath to be set up.
696
698
*/
697
699
static void
698
700
load_relmap_file (bool shared , bool lock_held )
699
701
{
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
+ {
701
721
char mapfilename [MAXPGPATH ];
702
722
pg_crc32c crc ;
703
723
int fd ;
704
724
int r ;
705
725
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 );
718
727
719
- /* Read data ... */
728
+ /* Open the target file. */
729
+ snprintf (mapfilename , sizeof (mapfilename ), "%s/%s" , dbpath ,
730
+ RELMAPPER_FILENAME );
720
731
fd = OpenTransientFile (mapfilename , O_RDONLY | PG_BINARY );
721
732
if (fd < 0 )
722
- ereport (FATAL ,
733
+ ereport (elevel ,
723
734
(errcode_for_file_access (),
724
735
errmsg ("could not open file \"%s\": %m" ,
725
736
mapfilename )));
@@ -734,16 +745,17 @@ load_relmap_file(bool shared, bool lock_held)
734
745
if (!lock_held )
735
746
LWLockAcquire (RelationMappingLock , LW_SHARED );
736
747
748
+ /* Now read the data. */
737
749
pgstat_report_wait_start (WAIT_EVENT_RELATION_MAP_READ );
738
750
r = read (fd , map , sizeof (RelMapFile ));
739
751
if (r != sizeof (RelMapFile ))
740
752
{
741
753
if (r < 0 )
742
- ereport (FATAL ,
754
+ ereport (elevel ,
743
755
(errcode_for_file_access (),
744
756
errmsg ("could not read file \"%s\": %m" , mapfilename )));
745
757
else
746
- ereport (FATAL ,
758
+ ereport (elevel ,
747
759
(errcode (ERRCODE_DATA_CORRUPTED ),
748
760
errmsg ("could not read file \"%s\": read %d of %zu" ,
749
761
mapfilename , r , sizeof (RelMapFile ))));
@@ -754,7 +766,7 @@ load_relmap_file(bool shared, bool lock_held)
754
766
LWLockRelease (RelationMappingLock );
755
767
756
768
if (CloseTransientFile (fd ) != 0 )
757
- ereport (FATAL ,
769
+ ereport (elevel ,
758
770
(errcode_for_file_access (),
759
771
errmsg ("could not close file \"%s\": %m" ,
760
772
mapfilename )));
@@ -763,7 +775,7 @@ load_relmap_file(bool shared, bool lock_held)
763
775
if (map -> magic != RELMAPPER_FILEMAGIC ||
764
776
map -> num_mappings < 0 ||
765
777
map -> num_mappings > MAX_MAPPINGS )
766
- ereport (FATAL ,
778
+ ereport (elevel ,
767
779
(errmsg ("relation mapping file \"%s\" contains invalid data" ,
768
780
mapfilename )));
769
781
@@ -773,7 +785,7 @@ load_relmap_file(bool shared, bool lock_held)
773
785
FIN_CRC32C (crc );
774
786
775
787
if (!EQ_CRC32C (crc , map -> crc ))
776
- ereport (FATAL ,
788
+ ereport (elevel ,
777
789
(errmsg ("relation mapping file \"%s\" contains incorrect checksum" ,
778
790
mapfilename )));
779
791
}
@@ -795,16 +807,16 @@ load_relmap_file(bool shared, bool lock_held)
795
807
*
796
808
* Because this may be called during WAL replay when MyDatabaseId,
797
809
* 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.
800
814
*/
801
815
static 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 )
805
818
{
806
819
int fd ;
807
- RelMapFile * realmap ;
808
820
char mapfilename [MAXPGPATH ];
809
821
810
822
/*
@@ -822,19 +834,8 @@ write_relmap_file(bool shared, RelMapFile *newmap,
822
834
* Open the target file. We prefer to do this before entering the
823
835
* critical section, so that an open() failure need not force PANIC.
824
836
*/
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 );
838
839
fd = OpenTransientFile (mapfilename , O_WRONLY | O_CREAT | PG_BINARY );
839
840
if (fd < 0 )
840
841
ereport (ERROR ,
@@ -934,16 +935,6 @@ write_relmap_file(bool shared, RelMapFile *newmap,
934
935
}
935
936
}
936
937
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
-
947
938
/* Critical section done */
948
939
if (write_wal )
949
940
END_CRIT_SECTION ();
@@ -990,10 +981,19 @@ perform_relmap_update(bool shared, const RelMapFile *updates)
990
981
merge_map_updates (& newmap , updates , allowSystemTableMods );
991
982
992
983
/* 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,
994
985
(shared ? InvalidOid : MyDatabaseId ),
995
986
(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 ));
997
997
998
998
/* Now we can release the lock */
999
999
LWLockRelease (RelationMappingLock );
@@ -1033,8 +1033,7 @@ relmap_redo(XLogReaderState *record)
1033
1033
* but grab the lock to interlock against load_relmap_file().
1034
1034
*/
1035
1035
LWLockAcquire (RelationMappingLock , LW_EXCLUSIVE );
1036
- write_relmap_file ((xlrec -> dbid == InvalidOid ), & newmap ,
1037
- false, true, false,
1036
+ write_relmap_file (& newmap , false, true, false,
1038
1037
xlrec -> dbid , xlrec -> tsid , dbpath );
1039
1038
LWLockRelease (RelationMappingLock );
1040
1039
0 commit comments