src/expire.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- getFreeFS
- expire_arts
- expire
/* $Id: expire.c,v 1.2 1998/08/02 20:34:59 proff Exp $
* $Copyright$
*/
#include "nglobal.h"
#include "filesystem.h"
#include "history.h"
#include "expire.h"
static bool getFreeFS (long *ffree, long *bfree)
/* [<][>][^][v][top][bottom][index][help] */
{
#ifdef HAVE_STATVFS
struct statvfs fs;
if (statvfs (".", &fs) < 0)
#else
#ifdef HAVE_STATFS
struct statfs fs;
if (statfs (".", &fs) < 0)
#else
#error no statfs type for this file system
#endif
#endif
{
loge (("unable to statfs() filesystem holding %s", con->cacheDir));
return FALSE;
}
*ffree = fs.f_ffree;
*bfree = fs.f_bavail;
return TRUE;
}
static time_t ti, OldestArt;
/*
* this routine is fast. also does xover db's
*/
static int expire_arts (char *group, int depth)
/* [<][>][^][v][top][bottom][index][help] */
{
DIR *dir;
struct dirent *d;
struct stat st;
int hi = 0, lo = 0, artnum;
struct newsgroup *n;
#if 0
bool mark = FALSE;
int low=1; /* TODO fix me */
#endif
if (!(dir = opendir (".")))
return -1;
settaskinfo("expiring");
while ((d = readdir (dir)))
{
char *p;
p = d->d_name;
if (!p || !*p || *p == '.')
continue;
#if 0
if ((*p >= '0' && *p <= '9') && mark)
{
char *p2 = strstr (p, "_xover");
if (p2)
*p2 = '\0';
if ((artnum = strToi (p)))
{
if (artnum < ((p2) ? low - XOVER_INDEX_SIZE : low))
{
if (p2)
{
*p2 = '_';
unlink (p);
Stats->expire_xovers++;
} else
{
unlink (p);
Stats->expire_articles++;
}
}
continue;
}
}
#endif
if (lstat (p, &st) == -1)
continue;
if ((*p >= '0' && *p <= '9') && S_ISREG (st.st_mode))
{
time_t t = (st.st_mtime > st.st_atime) ? st.st_mtime : st.st_atime;
if (t < OldestArt)
{
if (strstr (p, "_xover"))
{
if (unlink (p) == 0)
Stats->xoversExpired++;
} else
{
if (unlink (p) == 0)
Stats->articlesExpired++;
}
} else if (!strstr (p, "_xover"))
{
artnum = strToi(p);
if (!lo || artnum < lo)
lo = artnum;
if (artnum > hi)
hi = artnum;
}
continue;
}
if (S_ISDIR (st.st_mode))
{
char *newgroup = NULL;
if (chdir (p) < 0)
continue;
if (depth == 1)
newgroup = Sstrdup(p);
else if (depth > 1)
{
newgroup = Smalloc (strlen(group) + strlen(p) + 2);
sprintf (newgroup, "%s.%s", group, p);
}
if (!expire_arts (newgroup, depth + 1))
{
if (newgroup)
free(newgroup);
return FALSE;
}
if (newgroup)
free(newgroup);
if (chdir ("..") < 0) /* I'm stuck in a klien bottle! */
return FALSE;
rmdir (p);
}
}
if (depth > 1 && (n = newsgroup_find_add(group, NULL, TRUE)))
{
n->hi = hi;
n->lo = lo;
newsgroupUnlockWrite(n);
}
closedir (dir);
return TRUE;
}
EXPORT int volatile ExpireDaemonPid;
EXPORT bool expire (bool force)
/* [<][>][^][v][top][bottom][index][help] */
{
static time_t last_expire;
long ffree = 0, bfree = 0;
if (!force && time (NULL) < last_expire + con->expireCheckPeriod)
return TRUE;
last_expire = time (NULL);
if (!force)
getFreeFS (&ffree, &bfree);
if (!(force || bfree < con->minBlocksFree || ffree < con->minFilesFree))
return FALSE;
ti = time (NULL);
OldestArt = ti - con->maxArtAge;
if (Task->ti_state == nc_master)
{
if (!ExpireDaemonPid)
{
int pid;
sigset_t myset;
sigemptyset(&myset);
sigaddset(&myset, SIGCHLD);
sigprocmask (SIG_BLOCK, &myset, NULL);
pid = make_vm_proc (nc_expire, -1, "expire");
if (pid == 0)
{
sigprocmask (SIG_UNBLOCK, &myset, NULL);
if (chdir (con->cacheDir)==0)
{
expire_arts (NULL, 0);
retire_vm_proc (0);
}
else
{
loge (("couldn't chdir(\"%s\") for expire", con->cacheDir));
retire_vm_proc (1);
}
NOTREACHED;
}
if (pid > 0)
{
ExpireDaemonPid = pid;
sigprocmask (SIG_UNBLOCK, &myset, NULL);
}
}
}
else
{
if (chdir (con->cacheDir) == 0)
expire_arts (NULL, 0);
else
loge (("couldn't chdir(\"%s\") for expire", con->cacheDir));
}
chdir (con->cacheDir);
hisPrune ();
return TRUE;
}