Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "asfd.h"
4 : #include "async.h"
5 : #include "cmd.h"
6 : #include "cntr.h"
7 : #include "cstat.h"
8 : #include "fsops.h"
9 : #include "handy.h"
10 : #include "iobuf.h"
11 : #include "log.h"
12 : #include "times.h"
13 :
14 : #include "client/monitor/sel.h"
15 : #include "client/monitor/json_input.h"
16 : #include "server/bu_get.h"
17 : #include "server/monitor/json_output.h"
18 :
19 : #include <limits.h>
20 :
21 : #define CNTR_VERSION 3
22 : #define CNTR_PATH_BUF_LEN 256
23 :
24 : static void cntr_ent_free_content(struct cntr_ent *cntr_ent)
25 : {
26 : if(!cntr_ent) return;
27 650 : free_w(&cntr_ent->field);
28 650 : free_w(&cntr_ent->label);
29 : }
30 :
31 650 : static void cntr_ent_free(struct cntr_ent **cntr_ent)
32 : {
33 650 : if(!cntr_ent || !*cntr_ent) return;
34 1300 : cntr_ent_free_content(*cntr_ent);
35 650 : free_v((void **)cntr_ent);
36 : }
37 :
38 26 : struct cntr *cntr_alloc(void)
39 : {
40 26 : return (struct cntr *)calloc_w(1, sizeof(struct cntr), __func__);
41 : }
42 :
43 650 : static int add_cntr_ent(struct cntr *cntr, int flags,
44 : enum cmd cmd, const char *field, const char *label)
45 : {
46 650 : struct cntr_ent *cenew=NULL;
47 650 : if(!(cenew=(struct cntr_ent *)
48 650 : calloc_w(1, sizeof(struct cntr_ent), __func__))
49 650 : || !(cenew->field=strdup_w(field, __func__))
50 650 : || !(cenew->label=strdup_w(label, __func__)))
51 : goto error;
52 650 : cenew->flags=flags;
53 650 : cenew->cmd=cmd;
54 :
55 650 : if(cntr->list) cenew->next=cntr->list;
56 650 : cntr->list=cenew;
57 :
58 650 : cntr->ent[(uint8_t)cmd]=cenew;
59 650 : return 0;
60 : error:
61 0 : cntr_ent_free(&cenew);
62 0 : return -1;
63 : }
64 :
65 26 : static size_t calc_max_str_len(struct cntr *cntr, const char *cname)
66 : {
67 26 : size_t slen=0;
68 : char ullmax[64];
69 26 : struct cntr_ent *e=NULL;
70 :
71 : // See cntr_to_str().
72 : // First section - name/version/status
73 26 : slen+=strlen(cname);
74 26 : slen+=32; // More than enough space.
75 :
76 : // Second section.
77 26 : snprintf(ullmax, sizeof(ullmax),
78 : " %" PRIu64 "\n", (uint64_t)ULLONG_MAX);
79 676 : for(e=cntr->list; e; e=e->next)
80 : {
81 650 : if(e->flags & CNTR_SINGLE_FIELD)
82 : // %c%llu\t
83 234 : slen+=strlen(ullmax)+2;
84 : else
85 : // %c%llu/%llu/%llu/%llu/%llu\t
86 416 : slen+=(strlen(ullmax)*5)+6;
87 : }
88 :
89 : // Fourth section - a path. Cannot know how long this might be. Guess.
90 26 : slen+=CNTR_PATH_BUF_LEN+3; // %c%s\t\n
91 :
92 26 : slen+=1; // Terminating character.
93 :
94 26 : return slen;
95 : }
96 :
97 26 : int cntr_init(struct cntr *cntr, const char *cname, pid_t pid)
98 : {
99 26 : if(!cname)
100 : {
101 0 : logp("%s called with no client name\n", __func__);
102 0 : return -1;
103 : }
104 :
105 : // Add in reverse order, so that iterating over from the beginning
106 : // comes out in the right order.
107 26 : if(
108 26 : add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
109 : CMD_TIMESTAMP_END, "time_end", "End time")
110 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
111 : CMD_TIMESTAMP, "time_start", "Start time")
112 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
113 : CMD_BYTES_SENT, "bytes_sent", "Bytes sent")
114 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
115 : CMD_BYTES_RECV, "bytes_received", "Bytes received")
116 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
117 : CMD_BYTES, "bytes", "Bytes")
118 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
119 : CMD_BYTES_ESTIMATED, "bytes_estimated", "Bytes estimated")
120 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
121 : CMD_MESSAGE, "messages", "Messages")
122 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
123 : CMD_WARNING, "warnings", "Warnings")
124 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
125 : CMD_GRAND_TOTAL, "grand_total", "Grand total")
126 26 : || add_cntr_ent(cntr, 0,
127 : CMD_TOTAL, "total", "Total")
128 26 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
129 : CMD_ERROR, "errors", "Errors")
130 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
131 : CMD_DATA, "blocks", "Blocks")
132 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
133 : CMD_EFS_FILE, "efs_files", "EFS files")
134 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
135 : CMD_ENC_VSS_T, "vss_footers_encrypted", "VSS footers (enc)")
136 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
137 : CMD_VSS_T, "vss_footers", "VSS footers")
138 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
139 : CMD_ENC_VSS, "vss_headers_encrypted", "VSS headers (enc)")
140 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
141 : CMD_VSS, "vss_headers", "VSS headers")
142 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
143 : CMD_SPECIAL, "special_files", "Special files")
144 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
145 : CMD_SOFT_LINK, "hard_links", "Soft links")
146 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
147 : CMD_HARD_LINK, "soft_links", "Hard links")
148 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
149 : CMD_DIRECTORY, "directories", "Directories")
150 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
151 : CMD_ENC_METADATA, "meta_data_encrypted", "Meta data (enc)")
152 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
153 : CMD_METADATA, "meta_data", "Meta data")
154 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
155 : CMD_ENC_FILE, "files_encrypted", "Files (encrypted)")
156 26 : || add_cntr_ent(cntr, CNTR_TABULATE,
157 : CMD_FILE, "files", "Files")
158 : )
159 : return -1;
160 :
161 26 : cntr->ent[(uint8_t)CMD_TIMESTAMP]->count=(uint64_t)time(NULL);
162 :
163 26 : cntr->str_max_len=calc_max_str_len(cntr, cname);
164 26 : if(!(cntr->str=(char *)calloc_w(1, cntr->str_max_len, __func__))
165 26 : || !(cntr->cname=strdup_w(cname, __func__)))
166 : return -1;
167 26 : cntr->pid=pid;
168 :
169 26 : return 0;
170 : }
171 :
172 26 : static void cntr_free_content(struct cntr *cntr)
173 : {
174 : struct cntr_ent *e;
175 26 : struct cntr_ent *l=NULL;
176 676 : for(e=cntr->list; e; e=l)
177 : {
178 650 : l=e->next;
179 650 : cntr_ent_free(&e);
180 : }
181 26 : cntr->list=NULL;
182 26 : free_w(&cntr->str);
183 26 : free_w(&cntr->cname);
184 26 : }
185 :
186 357 : void cntr_free(struct cntr **cntr)
187 : {
188 357 : if(!cntr || !*cntr) return;
189 26 : cntr_free_content(*cntr);
190 26 : free_v((void **)cntr);
191 : }
192 :
193 154 : void cntrs_free(struct cntr **cntrs)
194 : {
195 : struct cntr *c;
196 : struct cntr *chead;
197 307 : if(!cntrs || !*cntrs) return;
198 : chead=*cntrs;
199 2 : while(chead)
200 : {
201 1 : c=chead;
202 1 : chead=chead->next;
203 1 : cntr_free(&c);
204 : }
205 1 : *cntrs=NULL;
206 : }
207 :
208 3 : const char *bytes_to_human(uint64_t counter)
209 : {
210 : static char ret[32]="";
211 3 : float div=(float)counter;
212 3 : char units[3]="";
213 :
214 3 : if(div<1024) return "";
215 :
216 0 : if((div/=1024)<1024)
217 0 : snprintf(units, sizeof(units), "KB");
218 0 : else if((div/=1024)<1024)
219 0 : snprintf(units, sizeof(units), "MB");
220 0 : else if((div/=1024)<1024)
221 0 : snprintf(units, sizeof(units), "GB");
222 0 : else if((div/=1024)<1024)
223 0 : snprintf(units, sizeof(units), "TB");
224 0 : else if((div/=1024)<1024)
225 0 : snprintf(units, sizeof(units), "EB");
226 : else
227 : {
228 0 : div/=1024;
229 0 : snprintf(units, sizeof(units), "PB");
230 : }
231 0 : snprintf(ret, sizeof(ret), " (%.2f %s)", div, units);
232 0 : return ret;
233 : }
234 :
235 : static void border(void)
236 : {
237 0 : logc("--------------------------------------------------------------------------------\n");
238 : }
239 :
240 0 : static void table_border(enum action act)
241 : {
242 0 : if(act==ACTION_BACKUP
243 0 : || act==ACTION_BACKUP_TIMED)
244 : {
245 0 : logc("%18s ------------------------------------------------------------\n", "");
246 : }
247 0 : if(act==ACTION_RESTORE
248 0 : || act==ACTION_VERIFY)
249 : {
250 0 : logc("%18s ------------------------------\n", "");
251 : }
252 0 : }
253 :
254 : static void set_count_val(struct cntr *cntr, char ch, uint64_t val)
255 : {
256 0 : if(!cntr) return;
257 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->count=val;
258 : }
259 :
260 : static void set_changed_val(struct cntr *cntr, char ch, uint64_t val)
261 : {
262 0 : if(!cntr) return;
263 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->changed=val;
264 : }
265 :
266 : static void set_same_val(struct cntr *cntr, char ch, uint64_t val)
267 : {
268 0 : if(!cntr) return;
269 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->same=val;
270 : }
271 :
272 : static void set_deleted_val(struct cntr *cntr, char ch, uint64_t val)
273 : {
274 0 : if(!cntr) return;
275 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->deleted=val;
276 : }
277 :
278 : static void set_phase1_val(struct cntr *cntr, char ch, uint64_t val)
279 : {
280 0 : if(!cntr) return;
281 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->phase1=val;
282 : }
283 :
284 : static void incr_count_val(struct cntr *cntr, char ch, uint64_t val)
285 : {
286 20 : if(!cntr) return;
287 5 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->count+=val;
288 : }
289 :
290 : static void incr_same_val(struct cntr *cntr, char ch, uint64_t val)
291 : {
292 37878 : if(!cntr) return;
293 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->same+=val;
294 : }
295 :
296 : static void incr_changed_val(struct cntr *cntr, char ch, uint64_t val)
297 : {
298 12 : if(!cntr) return;
299 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->changed+=val;
300 : }
301 :
302 : static void incr_deleted_val(struct cntr *cntr, char ch, uint64_t val)
303 : {
304 6 : if(!cntr) return;
305 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->deleted+=val;
306 : }
307 :
308 : static void incr_phase1_val(struct cntr *cntr, char ch, uint64_t val)
309 : {
310 0 : if(!cntr) return;
311 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->phase1+=val;
312 : }
313 :
314 : static void incr_count(struct cntr *cntr, char ch)
315 : {
316 10 : return incr_count_val(cntr, ch, 1);
317 : }
318 :
319 : static void incr_same(struct cntr *cntr, char ch)
320 : {
321 75756 : return incr_same_val(cntr, ch, 1);
322 : }
323 :
324 : static void incr_changed(struct cntr *cntr, char ch)
325 : {
326 24 : return incr_changed_val(cntr, ch, 1);
327 : }
328 :
329 : static void incr_deleted(struct cntr *cntr, char ch)
330 : {
331 12 : return incr_deleted_val(cntr, ch, 1);
332 : }
333 :
334 : static void incr_phase1(struct cntr *cntr, char ch)
335 : {
336 0 : return incr_phase1_val(cntr, ch, 1);
337 : }
338 :
339 : static void print_end(uint64_t val)
340 : {
341 0 : if(val) logc(" %" PRIu64 "\n", val);
342 : }
343 :
344 42394 : void cntr_add(struct cntr *c, char ch, int print)
345 : {
346 : struct cntr_ent *grand_total_ent;
347 42394 : if(!c) return;
348 5 : if(!(grand_total_ent=c->ent[CMD_GRAND_TOTAL])) return;
349 5 : if(print)
350 : {
351 5 : if(ch!=CMD_MESSAGE && ch!=CMD_WARNING)
352 0 : logc("%c", ch);
353 : }
354 5 : if(ch==CMD_FILE_CHANGED)
355 : {
356 0 : incr_changed(c, CMD_FILE);
357 0 : incr_changed(c, CMD_TOTAL);
358 : incr_changed(c, CMD_GRAND_TOTAL);
359 : }
360 : else
361 : {
362 10 : incr_count(c, ch);
363 5 : if(ch==CMD_WARNING || ch==CMD_MESSAGE) return;
364 : incr_count(c, CMD_TOTAL);
365 : }
366 :
367 0 : if(!((++grand_total_ent->count)%64) && print)
368 0 : print_end(grand_total_ent->count);
369 0 : fflush(stdout);
370 : }
371 :
372 0 : void cntr_add_phase1(struct cntr *c, char ch, int print)
373 : {
374 : static struct cntr_ent *total;
375 0 : incr_phase1(c, ch);
376 :
377 0 : total=c->ent[(uint8_t)CMD_GRAND_TOTAL];
378 0 : ++total->phase1;
379 0 : if(!print) return;
380 0 : if(total->phase1==1) logc("\n");
381 0 : logc("%c", ch);
382 0 : if(!((total->phase1)%64))
383 0 : print_end(total->phase1);
384 0 : fflush(stdout);
385 : }
386 :
387 0 : void cntr_add_val(struct cntr *c, char ch, uint64_t val)
388 : {
389 0 : incr_count_val(c, ch, val);
390 0 : }
391 :
392 33720 : void cntr_add_new(struct cntr *c, char ch)
393 : {
394 33720 : cntr_add(c, ch, 0);
395 33720 : }
396 :
397 12626 : void cntr_add_same(struct cntr *c, char ch)
398 : {
399 25252 : incr_same(c, ch);
400 12626 : incr_same(c, CMD_TOTAL);
401 12626 : incr_same(c, CMD_GRAND_TOTAL);
402 12626 : }
403 :
404 0 : void cntr_add_same_val(struct cntr *c, char ch, uint64_t val)
405 : {
406 0 : incr_same_val(c, ch, val);
407 0 : incr_same_val(c, CMD_TOTAL, val);
408 0 : incr_same_val(c, CMD_GRAND_TOTAL, val);
409 0 : }
410 :
411 4 : void cntr_add_changed(struct cntr *c, char ch)
412 : {
413 8 : incr_changed(c, ch);
414 4 : incr_changed(c, CMD_TOTAL);
415 4 : incr_changed(c, CMD_GRAND_TOTAL);
416 4 : }
417 :
418 0 : void cntr_add_changed_val(struct cntr *c, char ch, uint64_t val)
419 : {
420 0 : incr_changed_val(c, ch, val);
421 0 : incr_changed_val(c, CMD_TOTAL, val);
422 0 : incr_changed_val(c, CMD_GRAND_TOTAL, val);
423 0 : }
424 :
425 2 : void cntr_add_deleted(struct cntr *c, char ch)
426 : {
427 4 : incr_deleted(c, ch);
428 2 : incr_deleted(c, CMD_TOTAL);
429 2 : incr_deleted(c, CMD_GRAND_TOTAL);
430 2 : }
431 :
432 20 : void cntr_add_bytes(struct cntr *c, uint64_t bytes)
433 : {
434 20 : incr_count_val(c, CMD_BYTES, bytes);
435 20 : }
436 :
437 : static void cntr_set_sentbytes(struct cntr *c, uint64_t bytes)
438 : {
439 0 : set_count_val(c, CMD_BYTES_SENT, bytes);
440 : }
441 :
442 : static void cntr_set_recvbytes(struct cntr *c, uint64_t bytes)
443 : {
444 : set_count_val(c, CMD_BYTES_RECV, bytes);
445 : }
446 :
447 0 : static void quint_print(struct cntr_ent *ent, enum action act)
448 : {
449 : uint64_t a;
450 : uint64_t b;
451 : uint64_t c;
452 : uint64_t d;
453 : uint64_t e;
454 0 : if(!ent) return;
455 0 : a=ent->count;
456 0 : b=ent->changed;
457 0 : c=ent->same;
458 0 : d=ent->deleted;
459 0 : e=ent->phase1;
460 :
461 0 : if(!(ent->flags & CNTR_TABULATE)) return;
462 :
463 0 : if(!e && !a && !b && !c) return;
464 0 : logc("%18s:", ent->label);
465 0 : if(act==ACTION_BACKUP
466 0 : || act==ACTION_BACKUP_TIMED)
467 : {
468 0 : logc("%9" PRIu64 " ", a);
469 0 : logc("%9" PRIu64 " ", b);
470 0 : logc("%9" PRIu64 " ", c);
471 0 : logc("%9" PRIu64 " ", d);
472 : }
473 0 : if(act==ACTION_RESTORE
474 0 : || act==ACTION_VERIFY)
475 : {
476 0 : logc("%9s ", "");
477 : //logc("%9s ", "");
478 : //logc("%9s ", "");
479 : //logc("%9s ", "");
480 : }
481 0 : if(act==ACTION_ESTIMATE)
482 : {
483 0 : logc("%9s ", "");
484 0 : logc("%9s ", "");
485 0 : logc("%9" PRIu64 "\n", e);
486 : }
487 : else
488 : {
489 0 : logc("%9" PRIu64 " |", a+b+c);
490 0 : logc("%9" PRIu64 "\n", e);
491 : }
492 : }
493 :
494 : static uint64_t get_count(struct cntr_ent **ent, enum cmd cmd)
495 : {
496 0 : if(!ent[(uint8_t)cmd]) return 0;
497 0 : return ent[(uint8_t)cmd]->count;
498 : }
499 :
500 0 : static void bottom_part(struct cntr *c, enum action act)
501 : {
502 : uint64_t l;
503 0 : struct cntr_ent **e=c->ent;
504 0 : logc("\n");
505 0 : logc(" Messages: %11" PRIu64 "\n", get_count(e, CMD_MESSAGE));
506 0 : logc(" Warnings: %11" PRIu64 "\n", get_count(e, CMD_WARNING));
507 0 : logc("\n");
508 0 : logc(" Bytes estimated: %11" PRIu64, get_count(e, CMD_BYTES_ESTIMATED));
509 0 : logc("%s\n", bytes_to_human(get_count(e, CMD_BYTES_ESTIMATED)));
510 :
511 0 : if(act==ACTION_ESTIMATE) return;
512 :
513 0 : if(act==ACTION_BACKUP
514 0 : || act==ACTION_BACKUP_TIMED)
515 : {
516 0 : l=get_count(e, CMD_BYTES);
517 0 : logc(" Bytes in backup: %11" PRIu64, l);
518 0 : logc("%s\n", bytes_to_human(l));
519 : }
520 0 : if(act==ACTION_RESTORE)
521 : {
522 0 : l=get_count(e, CMD_BYTES);
523 0 : logc(" Bytes attempted: %11" PRIu64, l);
524 0 : logc("%s\n", bytes_to_human(l));
525 : }
526 0 : if(act==ACTION_VERIFY)
527 : {
528 0 : l=get_count(e, CMD_BYTES);
529 0 : logc(" Bytes checked: %11" PRIu64, l);
530 0 : logc("%s\n", bytes_to_human(l));
531 : }
532 :
533 0 : l=get_count(e, CMD_BYTES_RECV);
534 0 : logc(" Bytes received: %11" PRIu64, l);
535 0 : logc("%s\n", bytes_to_human(l));
536 :
537 0 : l=get_count(e, CMD_BYTES_SENT);
538 0 : logc(" Bytes sent: %11" PRIu64, l);
539 0 : logc("%s\n", bytes_to_human(l));
540 : }
541 :
542 29 : void cntr_print(struct cntr *cntr, enum action act, struct asfd *asfd)
543 : {
544 : struct cntr_ent *e;
545 : time_t now;
546 : time_t start;
547 : char time_start_str[32];
548 : char time_end_str[32];
549 58 : if(!cntr) return;
550 :
551 0 : if(asfd)
552 : {
553 0 : cntr_set_sentbytes(cntr, asfd->sent);
554 0 : cntr_set_recvbytes(cntr, asfd->rcvd);
555 : }
556 0 : now=time(NULL);
557 0 : start=(time_t)cntr->ent[(uint8_t)CMD_TIMESTAMP]->count;
558 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=(uint64_t)now;
559 :
560 : border();
561 0 : encode_time(start, time_start_str);
562 0 : encode_time(now, time_end_str);
563 0 : logc("Start time: %s\n", time_start_str);
564 0 : logc(" End time: %s\n", time_end_str);
565 0 : logc("Time taken: %s\n", time_taken(now-start));
566 0 : if(act==ACTION_BACKUP
567 0 : || act==ACTION_BACKUP_TIMED)
568 : {
569 0 : logc("%18s %9s %9s %9s %9s %9s |%9s\n",
570 : " ", "New", "Changed", "Duplicate", "Deleted", "Total", "Scanned");
571 : }
572 0 : if(act==ACTION_RESTORE
573 0 : || act==ACTION_VERIFY)
574 : {
575 0 : logc("%18s %9s %9s |%9s\n",
576 : " ", "", "Attempted", "Expected");
577 : }
578 0 : if(act==ACTION_ESTIMATE)
579 : {
580 0 : logc("%18s %9s %9s %9s\n",
581 : " ", "", "", "Scanned");
582 : }
583 0 : table_border(act);
584 :
585 0 : for(e=cntr->list; e; e=e->next)
586 0 : quint_print(e, act);
587 :
588 0 : table_border(act);
589 0 : bottom_part(cntr, act);
590 :
591 : border();
592 : }
593 :
594 : #ifndef HAVE_WIN32
595 :
596 7 : int cntr_stats_to_file(struct cntr *cntr,
597 : const char *directory, enum action act)
598 : {
599 7 : int ret=-1;
600 7 : int fd=-1;
601 7 : char *path=NULL;
602 7 : const char *fname=NULL;
603 7 : struct async *as=NULL;
604 7 : struct asfd *wfd=NULL;
605 7 : if(!cntr)
606 : return 0;
607 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count
608 0 : =(uint64_t)time(NULL);
609 :
610 0 : if(act==ACTION_BACKUP
611 0 : || act==ACTION_BACKUP_TIMED)
612 : fname="backup_stats";
613 0 : else if(act==ACTION_RESTORE)
614 : fname="restore_stats";
615 0 : else if(act==ACTION_VERIFY)
616 : fname="verify_stats";
617 : else
618 : return 0;
619 :
620 0 : if(!(path=prepend_s(directory, fname)))
621 : goto end;
622 0 : if((fd=open(
623 : path,
624 : #ifdef O_NOFOLLOW
625 : O_NOFOLLOW|
626 : #endif
627 : O_WRONLY|O_CREAT,
628 : 0666))<0)
629 : {
630 0 : logp("Could not open %s for writing in %s: %s\n",
631 0 : path, __func__, strerror(errno));
632 0 : goto end;
633 : }
634 :
635 0 : if(!(as=async_alloc())
636 0 : || as->init(as, 0)
637 0 : || !(wfd=setup_asfd_linebuf_write(as, "stats file", &fd)))
638 : {
639 0 : close_fd(&fd);
640 0 : goto end;
641 : }
642 :
643 0 : if(json_cntr(wfd, cntr))
644 : goto end;
645 :
646 0 : ret=0;
647 : end:
648 0 : free_w(&path);
649 0 : async_free(&as);
650 0 : asfd_free(&wfd);
651 0 : return ret;
652 : }
653 :
654 : #endif
655 :
656 22 : void cntr_print_end(struct cntr *cntr)
657 : {
658 : struct cntr_ent *grand_total_ent;
659 22 : if(!cntr) return;
660 0 : grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
661 0 : if(grand_total_ent)
662 : {
663 0 : print_end(grand_total_ent->count);
664 0 : logc("\n");
665 : }
666 : }
667 :
668 0 : void cntr_print_end_phase1(struct cntr *cntr)
669 : {
670 : struct cntr_ent *grand_total_ent;
671 0 : if(!cntr) return;
672 0 : grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
673 0 : if(grand_total_ent)
674 : {
675 0 : print_end(grand_total_ent->phase1);
676 0 : logc("\n");
677 : }
678 : }
679 :
680 : #ifndef HAVE_WIN32
681 : // Return string length.
682 0 : size_t cntr_to_str(struct cntr *cntr, const char *path)
683 : {
684 : static char tmp[CNTR_PATH_BUF_LEN+3]="";
685 0 : struct cntr_ent *e=NULL;
686 0 : char *str=cntr->str;
687 :
688 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=time(NULL);
689 :
690 0 : snprintf(str, cntr->str_max_len-1, "cntr\t%s.%d.%d\t%d\t%d\t",
691 : cntr->cname, cntr->pid, cntr->bno,
692 0 : CNTR_VERSION, cntr->cntr_status);
693 :
694 0 : for(e=cntr->list; e; e=e->next)
695 : {
696 0 : if(e->flags & CNTR_SINGLE_FIELD)
697 0 : snprintf(tmp, sizeof(tmp),
698 0 : "%c%" PRIu64"\t", e->cmd, e->count);
699 : else
700 0 : snprintf(tmp, sizeof(tmp),
701 : "%c%" PRIu64
702 : "/%" PRIu64
703 : "/%" PRIu64
704 : "/%" PRIu64
705 : "/%" PRIu64
706 : "\t",
707 0 : e->cmd, e->count, e->changed,
708 : e->same, e->deleted, e->phase1);
709 0 : strcat(str, tmp);
710 : }
711 :
712 : // Abuse CMD_DATAPTH.
713 0 : snprintf(tmp, sizeof(tmp), "%c%s\t\n", CMD_DATAPTH, path?path:"");
714 0 : strcat(str, tmp);
715 :
716 0 : return strlen(str);
717 : }
718 : #endif
719 :
720 0 : static int extract_ul(const char *value, struct cntr_ent *ent)
721 : {
722 0 : char *as=NULL;
723 0 : char *bs=NULL;
724 0 : char *cs=NULL;
725 0 : char *ds=NULL;
726 0 : char *es=NULL;
727 0 : char *copy=NULL;
728 0 : if(!value || !(copy=strdup_w(value, __func__))) return -1;
729 :
730 : // Do not want to use strtok, just in case I end up running more
731 : // than one at a time.
732 0 : as=copy;
733 0 : if((bs=strchr(as, '/')))
734 : {
735 0 : *bs='\0';
736 0 : ent->count=strtoull(as, NULL, 10);
737 0 : if((cs=strchr(++bs, '/')))
738 : {
739 0 : *cs='\0';
740 0 : ent->changed=strtoull(bs, NULL, 10);
741 0 : if((ds=strchr(++cs, '/')))
742 : {
743 0 : *ds='\0';
744 0 : ent->same=strtoull(cs, NULL, 10);
745 0 : if((es=strchr(++ds, '/')))
746 : {
747 0 : ent->deleted=strtoull(ds, NULL, 10);
748 0 : *es='\0';
749 0 : es++;
750 0 : ent->phase1=strtoull(es, NULL, 10);
751 : }
752 : }
753 : }
754 : }
755 : else
756 : {
757 : // Single field.
758 0 : ent->count=strtoull(as, NULL, 10);
759 : }
760 0 : free_w(©);
761 0 : return 0;
762 : }
763 :
764 : /*
765 : static char *get_backup_str(const char *s, int *deletable)
766 : {
767 : static char str[32]="";
768 : const char *cp=NULL;
769 : const char *dp=NULL;
770 : if(!s || !*s) return NULL;
771 : if(!(cp=strchr(s, ' '))
772 : || !(dp=strchr(cp+1, ' ')))
773 : snprintf(str, sizeof(str), "never");
774 : else
775 : {
776 : uint64_t backupnum=0;
777 : backupnum=strtoul(s, NULL, 10);
778 : snprintf(str, sizeof(str),
779 : "%07lu %s", backupnum, getdatestr(atol(dp+1)));
780 : if(*(cp+1)=='1') *deletable=1;
781 : }
782 : return str;
783 : }
784 : */
785 :
786 : /*
787 : static int add_to_backup_list(struct strlist **backups, const char *tok)
788 : {
789 : int deletable=0;
790 : const char *str=NULL;
791 : if(!(str=get_backup_str(tok, &deletable))) return 0;
792 : if(strlist_add(backups, (char *)str, deletable)) return -1;
793 : return 0;
794 : }
795 : */
796 :
797 0 : static int extract_cntrs(struct cntr *cntr, char **path)
798 : {
799 : char *tok;
800 0 : while((tok=strtok(NULL, "\t\n")))
801 : {
802 0 : switch(tok[0])
803 : {
804 : case CMD_DATAPTH:
805 0 : free_w(path);
806 0 : if(!(*path=strdup_w(tok+1, __func__)))
807 : return -1;
808 : break;
809 : default:
810 0 : if(cntr->ent[(uint8_t)tok[0]]
811 0 : && extract_ul(tok+1,
812 : cntr->ent[(uint8_t)tok[0]]))
813 : return -1;
814 : break;
815 : }
816 : }
817 : return 0;
818 : }
819 :
820 9 : int extract_client_pid_bno(char *buf, char **cname, pid_t *pid, int *bno)
821 : {
822 9 : char *cp=NULL;
823 9 : char *pp=NULL;
824 :
825 : // Extract the client name.
826 9 : if((cp=strchr(buf, '\t')))
827 3 : *cp='\0';
828 9 : if(!(*cname=strdup_w(buf, __func__)))
829 : return -1;
830 9 : if(cp)
831 3 : *cp='\t';
832 :
833 : // Extract the bno.
834 9 : if((pp=strrchr(*cname, '.')))
835 : {
836 4 : *pp='\0';
837 8 : *bno=(int)atoi(pp+1);
838 : // Extract the pid.
839 4 : if((pp=strrchr(*cname, '.')))
840 : {
841 0 : *pp='\0';
842 0 : *pid=(pid_t)atoi(pp+1);
843 : }
844 : }
845 : return 0;
846 : }
847 :
848 1 : int str_to_cntr(const char *str, struct cntr *cntr, char **path)
849 : {
850 1 : int ret=-1;
851 1 : char *tok=NULL;
852 1 : char *copy=NULL;
853 :
854 1 : if(!(copy=strdup_w(str, __func__)))
855 : return -1;
856 :
857 1 : if((tok=strtok(copy, "\t\n")))
858 : {
859 1 : int bno=0;
860 1 : pid_t pid=-1;
861 1 : char *tmp=NULL;
862 1 : char *cname=NULL;
863 : // First token is 'cntr'.
864 : // Second is client name/pid/bno.
865 1 : if(!(tmp=strtok(NULL, "\t\n")))
866 : {
867 0 : logp("Parsing problem in %s: null client\n",
868 : __func__);
869 0 : goto end;
870 : }
871 1 : if(extract_client_pid_bno(tmp, &cname, &pid, &bno))
872 : goto end;
873 1 : free_w(&cname);
874 1 : cntr->pid=pid;
875 1 : cntr->bno=bno;
876 : // Third is the cntr version.
877 1 : if(!(tmp=strtok(NULL, "\t\n")))
878 : {
879 0 : logp("Parsing problem in %s: null version\n",
880 : __func__);
881 0 : goto end;
882 : }
883 1 : if(atoi(tmp)!=CNTR_VERSION)
884 : {
885 : ret=0;
886 : goto end;
887 : }
888 : // Fourth is cntr_status.
889 0 : if(!(tmp=strtok(NULL, "\t\n")))
890 : {
891 0 : logp("Parsing problem in %s: null cntr_status\n",
892 : __func__);
893 0 : goto end;
894 : }
895 0 : cntr->cntr_status=(enum cntr_status)atoi(tmp);
896 :
897 0 : if(extract_cntrs(cntr, path)) goto end;
898 : }
899 :
900 : ret=0;
901 : end:
902 1 : free_w(©);
903 1 : return ret;
904 : }
905 :
906 : #ifndef HAVE_WIN32
907 7 : int cntr_send_bu(struct asfd *asfd, struct bu *bu, struct conf **confs,
908 : enum cntr_status cntr_status)
909 : {
910 7 : int ret=-1;
911 : uint16_t flags;
912 7 : struct cstat *clist=NULL;
913 7 : struct cstat *cstat=NULL;
914 :
915 7 : if(!get_int(confs[OPT_SEND_CLIENT_CNTR]))
916 : return 0;
917 :
918 0 : flags=bu->flags;
919 :
920 : // Want to setup a cstat and a bu so that we can piggy-back on the
921 : // status monitor cntr json code.
922 :
923 0 : if(!(cstat=cstat_alloc())
924 0 : || cstat_init(cstat,
925 0 : get_string(confs[OPT_CNAME]), NULL/*clientconfdir*/))
926 : goto end;
927 0 : cstat->cntrs=get_cntr(confs);
928 0 : cstat->protocol=get_protocol(confs);
929 0 : cstat->cntrs->cntr_status=cntr_status;
930 0 : cstat->run_status=RUN_STATUS_RUNNING;
931 :
932 : // Hacky provocation to get the json stuff to send counters in the
933 : // case where we are actually doing a restore.
934 0 : bu->flags|=BU_WORKING;
935 0 : cstat->bu=bu;
936 :
937 0 : clist=cstat;
938 :
939 0 : ret=json_send(asfd,
940 : clist,
941 : cstat,
942 : bu,
943 : NULL /* logfile */,
944 : NULL /* browse */,
945 : 0 /* use_cache */,
946 0 : version_to_long(get_string(confs[OPT_PEER_VERSION])));
947 : end:
948 0 : cstat->bu=NULL; // 'bu' was not ours to mess with.
949 0 : cstat->cntrs=NULL; // 'cntrs' was not ours to mess with.
950 0 : bu->flags=flags; // Set flags back to what the were before.
951 0 : cstat_free(&cstat);
952 0 : return ret;
953 : }
954 :
955 0 : int cntr_send_sdirs(struct asfd *asfd,
956 : struct sdirs *sdirs, struct conf **confs, enum cntr_status cntr_status)
957 : {
958 0 : int ret=-1;
959 0 : struct bu *bu=NULL;
960 0 : struct bu *bu_list=NULL;
961 :
962 : // FIX THIS:
963 : // It would be better just to set up the correct 'bu' entry instead
964 : // of loading everything and then looking through the list.
965 0 : if(bu_get_list_with_working(sdirs, &bu_list))
966 : goto end;
967 0 : for(bu=bu_list; bu; bu=bu->next)
968 0 : if((bu->flags & BU_WORKING)
969 : || (bu->flags & BU_FINISHING))
970 : break;
971 0 : if(!bu)
972 : {
973 0 : logp("could not find working or finishing backup in %s\n",
974 : __func__);
975 0 : goto end;
976 : }
977 0 : ret=cntr_send_bu(asfd, bu, confs, cntr_status);
978 : end:
979 0 : bu_list_free(&bu_list);
980 0 : return ret;
981 : }
982 : #endif
983 :
984 0 : static enum asl_ret cntr_recv_func(struct asfd *asfd,
985 : struct conf **confs,
986 : void *param)
987 : {
988 0 : struct sel *sel=(struct sel *)param;
989 0 : switch(json_input(asfd, sel))
990 : {
991 : case 0: return ASL_CONTINUE;
992 : case 1:
993 0 : case 2: return ASL_END_OK;
994 0 : default: return ASL_END_ERROR;
995 : }
996 : }
997 :
998 8 : int cntr_recv(struct asfd *asfd, struct conf **confs)
999 : {
1000 8 : int ret=-1;
1001 8 : struct sel *sel=NULL;
1002 : struct cntr_ent *e;
1003 8 : struct cntr *cntr=get_cntr(confs);
1004 :
1005 8 : if(!(sel=sel_alloc()))
1006 : goto end;
1007 8 : if(!get_int(confs[OPT_SEND_CLIENT_CNTR]))
1008 : goto ok;
1009 0 : if(json_input_init())
1010 : goto end;
1011 0 : if(asfd->simple_loop(asfd, confs, sel, __func__, cntr_recv_func)
1012 0 : || !sel->clist || !sel->clist->cntrs)
1013 : goto end;
1014 0 : for(e=sel->clist->cntrs->list; e; e=e->next)
1015 : {
1016 0 : set_count_val(cntr, e->cmd, e->count);
1017 0 : set_changed_val(cntr, e->cmd, e->changed);
1018 0 : set_same_val(cntr, e->cmd, e->same);
1019 0 : set_deleted_val(cntr, e->cmd, e->deleted);
1020 0 : set_phase1_val(cntr, e->cmd, e->phase1);
1021 : }
1022 : ok:
1023 : ret=0;
1024 : end:
1025 8 : json_input_free();
1026 8 : sel_free(&sel);
1027 8 : return ret;
1028 : }
1029 :
1030 0 : const char *cntr_status_to_str(struct cntr *cntr)
1031 : {
1032 0 : switch(cntr->cntr_status)
1033 : {
1034 : case CNTR_STATUS_SCANNING: return CNTR_STATUS_STR_SCANNING;
1035 0 : case CNTR_STATUS_BACKUP: return CNTR_STATUS_STR_BACKUP;
1036 0 : case CNTR_STATUS_MERGING: return CNTR_STATUS_STR_MERGING;
1037 0 : case CNTR_STATUS_SHUFFLING: return CNTR_STATUS_STR_SHUFFLING;
1038 0 : case CNTR_STATUS_LISTING: return CNTR_STATUS_STR_LISTING;
1039 0 : case CNTR_STATUS_RESTORING: return CNTR_STATUS_STR_RESTORING;
1040 0 : case CNTR_STATUS_VERIFYING: return CNTR_STATUS_STR_VERIFYING;
1041 0 : case CNTR_STATUS_DELETING: return CNTR_STATUS_STR_DELETING;
1042 0 : case CNTR_STATUS_DIFFING: return CNTR_STATUS_STR_DIFFING;
1043 0 : default: return "unknown";
1044 : }
1045 : }
1046 :
1047 0 : enum cntr_status cntr_str_to_status(const char *str)
1048 : {
1049 0 : if(!strcmp(str, CNTR_STATUS_STR_SCANNING))
1050 : return CNTR_STATUS_SCANNING;
1051 0 : else if(!strcmp(str, CNTR_STATUS_STR_BACKUP))
1052 : return CNTR_STATUS_BACKUP;
1053 0 : else if(!strcmp(str, CNTR_STATUS_STR_MERGING))
1054 : return CNTR_STATUS_MERGING;
1055 0 : else if(!strcmp(str, CNTR_STATUS_STR_SHUFFLING))
1056 : return CNTR_STATUS_SHUFFLING;
1057 0 : else if(!strcmp(str, CNTR_STATUS_STR_LISTING))
1058 : return CNTR_STATUS_LISTING;
1059 0 : else if(!strcmp(str, CNTR_STATUS_STR_RESTORING))
1060 : return CNTR_STATUS_RESTORING;
1061 0 : else if(!strcmp(str, CNTR_STATUS_STR_VERIFYING))
1062 : return CNTR_STATUS_VERIFYING;
1063 0 : else if(!strcmp(str, CNTR_STATUS_STR_DELETING))
1064 : return CNTR_STATUS_DELETING;
1065 0 : else if(!strcmp(str, CNTR_STATUS_STR_DIFFING))
1066 : return CNTR_STATUS_DIFFING;
1067 0 : return CNTR_STATUS_UNSET;
1068 : }
1069 :
1070 0 : const char *cntr_status_to_action_str(struct cntr *cntr)
1071 : {
1072 0 : switch(cntr->cntr_status)
1073 : {
1074 : case CNTR_STATUS_SCANNING:
1075 : case CNTR_STATUS_BACKUP:
1076 : case CNTR_STATUS_MERGING:
1077 : case CNTR_STATUS_SHUFFLING:
1078 : return "backup";
1079 : case CNTR_STATUS_LISTING:
1080 0 : return "list";
1081 : case CNTR_STATUS_RESTORING:
1082 0 : return "restore";
1083 : case CNTR_STATUS_VERIFYING:
1084 0 : return "verify";
1085 : case CNTR_STATUS_DELETING:
1086 0 : return "delete";
1087 : case CNTR_STATUS_DIFFING:
1088 0 : return "diff";
1089 : default:
1090 0 : return "unknown";
1091 : }
1092 : }
1093 :
1094 217920 : int check_fail_on_warning(int fail_on_warning, struct cntr_ent *warn_ent)
1095 : {
1096 217920 : if(!fail_on_warning || !warn_ent || !warn_ent->count)
1097 : return 0;
1098 0 : logp("fail_on_warning is set and warning count is %" PRIu64 "\n",
1099 : warn_ent->count);
1100 0 : return -1;
1101 : }
|