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 "log.h"
11 :
12 : #include "server/monitor/json_output.h"
13 :
14 : #include <limits.h>
15 :
16 : #define CNTR_VERSION 3
17 : #define CNTR_PATH_BUF_LEN 256
18 :
19 2125 : static void cntr_ent_free_content(struct cntr_ent *cntr_ent)
20 : {
21 4250 : if(!cntr_ent) return;
22 2125 : free_w(&cntr_ent->field);
23 2125 : free_w(&cntr_ent->label);
24 : }
25 :
26 2125 : static void cntr_ent_free(struct cntr_ent **cntr_ent)
27 : {
28 4250 : if(!cntr_ent || !*cntr_ent) return;
29 2125 : cntr_ent_free_content(*cntr_ent);
30 2125 : free_v((void **)cntr_ent);
31 : }
32 :
33 85 : struct cntr *cntr_alloc(void)
34 : {
35 85 : return (struct cntr *)calloc_w(1, sizeof(struct cntr), __func__);
36 : }
37 :
38 2125 : static int add_cntr_ent(struct cntr *cntr, int flags,
39 : enum cmd cmd, const char *field, const char *label)
40 : {
41 2125 : struct cntr_ent *cenew=NULL;
42 2125 : if(!(cenew=(struct cntr_ent *)
43 4250 : calloc_w(1, sizeof(struct cntr_ent), __func__))
44 2125 : || !(cenew->field=strdup_w(field, __func__))
45 6375 : || !(cenew->label=strdup_w(label, __func__)))
46 0 : goto error;
47 2125 : cenew->flags=flags;
48 2125 : cenew->cmd=cmd;
49 :
50 2125 : if(cntr->list) cenew->next=cntr->list;
51 2125 : cntr->list=cenew;
52 :
53 2125 : cntr->ent[(uint8_t)cmd]=cenew;
54 2125 : return 0;
55 : error:
56 0 : cntr_ent_free(&cenew);
57 0 : return -1;
58 : }
59 :
60 85 : static size_t calc_max_str_len(struct cntr *cntr, const char *cname)
61 : {
62 85 : size_t slen=0;
63 : char ullmax[64];
64 85 : struct cntr_ent *e=NULL;
65 :
66 : // See cntr_to_str().
67 : // First section - name/version/status
68 85 : slen+=strlen(cname);
69 85 : slen+=16; // More than enough space.
70 :
71 : // Second section.
72 : snprintf(ullmax, sizeof(ullmax),
73 85 : " %"PRIu64 "\n", (uint64_t)ULLONG_MAX);
74 2210 : for(e=cntr->list; e; e=e->next)
75 : {
76 2125 : if(e->flags & CNTR_SINGLE_FIELD)
77 : // %c%llu\t
78 765 : slen+=strlen(ullmax)+2;
79 : else
80 : // %c%llu/%llu/%llu/%llu/%llu\t
81 1360 : slen+=(strlen(ullmax)*5)+6;
82 : }
83 :
84 : // Fourth section - a path. Cannot know how long this might be. Guess.
85 85 : slen+=CNTR_PATH_BUF_LEN+3; // %c%s\t\n
86 :
87 85 : slen+=1; // Terminating character.
88 :
89 85 : return slen;
90 : }
91 :
92 85 : int cntr_init(struct cntr *cntr, const char *cname)
93 : {
94 85 : if(!cname)
95 : {
96 0 : logp("%s called with no client name\n", __func__);
97 0 : return -1;
98 : }
99 :
100 : // Add in reverse order, so that iterating over from the beginning
101 : // comes out in the right order.
102 85 : if(
103 : add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
104 85 : CMD_TIMESTAMP_END, "time_end", "End time")
105 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
106 85 : CMD_TIMESTAMP, "time_start", "Start time")
107 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
108 85 : CMD_BYTES_SENT, "bytes_sent", "Bytes sent")
109 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
110 85 : CMD_BYTES_RECV, "bytes_received", "Bytes received")
111 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
112 85 : CMD_BYTES, "bytes", "Bytes")
113 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
114 85 : CMD_BYTES_ESTIMATED, "bytes_estimated", "Bytes estimated")
115 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
116 85 : CMD_MESSAGE, "messages", "Messages")
117 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
118 85 : CMD_WARNING, "warnings", "Warnings")
119 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
120 85 : CMD_GRAND_TOTAL, "grand_total", "Grand total")
121 85 : || add_cntr_ent(cntr, 0,
122 85 : CMD_TOTAL, "total", "Total")
123 85 : || add_cntr_ent(cntr, CNTR_SINGLE_FIELD,
124 85 : CMD_ERROR, "errors", "Errors")
125 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
126 85 : CMD_DATA, "blocks", "Blocks")
127 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
128 85 : CMD_EFS_FILE, "efs_files", "EFS files")
129 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
130 85 : CMD_ENC_VSS_T, "vss_footers_encrypted", "VSS footers (enc)")
131 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
132 85 : CMD_VSS_T, "vss_footers", "VSS footers")
133 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
134 85 : CMD_ENC_VSS, "vss_headers_encrypted", "VSS headers (enc)")
135 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
136 85 : CMD_VSS, "vss_headers", "VSS headers")
137 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
138 85 : CMD_SPECIAL, "special_files", "Special files")
139 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
140 85 : CMD_SOFT_LINK, "hard_links", "Soft links")
141 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
142 85 : CMD_HARD_LINK, "soft_links", "Hard links")
143 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
144 85 : CMD_DIRECTORY, "directories", "Directories")
145 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
146 85 : CMD_ENC_METADATA, "meta_data_encrypted", "Meta data (enc)")
147 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
148 85 : CMD_METADATA, "meta_data", "Meta data")
149 85 : || add_cntr_ent(cntr, CNTR_TABULATE,
150 85 : CMD_ENC_FILE, "files_encrypted", "Files (encrypted)")
151 170 : || add_cntr_ent(cntr, CNTR_TABULATE,
152 85 : CMD_FILE, "files", "Files")
153 : )
154 0 : return -1;
155 :
156 85 : cntr->ent[(uint8_t)CMD_TIMESTAMP]->count=(uint64_t)time(NULL);
157 :
158 85 : cntr->str_max_len=calc_max_str_len(cntr, cname);
159 255 : if(!(cntr->str=(char *)calloc_w(1, cntr->str_max_len, __func__))
160 170 : || !(cntr->cname=strdup_w(cname, __func__)))
161 0 : return -1;
162 :
163 85 : return 0;
164 : }
165 :
166 85 : static void cntr_free_content(struct cntr *cntr)
167 : {
168 : struct cntr_ent *e;
169 85 : struct cntr_ent *l=NULL;
170 2210 : for(e=cntr->list; e; e=l)
171 : {
172 2125 : l=e->next;
173 2125 : cntr_ent_free(&e);
174 : }
175 85 : cntr->list=NULL;
176 85 : free_w(&cntr->str);
177 85 : free_w(&cntr->cname);
178 85 : }
179 :
180 186 : void cntr_free(struct cntr **cntr)
181 : {
182 372 : if(!cntr || !*cntr) return;
183 85 : cntr_free_content(*cntr);
184 85 : free_v((void **)cntr);
185 : }
186 :
187 2 : const char *bytes_to_human(uint64_t counter)
188 : {
189 : static char ret[32]="";
190 2 : float div=(float)counter;
191 2 : char units[3]="";
192 :
193 2 : if(div<1024) return "";
194 :
195 0 : if((div/=1024)<1024)
196 0 : snprintf(units, sizeof(units), "KB");
197 0 : else if((div/=1024)<1024)
198 0 : snprintf(units, sizeof(units), "MB");
199 0 : else if((div/=1024)<1024)
200 0 : snprintf(units, sizeof(units), "GB");
201 0 : else if((div/=1024)<1024)
202 0 : snprintf(units, sizeof(units), "TB");
203 0 : else if((div/=1024)<1024)
204 0 : snprintf(units, sizeof(units), "EB");
205 : else
206 : {
207 0 : div/=1024;
208 0 : snprintf(units, sizeof(units), "PB");
209 : }
210 0 : snprintf(ret, sizeof(ret), " (%.2f %s)", div, units);
211 0 : return ret;
212 : }
213 :
214 0 : static void border(void)
215 : {
216 0 : logc("--------------------------------------------------------------------------------\n");
217 0 : }
218 :
219 0 : static void table_border(enum action act)
220 : {
221 0 : if(act==ACTION_BACKUP
222 0 : || act==ACTION_BACKUP_TIMED)
223 : {
224 0 : logc("% 18s ------------------------------------------------------------\n", "");
225 : }
226 0 : if(act==ACTION_RESTORE
227 0 : || act==ACTION_VERIFY)
228 : {
229 0 : logc("% 18s ------------------------------\n", "");
230 : }
231 0 : }
232 :
233 0 : static void incr_count_val(struct cntr *cntr, char ch, uint64_t val)
234 : {
235 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->count+=val;
236 0 : }
237 :
238 0 : static void incr_same_val(struct cntr *cntr, char ch, uint64_t val)
239 : {
240 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->same+=val;
241 0 : }
242 :
243 0 : static void incr_changed_val(struct cntr *cntr, char ch, uint64_t val)
244 : {
245 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->changed+=val;
246 0 : }
247 :
248 0 : static void incr_deleted_val(struct cntr *cntr, char ch, uint64_t val)
249 : {
250 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->deleted+=val;
251 0 : }
252 :
253 0 : static void incr_phase1_val(struct cntr *cntr, char ch, uint64_t val)
254 : {
255 0 : if(cntr->ent[(uint8_t)ch]) cntr->ent[(uint8_t)ch]->phase1+=val;
256 0 : }
257 :
258 0 : static void incr_count(struct cntr *cntr, char ch)
259 : {
260 0 : return incr_count_val(cntr, ch, 1);
261 : }
262 :
263 0 : static void incr_same(struct cntr *cntr, char ch)
264 : {
265 0 : return incr_same_val(cntr, ch, 1);
266 : }
267 :
268 0 : static void incr_changed(struct cntr *cntr, char ch)
269 : {
270 0 : return incr_changed_val(cntr, ch, 1);
271 : }
272 :
273 0 : static void incr_deleted(struct cntr *cntr, char ch)
274 : {
275 0 : return incr_deleted_val(cntr, ch, 1);
276 : }
277 :
278 0 : static void incr_phase1(struct cntr *cntr, char ch)
279 : {
280 0 : return incr_phase1_val(cntr, ch, 1);
281 : }
282 :
283 0 : static void print_end(uint64_t val)
284 : {
285 0 : if(val) logc(" %"PRIu64 "\n", val);
286 0 : }
287 :
288 4 : void cntr_add(struct cntr *c, char ch, int print)
289 : {
290 : struct cntr_ent *grand_total_ent;
291 4 : if(!c) return;
292 0 : if(!(grand_total_ent=c->ent[CMD_GRAND_TOTAL])) return;
293 0 : if(print)
294 : {
295 0 : if(ch!=CMD_MESSAGE && ch!=CMD_WARNING)
296 0 : logc("%c", ch);
297 : }
298 0 : if(ch==CMD_FILE_CHANGED)
299 : {
300 0 : incr_changed(c, CMD_FILE);
301 0 : incr_changed(c, CMD_TOTAL);
302 0 : incr_changed(c, CMD_GRAND_TOTAL);
303 : }
304 : else
305 : {
306 0 : incr_count(c, ch);
307 0 : if(ch==CMD_WARNING || ch==CMD_MESSAGE) return;
308 0 : incr_count(c, CMD_TOTAL);
309 : }
310 :
311 0 : if(!((++grand_total_ent->count)%64) && print)
312 0 : print_end(grand_total_ent->count);
313 0 : fflush(stdout);
314 : }
315 :
316 0 : void cntr_add_phase1(struct cntr *c, char ch, int print)
317 : {
318 : static struct cntr_ent *total;
319 0 : incr_phase1(c, ch);
320 :
321 0 : total=c->ent[(uint8_t)CMD_GRAND_TOTAL];
322 0 : ++total->phase1;
323 0 : if(!print) return;
324 0 : if(total->phase1==1) logc("\n");
325 0 : logc("%c", ch);
326 0 : if(!((total->phase1)%64))
327 0 : print_end(total->phase1);
328 0 : fflush(stdout);
329 : }
330 :
331 0 : void cntr_add_val(struct cntr *c, char ch, uint64_t val, int print)
332 : {
333 0 : incr_count_val(c, ch, val);
334 0 : }
335 :
336 0 : void cntr_add_same(struct cntr *c, char ch)
337 : {
338 0 : incr_same(c, ch);
339 0 : incr_same(c, CMD_TOTAL);
340 0 : incr_same(c, CMD_GRAND_TOTAL);
341 0 : }
342 :
343 0 : void cntr_add_same_val(struct cntr *c, char ch, uint64_t val)
344 : {
345 0 : incr_same_val(c, ch, val);
346 0 : incr_same_val(c, CMD_TOTAL, val);
347 0 : incr_same_val(c, CMD_GRAND_TOTAL, val);
348 0 : }
349 :
350 0 : void cntr_add_changed(struct cntr *c, char ch)
351 : {
352 0 : incr_changed(c, ch);
353 0 : incr_changed(c, CMD_TOTAL);
354 0 : incr_changed(c, CMD_GRAND_TOTAL);
355 0 : }
356 :
357 0 : void cntr_add_changed_val(struct cntr *c, char ch, uint64_t val)
358 : {
359 0 : incr_changed_val(c, ch, val);
360 0 : incr_changed_val(c, CMD_TOTAL, val);
361 0 : incr_changed_val(c, CMD_GRAND_TOTAL, val);
362 0 : }
363 :
364 0 : void cntr_add_deleted(struct cntr *c, char ch)
365 : {
366 0 : incr_deleted(c, ch);
367 0 : incr_deleted(c, CMD_TOTAL);
368 0 : incr_deleted(c, CMD_GRAND_TOTAL);
369 0 : }
370 :
371 0 : void cntr_add_bytes(struct cntr *c, uint64_t bytes)
372 : {
373 0 : incr_count_val(c, CMD_BYTES, bytes);
374 0 : }
375 :
376 0 : void cntr_add_sentbytes(struct cntr *c, uint64_t bytes)
377 : {
378 0 : incr_count_val(c, CMD_BYTES_SENT, bytes);
379 0 : }
380 :
381 0 : void cntr_add_recvbytes(struct cntr *c, uint64_t bytes)
382 : {
383 0 : incr_count_val(c, CMD_BYTES_RECV, bytes);
384 0 : }
385 :
386 0 : static void quint_print(struct cntr_ent *ent, enum action act)
387 : {
388 : uint64_t a;
389 : uint64_t b;
390 : uint64_t c;
391 : uint64_t d;
392 : uint64_t e;
393 0 : if(!ent) return;
394 0 : a=ent->count;
395 0 : b=ent->changed;
396 0 : c=ent->same;
397 0 : d=ent->deleted;
398 0 : e=ent->phase1;
399 :
400 0 : if(!(ent->flags & CNTR_TABULATE)) return;
401 :
402 0 : if(!e && !a && !b && !c) return;
403 0 : logc("% 18s:", ent->label);
404 0 : if(act==ACTION_BACKUP
405 0 : || act==ACTION_BACKUP_TIMED)
406 : {
407 0 : logc("% 9llu ", a);
408 0 : logc("% 9llu ", b);
409 0 : logc("% 9llu ", c);
410 0 : logc("% 9llu ", d);
411 : }
412 0 : if(act==ACTION_RESTORE
413 0 : || act==ACTION_VERIFY)
414 : {
415 0 : logc("% 9s ", "");
416 : //logc("% 9s ", "");
417 : //logc("% 9s ", "");
418 : //logc("% 9s ", "");
419 : }
420 0 : if(act==ACTION_ESTIMATE)
421 : {
422 0 : logc("% 9s ", "");
423 0 : logc("% 9s ", "");
424 0 : logc("% 9llu\n", e);
425 : }
426 : else
427 : {
428 0 : logc("% 9llu |", a+b+c);
429 0 : logc("% 9llu\n", e);
430 : }
431 : }
432 :
433 0 : static uint64_t get_count(struct cntr_ent **ent, enum cmd cmd)
434 : {
435 0 : if(!ent[(uint8_t)cmd]) return 0;
436 0 : return ent[(uint8_t)cmd]->count;
437 : }
438 :
439 0 : static void bottom_part(struct cntr *c, enum action act)
440 : {
441 : uint64_t l;
442 0 : struct cntr_ent **e=c->ent;
443 0 : logc("\n");
444 0 : logc(" Messages: % 11llu\n", get_count(e, CMD_MESSAGE));
445 0 : logc(" Warnings: % 11llu\n", get_count(e, CMD_WARNING));
446 0 : logc("\n");
447 0 : logc(" Bytes estimated: % 11llu", get_count(e, CMD_BYTES_ESTIMATED));
448 0 : logc("%s\n", bytes_to_human(get_count(e, CMD_BYTES_ESTIMATED)));
449 :
450 0 : if(act==ACTION_ESTIMATE) return;
451 :
452 0 : if(act==ACTION_BACKUP
453 0 : || act==ACTION_BACKUP_TIMED)
454 : {
455 0 : l=get_count(e, CMD_BYTES);
456 0 : logc(" Bytes in backup: % 11llu", l);
457 0 : logc("%s\n", bytes_to_human(l));
458 : }
459 0 : if(act==ACTION_RESTORE)
460 : {
461 0 : l=get_count(e, CMD_BYTES);
462 0 : logc(" Bytes attempted: % 11llu", l);
463 0 : logc("%s\n", bytes_to_human(l));
464 : }
465 0 : if(act==ACTION_VERIFY)
466 : {
467 0 : l=get_count(e, CMD_BYTES);
468 0 : logc(" Bytes checked: % 11llu", l);
469 0 : logc("%s\n", bytes_to_human(l));
470 : }
471 :
472 0 : if(act==ACTION_BACKUP
473 0 : || act==ACTION_BACKUP_TIMED)
474 : {
475 0 : l=get_count(e, CMD_BYTES_RECV);
476 0 : logc(" Bytes received: % 11llu", l);
477 0 : logc("%s\n", bytes_to_human(l));
478 : }
479 0 : if(act==ACTION_BACKUP
480 0 : || act==ACTION_BACKUP_TIMED
481 0 : || act==ACTION_RESTORE)
482 : {
483 0 : l=get_count(e, CMD_BYTES_SENT);
484 0 : logc(" Bytes sent: % 11llu", l);
485 0 : logc("%s\n", bytes_to_human(l));
486 : }
487 : }
488 :
489 10 : void cntr_print(struct cntr *cntr, enum action act)
490 : {
491 : struct cntr_ent *e;
492 : time_t now;
493 : time_t start;
494 20 : if(!cntr) return;
495 0 : now=time(NULL);
496 0 : start=(time_t)cntr->ent[(uint8_t)CMD_TIMESTAMP]->count;
497 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=(uint64_t)now;
498 :
499 0 : border();
500 0 : logc("Start time: %s\n", getdatestr(start));
501 0 : logc(" End time: %s\n", getdatestr(now));
502 0 : logc("Time taken: %s\n", time_taken(now-start));
503 0 : if(act==ACTION_BACKUP
504 0 : || act==ACTION_BACKUP_TIMED)
505 : {
506 : logc("% 18s % 9s % 9s % 9s % 9s % 9s |% 9s\n",
507 0 : " ", "New", "Changed", "Unchanged", "Deleted", "Total", "Scanned");
508 : }
509 0 : if(act==ACTION_RESTORE
510 0 : || act==ACTION_VERIFY)
511 : {
512 : logc("% 18s % 9s % 9s |% 9s\n",
513 0 : " ", "", "Attempted", "Expected");
514 : }
515 0 : if(act==ACTION_ESTIMATE)
516 : {
517 : logc("% 18s % 9s % 9s %9s\n",
518 0 : " ", "", "", "Scanned");
519 : }
520 0 : table_border(act);
521 :
522 0 : for(e=cntr->list; e; e=e->next)
523 0 : quint_print(e, act);
524 :
525 0 : table_border(act);
526 0 : bottom_part(cntr, act);
527 :
528 0 : border();
529 : }
530 :
531 : #ifndef HAVE_WIN32
532 :
533 0 : int cntr_stats_to_file(struct cntr *cntr,
534 : const char *directory, enum action act, struct conf **confs)
535 : {
536 0 : int ret=-1;
537 0 : int fd=-1;
538 0 : char *path=NULL;
539 0 : const char *fname=NULL;
540 0 : struct async *as=NULL;
541 0 : struct asfd *wfd=NULL;
542 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count
543 0 : =(uint64_t)time(NULL);
544 :
545 0 : if(act==ACTION_BACKUP
546 0 : || act==ACTION_BACKUP_TIMED)
547 0 : fname="backup_stats";
548 0 : else if(act==ACTION_RESTORE)
549 0 : fname="restore_stats";
550 0 : else if(act==ACTION_VERIFY)
551 0 : fname="verify_stats";
552 : else
553 0 : return 0;
554 :
555 0 : if(!(path=prepend_s(directory, fname)))
556 0 : goto end;
557 0 : if((fd=open(path, O_WRONLY|O_CREAT, 0666))<0)
558 : {
559 : logp("Could not open %s for writing in %s: %s\n",
560 0 : path, __func__, strerror(errno));
561 0 : goto end;
562 : }
563 : // FIX THIS:
564 : // Pretty heavy duty to set up all this async stuff just so that the
565 : // json stuff can write to a simple file.
566 0 : if(!(as=async_alloc())
567 0 : || as->init(as, 0)
568 0 : || !(wfd=asfd_alloc())
569 0 : || wfd->init(wfd, "stats file",
570 0 : as, fd, NULL, ASFD_STREAM_LINEBUF, confs))
571 0 : goto end;
572 0 : as->asfd_add(as, wfd);
573 0 : fd=-1;
574 0 : if(json_cntr_to_file(wfd, cntr))
575 0 : goto end;
576 :
577 : // FIX THIS: make this use the json output stuff.
578 : // Need to add the following few fields to the cntrs somehow.
579 : /*
580 : fprintf(fp, "client_version:%s\n",
581 : conf->peer_version?conf->peer_version:"");
582 : fprintf(fp, "server_version:%s\n", VERSION);
583 : fprintf(fp, "client_is_windows:%d\n", conf->client_is_windows);
584 : for(e=cntr->list; e; e=e->next)
585 : quint_print_to_file(fp, e, act);
586 : */
587 :
588 0 : ret=0;
589 : end:
590 0 : close_fd(&fd);
591 0 : free_w(&path);
592 0 : async_free(&as);
593 0 : asfd_free(&wfd);
594 0 : return ret;
595 : }
596 :
597 : #endif
598 :
599 10 : void cntr_print_end(struct cntr *cntr)
600 : {
601 : struct cntr_ent *grand_total_ent;
602 20 : if(!cntr) return;
603 0 : grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
604 0 : if(grand_total_ent)
605 : {
606 0 : print_end(grand_total_ent->count);
607 0 : logc("\n");
608 : }
609 : }
610 :
611 0 : void cntr_print_end_phase1(struct cntr *cntr)
612 : {
613 : struct cntr_ent *grand_total_ent;
614 0 : if(!cntr) return;
615 0 : grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
616 0 : if(grand_total_ent)
617 : {
618 0 : print_end(grand_total_ent->phase1);
619 0 : logc("\n");
620 : }
621 : }
622 :
623 : #ifndef HAVE_WIN32
624 : // Return string length.
625 0 : size_t cntr_to_str(struct cntr *cntr, const char *path)
626 : {
627 : static char tmp[CNTR_PATH_BUF_LEN+3]="";
628 0 : struct cntr_ent *e=NULL;
629 0 : char *str=cntr->str;
630 :
631 0 : cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=time(NULL);
632 :
633 : snprintf(str, cntr->str_max_len-1, "%s\t%d\t%d\t",
634 0 : cntr->cname, CNTR_VERSION, cntr->cntr_status);
635 :
636 0 : for(e=cntr->list; e; e=e->next)
637 : {
638 0 : if(e->flags & CNTR_SINGLE_FIELD)
639 : snprintf(tmp, sizeof(tmp),
640 0 : "%c%"PRIu64"\t", e->cmd, e->count);
641 : else
642 : snprintf(tmp, sizeof(tmp),
643 : "%c%"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64"\t",
644 : e->cmd, e->count, e->same,
645 0 : e->changed, e->deleted, e->phase1);
646 0 : strcat(str, tmp);
647 : }
648 :
649 : // Abuse CMD_DATAPTH.
650 0 : snprintf(tmp, sizeof(tmp), "%c%s\t\n", CMD_DATAPTH, path?path:"");
651 0 : strcat(str, tmp);
652 :
653 0 : return strlen(str);
654 : }
655 : #endif
656 :
657 0 : static int extract_ul(const char *value, struct cntr_ent *ent)
658 : {
659 0 : char *as=NULL;
660 0 : char *bs=NULL;
661 0 : char *cs=NULL;
662 0 : char *ds=NULL;
663 0 : char *es=NULL;
664 0 : char *copy=NULL;
665 0 : if(!value || !(copy=strdup_w(value, __func__))) return -1;
666 :
667 : // Do not want to use strtok, just in case I end up running more
668 : // than one at a time.
669 0 : as=copy;
670 0 : if((bs=strchr(as, '/')))
671 : {
672 0 : *bs='\0';
673 0 : ent->count=strtoull(as, NULL, 10);
674 0 : if((cs=strchr(++bs, '/')))
675 : {
676 0 : *cs='\0';
677 0 : ent->changed=strtoull(bs, NULL, 10);
678 0 : if((ds=strchr(++cs, '/')))
679 : {
680 0 : *ds='\0';
681 0 : ent->same=strtoull(cs, NULL, 10);
682 0 : if((es=strchr(++ds, '/')))
683 : {
684 0 : ent->deleted=strtoull(ds, NULL, 10);
685 0 : *es='\0';
686 0 : es++;
687 0 : ent->phase1=strtoull(es, NULL, 10);
688 : }
689 : }
690 : }
691 : }
692 : else
693 : {
694 : // Single field.
695 0 : ent->count=strtoull(as, NULL, 10);
696 : }
697 0 : free_w(©);
698 0 : return 0;
699 : }
700 :
701 : /*
702 : static char *get_backup_str(const char *s, int *deletable)
703 : {
704 : static char str[32]="";
705 : const char *cp=NULL;
706 : const char *dp=NULL;
707 : if(!s || !*s) return NULL;
708 : if(!(cp=strchr(s, ' '))
709 : || !(dp=strchr(cp+1, ' ')))
710 : snprintf(str, sizeof(str), "never");
711 : else
712 : {
713 : uint64_t backupnum=0;
714 : backupnum=strtoul(s, NULL, 10);
715 : snprintf(str, sizeof(str),
716 : "%07lu %s", backupnum, getdatestr(atol(dp+1)));
717 : if(*(cp+1)=='1') *deletable=1;
718 : }
719 : return str;
720 : }
721 : */
722 :
723 : /*
724 : static int add_to_backup_list(struct strlist **backups, const char *tok)
725 : {
726 : int deletable=0;
727 : const char *str=NULL;
728 : if(!(str=get_backup_str(tok, &deletable))) return 0;
729 : if(strlist_add(backups, (char *)str, deletable)) return -1;
730 : return 0;
731 : }
732 : */
733 :
734 0 : static int extract_cntrs(struct cstat *cstat, char **path)
735 : {
736 : char *tok;
737 0 : struct cntr *cntr=cstat->cntr;
738 0 : while((tok=strtok(NULL, "\t\n")))
739 : {
740 0 : switch(tok[0])
741 : {
742 : case CMD_DATAPTH:
743 0 : free_w(path);
744 0 : if(!(*path=strdup_w(tok+1, __func__)))
745 0 : return -1;
746 0 : break;
747 : default:
748 0 : if(cntr->ent[(uint8_t)tok[0]]
749 0 : && extract_ul(tok+1,
750 0 : cntr->ent[(uint8_t)tok[0]]))
751 0 : return -1;
752 0 : break;
753 : }
754 : }
755 0 : return 0;
756 : }
757 :
758 0 : int str_to_cntr(const char *str, struct cstat *cstat, char **path)
759 : {
760 0 : int ret=-1;
761 0 : char *tok=NULL;
762 0 : char *copy=NULL;
763 :
764 0 : if(!(copy=strdup_w(str, __func__)))
765 0 : return -1;
766 :
767 0 : if((tok=strtok(copy, "\t\n")))
768 : {
769 0 : char *tmp=NULL;
770 : // First token is the client name. Do not need that here.
771 : // Second is the cntr version.
772 0 : if(!(tmp=strtok(NULL, "\t\n")))
773 : {
774 : logp("Parsing problem in %s: null version\n",
775 0 : __func__);
776 0 : goto end;
777 : }
778 0 : if(atoi(tmp)!=CNTR_VERSION)
779 : {
780 0 : ret=0;
781 0 : goto end;
782 : }
783 : // Third is cstat_status.
784 0 : if(!(tmp=strtok(NULL, "\t\n")))
785 : {
786 : logp("Parsing problem in %s: null cstat_status\n",
787 0 : __func__);
788 0 : goto end;
789 : }
790 0 : cstat->cntr->cntr_status=(enum cntr_status)atoi(tmp);
791 :
792 0 : if(extract_cntrs(cstat, path)) goto end;
793 : }
794 :
795 0 : ret=0;
796 : end:
797 0 : free_w(©);
798 0 : return ret;
799 : }
800 :
801 : #ifndef HAVE_WIN32
802 0 : int cntr_send(struct cntr *cntr)
803 : {
804 : /*
805 : size_t l;
806 : char buf[4096]="";
807 : l=cntr_to_str(get_cntr(confs[OPT_CNTR]), STATUS_RUNNING, " ");
808 : if(async_write_strn(CMD_GEN, buf, l))
809 : {
810 : logp("Error when sending counters to client.\n");
811 : return -1;
812 : }
813 : */
814 0 : return 0;
815 : }
816 : #endif
817 :
818 0 : static enum asl_ret cntr_recv_func(struct asfd *asfd,
819 : struct conf **confs, void *param)
820 : {
821 : /*
822 : if(str_to_cntr(asfd->rbuf->buf, NULL, NULL, NULL, NULL,
823 : conf->p1cntr, get_cntr(confs[OPT_CNTR]), NULL))
824 : return ASL_END_ERROR;
825 : */
826 0 : return ASL_END_OK;
827 : }
828 :
829 0 : int cntr_recv(struct asfd *asfd, struct conf **confs)
830 : {
831 0 : return asfd->simple_loop(asfd, confs, NULL, __func__, cntr_recv_func);
832 : }
833 :
834 0 : const char *cntr_status_to_str(struct cntr *cntr)
835 : {
836 0 : switch(cntr->cntr_status)
837 : {
838 0 : case CNTR_STATUS_SCANNING: return CNTR_STATUS_STR_SCANNING;
839 0 : case CNTR_STATUS_BACKUP: return CNTR_STATUS_STR_BACKUP;
840 0 : case CNTR_STATUS_MERGING: return CNTR_STATUS_STR_MERGING;
841 0 : case CNTR_STATUS_SHUFFLING: return CNTR_STATUS_STR_SHUFFLING;
842 0 : case CNTR_STATUS_LISTING: return CNTR_STATUS_STR_LISTING;
843 0 : case CNTR_STATUS_RESTORING: return CNTR_STATUS_STR_RESTORING;
844 0 : case CNTR_STATUS_VERIFYING: return CNTR_STATUS_STR_VERIFYING;
845 0 : case CNTR_STATUS_DELETING: return CNTR_STATUS_STR_DELETING;
846 0 : case CNTR_STATUS_DIFFING: return CNTR_STATUS_STR_DIFFING;
847 0 : default: return "unknown";
848 : }
849 : }
850 :
851 0 : enum cntr_status cntr_str_to_status(const char *str)
852 : {
853 0 : if(!strcmp(str, CNTR_STATUS_STR_SCANNING))
854 0 : return CNTR_STATUS_SCANNING;
855 0 : else if(!strcmp(str, CNTR_STATUS_STR_BACKUP))
856 0 : return CNTR_STATUS_BACKUP;
857 0 : else if(!strcmp(str, CNTR_STATUS_STR_MERGING))
858 0 : return CNTR_STATUS_MERGING;
859 0 : else if(!strcmp(str, CNTR_STATUS_STR_SHUFFLING))
860 0 : return CNTR_STATUS_SHUFFLING;
861 0 : else if(!strcmp(str, CNTR_STATUS_STR_LISTING))
862 0 : return CNTR_STATUS_LISTING;
863 0 : else if(!strcmp(str, CNTR_STATUS_STR_RESTORING))
864 0 : return CNTR_STATUS_RESTORING;
865 0 : else if(!strcmp(str, CNTR_STATUS_STR_VERIFYING))
866 0 : return CNTR_STATUS_VERIFYING;
867 0 : else if(!strcmp(str, CNTR_STATUS_STR_DELETING))
868 0 : return CNTR_STATUS_DELETING;
869 0 : else if(!strcmp(str, CNTR_STATUS_STR_DIFFING))
870 0 : return CNTR_STATUS_DIFFING;
871 0 : return CNTR_STATUS_UNSET;
872 : }
|