Skip to content
API Documentation
BastionGuard™
RsyncTask Class Reference
Inheritance diagram for RsyncTask:
AsyncTask

Public Member Functions

 RsyncTask ()
override void prepare ()
Gee.ArrayList< FileItem > parse_log (string log_file_path)
override void parse_stdout_line (string out_line)
override void parse_stderr_line (string err_line)
bool update_progress_parse_console_output (string line)
Public Member Functions inherited from AsyncTask
signal void stdout_line_read (string line)
signal void stderr_line_read (string line)
signal void task_complete ()
void write_stdin (string line)
virtual void execute ()
bool is_running ()
void stop (AppStatus status_to_update=AppStatus.CANCELLED)
void pause (AppStatus status_to_update=AppStatus.PAUSED)
void resume (AppStatus status_to_update=AppStatus.RUNNING)
void print_app_status ()

Public Attributes

bool delete_extra = true
bool delete_after = false
bool delete_excluded = false
bool relative = false
string rsync_log_file = ""
string exclude_from_file = ""
string link_from_path = ""
string source_path = ""
string dest_path = ""
bool verbose = true
bool io_nice = true
bool dry_run = false
GLib.Queue< string > status_lines
int64 status_line_count = 0
int64 total_size = 0
int64 count_created
int64 count_deleted
int64 count_modified
int64 count_checksum
int64 count_size
int64 count_timestamp
int64 count_permissions
int64 count_owner
int64 count_group
int64 count_unchanged
StringBuilder log
Public Attributes inherited from AsyncTask
AppStatus status = AppStatus.NOT_STARTED
GLib.Mutex status_line_mutex
int exit_code = 0
GLib.Timer timer
double progress = 0.0
double percent = 0.0
int64 prg_count = 0
int64 prg_count_total = 0

Protected Member Functions

override string build_script ()
override void finish_task ()
Protected Member Functions inherited from AsyncTask
 AsyncTask ()
string build_script ()
virtual bool begin ()
void parse_stdout_line (string out_line)
void parse_stderr_line (string err_line)
int read_exit_code ()

Private Types

enum  RegexType {
  Status , Created , LogCreated , Deleted ,
  LogDeleted , Modified , LogModified , Unchanged ,
  LogUnchanged , TotalSize , Count
}

Private Member Functions

void init_regular_expressions ()

Private Attributes

Regex[] regex_list = null

Additional Inherited Members

Protected Attributes inherited from AsyncTask
DataOutputStream dos_log = null
Pid child_pid = 0
string script_file = ""
string working_dir = ""
Properties inherited from AsyncTask
string status_line [get, set]
double elapsed [get]
string stat_time_elapsed [get]
string??? stat_time_remaining [get]

Detailed Description

Definition at line 31 of file RsyncTask.vala.

Member Enumeration Documentation

◆ RegexType

enum RsyncTask.RegexType
private
Enumerator
Status 
Created 
LogCreated 
Deleted 
LogDeleted 
Modified 
LogModified 
Unchanged 
LogUnchanged 
TotalSize 
Count 

Definition at line 33 of file RsyncTask.vala.

33 {
34 Status,
35 Created,
36 LogCreated,
37 Deleted,
38 LogDeleted,
39 Modified,
40 LogModified,
41 Unchanged,
42 LogUnchanged,
43 TotalSize,
44
45 Count
46 }

Constructor & Destructor Documentation

◆ RsyncTask()

RsyncTask.RsyncTask ( )
inline

Member Function Documentation

◆ build_script()

override string RsyncTask.build_script ( )
inlineprotected

Definition at line 185 of file RsyncTask.vala.

