pg_upgrade: Remove converter plugin facility.
We've not found a use for this so far, and the current need, which is to convert the visibility map to a new format, does not suit the existing design anyway. So just rip it out. Author: Masahiko Sawada, slightly revised by me. Discussion: 20160215211313.GB31273@momjian.us
This commit is contained in:
parent
a93aec4e0f
commit
6f56b41ac0
@ -8,7 +8,7 @@ top_builddir = ../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = check.o controldata.o dump.o exec.o file.o function.o info.o \
|
||||
option.o page.o parallel.o pg_upgrade.o relfilenode.o server.o \
|
||||
option.o parallel.o pg_upgrade.o relfilenode.o server.o \
|
||||
tablespace.o util.o version.o $(WIN32RES)
|
||||
|
||||
override CPPFLAGS := -DDLSUFFIX=\"$(DLSUFFIX)\" -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
|
||||
|
@ -80,8 +80,6 @@ check_and_dump_old_cluster(bool live_check)
|
||||
if (!live_check)
|
||||
start_postmaster(&old_cluster, true);
|
||||
|
||||
get_pg_database_relfilenode(&old_cluster);
|
||||
|
||||
/* Extract a list of databases and tables from the old cluster */
|
||||
get_db_and_rel_infos(&old_cluster);
|
||||
|
||||
|
@ -23,17 +23,13 @@ static int win32_pghardlink(const char *src, const char *dst);
|
||||
|
||||
|
||||
/*
|
||||
* copyAndUpdateFile()
|
||||
* copyFile()
|
||||
*
|
||||
* Copies a relation file from src to dst. If pageConverter is non-NULL, this function
|
||||
* uses that pageConverter to do a page-by-page conversion.
|
||||
* Copies a relation file from src to dst.
|
||||
*/
|
||||
const char *
|
||||
copyAndUpdateFile(pageCnvCtx *pageConverter,
|
||||
const char *src, const char *dst, bool force)
|
||||
copyFile(const char *src, const char *dst, bool force)
|
||||
{
|
||||
if (pageConverter == NULL)
|
||||
{
|
||||
#ifndef WIN32
|
||||
if (copy_file(src, dst, force) == -1)
|
||||
#else
|
||||
@ -42,70 +38,11 @@ copyAndUpdateFile(pageCnvCtx *pageConverter,
|
||||
return getErrorText();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We have a pageConverter object - that implies that the
|
||||
* PageLayoutVersion differs between the two clusters so we have to
|
||||
* perform a page-by-page conversion.
|
||||
*
|
||||
* If the pageConverter can convert the entire file at once, invoke
|
||||
* that plugin function, otherwise, read each page in the relation
|
||||
* file and call the convertPage plugin function.
|
||||
*/
|
||||
|
||||
#ifdef PAGE_CONVERSION
|
||||
if (pageConverter->convertFile)
|
||||
return pageConverter->convertFile(pageConverter->pluginData,
|
||||
dst, src);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int src_fd;
|
||||
int dstfd;
|
||||
char buf[BLCKSZ];
|
||||
ssize_t bytesRead;
|
||||
const char *msg = NULL;
|
||||
|
||||
if ((src_fd = open(src, O_RDONLY, 0)) < 0)
|
||||
return "could not open source file";
|
||||
|
||||
if ((dstfd = open(dst, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0)
|
||||
{
|
||||
close(src_fd);
|
||||
return "could not create destination file";
|
||||
}
|
||||
|
||||
while ((bytesRead = read(src_fd, buf, BLCKSZ)) == BLCKSZ)
|
||||
{
|
||||
#ifdef PAGE_CONVERSION
|
||||
if ((msg = pageConverter->convertPage(pageConverter->pluginData, buf, buf)) != NULL)
|
||||
break;
|
||||
#endif
|
||||
if (write(dstfd, buf, BLCKSZ) != BLCKSZ)
|
||||
{
|
||||
msg = "could not write new page to destination";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(src_fd);
|
||||
close(dstfd);
|
||||
|
||||
if (msg)
|
||||
return msg;
|
||||
else if (bytesRead != 0)
|
||||
return "found partial page in source file";
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* linkAndUpdateFile()
|
||||
* linkFile()
|
||||
*
|
||||
* Creates a hard link between the given relation files. We use
|
||||
* this function to perform a true in-place update. If the on-disk
|
||||
@ -114,12 +51,8 @@ copyAndUpdateFile(pageCnvCtx *pageConverter,
|
||||
* instead of copying the data from the old cluster to the new cluster.
|
||||
*/
|
||||
const char *
|
||||
linkAndUpdateFile(pageCnvCtx *pageConverter,
|
||||
const char *src, const char *dst)
|
||||
linkFile(const char *src, const char *dst)
|
||||
{
|
||||
if (pageConverter != NULL)
|
||||
return "Cannot in-place update this cluster, page-by-page conversion is required";
|
||||
|
||||
if (pg_link_file(src, dst) == -1)
|
||||
return getErrorText();
|
||||
else
|
||||
|
@ -1,164 +0,0 @@
|
||||
/*
|
||||
* page.c
|
||||
*
|
||||
* per-page conversion operations
|
||||
*
|
||||
* Copyright (c) 2010-2016, PostgreSQL Global Development Group
|
||||
* src/bin/pg_upgrade/page.c
|
||||
*/
|
||||
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include "pg_upgrade.h"
|
||||
|
||||
#include "storage/bufpage.h"
|
||||
|
||||
|
||||
#ifdef PAGE_CONVERSION
|
||||
|
||||
|
||||
static void getPageVersion(
|
||||
uint16 *version, const char *pathName);
|
||||
static pageCnvCtx *loadConverterPlugin(
|
||||
uint16 newPageVersion, uint16 oldPageVersion);
|
||||
|
||||
|
||||
/*
|
||||
* setupPageConverter()
|
||||
*
|
||||
* This function determines the PageLayoutVersion of the old cluster and
|
||||
* the PageLayoutVersion of the new cluster. If the versions differ, this
|
||||
* function loads a converter plugin and returns a pointer to a pageCnvCtx
|
||||
* object (in *result) that knows how to convert pages from the old format
|
||||
* to the new format. If the versions are identical, this function just
|
||||
* returns a NULL pageCnvCtx pointer to indicate that page-by-page conversion
|
||||
* is not required.
|
||||
*/
|
||||
pageCnvCtx *
|
||||
setupPageConverter(void)
|
||||
{
|
||||
uint16 oldPageVersion;
|
||||
uint16 newPageVersion;
|
||||
pageCnvCtx *converter;
|
||||
const char *msg;
|
||||
char dstName[MAXPGPATH];
|
||||
char srcName[MAXPGPATH];
|
||||
|
||||
snprintf(dstName, sizeof(dstName), "%s/global/%u", new_cluster.pgdata,
|
||||
new_cluster.pg_database_oid);
|
||||
snprintf(srcName, sizeof(srcName), "%s/global/%u", old_cluster.pgdata,
|
||||
old_cluster.pg_database_oid);
|
||||
|
||||
getPageVersion(&oldPageVersion, srcName);
|
||||
getPageVersion(&newPageVersion, dstName);
|
||||
|
||||
/*
|
||||
* If the old cluster and new cluster use the same page layouts, then we
|
||||
* don't need a page converter.
|
||||
*/
|
||||
if (newPageVersion != oldPageVersion)
|
||||
{
|
||||
/*
|
||||
* The clusters use differing page layouts, see if we can find a
|
||||
* plugin that knows how to convert from the old page layout to the
|
||||
* new page layout.
|
||||
*/
|
||||
|
||||
if ((converter = loadConverterPlugin(newPageVersion, oldPageVersion)) == NULL)
|
||||
pg_fatal("could not find plugin to convert from old page layout to new page layout\n");
|
||||
|
||||
return converter;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getPageVersion()
|
||||
*
|
||||
* Retrieves the PageLayoutVersion for the given relation.
|
||||
*
|
||||
* Returns NULL on success (and stores the PageLayoutVersion at *version),
|
||||
* if an error occurs, this function returns an error message (in the form
|
||||
* of a null-terminated string).
|
||||
*/
|
||||
static void
|
||||
getPageVersion(uint16 *version, const char *pathName)
|
||||
{
|
||||
int relfd;
|
||||
PageHeaderData page;
|
||||
ssize_t bytesRead;
|
||||
|
||||
if ((relfd = open(pathName, O_RDONLY, 0)) < 0)
|
||||
pg_fatal("could not open relation %s\n", pathName);
|
||||
|
||||
if ((bytesRead = read(relfd, &page, sizeof(page))) != sizeof(page))
|
||||
pg_fatal("could not read page header of %s\n", pathName);
|
||||
|
||||
*version = PageGetPageLayoutVersion(&page);
|
||||
|
||||
close(relfd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* loadConverterPlugin()
|
||||
*
|
||||
* This function loads a page-converter plugin library and grabs a
|
||||
* pointer to each of the (interesting) functions provided by that
|
||||
* plugin. The name of the plugin library is derived from the given
|
||||
* newPageVersion and oldPageVersion. If a plugin is found, this
|
||||
* function returns a pointer to a pageCnvCtx object (which will contain
|
||||
* a collection of plugin function pointers). If the required plugin
|
||||
* is not found, this function returns NULL.
|
||||
*/
|
||||
static pageCnvCtx *
|
||||
loadConverterPlugin(uint16 newPageVersion, uint16 oldPageVersion)
|
||||
{
|
||||
char pluginName[MAXPGPATH];
|
||||
void *plugin;
|
||||
|
||||
/*
|
||||
* Try to find a plugin that can convert pages of oldPageVersion into
|
||||
* pages of newPageVersion. For example, if we oldPageVersion = 3 and
|
||||
* newPageVersion is 4, we search for a plugin named:
|
||||
* plugins/convertLayout_3_to_4.dll
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME: we are searching for plugins relative to the current directory,
|
||||
* we should really search relative to our own executable instead.
|
||||
*/
|
||||
snprintf(pluginName, sizeof(pluginName), "./plugins/convertLayout_%d_to_%d%s",
|
||||
oldPageVersion, newPageVersion, DLSUFFIX);
|
||||
|
||||
if ((plugin = pg_dlopen(pluginName)) == NULL)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
pageCnvCtx *result = (pageCnvCtx *) pg_malloc(sizeof(*result));
|
||||
|
||||
result->old.PageVersion = oldPageVersion;
|
||||
result->new.PageVersion = newPageVersion;
|
||||
|
||||
result->startup = (pluginStartup) pg_dlsym(plugin, "init");
|
||||
result->convertFile = (pluginConvertFile) pg_dlsym(plugin, "convertFile");
|
||||
result->convertPage = (pluginConvertPage) pg_dlsym(plugin, "convertPage");
|
||||
result->shutdown = (pluginShutdown) pg_dlsym(plugin, "fini");
|
||||
result->pluginData = NULL;
|
||||
|
||||
/*
|
||||
* If the plugin has exported an initializer, go ahead and invoke it.
|
||||
*/
|
||||
if (result->startup)
|
||||
result->startup(MIGRATOR_API_VERSION, &result->pluginVersion,
|
||||
newPageVersion, oldPageVersion, &result->pluginData);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -260,8 +260,6 @@ prepare_new_cluster(void)
|
||||
new_cluster.bindir, cluster_conn_opts(&new_cluster),
|
||||
log_opts.verbose ? "--verbose" : "");
|
||||
check_ok();
|
||||
|
||||
get_pg_database_relfilenode(&new_cluster);
|
||||
}
|
||||
|
||||
|
||||
|
@ -269,7 +269,6 @@ typedef struct
|
||||
uint32 major_version; /* PG_VERSION of cluster */
|
||||
char major_version_str[64]; /* string PG_VERSION of cluster */
|
||||
uint32 bin_version; /* version returned from pg_ctl */
|
||||
Oid pg_database_oid; /* OID of pg_database relation */
|
||||
const char *tablespace_suffix; /* directory specification */
|
||||
} ClusterInfo;
|
||||
|
||||
@ -364,40 +363,8 @@ bool pid_lock_file_exists(const char *datadir);
|
||||
|
||||
/* file.c */
|
||||
|
||||
#ifdef PAGE_CONVERSION
|
||||
typedef const char *(*pluginStartup) (uint16 migratorVersion,
|
||||
uint16 *pluginVersion, uint16 newPageVersion,
|
||||
uint16 oldPageVersion, void **pluginData);
|
||||
typedef const char *(*pluginConvertFile) (void *pluginData,
|
||||
const char *dstName, const char *srcName);
|
||||
typedef const char *(*pluginConvertPage) (void *pluginData,
|
||||
const char *dstPage, const char *srcPage);
|
||||
typedef const char *(*pluginShutdown) (void *pluginData);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 oldPageVersion; /* Page layout version of the old cluster */
|
||||
uint16 newPageVersion; /* Page layout version of the new cluster */
|
||||
uint16 pluginVersion; /* API version of converter plugin */
|
||||
void *pluginData; /* Plugin data (set by plugin) */
|
||||
pluginStartup startup; /* Pointer to plugin's startup function */
|
||||
pluginConvertFile convertFile; /* Pointer to plugin's file converter
|
||||
* function */
|
||||
pluginConvertPage convertPage; /* Pointer to plugin's page converter
|
||||
* function */
|
||||
pluginShutdown shutdown; /* Pointer to plugin's shutdown function */
|
||||
} pageCnvCtx;
|
||||
|
||||
const pageCnvCtx *setupPageConverter(void);
|
||||
#else
|
||||
/* dummy */
|
||||
typedef void *pageCnvCtx;
|
||||
#endif
|
||||
|
||||
const char *copyAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
|
||||
const char *dst, bool force);
|
||||
const char *linkAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
|
||||
const char *dst);
|
||||
const char *copyFile(const char *src, const char *dst, bool force);
|
||||
const char *linkFile(const char *src, const char *dst);
|
||||
|
||||
void check_hard_link(void);
|
||||
FILE *fopen_priv(const char *path, const char *mode);
|
||||
|
@ -15,10 +15,8 @@
|
||||
#include "access/transam.h"
|
||||
|
||||
|
||||
static void transfer_single_new_db(pageCnvCtx *pageConverter,
|
||||
FileNameMap *maps, int size, char *old_tablespace);
|
||||
static void transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
|
||||
const char *suffix);
|
||||
static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace);
|
||||
static void transfer_relfile(FileNameMap *map, const char *suffix);
|
||||
|
||||
|
||||
/*
|
||||
@ -92,7 +90,6 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
|
||||
*new_db = NULL;
|
||||
FileNameMap *mappings;
|
||||
int n_maps;
|
||||
pageCnvCtx *pageConverter = NULL;
|
||||
|
||||
/*
|
||||
* Advance past any databases that exist in the new cluster but not in
|
||||
@ -116,11 +113,7 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
|
||||
{
|
||||
print_maps(mappings, n_maps, new_db->db_name);
|
||||
|
||||
#ifdef PAGE_CONVERSION
|
||||
pageConverter = setupPageConverter();
|
||||
#endif
|
||||
transfer_single_new_db(pageConverter, mappings, n_maps,
|
||||
old_tablespace);
|
||||
transfer_single_new_db(mappings, n_maps, old_tablespace);
|
||||
}
|
||||
/* We allocate something even for n_maps == 0 */
|
||||
pg_free(mappings);
|
||||
@ -129,45 +122,13 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_pg_database_relfilenode()
|
||||
*
|
||||
* Retrieves the relfilenode for a few system-catalog tables. We need these
|
||||
* relfilenodes later in the upgrade process.
|
||||
*/
|
||||
void
|
||||
get_pg_database_relfilenode(ClusterInfo *cluster)
|
||||
{
|
||||
PGconn *conn = connectToServer(cluster, "template1");
|
||||
PGresult *res;
|
||||
int i_relfile;
|
||||
|
||||
res = executeQueryOrDie(conn,
|
||||
"SELECT c.relname, c.relfilenode "
|
||||
"FROM pg_catalog.pg_class c, "
|
||||
" pg_catalog.pg_namespace n "
|
||||
"WHERE c.relnamespace = n.oid AND "
|
||||
" n.nspname = 'pg_catalog' AND "
|
||||
" c.relname = 'pg_database' "
|
||||
"ORDER BY c.relname");
|
||||
|
||||
i_relfile = PQfnumber(res, "relfilenode");
|
||||
cluster->pg_database_oid = atooid(PQgetvalue(res, 0, i_relfile));
|
||||
|
||||
PQclear(res);
|
||||
PQfinish(conn);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* transfer_single_new_db()
|
||||
*
|
||||
* create links for mappings stored in "maps" array.
|
||||
*/
|
||||
static void
|
||||
transfer_single_new_db(pageCnvCtx *pageConverter,
|
||||
FileNameMap *maps, int size, char *old_tablespace)
|
||||
transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace)
|
||||
{
|
||||
int mapnum;
|
||||
bool vm_crashsafe_match = true;
|
||||
@ -186,7 +147,7 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
|
||||
strcmp(maps[mapnum].old_tablespace, old_tablespace) == 0)
|
||||
{
|
||||
/* transfer primary file */
|
||||
transfer_relfile(pageConverter, &maps[mapnum], "");
|
||||
transfer_relfile(&maps[mapnum], "");
|
||||
|
||||
/* fsm/vm files added in PG 8.4 */
|
||||
if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
|
||||
@ -194,9 +155,9 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
|
||||
/*
|
||||
* Copy/link any fsm and vm files, if they exist
|
||||
*/
|
||||
transfer_relfile(pageConverter, &maps[mapnum], "_fsm");
|
||||
transfer_relfile(&maps[mapnum], "_fsm");
|
||||
if (vm_crashsafe_match)
|
||||
transfer_relfile(pageConverter, &maps[mapnum], "_vm");
|
||||
transfer_relfile(&maps[mapnum], "_vm");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,8 +170,7 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
|
||||
* Copy or link file from old cluster to new one.
|
||||
*/
|
||||
static void
|
||||
transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
|
||||
const char *type_suffix)
|
||||
transfer_relfile(FileNameMap *map, const char *type_suffix)
|
||||
{
|
||||
const char *msg;
|
||||
char old_file[MAXPGPATH];
|
||||
@ -268,15 +228,11 @@ transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
|
||||
/* Copying files might take some time, so give feedback. */
|
||||
pg_log(PG_STATUS, "%s", old_file);
|
||||
|
||||
if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
|
||||
pg_fatal("This upgrade requires page-by-page conversion, "
|
||||
"you must use copy mode instead of link mode.\n");
|
||||
|
||||
if (user_opts.transfer_mode == TRANSFER_MODE_COPY)
|
||||
{
|
||||
pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", old_file, new_file);
|
||||
|
||||
if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL)
|
||||
if ((msg = copyFile(old_file, new_file, true)) != NULL)
|
||||
pg_fatal("error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
|
||||
map->nspname, map->relname, old_file, new_file, msg);
|
||||
}
|
||||
@ -284,7 +240,7 @@ transfer_relfile(pageCnvCtx *pageConverter, FileNameMap *map,
|
||||
{
|
||||
pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"\n", old_file, new_file);
|
||||
|
||||
if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL)
|
||||
if ((msg = linkFile(old_file, new_file)) != NULL)
|
||||
pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
|
||||
map->nspname, map->relname, old_file, new_file, msg);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user