]> granicus.if.org Git - vnstat/commitdiff
year and 5 minute data added to json and xml, following image outputs implemented...
authorTeemu Toivola <git@humdi.net>
Mon, 30 Jan 2017 20:22:39 +0000 (22:22 +0200)
committerTeemu Toivola <git@humdi.net>
Mon, 30 Jan 2017 20:22:39 +0000 (22:22 +0200)
README.md
src/dbjson.c
src/dbshow.c
src/dbsql.c
src/dbxml.c
src/image.c
src/image.h
src/vnstat.c
src/vnstati.c

index 7b6e5ac2ecb24af381e8bbdbf39dbdb217ca54b0..0348cf2b7baca45e28510736bdd22606431cd468 100644 (file)
--- a/README.md
+++ b/README.md
@@ -2,34 +2,38 @@
 
 This is the development branch for vnStat 2.0 that uses a sqlite database
 for storing data instead of a C structure dump in a file. A better database
-format is needed for enabling longer duration statistics with user
-configurable durations. Yearly and 5 minute resolution statistics are now included.
+format was needed for enabling longer duration statistics with user configurable
+durations. Yearly and 5 minute resolution statistics are now included.
 
 # Status
 
 ##### Overall status
 
-  * alpha version with working daemon implementation
+  * alpha version
+    * has been tested so far only in 24/7 running servers
+  * vnstatd (daemon) has all features implemented
     * some sanity checks may be missing or disabled
   * vnstat (console output) has most features implemented
-  * vnstati (image output) lacks rewrite of most features
+  * vnstati (image output) lacks rewrite of some features
   * getting closer to replace vnStat 1.x
 
 ##### Done
 
-  * database creation and handling
-  * support for multiple interfaces
-  * dynamic data buffering in daemon, SaveInterval is honored
-  * 5 minute, hourly, daily, monthly, yearly and total traffic recorded to database
-  * legacy database files are read only during first startup for data import
-    * write support is no longer included in code
-  * full data import from vnStat 1.x database format including reconstructed yearly data
-  * legacy database is not kept in memory for each interface during daemon runtime
-  * new configuration options for data retention durations
-    * features can be disabled
-  * old data cleanup
-    * executed during startup and then once every hour
+  * vnstatd (daemon)
+    * database creation and handling
+    * support for multiple interfaces
+    * dynamic data buffering, SaveInterval is honored
+    * 5 minute, hourly, daily, monthly, yearly and total traffic recorded to database
+    * legacy database files are read only during first startup for data import
+      * write support is no longer included in code
+    * full data import from vnStat 1.x database format including reconstructed yearly data
+    * legacy database is not kept in memory for each interface during daemon runtime
+    * new configuration options for data retention durations
+      * features can be disabled
+    * old data cleanup
+      * executed during startup and then once every hour
   * most vnstat (console output) features
+  * many vnstati (image output) features
 
 ##### Removed features
 
@@ -45,9 +49,10 @@ configurable durations. Yearly and 5 minute resolution statistics are now includ
 
   * `grep TODO src/* tests/*`
   * continue daemon refactoring
+  * testing in more diverse environments
   * add missing sanity checks to daemon
   * image outputs
-    * all but daily
+    * summary and hourly + combinations
   * use of 5 minute resolution statistics
   * feature configurability
   * freeze database structure
index 42faaf5e860741b33e93e49eb26185543649eb43..5b04cd44ad67903083075340773f5a12714053d8 100644 (file)
@@ -31,7 +31,6 @@ void showjson(const char *interface, const int dbcount, const char mode)
        printf("\"traffic\":");
        printf("{\"total\":{\"rx\":%"PRIu64",\"tx\":%"PRIu64"},", info.rxtotal, info.txtotal);
 