185 {
186
187 var cmd = "export LC_ALL=C.UTF-8\n";
188
189 if (io_nice){
190 //cmd += "ionice -c2 -n7 ";
191 }
192
193 cmd += "rsync -aii";
194
195 //if (!dry_run){
196 // cmd += "i";
197 //}
198
199 cmd += " --recursive";
200
201 if (verbose){
202 cmd += " --verbose";
203 }
204 else{
205 cmd += " --quiet";
206 }
207
208 if (delete_extra){
209 cmd += " --delete";
210 }
211
212 if (delete_after){
213 cmd += " --delete-after";
214 }
215
216 cmd += " --force"; // allow deletion of non-empty directories
217
218 //cmd += " --numeric-ids";
219
220 cmd += " --stats";
221
222 cmd += " --sparse";
223
224 //if (relative){
225 // cmd += " --relative";
226 //}
227
228 if (delete_excluded){
229 cmd += " --delete-excluded";
230 }
231
232 if (dry_run){
233 cmd += " --dry-run";
234 }
235
236 if (link_from_path.length > 0){
237 if (!link_from_path.has_suffix("/")){
238 link_from_path = "%s/".printf(link_from_path);
239 }
240
241 cmd += " --link-dest='%s'".printf(escape_single_quote(link_from_path));
242 }
243
244 if (rsync_log_file.length > 0){
245 cmd += " --log-file='%s'".printf(escape_single_quote(rsync_log_file));
246 }
247
248 if (exclude_from_file.length > 0){
249 cmd += " --exclude-from='%s'".printf(escape_single_quote(exclude_from_file));
250
252 cmd += " --delete-excluded";
253 }
254 }
255
257
259
260 cmd += " '%s/'".printf(escape_single_quote(source_path));
261
262 cmd += " '%s/'".printf(escape_single_quote(dest_path));
263
264 return cmd;
265 }
string dest_path
bool dry_run
bool delete_excluded
string rsync_log_file
string source_path
string link_from_path
string exclude_from_file
bool verbose
bool delete_extra
bool delete_after
bool io_nice
string escape_single_quote(string file_path)
string remove_trailing_slash(string path)

References delete_after, delete_excluded, delete_extra, dest_path, dry_run, TeeJee.FileSystem.escape_single_quote(), exclude_from_file, io_nice, link_from_path, TeeJee.FileSystem.remove_trailing_slash(), rsync_log_file, source_path, and verbose.

◆ finish_task()

override void RsyncTask.finish_task ( )
inlineprotectedvirtual

Reimplemented from AsyncTask.

Definition at line 526 of file RsyncTask.vala.

526 {
527 if (0 < rsync_log_file.length) {
528 file_write(rsync_log_file + "-changes", log.str);
529 }
530 }
StringBuilder log
bool file_write(string file_path, string contents)

References TeeJee.FileSystem.file_write(), log, and rsync_log_file.

◆ init_regular_expressions()

void RsyncTask.init_regular_expressions ( )
inlineprivate

Definition at line 89 of file RsyncTask.vala.

