void create_target(file_entry_t *entry) { Assert(entry->action == FILE_ACTION_CREATE); switch (entry->type) { case FILE_TYPE_DIRECTORY: create_target_dir(entry->path); break; case FILE_TYPE_SYMLINK: create_target_symlink(entry->path, entry->link_target); break; case FILE_TYPE_REGULAR: /* can't happen. Regular files are created with open_target_file. */ pg_fatal("invalid action (CREATE) for regular file\n"); break; } }
/* * Copy all relation data files from datadir_source to datadir_target, which * are marked in the given data page map. */ void copy_executeFileMap(filemap_t *map) { file_entry_t *entry; for (entry = map->first; entry != NULL; entry = entry->next) { execute_pagemap(&entry->pagemap, entry->path); switch (entry->action) { case FILE_ACTION_NONE: /* ok, do nothing.. */ break; case FILE_ACTION_COPY: copy_file_range(entry->path, 0, entry->newsize, true); break; case FILE_ACTION_REMOVE: remove_target_file(entry->path); break; case FILE_ACTION_TRUNCATE: truncate_target_file(entry->path, entry->newsize); break; case FILE_ACTION_COPY_TAIL: copy_file_range(entry->path, entry->oldsize, entry->newsize, false); break; case FILE_ACTION_CREATEDIR: create_target_dir(entry->path); break; } } if (dstfd != -1) close_target_file(); }
/* * Fetch all changed blocks from remote source data directory. */ void libpq_executeFileMap(filemap_t *map) { file_entry_t *entry; const char *sql; PGresult *res; /* * First create a temporary table, and load it with the blocks that * we need to fetch. */ sql = "create temporary table fetchchunks(path text, begin int4, len int4);"; res = PQexec(conn, sql); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "error creating temporary table: %s\n", PQresultErrorMessage(res)); exit(1); } sql = "copy fetchchunks from stdin"; res = PQexec(conn, sql); if (PQresultStatus(res) != PGRES_COPY_IN) { fprintf(stderr, "unexpected result while sending file list: %s\n", PQresultErrorMessage(res)); exit(1); } for (entry = map->first; entry != NULL; entry = entry->next) { execute_pagemap(&entry->pagemap, entry->path); switch (entry->action) { case FILE_ACTION_NONE: /* ok, do nothing.. */ break; case FILE_ACTION_COPY: /* Truncate the old file out of the way, if any */ open_target_file(entry->path, true); copy_file_range(entry->path, 0, entry->newsize); break; case FILE_ACTION_REMOVE: remove_target_file(entry->path); break; case FILE_ACTION_TRUNCATE: truncate_target_file(entry->path, entry->newsize); break; case FILE_ACTION_COPY_TAIL: copy_file_range(entry->path, entry->oldsize, entry->newsize); break; case FILE_ACTION_CREATEDIR: create_target_dir(entry->path); break; case FILE_ACTION_REMOVEDIR: remove_target_dir(entry->path); break; } } if (PQputCopyEnd(conn, NULL) != 1) { fprintf(stderr, "error sending end-of-COPY: %s\n", PQerrorMessage(conn)); exit(1); } while ((res = PQgetResult(conn)) != NULL) { if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "unexpected result while sending file list: %s\n", PQresultErrorMessage(res)); exit(1); } } /* Ok, we've sent the file list. Now receive the files */ sql = "-- fetch all the blocks listed in the temp table.\n" "select path, begin, \n" " pg_read_binary_file(path, begin, len) as chunk\n" "from fetchchunks\n"; receiveFileChunks(sql); }