-       /* TODO: add years and 5 minutes */
        switch (mode) {
                case 'd':
                        jsondump(&info, "day", 1);
@@ -45,15 +44,25 @@ void showjson(const char *interface, const int dbcount, const char mode)
                case 'h':
                        jsondump(&info, "hour", 2);
                        break;
+               case 'y':
+                       jsondump(&info, "year", 4);
+                       break;
+               case '5':
+                       jsondump(&info, "fiveminute", 2);
+                       break;
                case 'a':
                default:
+                       jsondump(&info, "fiveminute", 2);
+                       printf(",");
+                       jsondump(&info, "hour", 2);
+                       printf(",");
                        jsondump(&info, "day", 1);
                        printf(",");
                        jsondump(&info, "month", 3);
                        printf(",");
-                       jsondump(&info, "top", 1);
+                       jsondump(&info, "year", 4);
                        printf(",");
-                       jsondump(&info, "hour", 2);
+                       jsondump(&info, "top", 1);
                        break;
        }
 
@@ -92,8 +101,9 @@ void jsondate(const time_t *date, const int type)
 {
        struct tm *d;
        char *type1 = "\"date\":{\"year\":%d,\"month\":%d,\"day\":%d}";
-       char *type2 = "\"date\":{\"year\":%d,\"month\":%d,\"day\":%d},\"time\":{\"hour\":%d,\"minutes\":%d}";
+       char *type2 = "\"date\":{\"year\":%d,\"month\":%d,\"day\":%d},\"time\":{\"hour\":%d,\"minute\":%d}";
        char *type3 = "\"date\":{\"year\":%d,\"month\":%d}";
+       char *type4 = "\"date\":{\"year\":%d}";
 
        d = localtime(date);
 
@@ -103,6 +113,8 @@ void jsondate(const time_t *date, const int type)
                printf(type2, 1900+d->tm_year, 1+d->tm_mon, d->tm_mday, d->tm_hour, d->tm_min);
        } else if (type == 3) {
                printf(type3, 1900+d->tm_year, 1+d->tm_mon);
+       } else if (type == 4) {
+               printf(type4, 1900+d->tm_year);
        }
 }
 
index f48054964dbacc6d6fd4c24a51214a23f9344e1d..743cebfc588de61d911a9e79fd5a7a55cec292bf 100644 (file)
@@ -345,13 +345,12 @@ void showlist(const interfaceinfo *interface, const char *listname)
                if (listtype == 4) {
                        printf("------");
                }
+               printf("-------------------------+-------------+------------");
                if (cfg.ostyle != 0) {
-                       printf("-------------------------+-------------+---------------------------------");
+                       printf("---------------------");
                        if (listtype != 4) {
                                printf("------");
                        }
-               } else {
-                       printf("-------------------------+-------------+------------");
                }
                printf("\n");
        }
@@ -429,13 +428,12 @@ void showlist(const interfaceinfo *interface, const char *listname)
                if (listtype == 4) {
                        printf("------");
                }
+               printf("-------------------------+-------------+------------");
                if (cfg.ostyle != 0) {
-                       printf("-------------------------+-------------+---------------------------------");
+                       printf("---------------------");
                        if (listtype != 4) {
                                printf("------");
                        }
-               } else {
-                       printf("-------------------------+-------------+------------");
                }
                printf("\n");
        }
index 11f3c5d5b47ca4deed53f910269c98d54175438e..8e7f4a21d0468c1fa4d52e366d591c7a6c7cd4da 100644 (file)
@@ -878,7 +878,11 @@ int db_getdata(dbdatalist **dbdata, dbdatalistinfo *listinfo, const char *iface,
        }
        sqlite3_finalize(sqlstmt);
 
-       /* TODO: should list be cleaned if it doesn't contain everything? */
+       /* clean list on failure */
+       if (!ret) {
+               dbdatalistfree(dbdata);
+               listinfo->count = 0;
+       }
 
        return ret;
 }
index 04bf49c8a7ab3450cf6aa9478c2db0407603cd04..573f988ca0b5ed06e0e4e2708f66c3beac1fe115 100644 (file)
@@ -29,7 +29,6 @@ void showxml(const char *interface, const char mode)
        printf("  <traffic>\n");
        printf("   <total><rx>%"PRIu64"</rx><tx>%"PRIu64"</tx></total>\n", info.rxtotal, info.txtotal);
 