89 {
90 if (regex_list != null){
91 return; // already initialized
92 }
93
94 regex_list = new Regex[RegexType.Count];
95
96 /*
97 2018/02/03 16:53:46 [2419] >f..t...... boot/grub/grubenv
98 >f.........
99 <dcstpoguax
100 cL
101 hD
102 .S
103 *
104 columns-1:
105 < > means that a file is being transferred
106 c means that a local change/creation is occurring for the item
107 h means that the item is a hard link to another item
108 . means that the item is not being updated (though it might have attributes that are being modified).
109 * means that the rest of the itemized-output area contains a message (e.g. "deleting").
110
111 columns-2:
112 f file, d directory, L symlink, D device, S special file (e.g. named sockets and fifos).
113
114 columns-3-11:
115 c regular file has different checksum or that symlink, device, or special file has changed value
116 s size of a regular file is different and is being updated
117 t modification time is different and is being updated
118 p permissions are different and is being updated
119 o owner is different and is being updated
120 g group is different and is being updated
121 u reserved for future use.
122 a ACL information changed.
123 x extended attribute information changed.
124 */
125
126 try {
127 //Example: status=-1
128 regex_list[RegexType.Status] = new Regex(
129 """([<>ch.*])([.fdLDS])(c|\+|\.| )(s|\+|\.| )(t|\+|\.| )(p|\+|\.| )(o|\+|\.| )(g|\+|\.| )(u|\+|\.| )(a|\+|\.| )(x|\+|\.| ) (.*)""");
130
131 regex_list[RegexType.Created] = new Regex(
132 """([<>ch.*])([.fdLDS])[+]{9} (.*)""");
133
134 regex_list[RegexType.LogCreated] = new Regex(
135 """[0-9\/]+ [0-9:.]+ \‍[[0-9]+\‍] ([<>ch.*])([.fdLDS])[+]{9} (.*)""");
136
137 regex_list[RegexType.Deleted] = new Regex(
138 """\*deleting[ \t]+(.*)""");
139
140 regex_list[RegexType.LogDeleted] = new Regex(
141 """[0-9\/]+ [0-9:.]+ \‍[[0-9]+\‍] \*deleting[ \t]+(.*)""");
142
143 regex_list[RegexType.Modified] = new Regex(
144 """([<>ch.])([.fdLDS])(c|\+|\.| )(s|\+|\.| )(t|\+|\.| )(p|\+|\.| )(o|\+|\.| )(g|\+|\.| )(u|\+|\.| )(a|\+|\.| )(x|\+|\.) (.*)""");
145
146 regex_list[RegexType.LogModified] = new Regex(
147 """[0-9\/]+ [0-9:.]+ \‍[[0-9]+\‍] ([<>ch.])([.fdLDS])(c|\+|\.| )(s|\+|\.| )(t|\+|\.| )(p|\+|\.| )(o|\+|\.| )(g|\+|\.| )(u|\+|\.| )(a|\+|\.| )(x|\+|\.) (.*)""");
148
149 regex_list[RegexType.Unchanged] = new Regex(
150 """([.h])([.fdLDS])[ ]{9} (.*)""");
151
152 regex_list[RegexType.LogUnchanged] = new Regex(
153 """[0-9\/]+ [0-9:.]+ \‍[[0-9]+\‍] ([.h])([.fdLDS])[ ]{9} (.*)""");
154
155 regex_list[RegexType.TotalSize] = new Regex(
156 """total size is ([0-9,]+)[ \t]+speedup is [0-9.]+""");
157
158 }
159 catch (Error e) {
160 log_error (e.message);
161 }
162 }
Regex[] regex_list
void log_error(string message, bool highlight=false, bool is_warning=false)

References Error, TeeJee.Logging.log_error(), and regex_list.

Referenced by RsyncTask().

◆ parse_log()

Gee.ArrayList< FileItem > RsyncTask.parse_log ( string log_file_path)
inline

Definition at line 267 of file RsyncTask.vala.

