Skip to content

Commit 81a13b8

Browse files
committed
[Issue #205] Do the listing of remote directory on remote agent
1 parent c363de2 commit 81a13b8

File tree

5 files changed

+204
-5
lines changed

5 files changed

+204
-5
lines changed

src/backup.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,12 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync)
331331
backup_files_list = parray_new();
332332

333333
/* list files with the logical path. omit $PGDATA */
334-
dir_list_file(backup_files_list, instance_config.pgdata,
335-
true, true, false, 0, FIO_DB_HOST);
334+
if (fio_is_remote(FIO_DB_HOST))
335+
fio_list_dir(backup_files_list, instance_config.pgdata,
336+
true, true, false, 0);
337+
else
338+
dir_list_file(backup_files_list, instance_config.pgdata,
339+
true, true, false, 0, FIO_LOCAL_HOST);
336340

337341
/*
338342
* Get database_map (name to oid) for use in partial restore feature.
@@ -345,11 +349,19 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync)
345349
* from external directory option
346350
*/
347351
if (external_dirs)
352+
{
348353
for (i = 0; i < parray_num(external_dirs); i++)
354+
{
349355
/* External dirs numeration starts with 1.
350356
* 0 value is not external dir */
351-
dir_list_file(backup_files_list, parray_get(external_dirs, i),
352-
false, true, false, i+1, FIO_DB_HOST);
357+
if (fio_is_remote(FIO_DB_HOST))
358+
fio_list_dir(backup_files_list, parray_get(external_dirs, i),
359+
false, true, false, i+1);
360+
else
361+
dir_list_file(backup_files_list, parray_get(external_dirs, i),
362+
false, true, false, i+1, FIO_LOCAL_HOST);
363+
}
364+
}
353365

354366
/* close ssh session in main thread */
355367
fio_disconnect();

src/catalog.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,7 @@ pgBackupWriteControl(FILE *out, pgBackup *backup)
17721772

17731773
/*
17741774
* Save the backup content into BACKUP_CONTROL_FILE.
1775+
* TODO: honor the strict flag
17751776
*/
17761777
void
17771778
write_backup(pgBackup *backup, bool strict)

src/pg_probackup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,9 @@ extern int fio_send_file_gz(const char *from_fullpath, const char *to_fullpath,
10351035
extern int fio_send_file(const char *from_fullpath, const char *to_fullpath, FILE* out,
10361036
pgFile *file, char **errormsg);
10371037

1038+
extern void fio_list_dir(parray *files, const char *root, bool exclude,
1039+
bool follow_symlink, bool add_root, int external_dir_num);
1040+
10381041
/* return codes for fio_send_pages() and fio_send_file() */
10391042
#define SEND_OK (0)
10401043
#define FILE_MISSING (-1)

src/utils/file.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,33 @@ typedef struct
3636
} fio_send_request;
3737

3838

39+
typedef struct
40+
{
41+
char path[MAXPGPATH];
42+
bool exclude;
43+
bool follow_symlink;
44+
bool add_root;
45+
int external_dir_num;
46+
} fio_list_dir_request;
47+
48+
typedef struct
49+
{
50+
mode_t mode;
51+
size_t size;
52+
time_t mtime;
53+
bool is_datafile;
54+
bool is_database;
55+
56+
Oid tblspcOid;
57+
Oid dbOid;
58+
Oid relOid;
59+
ForkName forkName;
60+
int segno;
61+
int external_dir_num;
62+
int linked_len;
63+
} fio_pgFile;
64+
65+
3966
/* Convert FIO pseudo handle to index in file descriptor array */
4067
#define fio_fileno(f) (((size_t)f - 1) | FIO_PIPE_MARKER)
4168

@@ -2036,6 +2063,157 @@ static void fio_send_file_impl(int out, char const* path)
20362063
return;
20372064
}
20382065

