Skip to content

Commit 83c7c0f

Browse files
committed
Added option to print rsync performance stats in cf-net
The performance stats are also logged. This way we can also study the performance through `cf-agent`'s debug logs. The following is an example of running cf-net with the `--stats` option: ``` $ sudo /var/cfengine/bin/cf-net --stats --host 192.168.56.10 get /var/cfengine/masterfiles/promises.cf Send signature statistics: 16970 bytes in (read from 'promises.cf') 2424 bytes out (sent to server) Receive delta statistics: 9 bytes in (received from server) 16970 bytes out (written to 'promises.cf.cfnew') ``` Changelog: Title Signed-off-by: Lars Erik Wik <lars.erik.wik@northern.tech>
1 parent 9c7dc43 commit 83c7c0f

File tree

6 files changed

+77
-15
lines changed

6 files changed

+77
-15
lines changed

cf-net/cf-net.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ typedef struct
5656
char *min_tls_version;
5757
char *allow_ciphers;
5858
char *use_protocol_version;
59+
bool print_stats;
5960
} CFNetOptions;
6061

6162
//*******************************************************************
@@ -114,6 +115,7 @@ static const struct option OPTIONS[] =
114115
{"tls-version", required_argument, 0, 't'},
115116
{"ciphers", required_argument, 0, 'c'},
116117
{"protocol", required_argument, 0, 'p'},
118+
{"stats", no_argument, 0, 's'},
117119
{NULL, 0, 0, '\0'}
118120
};
119121

@@ -129,6 +131,7 @@ static const char *const HINTS[] =
129131
"Minimum TLS version to use",
130132
"TLS ciphers to use (comma-separated list)",
131133
"Specify CFEngine protocol to use. Possible values: 'classic', 'tls', 'cookie', 'filestream', 'latest' (default)",
134+
"Print rsync performance statistics to stderr",
132135
NULL
133136
};
134137

@@ -234,6 +237,7 @@ static void CFNetSetDefault(CFNetOptions *opts){
234237
opts->min_tls_version = NULL;
235238
opts->allow_ciphers = NULL;
236239
opts->use_protocol_version = NULL;
240+
opts->print_stats = false;
237241
}
238242