-       /* TODO: add years and 5 minutes */
        switch (mode) {
                case 'd':
                        xmldump(&info, "day", 1);
@@ -43,12 +42,20 @@ void showxml(const char *interface, const char mode)
                case 'h':
                        xmldump(&info, "hour", 2);
                        break;
+               case 'y':
+                       xmldump(&info, "year", 4);
+                       break;
+               case '5':
+                       xmldump(&info, "fiveminute", 2);
+                       break;
                case 'a':
                default:
+                       xmldump(&info, "fiveminute", 2);
+                       xmldump(&info, "hour", 2);
                        xmldump(&info, "day", 1);
                        xmldump(&info, "month", 3);
+                       xmldump(&info, "year", 2);
                        xmldump(&info, "top", 1);
-                       xmldump(&info, "hour", 2);
                        break;
        }
 
@@ -84,6 +91,7 @@ void xmldate(const time_t *date, const int type)
        char *type1 = "<date><year>%d</year><month>%02d</month><day>%02d</day></date>";
        char *type2 = "<date><year>%d</year><month>%02d</month><day>%02d</day></date><time><hour>%02d</hour><minute>%02d</minute></time>";
        char *type3 = "<date><year>%d</year><month>%02d</month></date>";
+       char *type4 = "<date><year>%d</year></date>";
 
        d = localtime(date);
 
@@ -93,6 +101,8 @@ void xmldate(const time_t *date, const int type)
                printf(type2, 1900+d->tm_year, 1+d->tm_mon, d->tm_mday, d->tm_hour, d->tm_min);
        } else if (type == 3) {
                printf(type3, 1900+d->tm_year, 1+d->tm_mon);
+       } else if (type == 4) {
+               printf(type4, 1900+d->tm_year);
        }
 }
 