267 {
268
269 var list = new Gee.ArrayList<FileItem>();
270
271 string log_file = log_file_path;
272 DataOutputStream dos_changes = null;
273
274 if (!log_file.has_suffix("-changes")){
275
276 string log_file_changes = log_file_path + "-changes";
277
278 if (file_exists(log_file_changes)){
279 // use it
280 log_file = log_file_changes;
281 }
282 else{
283 // create one by initializing dos_changes
284 try {
285 var file = File.new_for_path(log_file_changes);
286 if (file.query_exists()){
287 file.delete();
288 }
289 var file_stream = file.create (FileCreateFlags.REPLACE_DESTINATION);
290 dos_changes = new DataOutputStream (file_stream);
291 }
292 catch (Error e) {
293 log_error (e.message);
294 }
295 }
296 }
297
298 log_debug("RsyncTask: parse_log()");
299 log_debug("log_file = %s".printf(log_file));
300
301 prg_count = 0;
302 prg_count_total = file_line_count(log_file) ?? 0;
303
304 try {
305 string line;
306 var file = File.new_for_path(log_file);
307 if (!file.query_exists ()) {
308 log_error(_("File not found") + ": %s".printf(log_file));
309 return list;
310 }
311
312 var dis = new DataInputStream (file.read());
313
314 string item_path = "";
315 string item_disk_path = "";
316 string item_status = "";
317
318 string item_basepath = path_combine(file_parent(log_file_path), "localhost");
319
320 while ((line = dis.read_line(null)) != null) {
321
322 prg_count++;
323
324 if (line.strip().length == 0) { continue; }
325
326 item_path = "";
327
328 MatchInfo match;
329 if (regex_list[RegexType.Created].match(line, 0, out match)
330 || regex_list[RegexType.LogCreated].match(line, 0, out match)) {
331
332 if (dos_changes != null){
333 dos_changes.put_string("%s\n".printf(line));
334 }
335
336 //log_debug("matched: created:%s".printf(line));
337
338 item_path = match.fetch(3).split(" -> ")[0].strip();
339 /*item_type = FileType.REGULAR;
340 if (match.fetch(2) == "d"){
341 item_type = FileType.DIRECTORY;
342 }
343 else if (match.fetch(2) == "L"){
344 item_is_symlink = true;
345 }*/
346 item_status = "created";
347 }
348 else if (regex_list[RegexType.LogDeleted].match(line, 0, out match)
349 || regex_list[RegexType.Deleted].match(line, 0, out match)) {
350
351 //log_debug("matched: deleted:%s".printf(line));
352
353 if (dos_changes != null){
354 dos_changes.put_string("%s\n".printf(line));
355 }
356
357 item_path = match.fetch(1).split(" -> ")[0].strip();
358 //item_type = item_path.has_suffix("/") ? FileType.DIRECTORY : FileType.REGULAR;
359 item_status = "deleted";
360 }
361 else if (regex_list[RegexType.Modified].match(line, 0, out match)
362 || regex_list[RegexType.LogModified].match(line, 0, out match)) {
363
364 //log_debug("matched: modified:%s".printf(line));
365
366 if (dos_changes != null){
367 dos_changes.put_string("%s\n".printf(line));
368 }
369
370 item_path = match.fetch(12).split(" -> ")[0].strip();
371
372 /*if (match.fetch(2) == "d"){
373 item_type = FileType.DIRECTORY;
374 }
375 else if (match.fetch(2) == "L"){
376 item_is_symlink = true;
377 }*/
378
379 if (match.fetch(3) == "c"){
380 item_status = "checksum";
381 }
382 else if (match.fetch(4) == "s"){
383 item_status = "size";
384 }
385 else if (match.fetch(5) == "t"){
386 item_status = "timestamp";
387 }
388 else if (match.fetch(6) == "p"){
389 item_status = "permissions";
390 }
391 else if (match.fetch(7) == "o"){
392 item_status = "owner";
393 }
394 else if (match.fetch(8) == "g"){
395 item_status = "group";
396 }
397 }
398 else if (regex_list[RegexType.LogUnchanged].match(line, 0, out match)) {
399 // ignore
400 }
401 else{
402 log_debug("not-matched: %s".printf(line));
403 }
404
405 if ((item_path.length > 0) && (item_path != "/./") && (item_path != "./")){
406
407 item_disk_path = path_combine(item_basepath, item_path);
408
409 var item = new FileItem.from_disk_path_with_basic_info(item_disk_path);
410 item.file_status = item_status;
411 list.add(item);
412 //log_debug("added: %s".printf(item_path));
413 }
414 }
415 }
416 catch (Error e) {
417 log_error (e.message);
418 }
419
420 if (dos_changes != null){
421 // archive the raw log file
422 log_msg("Archiving: %s".printf(log_file_path));
423 file_gzip(log_file_path);
424 }
425
426 log_debug("RsyncTask: parse_log(): exit");
427
428 return list;
429 }
#define _(s)
int64 prg_count
int64 prg_count_total
bool file_exists(string file_path)
string file_parent(string file_path)
string path_combine(string path1, string path2)
int64? file_line_count(string file_path)
bool file_gzip(string src_file)
void log_debug(string message)
void log_msg(string message, bool highlight=false)