239243
static void CFNetOptionsClear(CFNetOptions *opts)
@@ -289,7 +293,7 @@ static int CFNetParse(int argc, char **argv,
289293
*hostnames = NULL;
290294
int c = 0;
291295
int start_index = 1;
292-
const char *optstr = "+hMg:H:p:dvI"; // + means stop for non opt arg. :)
296+
const char *optstr = "+hMg:H:p:sdvI"; // + means stop for non opt arg. :)
293297
while ((c = getopt_long(argc, argv, optstr, OPTIONS, &start_index))
294298
!= -1)
295299
{
@@ -361,6 +365,11 @@ static int CFNetParse(int argc, char **argv,
361365
opts->use_protocol_version = xstrdup(optarg);
362366
break;
363367
}
368+
case 's':
369+
{
370+
opts->print_stats = true;
371+
break;
372+
}
364373
default:
365374
{
366375
// printf("Default optarg = '%s', c = '%c' = %i\n",
@@ -725,6 +734,7 @@ static int invalid_command(const char *cmd)
725734
typedef struct _GetFileData {
726735
const char *hostname;
727736
const char *use_protocol_version;
737+
bool print_stats;
728738
char remote_file[PATH_MAX];
729739
char local_file[PATH_MAX];
730740
bool ret;
@@ -741,7 +751,7 @@ static void *CFNetGetFile(void *arg)
741751
}
742752

743753
data->ret = ProtocolStatGet(conn, data->remote_file,
744-
data->local_file, 0644);
754+
data->local_file, 0644, data->print_stats);
745755
if (!data->ret)
746756
{
747757
printf("Could not stat: '%s'\n", data->remote_file);
@@ -858,6 +868,7 @@ static int CFNetGet(ARG_UNUSED CFNetOptions *opts, const char *hostname, char **
858868
threads[i]->data = (GetFileData*) xcalloc(1, sizeof(GetFileData));
859869
threads[i]->data->hostname = hostname;
860870
threads[i]->data->use_protocol_version = opts->use_protocol_version;
871+
threads[i]->data->print_stats = opts->print_stats;
861872
if (n_threads > 1)
862873
{
863874
if (strstr(local_file, "%d") != NULL)

libcfnet/client_code.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ bool CopyRegularFileNet(const char *source, const char *basis, const char *dest,
796796

797797
const ProtocolVersion version = ConnectionInfoProtocolVersion(conn->conn_info);
798798
if (ProtocolSupportsFileStream(version)) {
799-
return FileStreamFetch(conn->conn_info->ssl, basis, dest, mode);
799+
return FileStreamFetch(conn->conn_info->ssl, basis, dest, mode, false);
800800
}
801801

802802
int dd = safe_open_create_perms(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, mode);

libcfnet/file_stream.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -672,13 +672,18 @@ static rs_long_t GetSizeOfFile(FILE *file)
672672
*
673673
* @param conn The SSL connection object
674674
* @param filename The name of the basis file
675+
* @param print_stats Whether or not to print performance statistics
675676
* @return true on success, otherwise false
676677
*/
677-
static bool SendSignature(SSL *conn, const char *filename)
678+
static bool SendSignature(SSL *conn, const char *filename, bool print_stats)
678679
{
679680
assert(conn != NULL);
680681
assert(filename != NULL);
681682

683+
/* Variables used for performance statistics */
684+
size_t bytes_in = 0;
685+
size_t bytes_out = 0;
686+
682687
/* In this case, the input buffer does not need to be twice the message
683688
* size, because we can control how much we read into it */
684689
char in_buf[PROTOCOL_MESSAGE_SIZE], out_buf[PROTOCOL_MESSAGE_SIZE];
@@ -783,6 +788,7 @@ static bool SendSignature(SSL *conn, const char *filename)
783788

784789
bufs.next_in = in_buf;
785790
bufs.avail_in += n_bytes;
791+
bytes_in += n_bytes;
786792
}
787793

788794
/* Iterate job */
@@ -813,6 +819,7 @@ static bool SendSignature(SSL *conn, const char *filename)
813819

814820
bufs.next_out = out_buf;
815821
bufs.avail_out = PROTOCOL_MESSAGE_SIZE;
822+
bytes_out += present;
816823
}
817824
else if (res == RS_DONE)
818825
{
@@ -829,6 +836,16 @@ static bool SendSignature(SSL *conn, const char *filename)
829836
fclose(file);
830837
rs_job_free(job);
831838

839+
const char *msg =
840+
"Send signature statistics:\n"
841+
" %zu bytes in (read from '%s')\n"
842+
" %zu bytes out (sent to server)\n";
843+
Log(LOG_LEVEL_DEBUG, msg, bytes_in, filename, bytes_out);
844+
if (print_stats)
845+
{
846+
fprintf(stderr, msg, bytes_in, filename, bytes_out);
847+
}
848+
832849
return true;
833850
}
834851

@@ -839,15 +856,24 @@ static bool SendSignature(SSL *conn, const char *filename)
839856
* @param basis The name of basis file
840857
* @param dest The name of destination file
841858
* @param perms The desired file permissions of the destination file
859+
* @param print_stats Whether or not to print performance statistics
842860
* @return true on success, otherwise false
843861
*/
844862
static bool RecvDelta(
845-
SSL *conn, const char *basis, const char *dest, mode_t perms)
863+
SSL *conn,
864+
const char *basis,
865+
const char *dest,
866+
mode_t perms,
867+
bool print_stats)
846868
{
847869
assert(conn != NULL);
848870
assert(basis != NULL);
849871
assert(dest != NULL);
850872

873+
/* Variables used for performance statistics */
874+
size_t bytes_in = 0;
875+
size_t bytes_out = 0;
876+
851877
/* The input buffer has to be twice the message size, so that it can fit a
852878
* new message, as well as some tail data from the last job iteration */
853879
char in_buf[PROTOCOL_MESSAGE_SIZE * 2], out_buf[PROTOCOL_MESSAGE_SIZE];
@@ -953,6 +979,7 @@ static bool RecvDelta(
953979
bufs.eof_in = eof ? 1 : 0;
954980
bufs.next_in = in_buf;
955981
bufs.avail_in += n_bytes;
982+
bytes_in += n_bytes;
956983
}
957984

958985
res = rs_job_iter(job, &bufs);
@@ -998,6 +1025,7 @@ static bool RecvDelta(
9981025
n_wrote_total += present;
9991026
bufs.next_out = out_buf;
10001027
bufs.avail_out = sizeof(out_buf);
1028+
bytes_out += present;
10011029
}
10021030
} while (res != RS_DONE);
10031031

@@ -1012,11 +1040,25 @@ static bool RecvDelta(
10121040
return false;
10131041
}
10141042

1043+
const char *msg =
1044+
"Receive delta statistics:\n"
1045+
" %zu bytes in (received from server)\n"
1046+
" %zu bytes out (written to '%s')\n";
1047+
Log(LOG_LEVEL_DEBUG, msg, bytes_in, bytes_out, dest);
1048+
if (print_stats)
1049+
{
1050+
fprintf(stderr, msg, bytes_in, bytes_out, dest);
1051+
}
1052+
10151053
return true;
10161054
}
10171055

10181056
bool FileStreamFetch(
1019-
SSL *conn, const char *basis, const char *dest, mode_t perms)
1057+
SSL *conn,
1058+
const char *basis,
1059+
const char *dest,
1060+
mode_t perms,
1061+
bool print_stats)
10201062
{
10211063
assert(conn != NULL);
10221064
assert(basis != NULL);
@@ -1032,7 +1074,7 @@ bool FileStreamFetch(
10321074
Log(LOG_LEVEL_VERBOSE,
10331075
"Computing- & sending signature of file '%s'...",
10341076
basis);
1035-
if (!SendSignature(conn, basis))
1077+
if (!SendSignature(conn, basis, print_stats))
10361078
{
10371079
/* Error is already logged */
10381080
return false;
@@ -1041,7 +1083,7 @@ bool FileStreamFetch(
10411083
Log(LOG_LEVEL_VERBOSE,
10421084
"Receiving delta & applying patch to file '%s'...",
10431085
dest);
1044-
if (!RecvDelta(conn, basis, dest, perms))
1086+
if (!RecvDelta(conn, basis, dest, perms, print_stats))
10451087
{
10461088
/* Error is already logged */
10471089
return false;

libcfnet/file_stream.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,17 @@ bool FileStreamServe(SSL *conn, const char *filename);
9393
* @param basis The name of the basis file
9494
* @param dest The name of the destination file
9595
* @param perms The desired permissions of the destination file
96+
* @param print_stats Print performance statistics
9697
* @return true on success, otherwise false
9798
*
9899
* @note If the destination file is a symlink, this function fetches the
99100
* contents into the symlink target.
100101
*/
101102
bool FileStreamFetch(
102-
SSL *conn, const char *basis, const char *dest, mode_t perms);
103+
SSL *conn,
104+
const char *basis,
105+
const char *dest,
106+
mode_t perms,
107+
bool print_stats);
103108

104109
#endif // FILE_STREAM_H

libcfnet/protocol.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ Seq *ProtocolOpenDir(AgentConnection *conn, const char *path)
9292
}
9393

9494
bool ProtocolGet(AgentConnection *conn, const char *remote_path,
95-
const char *local_path, const uint32_t file_size, int perms)
95+
const char *local_path, const uint32_t file_size, int perms,
96+
bool print_stats)
9697
{
9798
assert(conn != NULL);
9899
assert(remote_path != NULL);
@@ -128,7 +129,8 @@ bool ProtocolGet(AgentConnection *conn, const char *remote_path,
128129
if (ProtocolSupportsFileStream(version))
129130
{
130131
/* Use file stream API if it is available */
131-
if (!FileStreamFetch(conn->conn_info->ssl, local_path, dest, perms))
132+
if (!FileStreamFetch(conn->conn_info->ssl, local_path, dest, perms,
133+
print_stats))
132134
{
133135
/* Error is already logged */
134136
success = false;
@@ -222,7 +224,7 @@ bool ProtocolGet(AgentConnection *conn, const char *remote_path,
222224
}
223225

224226
bool ProtocolStatGet(AgentConnection *conn, const char *remote_path,
225-
const char *local_path, int perms)
227+
const char *local_path, int perms, bool print_stats)
226228
{
227229
assert(conn != NULL);
228230
assert(remote_path != NULL);
@@ -237,7 +239,7 @@ bool ProtocolStatGet(AgentConnection *conn, const char *remote_path,
237239
return false;
238240
}
239241

240-
return ProtocolGet(conn, remote_path, local_path, sb.st_size, perms);
242+
return ProtocolGet(conn, remote_path, local_path, sb.st_size, perms, print_stats);
241243
}
242244

243245
bool ProtocolStat(AgentConnection *const conn, const char *const remote_path,

libcfnet/protocol.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Seq *ProtocolOpenDir(AgentConnection *conn, const char *path);
8484
* @param [in] local_path Path of received file
8585
* @param [in] file_size Size of file to get
8686
* @param [in] perms Permissions of local file
87+
* @param [in] print_stats Print RSYNC performance statistics
8788
* @return True if file was successfully transferred, false otherwise
8889
*
8990
* Example (for printing each directory entry):
@@ -104,7 +105,8 @@ Seq *ProtocolOpenDir(AgentConnection *conn, const char *path);
104105
* Translated to: GET /var/cfengine/masterfiles/update.cf
105106
*/
106107
bool ProtocolGet(AgentConnection *conn, const char *remote_path,
107-
const char *local_path, const uint32_t file_size, int perms);
108+
const char *local_path, const uint32_t file_size, int perms,
109+
bool print_stats);
108110

109111

110112
/**
@@ -114,7 +116,7 @@ bool ProtocolGet(AgentConnection *conn, const char *remote_path,
114116
* it.
115117
*/
116118
bool ProtocolStatGet(AgentConnection *conn, const char *remote_path,
117-
const char *local_path, int perms);
119+
const char *local_path, int perms, bool print_stats);
118120

119121
/**
120122
* Receives statistics about a remote file.

0 commit comments

Comments
 (0)