index 389fb3b72a7731c26894ef63ec6af16215666df6..0a9e14e9013ebd9c4513ba573a3e67fe3cc4ac9d 100644 (file)
@@ -17,15 +17,18 @@ void drawimage(IMAGECONTENT *ic)
 {
        switch (cfg.qmode) {
                case 1:
-                       drawdaily(ic);
+                       drawlist(ic, "day");
                        break;
-/*             case 2:
-                       drawmonthly(ic);
+               case 2:
+                       drawlist(ic, "month");
                        break;
                case 3:
-                       drawtop(ic);
+                       drawlist(ic, "top");
                        break;
-               case 5:
+               case 4:
+                       drawlist(ic, "year");
+                       break;
+/*             case 5:
                        if (cfg.slayout) {
                                drawsummary(ic, 0, 0);
                        } else {
@@ -265,17 +268,48 @@ void drawdonut(IMAGECONTENT *ic, const int x, const int y, const float rxp, cons
        gdImageFilledArc(ic->im, x, y, DINRAD-2, DINRAD-2, 0, 360, ic->cbackground, 0);
 }
 
-void drawdaily(IMAGECONTENT *ic)
+void drawlist(IMAGECONTENT *ic, const char *listname)
 {
-       int textx, texty;
-       int width, height, headermod;
-       uint64_t e_rx, e_tx;
-       char buffer[512], datebuff[16];
+       int limit, listtype, textx, texty, offsetx = 0, offsety = 0;
+       int width, height, headermod, i = 1;
+       uint64_t e_rx, e_tx, e_secs, div, mult;
+       char buffer[512], datebuff[16], stampformat[64];
+       char titlename[8], colname[8];
        struct tm *d;
        dbdatalist *datalist = NULL, *datalist_i = NULL;
        dbdatalistinfo datainfo;
 
-       if (!db_getdata(&datalist, &datainfo, ic->interface.name, "day", 30)) {
+       if (strcmp(listname, "day") == 0) {
+               listtype = 1;
+               strncpy_nt(colname, listname, 8);
+               snprintf(titlename, 8, "daily");
+               strncpy_nt(stampformat, cfg.dformat, 64);
+               limit = 30;
+       } else if (strcmp(listname, "month") == 0) {
+               listtype = 2;
+               strncpy_nt(colname, listname, 8);
+               snprintf(titlename, 8, "monthly");
+               strncpy_nt(stampformat, cfg.mformat, 64);
+               limit = 12;
+       } else if (strcmp(listname, "year") == 0) {
+               listtype = 3;
+               strncpy_nt(colname, listname, 8);
+               snprintf(titlename, 8, "yearly");
+               strncpy_nt(stampformat, "%Y", 64);
+               limit = -1;
+       } else if (strcmp(listname, "top") == 0) {
+               listtype = 4;
+               snprintf(colname, 8, "day");
+               snprintf(titlename, 8, "top 10");
+               strncpy_nt(stampformat, cfg.tformat, 64);
+               limit = 10;
+               offsetx = 30;
+               offsety = -16;
+       } else {
+               return;
+       }
+
+       if (!db_getdata(&datalist, &datainfo, ic->interface.name, listname, limit)) {
                printf("Error: Failed to fetch %s data.\n", "day");
                return;
        }
@@ -283,7 +317,12 @@ void drawdaily(IMAGECONTENT *ic)
        datalist_i = datalist;
 
        width = 500;
-       height = 98 + (12 * datainfo.count);
+       if (listtype == 4) {
+               height = 86;
+       } else {
+               height = 98;
+       }
+       height += 12 * datainfo.count;
 
        if (!ic->showheader) {
                headermod = 26;
@@ -297,46 +336,64 @@ void drawdaily(IMAGECONTENT *ic)
        colorinit(ic);
 
        if (strcmp(ic->interface.name, ic->interface.alias) == 0 || strlen(ic->interface.alias) == 0) {
-               snprintf(buffer, 512, "%s / daily", ic->interface.name);
+               snprintf(buffer, 512, "%s / %s", ic->interface.name, titlename);
        } else {
-               snprintf(buffer, 512, "%s (%s) / daily", ic->interface.alias, ic->interface.name);
+               snprintf(buffer, 512, "%s (%s) / %s", ic->interface.alias, ic->interface.name, titlename);
        }
 
        layoutinit(ic, buffer, width, height);
 
        if (datainfo.count) {
-               if (cfg.ostyle>2) {
-                       drawlegend(ic, 432, 40-headermod);
-               } else {
-                       drawlegend(ic, 385, 40-headermod);
+               if (listtype == 4) { // top
+                       if (cfg.ostyle<=2) {
+                               drawlegend(ic, 398, 40-headermod);
+                       }
+               } else { // everything else
+                       if (cfg.ostyle>2) {
+                               drawlegend(ic, 432, 40-headermod);
+                       } else {
+                               drawlegend(ic, 385, 40-headermod);
+                       }
                }
        }
 
        textx = 10;
        texty = 40-headermod;
 
+       if (listtype == 4) { // top
+               snprintf(buffer, 512, "   #      day        rx           tx          total");
+       } else { // everything else
+               snprintf(buffer, 512, " %8s       rx           tx          total", colname);
+       }
        if (cfg.ostyle>2) {
-               gdImageString(ic->im, gdFontGetSmall(), textx, texty, (unsigned char*)"     day        rx           tx          total       avg. rate", ic->ctext);
-               gdImageLine(ic->im, textx+2, texty+16, textx+392, texty+16, ic->cline);
-               gdImageLine(ic->im, textx+144, texty+2, textx+144, texty+40+(12*datainfo.count), ic->cline);
-               gdImageLine(ic->im, textx+222, texty+2, textx+222, texty+40+(12*datainfo.count), ic->cline);
-               gdImageLine(ic->im, textx+300, texty+2, textx+300, texty+40+(12*datainfo.count), ic->cline);
+               strcat(buffer, "       avg. rate");
+               gdImageString(ic->im, gdFontGetSmall(), textx, texty, (unsigned char*)buffer, ic->ctext);
+               gdImageLine(ic->im, textx+2, texty+16, textx+392+offsetx, texty+16, ic->cline);
+               gdImageLine(ic->im, textx+300+offsetx, texty+2, textx+300+offsetx, texty+40+offsety+(12*datainfo.count), ic->cline);
        } else {
-               gdImageString(ic->im, gdFontGetSmall(), textx, texty, (unsigned char*)"     day        rx           tx          total", ic->ctext);
-               gdImageLine(ic->im, textx+2, texty+16, textx+296, texty+16, ic->cline);
-               gdImageLine(ic->im, textx+144, texty+2, textx+144, texty+40+(12*datainfo.count), ic->cline);
-               gdImageLine(ic->im, textx+222, texty+2, textx+222, texty+40+(12*datainfo.count), ic->cline);
+               gdImageString(ic->im, gdFontGetSmall(), textx, texty, (unsigned char*)buffer, ic->ctext);
+               gdImageLine(ic->im, textx+2, texty+16, textx+296+offsetx, texty+16, ic->cline);
        }
+       gdImageLine(ic->im, textx+144+offsetx, texty+2, textx+144+offsetx, texty+40+offsety+(12*datainfo.count), ic->cline);
+       gdImageLine(ic->im, textx+222+offsetx, texty+2, textx+222+offsetx, texty+40+offsety+(12*datainfo.count), ic->cline);
 
        texty += 20;
 
        while (datalist_i != NULL) {
 
                d = localtime(&datalist_i->timestamp);
-               if (strftime(datebuff, 16, cfg.dformat, d)<=8) {
-                       snprintf(buffer, 32, "  %*s   ", getpadding(8, datebuff), datebuff);
+               if (listtype == 4) {
+                       if (strftime(datebuff, 16, stampformat, d)<=8) {
+                               snprintf(buffer, 32, "  %2d   %*s   ", i, getpadding(8, datebuff), datebuff);
+                       } else {
+                               snprintf(buffer, 32, "  %2d  %-*s ", i, getpadding(11, datebuff), datebuff);
+                       }
                } else {
-                       snprintf(buffer, 32, " %-*s ", getpadding(11, datebuff), datebuff);
+                       if (strftime(datebuff, 16, stampformat, d)<=8) {
+                               snprintf(buffer, 32, "  %*s   ", getpadding(8, datebuff), datebuff);
+                       } else {
+                               snprintf(buffer, 32, " %-*s ", getpadding(11, datebuff), datebuff);
+                       }
                }
                strncat(buffer, getvalue(datalist_i->rx, 10, 1), 32);
                strcat(buffer, "   ");
@@ -347,22 +404,46 @@ void drawdaily(IMAGECONTENT *ic)
                        strcat(buffer, "  ");
                        if (datalist_i->next == NULL) {
                                d = localtime(&ic->interface.updated);
-                               strncat(buffer, gettrafficrate(datalist_i->rx+datalist_i->tx, d->tm_sec+(d->tm_min*60)+(d->tm_hour*3600), 14), 32);
+                               if (listtype == 1) { // day
+                                       e_secs = d->tm_sec+(d->tm_min*60)+(d->tm_hour*3600);
+                               } else if (listtype == 2) { // month
+                                       e_secs = mosecs(datalist_i->timestamp, ic->interface.updated);
+                               } else if (listtype == 3) { // year
+                                       e_secs = d->tm_yday*86400+d->tm_sec+(d->tm_min*60)+(d->tm_hour*3600);
+                               } else if (listtype == 4) { // top
+                                       e_secs = 86400;
+                               }
                        } else {
-                               strncat(buffer, gettrafficrate(datalist_i->rx+datalist_i->tx, 86400, 14), 32);
+                               if (listtype == 1 || listtype == 4) { // day
+                                       e_secs = 86400;
+                               } else if (listtype == 2) { // month
+                                       e_secs = dmonth(d->tm_mon) * 86400;
+                               } else if (listtype == 3) { // year
+                                       e_secs = (365 + isleapyear(d->tm_year+1900)) * 86400;
+                               }
                        }
+                       strncat(buffer, gettrafficrate(datalist_i->rx+datalist_i->tx, e_secs, 14), 32);
                }
                gdImageString(ic->im, gdFontGetSmall(), textx, texty, (unsigned char*)buffer, ic->ctext);
-               if (cfg.ostyle>2) {
-                       drawbar(ic, textx+400, texty+4, 78, datalist_i->rx, datalist_i->tx, datainfo.max);
-               } else {
-                       drawbar(ic, textx+304, texty+4, 170, datalist_i->rx, datalist_i->tx, datainfo.max);
+               if (listtype == 4) { // top
+                       if (cfg.ostyle>2) {
+                               drawbar(ic, textx+428, texty+4, 52, datalist_i->rx, datalist_i->tx, datainfo.max);
+                       } else {
+                               drawbar(ic, textx+336, texty+4, 140, datalist_i->rx, datalist_i->tx, datainfo.max);
+                       }
+               } else { // everything else
+                       if (cfg.ostyle>2) {
+                               drawbar(ic, textx+400, texty+4, 78, datalist_i->rx, datalist_i->tx, datainfo.max);
+                       } else {
+                               drawbar(ic, textx+304, texty+4, 170, datalist_i->rx, datalist_i->tx, datainfo.max);
+                       }
                }
                texty += 12;
                if (datalist_i->next == NULL) {
                        break;
                }
                datalist_i = datalist_i->next;
+               i++;
        }
 
        if (!datainfo.count) {
@@ -371,19 +452,35 @@ void drawdaily(IMAGECONTENT *ic)
        }
 
        if (cfg.ostyle>2) {
-               gdImageLine(ic->im, textx+2, texty+5, textx+392, texty+5, ic->cline);
+               gdImageLine(ic->im, textx+2, texty+5, textx+392+offsetx, texty+5, ic->cline);
        } else {
-               gdImageLine(ic->im, textx+2, texty+5, textx+296, texty+5, ic->cline);
+               gdImageLine(ic->im, textx+2, texty+5, textx+296+offsetx, texty+5, ic->cline);
        }
 
-       if (datainfo.count) {
+       if (datainfo.count > 0 && listtype != 4) {
 
-               d=localtime(&ic->interface.updated);
-               if ( datalist_i->rx==0 || datalist_i->tx==0 || (d->tm_hour*60+d->tm_min)==0 ) {
-                       e_rx=e_tx=0;
+               d = localtime(&ic->interface.updated);
+               if ( datalist_i->rx==0 || datalist_i->tx==0 ) {
+                       e_rx = e_tx = 0;
                } else {
-                       e_rx=((datalist_i->rx)/(float)(d->tm_hour*60+d->tm_min))*1440;
-                       e_tx=((datalist_i->tx)/(float)(d->tm_hour*60+d->tm_min))*1440;
+                       div = 0;
+                       mult = 0;
+                       if (listtype == 1) { // day
+                               div = d->tm_hour * 60 + d->tm_min;
+                               mult = 1440;
+                       } else if (listtype == 2) { // month
+                               div = mosecs(datalist_i->timestamp, ic->interface.updated);
+                               mult = dmonth(d->tm_mon) * 86400;
+                       } else if (listtype == 3) { // year
+                               div = d->tm_yday * 1440 + d->tm_hour * 60 + d->tm_min;
+                               mult = 1440 * (365 + isleapyear(d->tm_year + 1900));
+                       }
+                       if (div > 0) {
+                               e_rx = ((datalist_i->rx) / (float)div) * mult;
+                               e_tx = ((datalist_i->tx) / (float)div) * mult;
+                       } else {
+                               e_rx = e_tx = 0;
+                       }
                }
                snprintf(buffer, 32, " estimated   ");
                strncat(buffer, getvalue(e_rx, 10, 2), 32);
@@ -465,6 +562,7 @@ void modcolor(int *rgb, const int offset, const int force)
        }
 }
 
+/* TODO: needs updating */
 char *getimagevalue(const uint64_t b, const int len, const int rate)
 {
        static char buffer[64];
@@ -500,6 +598,7 @@ char *getimagevalue(const uint64_t b, const int len, const int rate)
        return buffer;
 }
 
+/* TODO: needs updating */
 char *getimagescale(const uint64_t b, const int rate)
 {
        static char buffer[8];
index 0923ae0cba3ff575d53ee120d6e88d5eb64000e3..8a6e594d7586ac47d874b9ebe399577b039cab05 100644 (file)
@@ -38,9 +38,7 @@ void drawdonut(IMAGECONTENT *ic, const int x, const int y, const float rxp, cons
 void drawsummary(IMAGECONTENT *ic, int type, int rate);
 void drawoldsummary(IMAGECONTENT *ic, int type, int rate);
 void drawhourly(IMAGECONTENT *ic, int rate); */
-void drawdaily(IMAGECONTENT *ic);
-/*void drawmonthly(IMAGECONTENT *ic);
-void drawtop(IMAGECONTENT *ic); */
+void drawlist(IMAGECONTENT *ic, const char *listname);
 void hextorgb(char *input, int *rgb);
 void modcolor(int *rgb, const int offset, const int force);
 char *getimagevalue(const uint64_t b, const int len, const int rate);
index e6d1a3c9557b1b235212288d9920eafc4d2c89a7..d23be39f7552d4201e4947a05505248f1bd2be39 100644 (file)
@@ -203,13 +203,15 @@ int main(int argc, char *argv[]) {
                } else if (strcmp(argv[currentarg],"--xml")==0) {
                        if (currentarg+1<argc && argv[currentarg+1][0]!='-') {
                                p.xmlmode = argv[currentarg+1][0];
-                               if (strlen(argv[currentarg+1])!=1 || strchr("ahdmt", p.xmlmode)==NULL) {
+                               if (strlen(argv[currentarg+1])!=1 || strchr("a5hdmyt", p.xmlmode)==NULL) {
                                        printf("Error: Invalid mode parameter \"%s\" for --xml.\n", argv[currentarg+1]);
                                        printf(" Valid parameters:\n");
                                        printf("    a - all (default)\n");
+                                       printf("    5 - only 5 minutes\n");
                                        printf("    h - only hours\n");
                                        printf("    d - only days\n");
                                        printf("    m - only months\n");
+                                       printf("    y - only years\n");
                                        printf("    t - only top 10\n");
                                        return 1;
                                }
@@ -219,13 +221,15 @@ int main(int argc, char *argv[]) {
                } else if (strcmp(argv[currentarg],"--json")==0) {
                        if (currentarg+1<argc && argv[currentarg+1][0]!='-') {
                                p.jsonmode = argv[currentarg+1][0];
-                               if (strlen(argv[currentarg+1])!=1 || strchr("ahdmt", p.jsonmode)==NULL) {
+                               if (strlen(argv[currentarg+1])!=1 || strchr("a5hdmyt", p.jsonmode)==NULL) {
                                        printf("Error: Invalid mode parameter \"%s\" for --json.\n", argv[currentarg+1]);
                                        printf(" Valid parameters:\n");
                                        printf("    a - all (default)\n");
+                                       printf("    5 - only 5 minutes\n");
                                        printf("    h - only hours\n");
                                        printf("    d - only days\n");
                                        printf("    m - only months\n");
+                                       printf("    y - only years\n");
                                        printf("    t - only top 10\n");
                                        return 1;
                                }
index d4ba66d78921f38bd88b96e7e5e03620891d71ee..344fe3f206adefc0109f180a2790de40847cb6b4 100644 (file)
@@ -177,6 +177,8 @@ int main(int argc, char *argv[])
                        cfg.qmode = 2;
                } else if ((strcmp(argv[currentarg],"-t")==0) || (strcmp(argv[currentarg],"--top10"))==0) {
                        cfg.qmode = 3;
+               } else if ((strcmp(argv[currentarg],"-y")==0) || (strcmp(argv[currentarg],"--years"))==0) {
+                       cfg.qmode = 4;
                } else if ((strcmp(argv[currentarg],"-s")==0) || (strcmp(argv[currentarg],"--summary"))==0) {
                        cfg.qmode = 5;
                } else if ((strcmp(argv[currentarg],"-h")==0) || (strcmp(argv[currentarg],"--hours"))==0) {