References _, Error, TeeJee.FileSystem.file_exists(), TeeJee.FileSystem.file_gzip(), TeeJee.FileSystem.file_line_count(), TeeJee.FileSystem.file_parent(), FileItem.from_disk_path_with_basic_info(), TeeJee.Logging.log_debug(), TeeJee.Logging.log_error(), TeeJee.Logging.log_msg(), TeeJee.FileSystem.path_combine(), AsyncTask.prg_count, AsyncTask.prg_count_total, and regex_list.

Referenced by RsyncLogBox.parse_log_file_thread().

◆ parse_stderr_line()

override void RsyncTask.parse_stderr_line ( string err_line)
inline

Definition at line 437 of file RsyncTask.vala.

437 {
439 }
string err_line
bool update_progress_parse_console_output(string line)

References AsyncTask.err_line, and update_progress_parse_console_output().

◆ parse_stdout_line()

override void RsyncTask.parse_stdout_line ( string out_line)
inline

◆ prepare()

override void RsyncTask.prepare ( )
inlinevirtual

Reimplemented from AsyncTask.

Definition at line 164 of file RsyncTask.vala.

164 {
165 base.prepare();
166
167 //status_lines = new GLib.Queue<string>();
169 total_size = 0;
170
171 count_created = 0;
172 count_deleted = 0;
173 count_modified = 0;
174 count_checksum = 0;
175 count_size = 0;
176 count_timestamp = 0;
178 count_owner = 0;
179 count_group = 0;
180 count_unchanged = 0;
181
182 log = new StringBuilder();
183 }
int64 count_group
int64 count_deleted
int64 count_owner
int64 count_modified
int64 count_permissions
int64 count_size
int64 count_created
int64 count_timestamp
int64 count_unchanged
int64 status_line_count
int64 count_checksum
int64 total_size

References count_checksum, count_created, count_deleted, count_group, count_modified, count_owner, count_permissions, count_size, count_timestamp, count_unchanged, log, status_line_count, and total_size.

◆ update_progress_parse_console_output()

bool RsyncTask.update_progress_parse_console_output ( string line)
inline

Definition at line 441 of file RsyncTask.vala.

441 {
442 if ((line == null) || (line.length == 0)) {
443 return true;
444 }
445
447
448 if (prg_count_total > 0){
451 }
452
453 //MatchInfo match;
454 //if (regex_list[RegexType.Status].match(line, 0, out match)) {
455 // status_line = match.fetch(12);
456
457 //status_lines.push_tail(status_line);
458 //if (status_lines.get_length() > 15){
459 // status_lines.pop_head();
460 //}
461 //}
462 MatchInfo match;
463 if (regex_list[RegexType.Created].match(line, 0, out match)) {
464
465 //log_debug("matched: created:%s".printf(line));
466
468 status_line = match.fetch(3).split(" -> ")[0].strip();
469 log.append(line + "\n");
470 }
471 else if (regex_list[RegexType.Deleted].match(line, 0, out match)) {
472
473 //log_debug("matched: deleted:%s".printf(line));
474
476 status_line = match.fetch(1).split(" -> ")[0].strip();
477 log.append(line + "\n");
478 }
479 else if (regex_list[RegexType.Unchanged].match(line, 0, out match)) {
480
481 //log_debug("matched: unchanged:%s".printf(line));
482
484 status_line = match.fetch(3).split(" -> ")[0].strip();
485 }
486 else if (regex_list[RegexType.Modified].match(line, 0, out match)) {
487
488 //log_debug("matched: modified:%s".printf(line));
489
491 status_line = match.fetch(12).split(" -> ")[0].strip();
492 log.append(line + "\n");
493
494 if (match.fetch(3) == "c"){
496 }
497 else if (match.fetch(4) == "s"){
498 count_size++;
499 }
500 else if (match.fetch(5) == "t"){
502 }
503 else if (match.fetch(6) == "p"){
505 }
506 else if (match.fetch(7) == "o"){
507 count_owner++;
508 }
509 else if (match.fetch(8) == "g"){
510 count_group++;
511 }
512 else{
514 }
515 }
516 else if (regex_list[RegexType.TotalSize].match(line, 0, out match)) {
517 total_size = int64.parse(match.fetch(1).replace(",",""));
518 }
519 else{
520 //log_debug("not-matched: %s".printf(line));
521 }
522
523 return true;
524 }
double progress
string status_line

