LCOV - code coverage report
Current view: top level - src - cntr.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 195 516 37.8 %
Date: 2021-06-01 21:59:08 Functions: 24 40 60.0 %

          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         392 : void cntr_free(struct cntr **cntr)
     187             : {
     188         392 :         if(!cntr || !*cntr) return;
     189          26 :         cntr_free_content(*cntr);
     190          26 :         free_v((void **)cntr);
     191             : }
     192             : 
     193         155 : void cntrs_free(struct cntr **cntrs)
     194             : {
     195             :         struct cntr *c;
     196             :         struct cntr *chead;
     197         309 :         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          54 :         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          27 :         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          29 : void cntr_set_bytes(struct cntr *c, struct asfd *asfd)
     448             : {
     449          29 :         if(!asfd)
     450             :                 return;
     451          54 :         cntr_set_sentbytes(c, asfd->sent);
     452          27 :         cntr_set_recvbytes(c, asfd->rcvd);
     453             : }
     454             : 
     455           0 : static void quint_print(struct cntr_ent *ent, enum action act)
     456             : {
     457             :         uint64_t a;
     458             :         uint64_t b;
     459             :         uint64_t c;
     460             :         uint64_t d;
     461             :         uint64_t e;
     462           0 :         if(!ent) return;
     463           0 :         a=ent->count;
     464           0 :         b=ent->changed;
     465           0 :         c=ent->same;
     466           0 :         d=ent->deleted;
     467           0 :         e=ent->phase1;
     468             : 
     469           0 :         if(!(ent->flags & CNTR_TABULATE)) return;
     470             : 
     471           0 :         if(!e && !a && !b && !c) return;
     472           0 :         logc("%18s:", ent->label);
     473           0 :         if(act==ACTION_BACKUP
     474           0 :           || act==ACTION_BACKUP_TIMED)
     475             :         {
     476           0 :                 logc("%9" PRIu64 " ", a);
     477           0 :                 logc("%9" PRIu64 " ", b);
     478           0 :                 logc("%9" PRIu64 " ", c);
     479           0 :                 logc("%9" PRIu64 " ", d);
     480             :         }
     481           0 :         if(act==ACTION_RESTORE
     482           0 :           || act==ACTION_VERIFY)
     483             :         {
     484           0 :                 logc("%9s ", "");
     485             :                 //logc("%9s ", "");
     486             :                 //logc("%9s ", "");
     487             :                 //logc("%9s ", "");
     488             :         }
     489           0 :         if(act==ACTION_ESTIMATE)
     490             :         {
     491           0 :                 logc("%9s ", "");
     492           0 :                 logc("%9s ", "");
     493           0 :                 logc("%9" PRIu64 "\n", e);
     494             :         }
     495             :         else
     496             :         {
     497           0 :                 logc("%9" PRIu64 " |", a+b+c);
     498           0 :                 logc("%9" PRIu64 "\n", e);
     499             :         }
     500             : }
     501             : 
     502             : static uint64_t get_count(struct cntr_ent **ent, enum cmd cmd)
     503             : {
     504           0 :         if(!ent[(uint8_t)cmd]) return 0;
     505           0 :         return ent[(uint8_t)cmd]->count;
     506             : }
     507             : 
     508           0 : static void bottom_part(struct cntr *c, enum action act)
     509             : {
     510             :         uint64_t l;
     511           0 :         struct cntr_ent **e=c->ent;
     512           0 :         logc("\n");
     513           0 :         logc("             Messages:   %11" PRIu64 "\n", get_count(e, CMD_MESSAGE));
     514           0 :         logc("             Warnings:   %11" PRIu64 "\n", get_count(e, CMD_WARNING));
     515           0 :         logc("\n");
     516           0 :         logc("      Bytes estimated:   %11" PRIu64, get_count(e, CMD_BYTES_ESTIMATED));
     517           0 :         logc("%s\n", bytes_to_human(get_count(e, CMD_BYTES_ESTIMATED)));
     518             : 
     519           0 :         if(act==ACTION_ESTIMATE) return;
     520             : 
     521           0 :         if(act==ACTION_BACKUP
     522           0 :           || act==ACTION_BACKUP_TIMED)
     523             :         {
     524           0 :                 l=get_count(e, CMD_BYTES);
     525           0 :                 logc("      Bytes in backup:   %11" PRIu64, l);
     526           0 :                 logc("%s\n", bytes_to_human(l));
     527             :         }
     528           0 :         if(act==ACTION_RESTORE)
     529             :         {
     530           0 :                 l=get_count(e, CMD_BYTES);
     531           0 :                 logc("      Bytes attempted:   %11" PRIu64, l);
     532           0 :                 logc("%s\n", bytes_to_human(l));
     533             :         }
     534           0 :         if(act==ACTION_VERIFY)
     535             :         {
     536           0 :                 l=get_count(e, CMD_BYTES);
     537           0 :                 logc("        Bytes checked:   %11" PRIu64, l);
     538           0 :                 logc("%s\n", bytes_to_human(l));
     539             :         }
     540             : 
     541           0 :         l=get_count(e, CMD_BYTES_RECV);
     542           0 :         logc("       Bytes received:   %11" PRIu64, l);
     543           0 :         logc("%s\n", bytes_to_human(l));
     544             : 
     545           0 :         l=get_count(e, CMD_BYTES_SENT);
     546           0 :         logc("           Bytes sent:   %11" PRIu64, l);
     547           0 :         logc("%s\n", bytes_to_human(l));
     548             : }
     549             : 
     550          29 : void cntr_print(struct cntr *cntr, enum action act)
     551             : {
     552             :         struct cntr_ent *e;
     553             :         time_t now;
     554             :         time_t start;
     555             :         char time_start_str[32];
     556             :         char time_end_str[32];
     557          58 :         if(!cntr) return;
     558             : 
     559           0 :         now=time(NULL);
     560           0 :         start=(time_t)cntr->ent[(uint8_t)CMD_TIMESTAMP]->count;
     561           0 :         cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=(uint64_t)now;
     562             : 
     563             :         border();
     564           0 :         encode_time(start, time_start_str);
     565           0 :         encode_time(now, time_end_str);
     566           0 :         logc("Start time: %s\n", time_start_str);
     567           0 :         logc("  End time: %s\n", time_end_str);
     568           0 :         logc("Time taken: %s\n", time_taken(now-start));
     569           0 :         if(act==ACTION_BACKUP
     570           0 :           || act==ACTION_BACKUP_TIMED)
     571             :         {
     572           0 :           logc("%18s %9s %9s %9s %9s %9s |%9s\n",
     573             :             " ", "New", "Changed", "Duplicate", "Deleted", "Total", "Scanned");
     574             :         }
     575           0 :         if(act==ACTION_RESTORE
     576           0 :           || act==ACTION_VERIFY)
     577             :         {
     578           0 :           logc("%18s %9s %9s |%9s\n",
     579             :             " ", "", "Attempted", "Expected");
     580             :         }
     581           0 :         if(act==ACTION_ESTIMATE)
     582             :         {
     583           0 :           logc("%18s %9s %9s %9s\n",
     584             :             " ", "", "", "Scanned");
     585             :         }
     586           0 :         table_border(act);
     587             : 
     588           0 :         for(e=cntr->list; e; e=e->next)
     589           0 :                 quint_print(e, act);
     590             : 
     591           0 :         table_border(act);
     592           0 :         bottom_part(cntr, act);
     593             : 
     594             :         border();
     595             : }
     596             : 
     597             : #ifndef HAVE_WIN32
     598             : 
     599           7 : int cntr_stats_to_file(struct cntr *cntr,
     600             :         const char *directory, enum action act)
     601             : {
     602           7 :         int ret=-1;
     603           7 :         int fd=-1;
     604           7 :         char *path=NULL;
     605           7 :         char *pathtmp=NULL;
     606           7 :         const char *fname=NULL;
     607           7 :         struct async *as=NULL;
     608           7 :         struct asfd *wfd=NULL;
     609           7 :         if(!cntr)
     610             :                 return 0;
     611           0 :         cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count
     612           0 :                 =(uint64_t)time(NULL);
     613             : 
     614           0 :         if(act==ACTION_BACKUP
     615           0 :           ||  act==ACTION_BACKUP_TIMED)
     616             :                 fname="backup_stats";
     617           0 :         else if(act==ACTION_RESTORE)
     618             :                 fname="restore_stats";
     619           0 :         else if(act==ACTION_VERIFY)
     620             :                 fname="verify_stats";
     621             :         else
     622             :                 return 0;
     623             : 
     624           0 :         if(!(path=prepend_s(directory, fname))
     625           0 :           || !(pathtmp=prepend(path, ".tmp")))
     626             :                 goto end;
     627           0 :         if((fd=open(
     628             :                 pathtmp,
     629             : #ifdef O_NOFOLLOW
     630             :                 O_NOFOLLOW|
     631             : #endif
     632             :                 O_WRONLY|O_CREAT,
     633             :                 0666))<0)
     634             :         {
     635           0 :                 logp("Could not open %s for writing in %s: %s\n",
     636           0 :                         pathtmp, __func__, strerror(errno));
     637           0 :                 goto end;
     638             :         }
     639             : 
     640           0 :         if(!(as=async_alloc())
     641           0 :           || as->init(as, 0)
     642           0 :           || !(wfd=setup_asfd_linebuf_write(as, "stats file", &fd)))
     643             :         {
     644           0 :                 close_fd(&fd);
     645           0 :                 goto end;
     646             :         }
     647             : 
     648           0 :         if(json_cntr(wfd, cntr))
     649             :                 goto end;
     650             : 
     651           0 :         ret=0;
     652             : end:
     653           0 :         async_free(&as);
     654           0 :         asfd_free(&wfd);
     655           0 :         if(!ret && do_rename(pathtmp, path))
     656           0 :                 ret=-1;
     657             : 
     658           0 :         free_w(&path);
     659           0 :         free_w(&pathtmp);
     660           0 :         return ret;
     661             : }
     662             : 
     663             : #endif
     664             : 
     665          22 : void cntr_print_end(struct cntr *cntr)
     666             : {
     667             :         struct cntr_ent *grand_total_ent;
     668          22 :         if(!cntr) return;
     669           0 :         grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
     670           0 :         if(grand_total_ent)
     671             :         {
     672           0 :                 print_end(grand_total_ent->count);
     673           0 :                 logc("\n");
     674             :         }
     675             : }
     676             : 
     677           0 : void cntr_print_end_phase1(struct cntr *cntr)
     678             : {
     679             :         struct cntr_ent *grand_total_ent;
     680           0 :         if(!cntr) return;
     681           0 :         grand_total_ent=cntr->ent[CMD_GRAND_TOTAL];
     682           0 :         if(grand_total_ent)
     683             :         {
     684           0 :                 print_end(grand_total_ent->phase1);
     685           0 :                 logc("\n");
     686             :         }
     687             : }
     688             : 
     689             : #ifndef HAVE_WIN32
     690             : // Return string length.
     691           0 : size_t cntr_to_str(struct cntr *cntr, const char *path)
     692             : {
     693             :         static char tmp[CNTR_PATH_BUF_LEN+3]="";
     694           0 :         struct cntr_ent *e=NULL;
     695           0 :         char *str=cntr->str;
     696             : 
     697           0 :         cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count=time(NULL);
     698             : 
     699           0 :         snprintf(str, cntr->str_max_len-1, "cntr\t%s.%d.%d\t%d\t%d\t",
     700             :                 cntr->cname, cntr->pid, cntr->bno,
     701           0 :                 CNTR_VERSION, cntr->cntr_status);
     702             : 
     703           0 :         for(e=cntr->list; e; e=e->next)
     704             :         {
     705           0 :                 if(e->flags & CNTR_SINGLE_FIELD)
     706           0 :                         snprintf(tmp, sizeof(tmp),
     707           0 :                                 "%c%" PRIu64"\t", e->cmd, e->count);
     708             :                 else
     709           0 :                         snprintf(tmp, sizeof(tmp),
     710             :                         "%c%" PRIu64
     711             :                         "/%" PRIu64
     712             :                         "/%" PRIu64
     713             :                         "/%" PRIu64
     714             :                         "/%" PRIu64
     715             :                         "\t",
     716           0 :                                 e->cmd, e->count, e->changed,
     717             :                                 e->same, e->deleted, e->phase1);
     718           0 :                 strcat(str, tmp);
     719             :         }
     720             : 
     721             :         // Abuse CMD_DATAPTH.
     722           0 :         snprintf(tmp, sizeof(tmp), "%c%s\t\n", CMD_DATAPTH, path?path:"");
     723           0 :         strcat(str, tmp);
     724             : 
     725           0 :         return strlen(str);
     726             : }
     727             : #endif
     728             : 
     729           0 : static int extract_ul(const char *value, struct cntr_ent *ent)
     730             : {
     731           0 :         char *as=NULL;
     732           0 :         char *bs=NULL;
     733           0 :         char *cs=NULL;
     734           0 :         char *ds=NULL;
     735           0 :         char *es=NULL;
     736           0 :         char *copy=NULL;
     737           0 :         if(!value || !(copy=strdup_w(value, __func__))) return -1;
     738             : 
     739             :         // Do not want to use strtok, just in case I end up running more
     740             :         // than one at a time.
     741           0 :         as=copy;
     742           0 :         if((bs=strchr(as, '/')))
     743             :         {
     744           0 :                 *bs='\0';
     745           0 :                 ent->count=strtoull(as, NULL, 10);
     746           0 :                 if((cs=strchr(++bs, '/')))
     747             :                 {
     748           0 :                         *cs='\0';
     749           0 :                         ent->changed=strtoull(bs, NULL, 10);
     750           0 :                         if((ds=strchr(++cs, '/')))
     751             :                         {
     752           0 :                                 *ds='\0';
     753           0 :                                 ent->same=strtoull(cs, NULL, 10);
     754           0 :                                 if((es=strchr(++ds, '/')))
     755             :                                 {
     756           0 :                                         ent->deleted=strtoull(ds, NULL, 10);
     757           0 :                                         *es='\0';
     758           0 :                                         es++;
     759           0 :                                         ent->phase1=strtoull(es, NULL, 10);
     760             :                                 }
     761             :                         }
     762             :                 }
     763             :         }
     764             :         else
     765             :         {
     766             :                 // Single field.
     767           0 :                 ent->count=strtoull(as, NULL, 10);
     768             :         }
     769           0 :         free_w(&copy);
     770           0 :         return 0;
     771             : }
     772             : 
     773             : /*
     774             : static char *get_backup_str(const char *s, int *deletable)
     775             : {
     776             :         static char str[32]="";
     777             :         const char *cp=NULL;
     778             :         const char *dp=NULL;
     779             :         if(!s || !*s) return NULL;
     780             :         if(!(cp=strchr(s, ' '))
     781             :           || !(dp=strchr(cp+1, ' ')))
     782             :                 snprintf(str, sizeof(str), "never");
     783             :         else
     784             :         {
     785             :                 uint64_t backupnum=0;
     786             :                 backupnum=strtoul(s, NULL, 10);
     787             :                 snprintf(str, sizeof(str),
     788             :                         "%07lu %s", backupnum, getdatestr(atol(dp+1)));
     789             :                 if(*(cp+1)=='1') *deletable=1;
     790             :         }
     791             :         return str;
     792             : }
     793             : */
     794             : 
     795             : /*
     796             : static int add_to_backup_list(struct strlist **backups, const char *tok)
     797             : {
     798             :         int deletable=0;
     799             :         const char *str=NULL;
     800             :         if(!(str=get_backup_str(tok, &deletable))) return 0;
     801             :         if(strlist_add(backups, (char *)str, deletable)) return -1;
     802             :         return 0;
     803             : }
     804             : */
     805             : 
     806           0 : static int extract_cntrs(struct cntr *cntr, char **path)
     807             : {
     808             :         char *tok;
     809           0 :         while((tok=strtok(NULL, "\t\n")))
     810             :         {
     811           0 :                 switch(tok[0])
     812             :                 {
     813             :                         case CMD_DATAPTH:
     814           0 :                                 free_w(path);
     815           0 :                                 if(!(*path=strdup_w(tok+1, __func__)))
     816             :                                         return -1;
     817             :                                 break;
     818             :                         default:
     819           0 :                                 if(cntr->ent[(uint8_t)tok[0]]
     820           0 :                                   && extract_ul(tok+1,
     821             :                                         cntr->ent[(uint8_t)tok[0]]))
     822             :                                                 return -1;
     823             :                                 break;
     824             :                 }
     825             :         }
     826             :         return 0;
     827             : }
     828             : 
     829           9 : int extract_client_pid_bno(char *buf, char **cname, pid_t *pid, int *bno)
     830             : {
     831           9 :         char *cp=NULL;
     832           9 :         char *pp=NULL;
     833             : 
     834             :         // Extract the client name.
     835           9 :         if((cp=strchr(buf, '\t')))
     836           3 :                 *cp='\0';
     837           9 :         if(!(*cname=strdup_w(buf, __func__)))
     838             :                 return -1;
     839           9 :         if(cp)
     840           3 :                 *cp='\t';
     841             : 
     842             :         // Extract the bno.
     843           9 :         if((pp=strrchr(*cname, '.')))
     844             :         {
     845           4 :                 *pp='\0';
     846           8 :                 *bno=(int)atoi(pp+1);
     847             :                 // Extract the pid.
     848           4 :                 if((pp=strrchr(*cname, '.')))
     849             :                 {
     850           0 :                         *pp='\0';
     851           0 :                         *pid=(pid_t)atoi(pp+1);
     852             :                 }
     853             :         }
     854             :         return 0;
     855             : }
     856             : 
     857           1 : int str_to_cntr(const char *str, struct cntr *cntr, char **path)
     858             : {
     859           1 :         int ret=-1;
     860           1 :         char *tok=NULL;
     861           1 :         char *copy=NULL;
     862             : 
     863           1 :         if(!(copy=strdup_w(str, __func__)))
     864             :                 return -1;
     865             : 
     866           1 :         if((tok=strtok(copy, "\t\n")))
     867             :         {
     868           1 :                 int bno=0;
     869           1 :                 pid_t pid=-1;
     870           1 :                 char *tmp=NULL;
     871           1 :                 char *cname=NULL;
     872             :                 // First token is 'cntr'.
     873             :                 // Second is client name/pid/bno.
     874           1 :                 if(!(tmp=strtok(NULL, "\t\n")))
     875             :                 {
     876           0 :                         logp("Parsing problem in %s: null client\n",
     877             :                                 __func__);
     878           0 :                         goto end;
     879             :                 }
     880           1 :                 if(extract_client_pid_bno(tmp, &cname, &pid, &bno))
     881             :                         goto end;
     882           1 :                 free_w(&cname);
     883           1 :                 cntr->pid=pid;
     884           1 :                 cntr->bno=bno;
     885             :                 // Third is the cntr version.
     886           1 :                 if(!(tmp=strtok(NULL, "\t\n")))
     887             :                 {
     888           0 :                         logp("Parsing problem in %s: null version\n",
     889             :                                 __func__);
     890           0 :                         goto end;
     891             :                 }
     892           1 :                 if(atoi(tmp)!=CNTR_VERSION)
     893             :                 {
     894             :                         ret=0;
     895             :                         goto end;
     896             :                 }
     897             :                 // Fourth is cntr_status.
     898           0 :                 if(!(tmp=strtok(NULL, "\t\n")))
     899             :                 {
     900           0 :                         logp("Parsing problem in %s: null cntr_status\n",
     901             :                                 __func__);
     902           0 :                         goto end;
     903             :                 }
     904           0 :                 cntr->cntr_status=(enum cntr_status)atoi(tmp);
     905             : 
     906           0 :                 if(extract_cntrs(cntr, path)) goto end;
     907             :         }
     908             : 
     909             :         ret=0;
     910             : end:
     911           1 :         free_w(&copy);
     912           1 :         return ret;
     913             : }
     914             : 
     915             : #ifndef HAVE_WIN32
     916           7 : int cntr_send_bu(struct asfd *asfd, struct bu *bu, struct conf **confs,
     917             :         enum cntr_status cntr_status)
     918             : {
     919           7 :         int ret=-1;
     920             :         uint16_t flags;
     921           7 :         struct cstat *clist=NULL;
     922           7 :         struct cstat *cstat=NULL;
     923             : 
     924           7 :         if(!get_int(confs[OPT_SEND_CLIENT_CNTR]))
     925             :                 return 0;
     926             : 
     927           0 :         flags=bu->flags;
     928             : 
     929             :         // Want to setup a cstat and a bu so that we can piggy-back on the
     930             :         // status monitor cntr json code.
     931             : 
     932           0 :         if(!(cstat=cstat_alloc())
     933           0 :           || cstat_init(cstat,
     934           0 :                 get_string(confs[OPT_CNAME]), NULL/*clientconfdir*/))
     935             :                         goto end;
     936           0 :         cstat->cntrs=get_cntr(confs);
     937           0 :         cstat->protocol=get_protocol(confs);
     938           0 :         cstat->cntrs->cntr_status=cntr_status;
     939           0 :         cstat->run_status=RUN_STATUS_RUNNING;
     940             : 
     941             :         // Hacky provocation to get the json stuff to send counters in the
     942             :         // case where we are actually doing a restore.
     943           0 :         bu->flags|=BU_WORKING;
     944           0 :         cstat->bu=bu;
     945             : 
     946           0 :         clist=cstat;
     947             : 
     948           0 :         ret=json_send(asfd,
     949             :                 clist,
     950             :                 cstat,
     951             :                 bu,
     952             :                 NULL /* logfile */,
     953             :                 NULL /* browse */,
     954             :                 0 /* use_cache */,
     955           0 :                 version_to_long(get_string(confs[OPT_PEER_VERSION])));
     956             : end:
     957           0 :         cstat->bu=NULL; // 'bu' was not ours to mess with.
     958           0 :         cstat->cntrs=NULL; // 'cntrs' was not ours to mess with.
     959           0 :         bu->flags=flags; // Set flags back to what the were before.
     960           0 :         cstat_free(&cstat);
     961           0 :         return ret;
     962             : }
     963             : 
     964           0 : int cntr_send_sdirs(struct asfd *asfd,
     965             :         struct sdirs *sdirs, struct conf **confs, enum cntr_status cntr_status)
     966             : {
     967           0 :         int ret=-1;
     968           0 :         struct bu *bu=NULL;
     969           0 :         struct bu *bu_list=NULL;
     970             : 
     971             :         // FIX THIS:
     972             :         // It would be better just to set up the correct 'bu' entry instead
     973             :         // of loading everything and then looking through the list.
     974           0 :         if(bu_get_list_with_working(sdirs, &bu_list))
     975             :                 goto end;
     976           0 :         for(bu=bu_list; bu; bu=bu->next)
     977           0 :                 if((bu->flags & BU_WORKING)
     978             :                   || (bu->flags & BU_FINISHING))
     979             :                         break;
     980           0 :         if(!bu)
     981             :         {
     982           0 :                 logp("could not find working or finishing backup in %s\n",
     983             :                         __func__);
     984           0 :                 goto end;
     985             :         }
     986           0 :         ret=cntr_send_bu(asfd, bu, confs, cntr_status);
     987             : end:
     988           0 :         bu_list_free(&bu_list);
     989           0 :         return ret;
     990             : }
     991             : #endif
     992             : 
     993           0 : static enum asl_ret cntr_recv_func(struct asfd *asfd,
     994             :         struct conf **confs,
     995             :         void *param)
     996             : {
     997           0 :         struct sel *sel=(struct sel *)param;
     998           0 :         switch(json_input(asfd, sel))
     999             :         {
    1000             :                 case 0: return ASL_CONTINUE;
    1001             :                 case 1:
    1002           0 :                 case 2: return ASL_END_OK;
    1003           0 :                 default: return ASL_END_ERROR;
    1004             :         }
    1005             : }
    1006             : 
    1007           8 : int cntr_recv(struct asfd *asfd, struct conf **confs)
    1008             : {
    1009           8 :         int ret=-1;
    1010           8 :         struct sel *sel=NULL;
    1011             :         struct cntr_ent *e;
    1012           8 :         struct cntr *cntr=get_cntr(confs);
    1013             : 
    1014           8 :         if(!(sel=sel_alloc()))
    1015             :                 goto end;
    1016           8 :         if(!get_int(confs[OPT_SEND_CLIENT_CNTR]))
    1017             :                 goto ok;
    1018           0 :         if(json_input_init())
    1019             :                 goto end;
    1020           0 :         if(asfd->simple_loop(asfd, confs, sel, __func__, cntr_recv_func)
    1021           0 :           || !sel->clist || !sel->clist->cntrs)
    1022             :                 goto end;
    1023           0 :         for(e=sel->clist->cntrs->list; e; e=e->next)
    1024             :         {
    1025           0 :                 set_count_val(cntr, e->cmd, e->count);
    1026           0 :                 set_changed_val(cntr, e->cmd, e->changed);
    1027           0 :                 set_same_val(cntr, e->cmd, e->same);
    1028           0 :                 set_deleted_val(cntr, e->cmd, e->deleted);
    1029           0 :                 set_phase1_val(cntr, e->cmd, e->phase1);
    1030             :         }
    1031             : ok:
    1032             :         ret=0;
    1033             : end:
    1034           8 :         json_input_free();
    1035           8 :         sel_free(&sel);
    1036           8 :         return ret;
    1037             : }
    1038             : 
    1039           0 : const char *cntr_status_to_str(struct cntr *cntr)
    1040             : {
    1041           0 :         switch(cntr->cntr_status)
    1042             :         {
    1043             :                 case CNTR_STATUS_SCANNING: return CNTR_STATUS_STR_SCANNING;
    1044           0 :                 case CNTR_STATUS_BACKUP: return CNTR_STATUS_STR_BACKUP;
    1045           0 :                 case CNTR_STATUS_MERGING: return CNTR_STATUS_STR_MERGING;
    1046           0 :                 case CNTR_STATUS_SHUFFLING: return CNTR_STATUS_STR_SHUFFLING;
    1047           0 :                 case CNTR_STATUS_LISTING: return CNTR_STATUS_STR_LISTING;
    1048           0 :                 case CNTR_STATUS_RESTORING: return CNTR_STATUS_STR_RESTORING;
    1049           0 :                 case CNTR_STATUS_VERIFYING: return CNTR_STATUS_STR_VERIFYING;
    1050           0 :                 case CNTR_STATUS_DELETING: return CNTR_STATUS_STR_DELETING;
    1051           0 :                 case CNTR_STATUS_DIFFING: return CNTR_STATUS_STR_DIFFING;
    1052           0 :                 default: return "unknown";
    1053             :         }
    1054             : }
    1055             : 
    1056           0 : enum cntr_status cntr_str_to_status(const char *str)
    1057             : {
    1058           0 :         if(!strcmp(str, CNTR_STATUS_STR_SCANNING))
    1059             :                 return CNTR_STATUS_SCANNING;
    1060           0 :         else if(!strcmp(str, CNTR_STATUS_STR_BACKUP))
    1061             :                 return CNTR_STATUS_BACKUP;
    1062           0 :         else if(!strcmp(str, CNTR_STATUS_STR_MERGING))
    1063             :                 return CNTR_STATUS_MERGING;
    1064           0 :         else if(!strcmp(str, CNTR_STATUS_STR_SHUFFLING))
    1065             :                 return CNTR_STATUS_SHUFFLING;
    1066           0 :         else if(!strcmp(str, CNTR_STATUS_STR_LISTING))
    1067             :                 return CNTR_STATUS_LISTING;
    1068           0 :         else if(!strcmp(str, CNTR_STATUS_STR_RESTORING))
    1069             :                 return CNTR_STATUS_RESTORING;
    1070           0 :         else if(!strcmp(str, CNTR_STATUS_STR_VERIFYING))
    1071             :                 return CNTR_STATUS_VERIFYING;
    1072           0 :         else if(!strcmp(str, CNTR_STATUS_STR_DELETING))
    1073             :                 return CNTR_STATUS_DELETING;
    1074           0 :         else if(!strcmp(str, CNTR_STATUS_STR_DIFFING))
    1075             :                 return CNTR_STATUS_DIFFING;
    1076           0 :         return CNTR_STATUS_UNSET;
    1077             : }
    1078             : 
    1079           0 : const char *cntr_status_to_action_str(struct cntr *cntr)
    1080             : {
    1081           0 :         switch(cntr->cntr_status)
    1082             :         {
    1083             :                 case CNTR_STATUS_SCANNING:
    1084             :                 case CNTR_STATUS_BACKUP:
    1085             :                 case CNTR_STATUS_MERGING:
    1086             :                 case CNTR_STATUS_SHUFFLING:
    1087             :                         return "backup";
    1088             :                 case CNTR_STATUS_LISTING:
    1089           0 :                         return "list";
    1090             :                 case CNTR_STATUS_RESTORING:
    1091           0 :                         return "restore";
    1092             :                 case CNTR_STATUS_VERIFYING:
    1093           0 :                         return "verify";
    1094             :                 case CNTR_STATUS_DELETING:
    1095           0 :                         return "delete";
    1096             :                 case CNTR_STATUS_DIFFING:
    1097           0 :                         return "diff";
    1098             :                 default:
    1099           0 :                         return "unknown";
    1100             :         }
    1101             : }
    1102             : 
    1103      217920 : int check_fail_on_warning(int fail_on_warning, struct cntr_ent *warn_ent)
    1104             : {
    1105      217920 :         if(!fail_on_warning || !warn_ent || !warn_ent->count)
    1106             :                 return 0;
    1107           0 :         logp("fail_on_warning is set and warning count is %" PRIu64 "\n",
    1108             :                 warn_ent->count);
    1109           0 :         return -1;
    1110             : }

Generated by: LCOV version 1.13