@@ -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 */
20402218void 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 );
0 commit comments