From 83a0e0539c2d5affa16addd273ba159dca557dd1 Mon Sep 17 00:00:00 2001 From: Dilip Kumar Date: Tue, 15 Mar 2022 09:18:52 +0530 Subject: [PATCH v15 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 | 60 +++++++++++++++++++++++++++++++++++++ src/include/utils/relmapper.h | 4 ++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c index c3fef70..d2e7890 100644 --- a/src/backend/utils/cache/relmapper.c +++ b/src/backend/utils/cache/relmapper.c @@ -252,6 +252,60 @@ 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; + + /* Read the relmap file from the source database. */ + read_relmap_file(&map, dbpath, false, ERROR); + + /* 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; +} + +/* + * RelationMapCopy + * + * Copy relmapfile from source db path to the destination db path and WAL log + * the operation. + */ +void +RelationMapCopy(Oid dbid, Oid tsid, char *srcdbpath, char *dstdbpath) +{ + RelMapFile map; + + /* + * Read the relmap file from the source database. This function is only + * called during the create database, so elevel can be ERROR. + */ + read_relmap_file(&map, srcdbpath, false, ERROR); + + /* + * Write map contents into the destination database's relmap file. No + * sinval needed because we are creating new file while creating a new + * database so no one else must be accessing this file and for the same + * reason we don't need to acquire the RelationMappingLock as well. And, + * we also don't need to preserve files because we are creating a new + * database so in case of anerror relation files will be deleted anyway. + */ + write_relmap_file(&map, true, false, false, dbid, tsid, dstdbpath); +} + +/* * RelationMapUpdateMap * * Install a new relfilenode mapping for the specified relation. @@ -1033,6 +1087,12 @@ relmap_redo(XLogReaderState *record) * * There shouldn't be anyone else updating relmaps during WAL replay, * but grab the lock to interlock against load_relmap_file(). + * + * Note - this WAL is also written for copying the relmap file while + * creating a database. Therefore, it makes no sense to acquire a + * relmap lock or send sinval. But if we want to avoid that, then we + * must set an extra flag in WAL. So let it grab the lock and send + * sinval because there is no harm in that. */ LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE); write_relmap_file(&newmap, false, true, false, diff --git a/src/include/utils/relmapper.h b/src/include/utils/relmapper.h index 9fbb5a7..f10353e 100644 --- a/src/include/utils/relmapper.h +++ b/src/include/utils/relmapper.h @@ -38,7 +38,9 @@ typedef struct xl_relmap_update extern Oid RelationMapOidToFilenode(Oid relationId, bool shared); extern Oid RelationMapFilenodeToOid(Oid relationId, bool shared); - +extern Oid RelationMapOidToFilenodeForDatabase(char *dbpath, Oid relationId); +extern void RelationMapCopy(Oid dbid, Oid tsid, char *srcdbpath, + char *dstdbpath); extern void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate); -- 1.8.3.1