References count_checksum, count_created, count_deleted, count_group, count_modified, count_owner, count_permissions, count_size, count_timestamp, count_unchanged, log, AsyncTask.prg_count, AsyncTask.prg_count_total, AsyncTask.progress, regex_list, AsyncTask.status_line, status_line_count, and total_size.

Referenced by parse_stderr_line(), and parse_stdout_line().

Member Data Documentation

◆ count_checksum

int64 RsyncTask.count_checksum

◆ count_created

◆ count_deleted

int64 RsyncTask.count_deleted

◆ count_group

int64 RsyncTask.count_group

◆ count_modified

int64 RsyncTask.count_modified

◆ count_owner

int64 RsyncTask.count_owner

◆ count_permissions

int64 RsyncTask.count_permissions

◆ count_size

int64 RsyncTask.count_size

◆ count_timestamp

int64 RsyncTask.count_timestamp

◆ count_unchanged

int64 RsyncTask.count_unchanged

◆ delete_after

bool RsyncTask.delete_after = false

Definition at line 50 of file RsyncTask.vala.

Referenced by build_script().

◆ delete_excluded

bool RsyncTask.delete_excluded = false

Definition at line 51 of file RsyncTask.vala.

Referenced by build_script().

◆ delete_extra

bool RsyncTask.delete_extra = true

Definition at line 49 of file RsyncTask.vala.

Referenced by build_script().

◆ dest_path

string RsyncTask.dest_path = ""

Definition at line 58 of file RsyncTask.vala.

Referenced by build_script().

◆ dry_run

bool RsyncTask.dry_run = false

Definition at line 61 of file RsyncTask.vala.

Referenced by build_script().

◆ exclude_from_file

string RsyncTask.exclude_from_file = ""

Definition at line 55 of file RsyncTask.vala.

Referenced by build_script().

◆ io_nice

bool RsyncTask.io_nice = true

Definition at line 60 of file RsyncTask.vala.

Referenced by build_script().

◆ link_from_path

string RsyncTask.link_from_path = ""

Definition at line 56 of file RsyncTask.vala.

Referenced by build_script().

◆ log

StringBuilder RsyncTask.log

Definition at line 82 of file RsyncTask.vala.

Referenced by finish_task(), prepare(), and update_progress_parse_console_output().

◆ regex_list

Regex [] RsyncTask.regex_list = null
private

◆ relative

bool RsyncTask.relative = false

Definition at line 52 of file RsyncTask.vala.

◆ rsync_log_file

string RsyncTask.rsync_log_file = ""

Definition at line 54 of file RsyncTask.vala.

Referenced by build_script(), and finish_task().

◆ source_path

string RsyncTask.source_path = ""

Definition at line 57 of file RsyncTask.vala.

Referenced by build_script().

◆ status_line_count

int64 RsyncTask.status_line_count = 0

Definition at line 68 of file RsyncTask.vala.

Referenced by prepare(), and update_progress_parse_console_output().

◆ status_lines

GLib.Queue<string> RsyncTask.status_lines

Definition at line 67 of file RsyncTask.vala.

Referenced by RsyncTask().

◆ total_size

int64 RsyncTask.total_size = 0

◆ verbose

bool RsyncTask.verbose = true

Definition at line 59 of file RsyncTask.vala.

Referenced by build_script().


The documentation for this class was generated from the following file:
  • BastionGuard/thirdparty/bastionguard-backup/src/Utility/RsyncTask.vala