]> git.ipfire.org Git - thirdparty/sarg.git/blobdiff - totday.c
Optimize away a useless strcpy.
[thirdparty/sarg.git] / totday.c
index 38adc11f4713bd36267d2b033916cd3f1e0133e2..9d80b8ba74b7bd67f8da470273329594f045eb41 100644 (file)
--- a/totday.c
+++ b/totday.c
@@ -1,6 +1,6 @@
 /*
  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
- *                                                            1998, 2010
+ *                                                            1998, 2015
  *
  * SARG donations:
  *      please look at http://sarg.sourceforge.net/donations.php
 #include "include/conf.h"
 #include "include/defs.h"
 
-void day_totalize(const char *tmp, const struct userinfostruct *uinfo, int indexonly)
+//! The daily statistics for one user.
+struct DayStruct
 {
+       int ndaylist;
+       int maxindex;
+       int daylist[MAX_DATETIME_DAYS];
+       long long int bytes[MAX_DATETIME_DAYS*24];
+       long long int elap[MAX_DATETIME_DAYS*24];
+};
 
-   FILE *fp_in, *fp_ou;
-
-   char buf[200];
-   char date[20];
-   long long int hour;
-   long long int bytes;
-   long long int elap;
-   long long int tbytes[MAX_DATETIME_DAYS*24];
-   long long int telap[MAX_DATETIME_DAYS*24];
-   int day,month,year;
-   int daylist[MAX_DATETIME_DAYS];
-   int ndaylist;
-   int daynum;
-   int dayidx;
-   int i;
-   char wdirname[2048];
-   char arqout[2048];
-   char colsep;
-   struct getwordstruct gwarea;
-
-   if(indexonly) return;
-   if((ReportType & REPORT_TYPE_USERS_SITES) == 0) return;
-   if (datetimeby==0) return;
-
-   if (snprintf(wdirname,sizeof(wdirname),"%s/%s.htmp",tmp,uinfo->filename)>=sizeof(wdirname)) {
-      debuga(_("File name too long: %s/%s%s\n"),tmp,uinfo->filename,".htmp");
-      exit(EXIT_FAILURE);
-   }
-   if (snprintf(arqout,sizeof(arqout),"%s/%s.day",tmp,uinfo->filename)>=sizeof(arqout)) {
-      debuga(_("File name too long: %s/%s%s\n"),tmp,uinfo->filename,".day");
-      exit(EXIT_FAILURE);
-   }
-
-   if((fp_in=fopen(wdirname,"r"))==NULL) {
-      debuga(_("(totday) Cannot open log file %s\n"),wdirname);
-      exit(EXIT_FAILURE);
-   }
-
-   memset(tbytes,0,sizeof(tbytes));
-   memset(telap,0,sizeof(tbytes));
-   ndaylist=0;
-
-   while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
-      fixendofline(buf);
-      getword_start(&gwarea,buf);
-      if (getword(date,sizeof(date),&gwarea,'\t')<0 || getword_atoll(&hour,&gwarea,'\t')<0) {
-         debuga(_("There is a broken record or garbage in file %s\n"),wdirname);
-         exit(EXIT_FAILURE);
-      }
-      if (sscanf(date,"%d/%d/%d",&day,&month,&year)!=3) continue;
-      if (day<1 || day>31 || month<1 || month>12 || year>9999) continue;
-      if (hour<0 || hour>=24) continue;
-      daynum=(year*10000)+(month*100)+day;
-      for (dayidx=0 ; dayidx<ndaylist && daynum!=daylist[dayidx] ; dayidx++);
-      if (dayidx>=ndaylist) {
-         if (dayidx>=sizeof(daylist)/sizeof(*daylist)) {
-            debuga(_("Too many different dates in %s\n"),wdirname);
-            exit(EXIT_FAILURE);
-         }
-         daylist[ndaylist++]=daynum;
-      }
-      i=dayidx*24+hour;
-      if ((datetimeby & DATETIME_BYTE)!=0) {
-         colsep=((datetimeby & DATETIME_ELAP)!=0) ? '\t' : '\0';
-         if (getword_atoll(&bytes,&gwarea,colsep)<0) {
-            debuga(_("Invalid number of bytes in file %s\n"),wdirname);
-            exit(EXIT_FAILURE);
-         }
-         tbytes[i]+=bytes;
-      }
-      if ((datetimeby & DATETIME_ELAP)!=0) {
-         if (getword_atoll(&elap,&gwarea,'\0')<0) {
-            debuga(_("Invalid elapsed time in file %s\n"),wdirname);
-            exit(EXIT_FAILURE);
-         }
-         telap[i]+=elap;
-      }
-   }
-   fclose(fp_in);
-
-   if((fp_ou=fopen(arqout,"w"))==NULL) {
-     debuga(_("(totday) Cannot open log file %s\n"),arqout);
-     exit(EXIT_FAILURE);
-   }
-
-   for (i=0 ; i<sizeof(tbytes)/sizeof(*tbytes) ; i++) {
-      if (tbytes[i]==0 && telap[i]==0) continue;
-      dayidx=i/24;
-      if (dayidx>sizeof(daylist)/sizeof(*daylist)) continue;
-      hour=i%24;
-      daynum=daylist[dayidx];
-      day=daynum%100;
-      month=(daynum/100)%100;
-      year=daynum/10000;
-      fprintf(fp_ou,"%d/%d/%d\t%d",day,month,year,(int)hour);
-      if ((datetimeby & DATETIME_BYTE)!=0) fprintf(fp_ou,"\t%"PRIu64"",(uint64_t)tbytes[i]);
-      if ((datetimeby & DATETIME_ELAP)!=0) fprintf(fp_ou,"\t%"PRIu64"",(uint64_t)telap[i]);
-      fputs("\n",fp_ou);
-   }
-
-   if (fclose(fp_ou)==EOF) {
-      debuga(_("Failed to close file %s - %s\n"),arqout,strerror(errno));
-      exit(EXIT_FAILURE);
-   }
-
-   if (unlink(wdirname)==-1) {
-      debuga(_("Cannot delete temporary file %s - %s\n"),wdirname,strerror(errno));
-      exit(EXIT_FAILURE);
-   }
-   return;
+/*!
+Prepare the object to store the daily statistics of one user.
+
+\return The object to pass to other functions in this module.
+The object must be freed with a call to day_cleanup().
+*/
+DayObject day_prepare(void)
+{
+       DayObject ddata;
+
+       ddata=(DayObject)malloc(sizeof(*ddata));
+       if (!ddata)
+       {
+               debuga(__FILE__,__LINE__,_("Not enough memory to store the daily statistics\n"));
+               exit(EXIT_FAILURE);
+       }
+
+       return(ddata);
+}
+
+/*!
+Free the memory allocated by day_prepare().
+
+\param ddata The object returned by day_prepare().
+*/
+void day_cleanup(DayObject ddata)
+{
+       if (ddata) free(ddata);
+}
+
+/*!
+Prepare the object for a new user.
+
+\param ddata The object created by day_prepare().
+*/
+void day_newuser(DayObject ddata)
+{
+       if (ddata)
+       {
+               ddata->ndaylist=0;
+               ddata->maxindex=0;
+               memset(ddata->bytes,0,sizeof(ddata->bytes));
+               memset(ddata->elap,0,sizeof(ddata->elap));
+       }
+}
+
+/*!
+Store one data point in the statistics.
+
+\param ddata The object to store the statistics.
+\param date The date of the data point formated as day/month/year.
+\param time The time of the data point.
+\param elap The time spent processing the user's request on the proxy.
+\param bytes The number of bytes transfered by the user.
+*/
+void day_addpoint(DayObject ddata,const char *date, const char *time, long long int elap, long long int bytes)
+{
+       int hour;
+       int day,month,year;
+       int daynum;
+       int dayidx;
+       int i;
+
+       if (!ddata) return;
+       if (sscanf(date,"%d/%d/%d",&day,&month,&year)!=3) {
+               debuga(__FILE__,__LINE__,_("Invalid date \"%s\" for the hourly statistics\n"),date);
+               exit(EXIT_FAILURE);
+       }
+       if (day<1 || day>31 || month<1 || month>12 || year>9999) {
+               debuga(__FILE__,__LINE__,_("Invalid date component in \"%s\" for the hourly statistics\n"),date);
+               exit(EXIT_FAILURE);
+       }
+       hour=atoi(time);
+       if (hour<0 || hour>=24) {
+               debuga(__FILE__,__LINE__,_("Invalid hour %d for the hourly statistics\n"),hour);
+               exit(EXIT_FAILURE);
+       }
+       daynum=(year*10000)+(month*100)+day;
+       for (dayidx=ddata->ndaylist-1 ; dayidx>=0 && daynum!=ddata->daylist[dayidx] ; dayidx--);
+       if (dayidx<0) {
+               dayidx=ddata->ndaylist++;
+               if (dayidx>=sizeof(ddata->daylist)/sizeof(*ddata->daylist)) {
+                       debuga(__FILE__,__LINE__,_("Too many different dates for the hourly statistics\n"));
+                       exit(EXIT_FAILURE);
+               }
+               ddata->daylist[dayidx]=daynum;
+       }
+       i=dayidx*24+hour;
+       if (i>=ddata->maxindex) ddata->maxindex=i+1;
+       ddata->bytes[i]+=bytes;
+       ddata->elap[i]+=elap;
 }
