From a62e427ba8d0ba2f4adaf722e728c70ec58a3621 Mon Sep 17 00:00:00 2001 From: dilipkumar Date: Mon, 4 Oct 2021 13:50:44 +0530 Subject: [PATCH v9 2/6] Extend relmap interfaces Support new interfaces in relmapper, 1) Support copying the relmap file from one database path to the other database path. 2) And another interface for getting filenode from oid. We already have RelationMapOidToFilenode for the same purpose but that assumes we are connected to the database for which we want to get the mapping. So this new interface will do the same but instead, it will get the mapping for the input database. These interfaces are required for next patch, for supporting the wal logged created database. --- src/backend/utils/cache/relmapper.c | 123 +++++++++++++++++++++++++++++++----- src/include/utils/relmapper.h | 6 +- 2 files changed, 113 insertions(+), 16 deletions(-) diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c index 56495f0..86a85c8 100644 --- a/src/backend/utils/cache/relmapper.c +++ b/src/backend/utils/cache/relmapper.c @@ -141,7 +141,7 @@ static void read_relmap_file(char *mapfilename, RelMapFile *map, static void write_relmap_file_internal(char *mapfilename, RelMapFile *newmap, bool write_wal, bool send_sinval, bool preserve_files, Oid dbid, Oid tsid, - const char *dbpath); + const char *dbpath, bool create); static void load_relmap_file(bool shared, bool lock_held); static void write_relmap_file(bool shared, RelMapFile *newmap, bool write_wal, bool send_sinval, bool preserve_files, @@ -256,6 +256,37 @@ RelationMapFilenodeToOid(Oid filenode, bool shared) } /* + * RelationMapOidToFilenodeForDatabase + * + * Same as RelationMapOidToFilenode, but instead of reading the mapping from + * the database we are connected to it will read the mapping from the input + * database. + */ +Oid +RelationMapOidToFilenodeForDatabase(char *dbpath, Oid relationId) +{ + RelMapFile map; + int i; + char mapfilename[MAXPGPATH]; + + /* Relmap file path for the given dbpath. */ + snprintf(mapfilename, sizeof(mapfilename), "%s/%s", + dbpath, RELMAPPER_FILENAME); + + /* Read the relmap file from the source database. */ + read_relmap_file(mapfilename, &map, false); + + /* Iterate over the relmap entries to find the input relation oid. */ + for (i = 0; i < map.num_mappings; i++) + { + if (relationId == map.mappings[i].mapoid) + return map.mappings[i].mapfilenode; + } + + return InvalidOid; +} + +/* * RelationMapUpdateMap * * Install a new relfilenode mapping for the specified relation. @@ -693,7 +724,43 @@ RestoreRelationMap(char *startAddress) } /* - * read_relmap_file -- read data from given mapfilename file. + * CopyRelationMap + * + * Copy relmapfile from source db path to the destination db path and WAL log + * the operation. This function is only called during the create database, so + * the destination database is not yet visible to anyone else, thus we don't + * need to acquire the relmap lock while updating the destination relmap. + */ +void +CopyRelationMap(Oid dbid, Oid tsid, char *srcdbpath, char *dstdbpath) +{ + RelMapFile map; + char mapfilename[MAXPGPATH]; + + /* Relmap file path of the source database. */ + snprintf(mapfilename, sizeof(mapfilename), "%s/%s", + srcdbpath, RELMAPPER_FILENAME); + + /* Read the relmap file from the source database. */ + read_relmap_file(mapfilename, &map, false); + + /* Relmap file path of the destination database. */ + snprintf(mapfilename, sizeof(mapfilename), "%s/%s", + dstdbpath, RELMAPPER_FILENAME); + + /* + * Write map contents into the destination database's relmap file. + * write_relmap_file_internal, expects that the CRC should have been + * computed and stored in the input map. But, since we have read this map + * from the source database and directly writing to the destination file + * without updating it so we don't need to recompute it. + */ + write_relmap_file_internal(mapfilename, &map, true, false, true, dbid, + tsid, dstdbpath, true); +} + +/* + * read_relmap_file - read data from given mapfilename file. * * Because the map file is essential for access to core system catalogs, * failure to read it is a fatal error. @@ -796,15 +863,18 @@ load_relmap_file(bool shared, bool lock_held) } /* - * Helper function for write_relmap_file, Read comments atop write_relmap_file - * for more details. The CRC should be computed by the caller and stored in - * the newmap. + * Helper function for write_relmap_file and CopyRelationMap, Read comments + * atop write_relmap_file for more details. The CRC should be computed by the + * caller and stored in the newmap. + * + * Pass the create = true, if we are copying the relmap file during CREATE + * DATABASE command. */ static void write_relmap_file_internal(char *mapfilename, RelMapFile *newmap, bool write_wal, bool send_sinval, bool preserve_files, Oid dbid, Oid tsid, - const char *dbpath) + const char *dbpath, bool create) { int fd; @@ -830,6 +900,7 @@ write_relmap_file_internal(char *mapfilename, RelMapFile *newmap, xlrec.dbid = dbid; xlrec.tsid = tsid; xlrec.nbytes = sizeof(RelMapFile); + xlrec.create = create; XLogBeginInsert(); XLogRegisterData((char *) (&xlrec), MinSizeOfRelmapUpdate); @@ -971,7 +1042,7 @@ write_relmap_file(bool shared, RelMapFile *newmap, /* Write the map to the relmap file. */ write_relmap_file_internal(mapfilename, newmap, write_wal, send_sinval, preserve_files, dbid, tsid, - dbpath); + dbpath, false); /* * Success, update permanent copy. During bootstrap, we might be working @@ -1063,15 +1134,37 @@ relmap_redo(XLogReaderState *record) * Write out the new map and send sinval, but of course don't write a * new WAL entry. There's no surrounding transaction to tell to * preserve files, either. - * - * There shouldn't be anyone else updating relmaps during WAL replay, - * but grab the lock to interlock against load_relmap_file(). */ - LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE); - write_relmap_file((xlrec->dbid == InvalidOid), &newmap, - false, true, false, - xlrec->dbid, xlrec->tsid, dbpath); - LWLockRelease(RelationMappingLock); + if (!xlrec->create) + { + /* + * There shouldn't be anyone else updating relmaps during WAL + * replay, but grab the lock to interlock against + * load_relmap_file(). + */ + LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE); + write_relmap_file((xlrec->dbid == InvalidOid), &newmap, + false, true, false, + xlrec->dbid, xlrec->tsid, dbpath); + LWLockRelease(RelationMappingLock); + } + else + { + char mapfilename[MAXPGPATH]; + + /* Construct the mapfilename. */ + snprintf(mapfilename, sizeof(mapfilename), "%s/%s", + dbpath, RELMAPPER_FILENAME); + + /* + * We don't need to take relmap lock because this wal is logged + * while creating a new database, so there could be no one else + * reading/writing the relmap file. + */ + write_relmap_file_internal(mapfilename, &newmap, false, false, + false, xlrec->dbid, xlrec->tsid, dbpath, + true); + } pfree(dbpath); } diff --git a/src/include/utils/relmapper.h b/src/include/utils/relmapper.h index 9fbb5a7..e5635bd 100644 --- a/src/include/utils/relmapper.h +++ b/src/include/utils/relmapper.h @@ -29,6 +29,7 @@ typedef struct xl_relmap_update Oid dbid; /* database ID, or 0 for shared map */ Oid tsid; /* database's tablespace, or pg_global */ int32 nbytes; /* size of relmap data */ + bool create; /* true if creating new relmap */ char data[FLEXIBLE_ARRAY_MEMBER]; } xl_relmap_update; @@ -39,6 +40,8 @@ extern Oid RelationMapOidToFilenode(Oid relationId, bool shared); extern Oid RelationMapFilenodeToOid(Oid relationId, bool shared); +extern Oid RelationMapOidToFilenodeForDatabase(char *dbpath, Oid relationId); + extern void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate); @@ -62,7 +65,8 @@ extern void RelationMapInitializePhase3(void); extern Size EstimateRelationMapSpace(void); extern void SerializeRelationMap(Size maxSize, char *startAddress); extern void RestoreRelationMap(char *startAddress); - +extern void CopyRelationMap(Oid dbid, Oid tsid, char *srcdbpath, + char *dstdbpath); extern void relmap_redo(XLogReaderState *record); extern void relmap_desc(StringInfo buf, XLogReaderState *record); extern const char *relmap_identify(uint8 info); -- 1.8.3.1