tests/datacache_tests.c tests/datacache_tests.h \
tests/config_tests.c tests/config_tests.h \
tests/fs_tests.c tests/fs_tests.h \
- tests/id_tests.c tests/id_tests.h
+ tests/id_tests.c tests/id_tests.h \
+ tests/daemon_tests.c tests/daemon_tests.h
#check_vnstat_SOURCES = tests/vnstat_tests.c tests/vnstat_tests.h \
# tests/common_tests.c tests/common_tests.h \
tests/dbsql_tests.c tests/dbsql_tests.h \
tests/datacache_tests.c tests/datacache_tests.h \
tests/config_tests.c tests/config_tests.h tests/fs_tests.c \
- tests/fs_tests.h tests/id_tests.c tests/id_tests.h src/cfg.c \
- src/cfg.h src/common.c src/common.h src/daemon.c src/daemon.h \
+ tests/fs_tests.h tests/id_tests.c tests/id_tests.h \
+ tests/daemon_tests.c tests/daemon_tests.h src/cfg.c src/cfg.h \
+ src/common.c src/common.h src/daemon.c src/daemon.h \
src/dbsql.c src/dbsql.h src/dbaccess.c src/dbaccess.h \
src/dbcache.c src/dbcache.h src/datacache.c src/datacache.h \
src/dbjson.c src/dbjson.h src/dbmerge.c src/dbmerge.h \
@HAVE_CHECK_TRUE@ tests/check_vnstat-config_tests.$(OBJEXT) \
@HAVE_CHECK_TRUE@ tests/check_vnstat-fs_tests.$(OBJEXT) \
@HAVE_CHECK_TRUE@ tests/check_vnstat-id_tests.$(OBJEXT) \
+@HAVE_CHECK_TRUE@ tests/check_vnstat-daemon_tests.$(OBJEXT) \
@HAVE_CHECK_TRUE@ src/check_vnstat-cfg.$(OBJEXT) \
@HAVE_CHECK_TRUE@ src/check_vnstat-common.$(OBJEXT) \
@HAVE_CHECK_TRUE@ src/check_vnstat-daemon.$(OBJEXT) \
@HAVE_CHECK_TRUE@ tests/datacache_tests.h tests/config_tests.c \
@HAVE_CHECK_TRUE@ tests/config_tests.h tests/fs_tests.c \
@HAVE_CHECK_TRUE@ tests/fs_tests.h tests/id_tests.c \
-@HAVE_CHECK_TRUE@ tests/id_tests.h src/cfg.c src/cfg.h \
+@HAVE_CHECK_TRUE@ tests/id_tests.h tests/daemon_tests.c \
+@HAVE_CHECK_TRUE@ tests/daemon_tests.h src/cfg.c src/cfg.h \
@HAVE_CHECK_TRUE@ src/common.c src/common.h src/daemon.c \
@HAVE_CHECK_TRUE@ src/daemon.h src/dbsql.c src/dbsql.h \
@HAVE_CHECK_TRUE@ src/dbaccess.c src/dbaccess.h src/dbcache.c \
tests/$(DEPDIR)/$(am__dirstamp)
tests/check_vnstat-id_tests.$(OBJEXT): tests/$(am__dirstamp) \
tests/$(DEPDIR)/$(am__dirstamp)
+tests/check_vnstat-daemon_tests.$(OBJEXT): tests/$(am__dirstamp) \
+ tests/$(DEPDIR)/$(am__dirstamp)
src/$(am__dirstamp):
@$(MKDIR_P) src
@: > src/$(am__dirstamp)
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vnstatd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_vnstat-common_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_vnstat-config_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_vnstat-daemon_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_vnstat-datacache_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_vnstat-dbsql_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_vnstat-fs_tests.Po@am__quote@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_vnstat_CFLAGS) $(CFLAGS) -c -o tests/check_vnstat-id_tests.obj `if test -f 'tests/id_tests.c'; then $(CYGPATH_W) 'tests/id_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/id_tests.c'; fi`
+tests/check_vnstat-daemon_tests.o: tests/daemon_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_vnstat_CFLAGS) $(CFLAGS) -MT tests/check_vnstat-daemon_tests.o -MD -MP -MF tests/$(DEPDIR)/check_vnstat-daemon_tests.Tpo -c -o tests/check_vnstat-daemon_tests.o `test -f 'tests/daemon_tests.c' || echo '$(srcdir)/'`tests/daemon_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_vnstat-daemon_tests.Tpo tests/$(DEPDIR)/check_vnstat-daemon_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/daemon_tests.c' object='tests/check_vnstat-daemon_tests.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_vnstat_CFLAGS) $(CFLAGS) -c -o tests/check_vnstat-daemon_tests.o `test -f 'tests/daemon_tests.c' || echo '$(srcdir)/'`tests/daemon_tests.c
+
+tests/check_vnstat-daemon_tests.obj: tests/daemon_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_vnstat_CFLAGS) $(CFLAGS) -MT tests/check_vnstat-daemon_tests.obj -MD -MP -MF tests/$(DEPDIR)/check_vnstat-daemon_tests.Tpo -c -o tests/check_vnstat-daemon_tests.obj `if test -f 'tests/daemon_tests.c'; then $(CYGPATH_W) 'tests/daemon_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/daemon_tests.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/check_vnstat-daemon_tests.Tpo tests/$(DEPDIR)/check_vnstat-daemon_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/daemon_tests.c' object='tests/check_vnstat-daemon_tests.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_vnstat_CFLAGS) $(CFLAGS) -c -o tests/check_vnstat-daemon_tests.obj `if test -f 'tests/daemon_tests.c'; then $(CYGPATH_W) 'tests/daemon_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/daemon_tests.c'; fi`
+
src/check_vnstat-cfg.o: src/cfg.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_vnstat_CFLAGS) $(CFLAGS) -MT src/check_vnstat-cfg.o -MD -MP -MF src/$(DEPDIR)/check_vnstat-cfg.Tpo -c -o src/check_vnstat-cfg.o `test -f 'src/cfg.c' || echo '$(srcdir)/'`src/cfg.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/check_vnstat-cfg.Tpo src/$(DEPDIR)/check_vnstat-cfg.Po
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. Everything is stored using UTC dates which should
-help with possible timezone and daylight saving time related issues.
-Yearly and 5 minute resolution statistics are also planned.
+configurable durations. Yearly and 5 minute resolution statistics are also planned.
# Status
##### Overall status
- * prototype
- * not usable due to lack of outputs
+ * only daemon is being compiled
+ * alpha version with minimal working daemon implementation
+ * many sanity checks are missing or disabled
* don't even try with a user that has write access to any vnStat 1.x database files
##### Done
- * database creation with basic insert functionality
+ * 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 aren't being accessed
##### TODO
- * remove writing of old format database files
- * data buffering in daemon instead of writing to disk once every update cycle
+ * continue daemon refactoring
+ * add missing sanity checks to daemon
+ * rewrite disabled tests
* data import from vnStat 1.x database format
* all outputs (text and image)
+ * use of 5 minute resolution statistics
* old data cleanup, everything gets currently stored forever
- * top 10, missing from current database structure
- * should it still be only for days or also top 10 months?
+ * top 10, included in database schema but not populated
* feature configurability
* freeze database structure
* documentation
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for vnstat 2.0_prototype.
+# Generated by GNU Autoconf 2.69 for vnstat 2.0_alpha.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
# Identity of this package.
PACKAGE_NAME='vnstat'
PACKAGE_TARNAME='vnstat'
-PACKAGE_VERSION='2.0_prototype'
-PACKAGE_STRING='vnstat 2.0_prototype'
+PACKAGE_VERSION='2.0_alpha'
+PACKAGE_STRING='vnstat 2.0_alpha'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures vnstat 2.0_prototype to adapt to many kinds of systems.
+\`configure' configures vnstat 2.0_alpha to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of vnstat 2.0_prototype:";;
+ short | recursive ) echo "Configuration of vnstat 2.0_alpha:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-vnstat configure 2.0_prototype
+vnstat configure 2.0_alpha
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by vnstat $as_me 2.0_prototype, which was
+It was created by vnstat $as_me 2.0_alpha, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='vnstat'
- VERSION='2.0_prototype'
+ VERSION='2.0_alpha'
cat >>confdefs.h <<_ACEOF
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by vnstat $as_me 2.0_prototype, which was
+This file was extended by vnstat $as_me 2.0_alpha, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-vnstat config.status 2.0_prototype
+vnstat config.status 2.0_alpha
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
-AC_INIT([vnstat], [2.0_prototype])
+AC_INIT([vnstat], [2.0_alpha])
AM_INIT_AUTOMAKE([foreign subdir-objects std-options -Wall -Werror])
AM_MAINTAINER_MODE
#include "common.h"
#include "ifinfo.h"
+#include "dbsql.h"
#include "dbaccess.h"
-#include "dbcache.h"
+#include "datacache.h"
#include "misc.h"
#include "cfg.h"
#include "ibw.h"
signal(SIGTTIN,SIG_IGN);
}
-int addinterfaces(const char *dirname, const int running)
+int addinterfaces(DSTATE *s)
{
- char *ifacelist, interface[32];
+ char *ifacelist, interface[32], buffer[32];
int index = 0, count = 0, bwlimit = 0;
/* get list of currently visible interfaces */
}
/* skip already known interfaces */
- if (checkdb(interface, dirname)) {
+ if (db_getinterfacecountbyname(interface)) {
if (debug)
printf("already known\n");
continue;
}
/* create database for interface */
+ if (!db_addinterface(interface)) {
+ if (debug)
+ printf("add failed, skip\n");
+ }
+
+ /* TODO: cleanup, this isn't probably going to be needed
initdb();
strncpy_nt(data.interface, interface, 32);
- strncpy_nt(data.nick, data.interface, 32);
+ strncpy_nt(data.nick, data.interface, 32);*/
+
if (!getifinfo(interface)) {
if (debug)
printf("getifinfo failed, skip\n");
continue;
}
- parseifinfo(1);
- if (!writedb(interface, dirname, 1)) {
- continue;
- }
+
+ /* TODO: this is most likely the wrong place to set btime */
+ snprintf(buffer, 32, "%"PRIu64"", (uint64_t)MAX32);
+ db_setinfo("btime", buffer, 1);
+
+ db_setcounters(interface, ifinfo.rx, ifinfo.tx);
+
+ // TODO: cleanup
+ //parseifinfo(1);
+
count++;
bwlimit = ibwget(interface);
- if (!running) {
+ if (!s->running) {
if (bwlimit > 0) {
printf("\"%s\" added with %d Mbit bandwidth limit.\n", interface, bwlimit);
} else {
} else {
if (debug)
printf("\%s\" added with %d Mbit bandwidth limit to cache.\n", interface, bwlimit);
- cacheadd(interface, 1);
+ // TODO: cleanup: cacheadd(interface, 1);
+ datacache_add(&s->dcache, interface, 1);
}
}
- if (count && !running) {
+ if (count && !s->running) {
if (count==1) {
printf("-> %d interface added.\n", count);
} else {
s->forcesave = 0;
s->noadd = 0;
s->alwaysadd = 0;
- s->dbhash = 0;
+ s->iflisthash = 0;
s->cfgfile[0] = '\0';
s->dirname[0] = '\0';
s->user[0] = '\0';
s->prevdbsave = 0;
s->dbcount = 0;
s->dodbsave = 0;
- s->datalist = NULL;
+ s->dcache = NULL;
}
void preparedatabases(DSTATE *s)
{
- DIR *dir;
- struct dirent *di;
+ /*DIR *dir;
+ struct dirent *di;*/
- /* check that directory is ok */
- if ((dir=opendir(s->dirname))==NULL) {
- printf("Error: Unable to open database directory \"%s\": %s\n", s->dirname, strerror(errno));
- printf("Make sure it exists and is at least read enabled for current user.\n");
- printf("Exiting...\n");
- exit(EXIT_FAILURE);
- }
-
- /* check if there's something to work with */
- s->dbcount = 0;
- while ((di=readdir(dir))) {
- if ((di->d_name[0]!='.') && (strcmp(di->d_name, DATABASEFILE)!=0)) {
- s->dbcount++;
- }
- }
- closedir(dir);
+ s->dbcount = db_getinterfacecount();
if (s->dbcount > 0 && !s->alwaysadd) {
s->dbcount = 0;
printf("Zero database found, adding available interfaces...\n");
}
- if (!addinterfaces(s->dirname, s->running) && s->dbcount == 0) {
+ /* TODO: import legacy databases first if found when the sqldb doesn't contain any interfaces
+ if ((dir=opendir(s->dirname))==NULL) {
+ printf("Error: Unable to open database directory \"%s\": %s\n", s->dirname, strerror(errno));
+ printf("Make sure it exists and is at least read enabled for current user.\n");
+ printf("Exiting...\n");
+ exit(EXIT_FAILURE);
+ }
+
+ s->dbcount = 0;
+ while ((di=readdir(dir))) {
+ if ((di->d_name[0]!='.') && (strcmp(di->d_name, DATABASEFILE)!=0)) {
+ s->dbcount++;
+ }
+ }
+ closedir(dir);*/
+
+ if (!addinterfaces(s) && s->dbcount == 0) {
printf("Nothing to do, exiting.\n");
exit(EXIT_FAILURE);
}
void filldatabaselist(DSTATE *s)
{
- DIR *dir;
- struct dirent *di;
+ dbiflist *dbifl = NULL, *dbifl_iterator = NULL;
- if ((dir=opendir(s->dirname))==NULL) {
- snprintf(errorstring, 512, "Unable to access database directory \"%s\" (%s), exiting.", s->dirname, strerror(errno));
+ if (db_getiflist(&dbifl) < 0) {
+ snprintf(errorstring, 512, "Unable to access database(%s), exiting.", strerror(errno));
printe(PT_Error);
+ /* TODO: this sequence should be a function, database handling is missing */
+
/* clean daemon stuff before exit */
if (s->rundaemon && !debug) {
close(pidfile);
exit(EXIT_FAILURE);
}
- while ((di=readdir(dir))) {
- if ((di->d_name[0]=='.') || (strcmp(di->d_name, DATABASEFILE)==0)) {
- continue;
- }
+ dbifl_iterator = dbifl;
+ while (dbifl_iterator != NULL) {
if (debug) {
- printf("\nProcessing file \"%s/%s\"...\n", s->dirname, di->d_name);
+ printf("\nProcessing interface \"%s\"...\n", dbifl_iterator->interface);
}
-
- if (!cacheadd(di->d_name, s->sync)) {
+ // TODO: cleanup: if (!cacheadd(dbifl->interface, s->sync)) {
+ if (!datacache_add(&s->dcache, dbifl_iterator->interface, s->sync)) {
snprintf(errorstring, 512, "Cache memory allocation failed, exiting.");
printe(PT_Error);
exit(EXIT_FAILURE);
}
s->dbcount++;
+ dbifl_iterator = dbifl_iterator->next;
}
- closedir(dir);
+ dbiflistfree(&dbifl);
s->sync = 0;
/* disable update interval check for one loop if database list was refreshed */
intsignal = 42;
s->prevdbsave = s->current;
/* list monitored interfaces to log */
- cachestatus();
+ datacache_status(&s->dcache);
} else {
s->updateinterval = 120;
}
void adjustsaveinterval(DSTATE *s)
{
/* modify active save interval if all interfaces are unavailable */
- if (cacheactivecount() > 0) {
+ if (datacache_activecount(&s->dcache) > 0) {
s->saveinterval = cfg.saveinterval * 60;
} else {
s->saveinterval = cfg.offsaveinterval * 60;
}
}
-void processdatalist(DSTATE *s)
+void processdatacache(DSTATE *s)
{
- while (s->datalist!=NULL) {
+ uint64_t rx, tx;
+ uint64_t rxchange, txchange;
+ uint64_t maxtransfer;
+ time_t interval;
+ int maxbw;
+ datacache *iterator = s->dcache;
+ xferlog *logiterator;
+ dbiflist *dbifl = NULL, *dbifl_iterator = NULL;
+
+ while (iterator != NULL) {
+
+ maxbw = 0;
+ maxtransfer = 0;
+ rx = tx = 0;
+ rxchange = txchange = 0;
if (debug) {
- printf("d: processing %s (%d)...\n", s->datalist->data.interface, s->dodbsave);
- }
-
- /* get data from cache if available */
- if (!datalist_cacheget(s)) {
- s->datalist = s->datalist->next;
- continue;
+ printf("dc: processing %s (%d)...\n", iterator->interface, s->dodbsave);
}
- /* get info if interface has been marked as active */
- datalist_getifinfo(s);
-
- /* check that the time is correct and update cached data */
- if (!datalist_timevalidation(s)) {
- s->datalist = s->datalist->next;
- continue;
- }
-
- /* write data to file if now is the time for it */
- if (!datalist_writedb(s)) {
- /* remove interface from update list since the database file doesn't exist anymore */
- snprintf(errorstring, 512, "Removing interface \"%s\" from update list.", s->datalist->data.interface);
- printe(PT_Info);
- s->datalist = cacheremove(s->datalist->data.interface);
- s->dbcount--;
- cachestatus();
- continue;
+ if (!iterator->filled) {
+ if (!db_getcounters(iterator->interface, &rx, &tx)) {
+ iterator = iterator->next;
+ continue;
+ }
+ iterator->currx = rx;
+ iterator->curtx = tx;
+ /* TODO: "updated" info from database needed */
+ iterator->updated = time(NULL);
+ iterator->filled = 1;
+ /* enforce interface status check */
+ s->iflisthash = 0;
}
- s->datalist = s->datalist->next;
- }
-}
-
-int datalist_cacheget(DSTATE *s)
-{
- if (cacheget(s->datalist)==0) {
+ if (iterator->active) {
+ if (!getifinfo(iterator->interface)) {
+ /* disable interface since we can't access its data */
+ data.active = 0;
+ snprintf(errorstring, 512, "Interface \"%s\" not available, disabling.", data.interface);
+ printe(PT_Info);
+ } else {
+ if (iterator->syncneeded) { /* if --sync was used during startup */
+ iterator->currx = ifinfo.rx;
+ iterator->curtx = ifinfo.tx;
+ iterator->syncneeded = 0;
+ } else {
+ if (iterator->updated > ifinfo.timestamp) {
+ /* skip update if previous update is less than a day in the future */
+ /* otherwise exit with error message since the clock is problably messed */
+ if (iterator->updated > (ifinfo.timestamp+86400)) {
+ snprintf(errorstring, 512, "Interface \"%s\" has previous update date too much in the future, exiting. (%u / %u)", iterator->interface, (unsigned int)iterator->updated, (unsigned int)ifinfo.timestamp);
+ printe(PT_Error);
+
+ /* clean daemon stuff before exit */
+ if (s->rundaemon && !debug) {
+ close(pidfile);
+ unlink(cfg.pidfile);
+ }
+ ibwflush();
+ exit(EXIT_FAILURE);
+ }
+ iterator = iterator->next;
+ continue;
+ }
+
+ interval = ifinfo.timestamp - iterator->updated;
+ if ( (interval > 1) && (interval < (60*MAXUPDATEINTERVAL)) ) {
+ /* TODO: add btime handling here */
+
+ rxchange = countercalc(&iterator->currx, &ifinfo.rx);
+ txchange = countercalc(&iterator->curtx, &ifinfo.tx);
+
+ /* get bandwidth limit for current interface */
+ maxbw = ibwget(iterator->interface);
+
+ if (maxbw > 0) {
+
+ /* calculate maximum possible transfer since last update based on set maximum rate */
+ /* and add 10% in order to be on the safe side */
+ maxtransfer = ceil((maxbw/(float)8)*interval*(float)1.1) * 1024 * 1024;
+
+ if (debug)
+ printf("interval: %"PRIu64" maxbw: %d maxrate: %"PRIu64" rxc: %"PRIu64" txc: %"PRIu64"\n", (uint64_t)interval, maxbw, maxtransfer, rxchange, txchange);
+
+ /* sync counters if traffic is greater than set maximum */
+ if ( (rxchange > maxtransfer) || (txchange > maxtransfer) ) {
+ snprintf(errorstring, 512, "Traffic rate for \"%s\" higher than set maximum %d Mbit (%"PRIu64"->%"PRIu64", r%"PRIu64" t%"PRIu64"), syncing.", iterator->interface, maxbw, (uint64_t)interval, maxtransfer, rxchange, txchange);
+ printe(PT_Info);
+ rxchange = txchange = 0;
+ }
+ }
+
+ if (rxchange || txchange) {
+ xferlog_add(&iterator->log, ifinfo.timestamp - (ifinfo.timestamp % 300), rxchange, txchange);
+ }
+ }
+ iterator->currx = ifinfo.rx;
+ iterator->curtx = ifinfo.tx;
+ iterator->updated = ifinfo.timestamp;
+ }
- /* try to read data from file if not cached */
- if (readdb(s->datalist->data.interface, s->dirname, 0)==0) {
- /* mark cache as filled on read success and force interface status update */
- s->datalist->filled = 1;
- s->dbhash = 0;
+ }
} else {
- return 0;
+ if (debug)
+ printf("dc: interface is disabled\n");
}
- }
- return 1;
-}
-void datalist_getifinfo(DSTATE *s)
-{
- if (!data.active) {
- if (debug)
- printf("d: interface is disabled\n");
- return;
- }
-
- if (!getifinfo(data.interface)) {
- /* disable interface since we can't access its data */
- data.active = 0;
- snprintf(errorstring, 512, "Interface \"%s\" not available, disabling.", data.interface);
- printe(PT_Info);
- return;
- }
-
- if (s->datalist->sync) { /* if --sync was used during startup */
- data.currx = ifinfo.rx;
- data.curtx = ifinfo.tx;
- s->datalist->sync = 0;
- } else {
- parseifinfo(0);
- }
-}
-
-int datalist_timevalidation(DSTATE *s)
-{
- if (s->current >= data.lastupdated) {
- data.lastupdated = s->current;
- cacheupdate();
- return 1;
- }
-
- /* skip update if previous update is less than a day in the future */
- /* otherwise exit with error message since the clock is problably messed */
- if (data.lastupdated > (s->current+86400)) {
- snprintf(errorstring, 512, "Interface \"%s\" has previous update date too much in the future, exiting. (%u / %u)", data.interface, (unsigned int)data.lastupdated, (unsigned int)s->current);
- printe(PT_Error);
-
- /* clean daemon stuff before exit */
- if (s->rundaemon && !debug) {
- close(pidfile);
- unlink(cfg.pidfile);
+ if (s->dodbsave) {
+ /* TODO: error handling needed, if the disk is full then keep the cache up to some time limit */
+
+ if (db_getinterfacecountbyname(iterator->interface)) {
+ logiterator = iterator->log;
+ while (logiterator != NULL) {
+ db_addtraffic_dated(iterator->interface, logiterator->rx, logiterator->tx, (uint64_t)logiterator->timestamp);
+ logiterator = logiterator->next;
+ }
+ xferlog_clear(&iterator->log);
+ db_setcounters(iterator->interface, iterator->currx, iterator->curtx);
+ if (!iterator->active) {
+ db_setactive(iterator->interface, iterator->active);
+ }
+ } else {
+ /* add interface for removal since it doesn't exists in the database anymore */
+ dbiflistadd(&dbifl, iterator->interface);
+ }
}
- ibwflush();
- exit(EXIT_FAILURE);
- }
-
- return 0;
-}
-
-int datalist_writedb(DSTATE *s)
-{
- if (!s->dodbsave) {
- return 1;
- }
-
- if (!checkdb(s->datalist->data.interface, s->dirname)) {
- snprintf(errorstring, 512, "Database for interface \"%s\" no longer exists.", s->datalist->data.interface);
- printe(PT_Info);
- return 0;
- }
- if (!validatedb()) {
- snprintf(errorstring, 512, "Cached data for interface \"%s\" failed validation. Reloading data from file.", s->datalist->data.interface);
- printe(PT_Error);
- if (readdb(s->datalist->data.interface, s->dirname, 0)==0) {
- cacheupdate();
- return 1;
- }
- /* remove interface from update list if reload failed */
- return 0;
+ iterator = iterator->next;
}
- if (spacecheck(s->dirname)) {
- if (writedb(s->datalist->data.interface, s->dirname, 0)) {
- if (!s->dbsaved) {
- snprintf(errorstring, 512, "Database write possible again.");
- printe(PT_Info);
- s->dbsaved = 1;
- }
- } else {
- if (s->dbsaved) {
- snprintf(errorstring, 512, "Unable to write database, continuing with cached data.");
- printe(PT_Error);
- s->dbsaved = 0;
- }
- }
- } else {
- /* show freespace error only once */
- if (s->dbsaved) {
- snprintf(errorstring, 512, "Free diskspace check failed, unable to write database, continuing with cached data.");
- printe(PT_Error);
- s->dbsaved = 0;
+ if (dbifl != NULL) {
+ dbifl_iterator = dbifl;
+ while (dbifl_iterator != NULL) {
+ snprintf(errorstring, 512, "Removing interface \"%s\" from update list.", dbifl_iterator->interface);
+ printe(PT_Info);
+ datacache_remove(&s->dcache, dbifl_iterator->interface);
+ s->dbcount--;
+ dbifl_iterator = dbifl_iterator->next;
}
+ datacache_status(&s->dcache);
+ dbiflistfree(&dbifl);
}
- return 1;
}
void handleintsignals(DSTATE *s)
case SIGHUP:
snprintf(errorstring, 512, "SIGHUP received, flushing data to disk and reloading config.");
printe(PT_Info);
- cacheflush(s->dirname);
+ /* TODO: cleanup: cacheflush(s->dirname); */
s->dbcount = 0;
ibwflush();
+ db_close();
if (loadcfg(s->cfgfile)) {
strncpy_nt(s->dirname, cfg.dbdir, 512);
}
ibwloadcfg(s->cfgfile);
+ db_open(1);
break;
case SIGINT:
preparevnstatdir(cfg.logfile, s->user, s->group);
}
}
+
+void datacache_status(datacache **dc)
+{
+ char buffer[512], bwtemp[16];
+ int b = 13, count = 0, bwlimit = 0;
+ datacache *iterator = *dc;
+
+ snprintf(buffer, b, "Monitoring: ");
+
+ while (iterator != NULL) {
+ if ((b+strlen(iterator->interface)+16) < 508) {
+ bwlimit = ibwget(iterator->interface);
+ if (bwlimit < 0) {
+ snprintf(bwtemp, 16, " (no limit) ");
+ } else {
+ snprintf(bwtemp, 16, " (%d Mbit) ", bwlimit);
+ }
+ strncat(buffer, iterator->interface, strlen(iterator->interface));
+ strncat(buffer, bwtemp, strlen(bwtemp));
+ b += strlen(iterator->interface) + strlen(bwtemp);
+ } else {
+ strcat(buffer, "...");
+ break;
+ }
+ count++;
+ iterator = iterator->next;
+ }
+
+ if (count) {
+ strncpy_nt(errorstring, buffer, 512);
+ errorstring[511] = '\0';
+ } else {
+ snprintf(errorstring, 512, "Nothing to monitor");
+ }
+ printe(PT_Info);
+}
+
+void interfacechangecheck(DSTATE *s)
+{
+ char *ifacelist, interface[32];
+ datacache *iterator = s->dcache;
+ uint32_t newhash;
+ int offset, found;
+
+ /* get list of currently visible interfaces */
+ if (getiflist(&ifacelist, 0)==0) {
+ free(ifacelist);
+ s->iflisthash = 0;
+ return;
+ }
+
+ newhash = simplehash(ifacelist, (int)strlen(ifacelist));
+
+ if (s->iflisthash == newhash) {
+ free(ifacelist);
+ return;
+ }
+
+ /* search for changes if hash doesn't match */
+ if (debug) {
+ printf("ifacelist changed: '%s' %u <> %u\n", ifacelist, s->iflisthash, newhash);
+ }
+
+ while (iterator != NULL) {
+
+ if (!iterator->filled) {
+ iterator = iterator->next;
+ continue;
+ }
+
+ found = offset = 0;
+
+ while (offset <= (int)strlen(ifacelist)) {
+ sscanf(ifacelist+offset, "%31s", interface);
+ if (strcmp(iterator->interface, interface) == 0) {
+ found = 1;
+ break;
+ }
+ offset += (int)strlen(interface) + 1;
+ }
+
+ if (iterator->active == 1 && found == 0) {
+ iterator->active = 0;
+ iterator->currx = 0;
+ iterator->curtx = 0;
+ if (cfg.savestatus) {
+ s->forcesave = 1;
+ }
+ snprintf(errorstring, 512, "Interface \"%s\" disabled.", iterator->interface);
+ printe(PT_Info);
+ } else if (iterator->active == 0 && found == 1) {
+ iterator->active = 1;
+ iterator->currx = 0;
+ iterator->curtx = 0;
+ if (cfg.savestatus) {
+ s->forcesave = 1;
+ }
+ snprintf(errorstring, 512, "Interface \"%s\" enabled.", iterator->interface);
+ printe(PT_Info);
+ }
+
+ iterator = iterator->next;
+ }
+ free(ifacelist);
+
+ s->iflisthash = newhash;
+}
+
+uint32_t simplehash(const char *data, int len)
+{
+ uint32_t hash = len;
+
+ if (len <= 0 || data == NULL) {
+ return 0;
+ }
+
+ for (len--; len >= 0; len--) {
+ if (len > 0) {
+ hash += (int)data[len] * len;
+ } else {
+ hash += (int)data[len];
+ }
+ }
+
+ return hash;
+}
int running, updateinterval, dbcount, dodbsave, rundaemon;
int dbsaved, showhelp, sync, saveinterval, forcesave, noadd;
int alwaysadd;
- uint32_t dbhash;
+ uint32_t iflisthash;
char cfgfile[512], dirname[512];
char user[33], group[33];
time_t current, prevdbupdate, prevdbsave;
- datanode *datalist;
+ datacache *dcache;
} DSTATE;
void daemonize(void);
-int addinterfaces(const char *dirname, const int running);
void debugtimestamp(void);
+int addinterfaces(DSTATE *s);
void initdstate(DSTATE *s);
void preparedatabases(DSTATE *s);
void setsignaltraps(void);
void filldatabaselist(DSTATE *s);
void adjustsaveinterval(DSTATE *s);
void checkdbsaveneed(DSTATE *s);
+void processdatacache(DSTATE *s);
void processdatalist(DSTATE *s);
-int datalist_cacheget(DSTATE *s);
-void datalist_getifinfo(DSTATE *s);
-int datalist_timevalidation(DSTATE *s);
-int datalist_writedb(DSTATE *s);
void handleintsignals(DSTATE *s);
void preparedirs(DSTATE *s);
+void datacache_status(datacache **dc);
+
+void interfacechangecheck(DSTATE *s);
+uint32_t simplehash(const char *data, int len);
+
#endif
printf(" xferlog: ");
}
while (logiterator != NULL) {
- printf("%d: %"PRIu64" - %"PRIu64" / %"PRIu64" ", i, (uint64_t)logiterator->timestamp, logiterator->rx, logiterator->tx);
+ printf("%d: %"PRIu64" - %"PRIu64" / %"PRIu64"", i, (uint64_t)logiterator->timestamp, logiterator->rx, logiterator->tx);
+ if (logiterator->next != NULL) {
+ printf(", ");
+ }
logiterator = logiterator->next;
i++;
}
return c;
}
-
-uint32_t dbcheck(uint32_t dbhash, int *forcesave)
-{
- char *ifacelist, interface[32];
- datanode *p = dataptr;
- uint32_t newhash;
- int offset, found;
-
- /* get list of currently visible interfaces */
- if (getiflist(&ifacelist, 0)==0) {
- free(ifacelist);
- return 0;
- }
-
- newhash = simplehash(ifacelist, (int)strlen(ifacelist));
-
- if (newhash == dbhash) {
- free(ifacelist);
- return newhash;
- }
-
- /* search for changes if hash doesn't match */
- if (debug) {
- printf("ifacelist changed: '%s' %u <> %u\n", ifacelist, dbhash, newhash);
- }
-
- while (p != NULL) {
-
- if (p->filled) {
- found = offset = 0;
-
- while (offset <= (int)strlen(ifacelist)) {
- sscanf(ifacelist+offset, "%31s", interface);
- if (strcmp(p->data.interface, interface)==0) {
- found = 1;
- break;
- }
- offset += (int)strlen(interface)+1;
- }
-
- if (p->data.active==1 && found==0) {
- p->data.active = 0;
- p->data.currx = p->data.curtx = 0;
- if (cfg.savestatus) {
- *forcesave = 1;
- }
- snprintf(errorstring, 512, "Interface \"%s\" disabled.", p->data.interface);
- printe(PT_Info);
- } else if (p->data.active==0 && found==1) {
- p->data.active = 1;
- p->data.currx = p->data.curtx = 0;
- if (cfg.savestatus) {
- *forcesave = 1;
- }
- snprintf(errorstring, 512, "Interface \"%s\" enabled.", p->data.interface);
- printe(PT_Info);
- }
- }
- p = p->next;
- }
-
- free(ifacelist);
-
- return newhash;
-}
-
-uint32_t simplehash(const char *data, int len)
-{
- uint32_t hash = len;
-
- if (len <= 0 || data == NULL) {
- return 0;
- }
-
- for (len--; len >= 0; len--) {
- if (len > 0) {
- hash += (int)data[len] * len;
- } else {
- hash += (int)data[len];
- }
- }
-
- return hash;
-}
void cacheflush(const char *dirname);
int cachecount(void);
int cacheactivecount(void);
-uint32_t dbcheck(uint32_t dbhash, int *forcesave);
-uint32_t simplehash(const char *data, int len);
/* global variables */
datanode *dataptr;
}
if (debug)
- printf("add %s (%"PRId64"): rx %"PRIu64" - tx %"PRIu64"\n", iface, (int64_t)ifaceid, rx, tx);
+ printf("db add %s (%"PRId64"): rx %"PRIu64" - tx %"PRIu64"\n", iface, (int64_t)ifaceid, rx, tx);
if (!db_begintransaction()) {
return 0;
p->limit = speed;
p->retries = 0;
p->detected = current;
- return speed;
+ return speed; /* TODO: fix mismatch between type of speed and return */
}
p->retries++;
}
*/
#include "common.h"
-#include "dbcache.h"
+#include "datacache.h"
#include "dbsql.h"
#include "cfg.h"
#include "ibw.h"
int main(int argc, char *argv[])
{
int currentarg;
- uint32_t prevdbhash;
+ uint32_t previflisthash;
DSTATE s;
initdstate(&s);
/* track interface status only if at least one database exists */
if (s.dbcount != 0) {
- prevdbhash = s.dbhash;
- s.dbhash = dbcheck(s.dbhash, &s.forcesave);
- if (s.alwaysadd && s.dbhash != prevdbhash && prevdbhash != 0) {
- s.dbcount += addinterfaces(s.dirname, s.running);
+ previflisthash = s.iflisthash;
+ interfacechangecheck(&s);
+ if (s.alwaysadd && s.iflisthash != previflisthash && previflisthash != 0) {
+ s.dbcount += addinterfaces(&s);
}
}
if (debug) {
debugtimestamp();
- cacheshow();
+ datacache_debug(&s.dcache);
ibwlist();
}
/* update data cache */
} else {
s.prevdbupdate = s.current;
- s.datalist = dataptr;
adjustsaveinterval(&s);
checkdbsaveneed(&s);
- processdatalist(&s);
+ processdatacache(&s);
if (debug) {
printf("\n");
}
}
- cacheflush(s.dirname);
+ // TODO: replace: cacheflush(s.dirname);
+
+ /* TODO: remove this temporary cleanup */
+ datacache_clear(&s.dcache);
+
+
ibwflush();
db_close();
#include "daemon_tests.h"
#include "common.h"
#include "dbaccess.h"
-#include "dbcache.h"
+#include "datacache.h"
+#include "ifinfo.h"
#include "cfg.h"
#include "fs.h"
#include "daemon.h"
START_TEST(addinterfaces_does_nothing_with_no_files)
{
+ DSTATE s;
linuxonly;
defaultcfg();
+ initdstate(&s);
suppress_output();
ck_assert_int_eq(remove_directory(TESTDIR), 1);
ck_assert_int_eq(clean_testdbdir(), 1);
- ck_assert_int_eq(addinterfaces(TESTDBDIR, 0), 0);
+ ck_assert_int_eq(addinterfaces(&s), 0);
}
END_TEST
START_TEST(addinterfaces_adds_interfaces)
{
int ret;
+ DSTATE s;
linuxonly;
defaultcfg();
+ initdstate(&s);
suppress_output();
ck_assert_int_eq(remove_directory(TESTDIR), 1);
ck_assert_int_eq(clean_testdbdir(), 1);
fake_proc_net_dev("a", "ethtwo", 5, 6, 7, 8);
fake_proc_net_dev("a", "sit0", 0, 0, 0, 0);
- ret = addinterfaces(TESTDBDIR, 0);
+ ret = addinterfaces(&s);
ck_assert_int_eq(ret, 2);
- ck_assert_int_eq(check_dbfile_exists("ethone", sizeof(DATA)), 1);
+ /* TODO: add database content checks also here? */
+ ck_assert_int_eq(check_dbfile_exists("ethone", sizeof(DATA)), 0);
ck_assert_int_eq(check_dbfile_exists(".ethone", sizeof(DATA)), 0);
- ck_assert_int_eq(check_dbfile_exists("ethtwo", sizeof(DATA)), 1);
+ ck_assert_int_eq(check_dbfile_exists("ethtwo", sizeof(DATA)), 0);
ck_assert_int_eq(check_dbfile_exists(".ethtwo", sizeof(DATA)), 0);
}
END_TEST
-
+/*
START_TEST(addinterfaces_adds_only_new_interfaces)
{
int ret;
ck_assert_int_eq(check_dbfile_exists(".eththree", sizeof(DATA)), 0);
}
END_TEST
-
+*/
START_TEST(initdstate_does_not_crash)
{
DSTATE s;
preparedatabases(&s);
- ck_assert_int_eq(check_dbfile_exists("ethone", sizeof(DATA)), 1);
+ /* TODO: add database content checks also here? */
+ ck_assert_int_eq(check_dbfile_exists("ethone", sizeof(DATA)), 0);
ck_assert_int_eq(check_dbfile_exists(".ethone", sizeof(DATA)), 0);
- ck_assert_int_eq(check_dbfile_exists("ethtwo", sizeof(DATA)), 1);
+ ck_assert_int_eq(check_dbfile_exists("ethtwo", sizeof(DATA)), 0);
ck_assert_int_eq(check_dbfile_exists(".ethtwo", sizeof(DATA)), 0);
}
END_TEST
filldatabaselist(&s);
}
END_TEST
-
+/*
START_TEST(filldatabaselist_does_not_exit_with_empty_database_dir)
{
DSTATE s;
ck_assert_int_eq(remove_directory(TESTDIR), 1);
ck_assert_int_eq(clean_testdbdir(), 1);
+ // TODO: update test to open database
filldatabaselist(&s);
ck_assert_int_eq(s.dbcount, 0);
ck_assert_int_eq(s.saveinterval, cfg.saveinterval * 60);
}
END_TEST
-
+*/
START_TEST(checkdbsaveneed_has_no_need)
{
DSTATE s;
}
END_TEST
-START_TEST(datalist_cacheget_with_no_database)
-{
- DSTATE s;
- defaultcfg();
- initdb();
- initdstate(&s);
- disable_logprints();
- strncpy_nt(s.dirname, TESTDBDIR, 512);
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- ck_assert_int_eq(clean_testdbdir(), 1);
- ck_assert_int_eq(cacheadd("name1", 0), 1);
- s.dbcount = 1;
- s.dbhash = 123;
- s.datalist = dataptr;
-
- ck_assert_int_eq(datalist_cacheget(&s), 0);
- ck_assert_int_eq(s.dbhash, 123);
- ck_assert_int_eq(s.datalist->filled, 0);
-}
-END_TEST
-
-START_TEST(datalist_cacheget_with_database)
-{
- DSTATE s;
- defaultcfg();
- initdb();
- initdstate(&s);
- strncpy_nt(s.dirname, TESTDBDIR, 512);
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- ck_assert_int_eq(clean_testdbdir(), 1);
- ck_assert_int_eq(cacheadd("name1", 0), 1);
- strncpy_nt(data.interface, "name1", 32);
- ck_assert_int_eq(writedb("name1", TESTDBDIR, 1), 1);
- ck_assert_int_eq(check_dbfile_exists("name1", sizeof(DATA)), 1);
- s.dbcount = 1;
- s.dbhash = 123;
- s.datalist = dataptr;
-
- ck_assert_int_eq(datalist_cacheget(&s), 1);
- ck_assert_int_eq(s.dbhash, 0);
- ck_assert_int_eq(s.datalist->filled, 1);
-}
-END_TEST
-
-START_TEST(datalist_getifinfo_with_disabled_interface)
-{
- DSTATE s;
-
- linuxonly;
-
- initdb();
- initdstate(&s);
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- data.active = 0;
-
- datalist_getifinfo(&s);
-
- ck_assert_int_eq(data.active, 0);
-}
-END_TEST
-
-START_TEST(datalist_getifinfo_with_enabled_unavailable_interface)
-{
- DSTATE s;
-
- linuxonly;
-
- initdb();
- initdstate(&s);
- disable_logprints();
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- strncpy_nt(data.interface, "name1", 32);
- data.active = 1;
-
- datalist_getifinfo(&s);
-
- ck_assert_int_eq(data.active, 0);
-}
-END_TEST
-
-START_TEST(datalist_getifinfo_with_interface_sync)
+START_TEST(processdatacache_empty_does_nothing)
{
DSTATE s;
-
- linuxonly;
-
- initdb();
initdstate(&s);
- disable_logprints();
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- fake_proc_net_dev("w", "name1", 1025, 2050, 30, 40);
- strncpy_nt(data.interface, "name1", 32);
- ck_assert_int_eq(cacheadd("name1", 1), 1);
- data.active = 1;
- data.currx = 1;
- data.curtx = 2;
- s.dbcount = 1;
- s.datalist = dataptr;
- ck_assert_int_eq(s.datalist->sync, 1);
- ck_assert_int_eq(data.currx, 1);
- ck_assert_int_eq(data.curtx, 2);
- ck_assert_int_eq(data.totalrxk, 0);
- ck_assert_int_eq(data.totaltxk, 0);
-
- datalist_getifinfo(&s);
-
- ck_assert_int_eq(data.active, 1);
- ck_assert_int_eq(data.totalrxk, 0);
- ck_assert_int_eq(data.totaltxk, 0);
- ck_assert_int_eq(data.currx, 1025);
- ck_assert_int_eq(data.curtx, 2050);
- ck_assert_int_eq(s.datalist->sync, 0);
-}
-END_TEST
-
-START_TEST(datalist_getifinfo_with_interface_and_no_sync)
-{
- DSTATE s;
-
- linuxonly;
- initdb();
- initdstate(&s);
- disable_logprints();
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- fake_proc_net_dev("w", "name1", 1025, 2050, 30, 40);
- strncpy_nt(data.interface, "name1", 32);
- ck_assert_int_eq(cacheadd("name1", 0), 1);
- data.active = 1;
- data.currx = 1;
- data.curtx = 2;
- s.dbcount = 1;
- s.datalist = dataptr;
- ck_assert_int_eq(s.datalist->sync, 0);
- ck_assert_int_eq(data.currx, 1);
- ck_assert_int_eq(data.curtx, 2);
- ck_assert_int_eq(data.totalrxk, 0);
- ck_assert_int_eq(data.totaltxk, 0);
-
- datalist_getifinfo(&s);
-
- ck_assert_int_eq(data.active, 1);
- ck_assert_int_eq(data.totalrxk, 1);
- ck_assert_int_eq(data.totaltxk, 2);
- ck_assert_int_eq(data.currx, 1025);
- ck_assert_int_eq(data.curtx, 2050);
- ck_assert_int_eq(s.datalist->sync, 0);
-}
-END_TEST
-
-START_TEST(datalist_timevalidation_in_normal_time)
-{
- DSTATE s;
- initdb();
- initdstate(&s);
- data.lastupdated = time(NULL);
- s.current = time(NULL);
-
- ck_assert_int_eq(datalist_timevalidation(&s), 1);
- ck_assert_int_eq(data.lastupdated, s.current);
- s.current++;
- ck_assert_int_eq(datalist_timevalidation(&s), 1);
- ck_assert_int_eq(data.lastupdated, s.current);
-}
-END_TEST
-
-START_TEST(datalist_timevalidation_in_future_time)
-{
- DSTATE s;
- initdb();
- initdstate(&s);
- data.lastupdated = time(NULL)+10;
- s.current = time(NULL);
-
- ck_assert_int_eq(datalist_timevalidation(&s), 0);
- ck_assert_int_ne(data.lastupdated, s.current);
-}
-END_TEST
-
-START_TEST(datalist_timevalidation_in_too_future_time)
-{
- DSTATE s;
- initdb();
- initdstate(&s);
- disable_logprints();
- data.lastupdated = time(NULL)+90000;
- s.current = time(NULL);
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
-
- ck_assert_int_eq(datalist_timevalidation(&s), 0);
- ck_assert_int_ne(data.lastupdated, s.current);
-}
-END_TEST
-
-START_TEST(datalist_writedb_does_not_save_unless_requested)
-{
- DSTATE s;
- initdstate(&s);
- s.dodbsave = 0;
- s.dbsaved = 0;
-
- ck_assert_int_eq(datalist_writedb(&s), 1);
- ck_assert_int_eq(s.dbsaved, 0);
-}
-END_TEST
-
-START_TEST(datalist_writedb_detects_missing_database_file)
-{
- DSTATE s;
- initdstate(&s);
- s.dodbsave = 1;
- s.dbsaved = 0;
- disable_logprints();
- strncpy_nt(s.dirname, TESTDBDIR, 512);
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- ck_assert_int_eq(cacheadd("name1", 0), 1);
- s.datalist = dataptr;
-
- ck_assert_int_eq(datalist_writedb(&s), 0);
- ck_assert_int_eq(s.dbsaved, 0);
-}
-END_TEST
-
-START_TEST(datalist_writedb_writes_database_file)
-{
- DSTATE s;
- initdb();
- initdstate(&s);
- s.dodbsave = 1;
- s.dbsaved = 0;
- disable_logprints();
- strncpy_nt(data.interface, "name1", 32);
- strncpy_nt(s.dirname, TESTDBDIR, 512);
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- ck_assert_int_eq(clean_testdbdir(), 1);
- ck_assert_int_eq(create_zerosize_dbfile("name1"), 1);
- ck_assert_int_eq(cacheadd("name1", 0), 1);
- s.datalist = dataptr;
-
- ck_assert_int_eq(datalist_writedb(&s), 1);
- ck_assert_int_eq(s.dbsaved, 1);
- ck_assert_int_eq(check_dbfile_exists("name1", sizeof(DATA)), 1);
- ck_assert_int_eq(check_dbfile_exists(".name1", 0), 1);
-}
-END_TEST
-
-START_TEST(processdatalist_empty_does_nothing)
-{
- DSTATE s;
- initdstate(&s);
-
- processdatalist(&s);
-}
-END_TEST
-
-START_TEST(processdatalist_filled_does_things)
-{
- DSTATE s;
-
- linuxonly;
-
- initdb();
- initdstate(&s);
- disable_logprints();
- s.current = time(NULL);
- strncpy_nt(s.dirname, TESTDBDIR, 512);
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- ck_assert_int_eq(clean_testdbdir(), 1);
- ck_assert_int_eq(create_zerosize_dbfile("ethnormal"), 1);
- ck_assert_int_eq(create_zerosize_dbfile("ethunavailable"), 1);
- ck_assert_int_eq(create_zerosize_dbfile("ethbogus"), 1);
- ck_assert_int_eq(create_zerosize_dbfile("ethfuture"), 1);
- fake_proc_net_dev("w", "ethbogus", 1, 2, 3, 4);
- fake_proc_net_dev("a", "ethnormal", 1024, 2048, 30, 40);
- fake_proc_net_dev("a", "ethnodb", 2048, 3072, 40, 50);
- fake_proc_net_dev("a", "ethfuture", 3072, 4096, 50, 60);
-
- strcpy(data.interface, "ethnormal");
- ck_assert_int_eq(cacheupdate(), 1);
- strcpy(data.interface, "ethunavailable");
- ck_assert_int_eq(cacheupdate(), 1);
- strcpy(data.interface, "ethnodb");
- ck_assert_int_eq(cacheupdate(), 1);
- strcpy(data.interface, "ethfuture");
- data.lastupdated = time(NULL)+10;
- ck_assert_int_eq(cacheupdate(), 1);
- strcpy(data.interface, "ethbogus");
- data.lastupdated = time(NULL);
- data.version = 0;
- ck_assert_int_eq(cacheupdate(), 1);
- strcpy(data.interface, "foo");
- s.dbcount = 5;
- s.dodbsave = 1;
- s.datalist = dataptr;
-
- processdatalist(&s);
- ck_assert_int_eq(s.dbcount, 4);
- ck_assert_int_eq(cachegetname("ethnodb"), 0);
- ck_assert_int_eq(cachegetname("ethunavailable"), 1);
- ck_assert_int_eq(data.active, 0);
- ck_assert_int_eq(cachegetname("ethnormal"), 1);
- ck_assert_int_eq(data.active, 1);
- ck_assert_int_eq(data.currx, 1024);
- ck_assert_int_eq(data.curtx, 2048);
- ck_assert_int_eq(cachegetname("ethfuture"), 1);
- ck_assert_int_eq(data.active, 1);
- ck_assert_int_eq(data.currx, 0);
- ck_assert_int_eq(data.curtx, 0);
- ck_assert_int_eq(cachegetname("ethbogus"), 1);
- ck_assert_int_eq(data.active, 1);
- ck_assert_int_eq(data.currx, 0);
- ck_assert_int_eq(data.curtx, 0);
+ processdatacache(&s);
}
END_TEST
}
END_TEST
+START_TEST(interfacechangecheck_with_no_interfaces)
+{
+ DSTATE s;
+
+ linuxonly;
+
+ initdstate(&s);
+ ck_assert_int_eq(remove_directory(TESTDIR), 1);
+ interfacechangecheck(&s);
+ ck_assert_int_eq(s.iflisthash, 0);
+ ck_assert_int_eq(s.forcesave, 0);
+}
+END_TEST
+
+START_TEST(interfacechangecheck_with_empty_cache)
+{
+ DSTATE s;
+
+ linuxonly;
+
+ initdstate(&s);
+ ck_assert_int_eq(remove_directory(TESTDIR), 1);
+ fake_proc_net_dev("w", "ethsomething", 1, 2, 3, 4);
+ fake_proc_net_dev("a", "ethelse", 5, 6, 7, 8);
+
+ interfacechangecheck(&s);
+ ck_assert_int_ne(s.iflisthash, 0);
+ ck_assert_int_eq(s.forcesave, 0);
+}
+END_TEST
+
+START_TEST(interfacechangecheck_with_no_changes_in_iflist)
+{
+ DSTATE s;
+ uint32_t ifhash;
+ char *ifacelist;
+
+ linuxonly;
+
+ initdstate(&s);
+ ck_assert_int_eq(remove_directory(TESTDIR), 1);
+ fake_proc_net_dev("w", "ethsomething", 1, 2, 3, 4);
+ fake_proc_net_dev("a", "ethelse", 5, 6, 7, 8);
+ ck_assert_int_ne(getiflist(&ifacelist, 0), 0);
+ ifhash = simplehash(ifacelist, (int)strlen(ifacelist));
+ s.iflisthash = ifhash;
+
+ interfacechangecheck(&s);
+ ck_assert_int_eq(s.iflisthash, ifhash);
+ ck_assert_int_eq(s.forcesave, 0);
+}
+END_TEST
+/* TODO: rewrite
+START_TEST(interfacechangecheck_with_filled_cache)
+{
+ DSTATE s;
+
+ linuxonly;
+
+ initdb();
+ defaultcfg();
+ disable_logprints();
+ initdstate(&s);
+ ck_assert_int_eq(remove_directory(TESTDIR), 1);
+
+ ck_assert_int_eq(cachecount(), 0);
+ strcpy(data.interface, "ethbasic");
+ ck_assert_int_eq(cacheupdate(), 1);
+ strcpy(data.interface, "ethactive");
+ ck_assert_int_eq(cacheupdate(), 1);
+ strcpy(data.interface, "ethnotactive");
+ data.active = 0;
+ ck_assert_int_eq(cacheupdate(), 1);
+ ck_assert_int_eq(cachecount(), 3);
+ ck_assert_int_eq(cacheactivecount(), 2);
+
+ fake_proc_net_dev("w", "ethbasic", 1, 2, 3, 4);
+ fake_proc_net_dev("a", "ethnotactive", 5, 6, 7, 8);
+
+ ck_assert_int_ne(interfacechangecheck(0, &forcesave), 0);
+ ck_assert_int_eq(forcesave, 1);
+}
+END_TEST
+*/
+
void add_daemon_tests(Suite *s)
{
TCase *tc_daemon = tcase_create("Daemon");
tcase_add_test(tc_daemon, initdstate_does_not_crash);
tcase_add_test(tc_daemon, addinterfaces_does_nothing_with_no_files);
tcase_add_test(tc_daemon, addinterfaces_adds_interfaces);
- tcase_add_test(tc_daemon, addinterfaces_adds_only_new_interfaces);
- tcase_add_test(tc_daemon, addinterfaces_adds_to_cache_when_running);
+ //tcase_add_test(tc_daemon, addinterfaces_adds_only_new_interfaces);
+ //tcase_add_test(tc_daemon, addinterfaces_adds_to_cache_when_running);
tcase_add_exit_test(tc_daemon, preparedatabases_exits_with_no_database_dir, 1);
tcase_add_exit_test(tc_daemon, preparedatabases_exits_with_no_databases, 1);
tcase_add_exit_test(tc_daemon, preparedatabases_exits_with_no_databases_and_noadd, 1);
tcase_add_test(tc_daemon, preparedatabases_with_no_databases_creates_databases);
tcase_add_test(tc_daemon, setsignaltraps_does_not_exit);
tcase_add_exit_test(tc_daemon, filldatabaselist_exits_with_no_database_dir, 1);
- tcase_add_test(tc_daemon, filldatabaselist_does_not_exit_with_empty_database_dir);
- tcase_add_test(tc_daemon, filldatabaselist_adds_databases);
- tcase_add_test(tc_daemon, adjustsaveinterval_with_empty_cache);
- tcase_add_test(tc_daemon, adjustsaveinterval_with_filled_cache);
+ //tcase_add_test(tc_daemon, filldatabaselist_does_not_exit_with_empty_database_dir);
+ //tcase_add_test(tc_daemon, filldatabaselist_adds_databases);
+ //tcase_add_test(tc_daemon, adjustsaveinterval_with_empty_cache);
+ //tcase_add_test(tc_daemon, adjustsaveinterval_with_filled_cache);
tcase_add_test(tc_daemon, checkdbsaveneed_has_no_need);
tcase_add_test(tc_daemon, checkdbsaveneed_is_forced);
tcase_add_test(tc_daemon, checkdbsaveneed_needs);
- tcase_add_test(tc_daemon, datalist_cacheget_with_no_database);
- tcase_add_test(tc_daemon, datalist_cacheget_with_database);
- tcase_add_test(tc_daemon, datalist_getifinfo_with_disabled_interface);
- tcase_add_test(tc_daemon, datalist_getifinfo_with_enabled_unavailable_interface);
- tcase_add_test(tc_daemon, datalist_getifinfo_with_interface_sync);
- tcase_add_test(tc_daemon, datalist_getifinfo_with_interface_and_no_sync);
- tcase_add_test(tc_daemon, datalist_timevalidation_in_normal_time);
- tcase_add_test(tc_daemon, datalist_timevalidation_in_future_time);
- tcase_add_exit_test(tc_daemon, datalist_timevalidation_in_too_future_time, 1);
- tcase_add_test(tc_daemon, datalist_writedb_does_not_save_unless_requested);
- tcase_add_test(tc_daemon, datalist_writedb_detects_missing_database_file);
- tcase_add_test(tc_daemon, datalist_writedb_writes_database_file);
- tcase_add_test(tc_daemon, processdatalist_empty_does_nothing);
- tcase_add_test(tc_daemon, processdatalist_filled_does_things);
+ tcase_add_test(tc_daemon, processdatacache_empty_does_nothing);
tcase_add_test(tc_daemon, handleintsignals_handles_signals);
tcase_add_test(tc_daemon, preparedirs_with_no_dir);
tcase_add_test(tc_daemon, preparedirs_with_dir);
+ tcase_add_test(tc_daemon, interfacechangecheck_with_no_interfaces);
+ tcase_add_test(tc_daemon, interfacechangecheck_with_empty_cache);
+ tcase_add_test(tc_daemon, interfacechangecheck_with_no_changes_in_iflist);
+ //tcase_add_test(tc_daemon, interfacechangecheck_with_filled_cache);
suite_add_tcase(s, tc_daemon);
}
-
-int cachegetname(const char *iface)
-{
- datanode *dn;
- dn = dataptr;
-
- while (dn != NULL) {
- if (strcmp(dn->data.interface, iface) == 0) {
- memcpy(&data, &dn->data, sizeof(data));
- return 1;
- }
- dn = dn->next;
- }
- return 0;
-}
#define DAEMON_TESTS_H
void add_daemon_tests(Suite *s);
-int cachegetname(const char *iface);
#endif
#include "common.h"
#include "ifinfo.h"
#include "dbaccess.h"
-#include "dbcache.h"
#include "dbshow.h"
#include "dbxml.h"
#include "dbjson.h"
}
END_TEST
-START_TEST(dbcheck_with_no_interfaces)
-{
- int forcesave = 0;
-
- linuxonly;
-
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- ck_assert_int_eq(dbcheck(0, &forcesave), 0);
- ck_assert_int_eq(forcesave, 0);
-}
-END_TEST
-
-START_TEST(dbcheck_with_empty_cache)
-{
- int forcesave = 0;
-
- linuxonly;
-
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- fake_proc_net_dev("w", "ethsomething", 1, 2, 3, 4);
- fake_proc_net_dev("a", "ethelse", 5, 6, 7, 8);
-
- ck_assert_int_ne(dbcheck(0, &forcesave), 0);
- ck_assert_int_eq(forcesave, 0);
-}
-END_TEST
-
-START_TEST(dbcheck_with_no_changes_in_iflist)
-{
- int forcesave = 0;
- uint32_t ifhash;
- char *ifacelist;
-
- linuxonly;
-
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
- fake_proc_net_dev("w", "ethsomething", 1, 2, 3, 4);
- fake_proc_net_dev("a", "ethelse", 5, 6, 7, 8);
- ck_assert_int_ne(getiflist(&ifacelist, 0), 0);
- ifhash = simplehash(ifacelist, (int)strlen(ifacelist));
-
- ck_assert_int_eq(dbcheck(ifhash, &forcesave), ifhash);
- ck_assert_int_eq(forcesave, 0);
-}
-END_TEST
-
-START_TEST(dbcheck_with_filled_cache)
-{
- int forcesave = 0;
-
- linuxonly;
-
- initdb();
- defaultcfg();
- disable_logprints();
- ck_assert_int_eq(remove_directory(TESTDIR), 1);
-
- ck_assert_int_eq(cachecount(), 0);
- strcpy(data.interface, "ethbasic");
- ck_assert_int_eq(cacheupdate(), 1);
- strcpy(data.interface, "ethactive");
- ck_assert_int_eq(cacheupdate(), 1);
- strcpy(data.interface, "ethnotactive");
- data.active = 0;
- ck_assert_int_eq(cacheupdate(), 1);
- ck_assert_int_eq(cachecount(), 3);
- ck_assert_int_eq(cacheactivecount(), 2);
-
- fake_proc_net_dev("w", "ethbasic", 1, 2, 3, 4);
- fake_proc_net_dev("a", "ethnotactive", 5, 6, 7, 8);
-
- ck_assert_int_ne(dbcheck(0, &forcesave), 0);
- ck_assert_int_eq(forcesave, 1);
-}
-END_TEST
-
START_TEST(importdb_can_parse_exported_database)
{
int i;
tcase_add_test(tc_db, validatedb_with_initdb);
tcase_add_test(tc_db, validatedb_with_invalid_totals);
tcase_add_test(tc_db, validatedb_with_top10_use);
- tcase_add_test(tc_db, dbcheck_with_no_interfaces);
- tcase_add_test(tc_db, dbcheck_with_empty_cache);
- tcase_add_test(tc_db, dbcheck_with_no_changes_in_iflist);
- tcase_add_test(tc_db, dbcheck_with_filled_cache);
tcase_add_test(tc_db, importdb_can_parse_exported_database);
tcase_add_test(tc_db, database_outputs_do_not_crash);
tcase_add_test(tc_db, showbar_with_zero_len_is_nothing);
#include "config_tests.h"
//#include "ifinfo_tests.h"
//#include "misc_tests.h"
-//#include "daemon_tests.h"
+#include "daemon_tests.h"
#include "datacache_tests.h"
#include "fs_tests.h"
#include "id_tests.h"
add_config_tests(s);
//add_ifinfo_tests(s);
//add_misc_tests(s);
- //add_daemon_tests(s);
+ add_daemon_tests(s);
add_datacache_tests(s);
add_fs_tests(s);
add_id_tests(s);