+
+/*!
+Store the dayly statistics in the file.
+
+\param ddata The object containing the statistics.
+\param tmp The temporary directory to store the file into.
+\param uinfo The user's data.
+*/
+void day_totalize(DayObject ddata,const char *tmp, const struct userinfostruct *uinfo)
+{
+       FILE *fp_ou;
+       int hour;
+       int day,month,year;
+       int i;
+       int daynum;
+       int dayidx;
+       char arqout[2048];
+
+       if (datetimeby==0) return;
+       if (!ddata) return;
+
+       if (snprintf(arqout,sizeof(arqout),"%s/%s.day",tmp,uinfo->filename)>=sizeof(arqout)) {
+               debuga(__FILE__,__LINE__,_("Path too long: "));
+               debuga_more("%s/%s%s\n",tmp,uinfo->filename,".day");
+               exit(EXIT_FAILURE);
+       }
+
+       if((fp_ou=fopen(arqout,"w"))==NULL) {
+               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arqout,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       for (i=0 ; i<ddata->maxindex ; i++) {
+               if (ddata->bytes[i]==0 && ddata->elap[i]==0) continue;
+               dayidx=i/24;
+               if (dayidx>=sizeof(ddata->daylist)/sizeof(*ddata->daylist)) {
+                       debuga(__FILE__,__LINE__,_("Invalid day index found in the hourly statistics\n"));
+                       exit(EXIT_FAILURE);
+               }
+               hour=i%24;
+               daynum=ddata->daylist[dayidx];
+               day=daynum%100;
+               month=(daynum/100)%100;
+               year=daynum/10000;
+               fprintf(fp_ou,"%d/%d/%d\t%d",day,month,year,hour);
+               if ((datetimeby & DATETIME_BYTE)!=0) fprintf(fp_ou,"\t%"PRIu64"",(uint64_t)ddata->bytes[i]);
+               if ((datetimeby & DATETIME_ELAP)!=0) fprintf(fp_ou,"\t%"PRIu64"",(uint64_t)ddata->elap[i]);
+               fputs("\n",fp_ou);
+       }
+
+       if (fclose(fp_ou)==EOF) {
+               debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),arqout,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       return;
+}
+
+/*!
+Delete the temporary file generated by day_totalize().
+
+\param uinfo The user whose daily statistics are to be deleted.
+*/
+void day_deletefile(const struct userinfostruct *uinfo)
+{
+       char arqout[2048];
+
+       if (KeepTempLog) return;
+
+       if (snprintf(arqout,sizeof(arqout),"%s/%s.day",tmp,uinfo->filename)>=sizeof(arqout)) {
+               debuga(__FILE__,__LINE__,_("Path too long: "));
+               debuga_more("%s/%s%s\n",tmp,uinfo->filename,".day");
+               exit(EXIT_FAILURE);
+       }
+
+       if (unlink(arqout))
+               debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),arqout,strerror(errno));
+}
+