2066+
/* Compile the array of files located on remote machine in directory root */
2067+
void fio_list_dir(parray *files, const char *root, bool exclude,
2068+
bool follow_symlink, bool add_root, int external_dir_num)
2069+
{
2070+
fio_header hdr;
2071+
fio_list_dir_request req;
2072+
char *buf = pgut_malloc(CHUNK_SIZE);
2073+
2074+
/* Send to the agent message with parameters for directory listing */
2075+
snprintf(req.path, MAXPGPATH, "%s", root);
2076+
req.exclude = exclude;
2077+
req.follow_symlink = follow_symlink;
2078+
req.add_root = add_root;
2079+
req.external_dir_num = external_dir_num;
2080+
2081+
hdr.cop = FIO_LIST_DIR;
2082+
hdr.size = sizeof(req);
2083+
2084+
IO_CHECK(fio_write_all(fio_stdout, &hdr, sizeof(hdr)), sizeof(hdr));
2085+
IO_CHECK(fio_write_all(fio_stdout, &req, hdr.size), hdr.size);
2086+
2087+
for (;;)
2088+
{
2089+
/* receive data */
2090+
IO_CHECK(fio_read_all(fio_stdin, &hdr, sizeof(hdr)), sizeof(hdr));
2091+
2092+
if (hdr.cop == FIO_SEND_FILE_EOF)
2093+
{
2094+
/* the work is done */
2095+
break;
2096+
}
2097+
else if (hdr.cop == FIO_SEND_FILE)
2098+
{
2099+
pgFile *file = NULL;
2100+
fio_pgFile fio_file;
2101+
2102+
/* receive rel_path */
2103+
IO_CHECK(fio_read_all(fio_stdin, buf, hdr.size), hdr.size);
2104+
file = pgFileInit(buf);
2105+
2106+
/* receive metainformation */
2107+
IO_CHECK(fio_read_all(fio_stdin, &fio_file, sizeof(fio_file)), sizeof(fio_file));
2108+
2109+
file->mode = fio_file.mode;
2110+
file->size = fio_file.size;
2111+
file->mtime = fio_file.mtime;
2112+
file->is_datafile = fio_file.is_datafile;
2113+
file->is_database = fio_file.is_database;
2114+
file->tblspcOid = fio_file.tblspcOid;
2115+
file->dbOid = fio_file.dbOid;
2116+
file->relOid = fio_file.relOid;
2117+
file->forkName = fio_file.forkName;
2118+
file->segno = fio_file.segno;
2119+
file->external_dir_num = fio_file.external_dir_num;
2120+
2121+
if (fio_file.linked_len > 0)
2122+
{
2123+
IO_CHECK(fio_read_all(fio_stdin, buf, fio_file.linked_len), fio_file.linked_len);
2124+
2125+
file->linked = pgut_malloc(fio_file.linked_len);
2126+
snprintf(file->linked, fio_file.linked_len, "%s", buf);
2127+
}
2128+
2129+
// elog(INFO, "Received file: %s, mode: %u, size: %lu, mtime: %lu",
2130+
// file->rel_path, file->mode, file->size, file->mtime);
2131+
2132+
parray_append(files, file);
2133+
}
2134+
else
2135+
{
2136+
/* TODO: fio_disconnect may get assert fail when running after this */
2137+
elog(ERROR, "Remote agent returned message of unexpected type: %i", hdr.cop);
2138+
}
2139+
}
2140+
2141+
pg_free(buf);
2142+
}
2143+
2144+
2145+
/*
2146+
* To get the arrays of files we use the same function dir_list_file(),
2147+
* that is used for local backup.
2148+
* After that we iterate over arrays and for every file send at least
2149+
* two messages to main process:
2150+
* 1. rel_path
2151+
* 2. metainformation (size, mtime, etc)
2152+
* 3. link path (optional)
2153+
*
2154+
* TODO: replace FIO_SEND_FILE and FIO_SEND_FILE_EOF with dedicated messages
2155+
*/
2156+
static void fio_list_dir_impl(int out, char* buf)
2157+
{
2158+
int i;
2159+
fio_header hdr;
2160+
fio_list_dir_request *req = (fio_list_dir_request*) buf;
2161+
parray *file_files = parray_new();
2162+
2163+
/*
2164+
* Disable logging into console any messages with exception of ERROR messages,
2165+
* to avoid sending messages to main process, because it may screw his FIO message parsing.
2166+
*/
2167+
instance_config.logger.log_level_console = ERROR;
2168+
2169+
dir_list_file(file_files, req->path, req->exclude, req->follow_symlink,
2170+
req->add_root, req->external_dir_num, FIO_LOCAL_HOST);
2171+
2172+
/* send information about files to the main process */
2173+
for (i = 0; i < parray_num(file_files); i++)
2174+
{
2175+
fio_pgFile fio_file;
2176+
pgFile *file = (pgFile *) parray_get(file_files, i);
2177+
2178+
fio_file.mode = file->mode;
2179+
fio_file.size = file->size;
2180+
fio_file.mtime = file->mtime;
2181+
fio_file.is_datafile = file->is_datafile;
2182+
fio_file.is_database = file->is_database;
2183+
fio_file.tblspcOid = file->tblspcOid;
2184+
fio_file.dbOid = file->dbOid;
2185+
fio_file.relOid = file->relOid;
2186+
fio_file.forkName = file->forkName;
2187+
fio_file.segno = file->segno;
2188+
fio_file.external_dir_num = file->external_dir_num;
2189+
2190+
if (file->linked)
2191+
fio_file.linked_len = strlen(file->linked) + 1;
2192+
else
2193+
fio_file.linked_len = 0;
2194+
2195+
hdr.cop = FIO_SEND_FILE;
2196+
hdr.size = strlen(file->rel_path) + 1;
2197+
2198+
/* send rel_path first */
2199+
IO_CHECK(fio_write_all(out, &hdr, sizeof(hdr)), sizeof(hdr));
2200+
IO_CHECK(fio_write_all(out, file->rel_path, hdr.size), hdr.size);
2201+
2202+
/* now send file metainformation */
2203+
IO_CHECK(fio_write_all(out, &fio_file, sizeof(fio_file)), sizeof(fio_file));
2204+
2205+
/* If file is a symlink, then send link path */
2206+
if (file->linked)
2207+
IO_CHECK(fio_write_all(out, file->linked, fio_file.linked_len), fio_file.linked_len);
2208+
2209+
pgFileFree(file);
2210+
}
2211+
2212+
parray_free(file_files);
2213+
hdr.cop = FIO_SEND_FILE_EOF;
2214+
IO_CHECK(fio_write_all(out, &hdr, sizeof(hdr)), sizeof(hdr));
2215+
}
2216+
20392217
/* Execute commands at remote host */
20402218
void fio_communicate(int in, int out)
20412219
{
@@ -2173,6 +2351,10 @@ void fio_communicate(int in, int out)
21732351
case FIO_TRUNCATE: /* Truncate file */
21742352
SYS_CHECK(ftruncate(fd[hdr.handle], hdr.arg));
21752353
break;
2354+
case FIO_LIST_DIR:
2355+
// buf contain fio_send_request header and bitmap.
2356+
fio_list_dir_impl(out, buf);
2357+
break;
21762358
case FIO_SEND_PAGES:
21772359
// buf contain fio_send_request header and bitmap.
21782360
fio_send_pages_impl(out, buf);

src/utils/file.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ typedef enum
4646
FIO_DISCONNECT,
4747
FIO_DISCONNECTED,
4848
/* message for compatibility check */
49-
FIO_AGENT_VERSION
49+
FIO_AGENT_VERSION,
50+
FIO_LIST_DIR
5051
} fio_operations;
5152

5253
typedef enum

0 commit comments

Comments
 (0)