Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

NewsCacheClean.cc File Reference

#include "config.h"
#include <string.h>
#include <getopt.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <algorithm>
#include "Debug.h"
#include "setugid.h"
#include "Config.h"
#include "Logger.h"
#include "NServer.h"

Go to the source code of this file.

Classes

class  Entry
struct  cache_statistic

Defines

#define PACKAGE   PACKAGE_NEWSCACHECLEAN
#define MAX(a, b)   (((a)>(b))?(a):(b))
#define FILE_ACCESS_TABLE_ENTRIES   100000
#define USAGE

Functions

bool sort_entries (const Entry *l, const Entry *r)
void clean (const char *cpath)
void remove_elements (long max_blocks, struct cache_statistic *pS)
int main (int argc, char **argv)

Variables

Logger slog
const char * cmnd
Config Cfg
vector< Entry * > pvector
long _blocks = 0


Define Documentation

#define FILE_ACCESS_TABLE_ENTRIES   100000
 

Definition at line 67 of file NewsCacheClean.cc.

#define MAX a,
 )     (((a)>(b))?(a):(b))
 

Definition at line 66 of file NewsCacheClean.cc.

#define PACKAGE   PACKAGE_NEWSCACHECLEAN
 

Definition at line 63 of file NewsCacheClean.cc.

Referenced by main(), nnrpd(), and ns_mode().

#define USAGE
 

Value:

"       -h, --help\n"\
"              Show summary of options.\n"\
"\n"\
"       -v, --version\n"\
"              Show version of program.\n"\
"\n"\
"       -c --configuration config-file\n"\
"\n"\
"       -s --statistic\n"\
"              Show statistic informations.\n"\
"\n"\
"       -p --print-purgetable\n"\
"              Print the sorted purge table.\n"\
"\n"\
"       -t --try\n"\
"              Try, not really removing files.\n"\

Definition at line 320 of file NewsCacheClean.cc.


Function Documentation

void clean const char *  cpath  ) 
 

Definition at line 205 of file NewsCacheClean.cc.

References _blocks, Cfg, Logger::Error, NVNewsgroup::firstnbr(), NVNewsgroup::lastnbr(), MAX, NC_CATCH_ALL, Logger::p(), pvector, slog, Config::SpoolDirectory, and VERB.

Referenced by main().

00206 {
00207         VERB(slog.p(Logger::Debug) << "clean(" << cpath << ")\n");
00208         DIR *d;
00209         time_t dbatime;
00210         char buf[MAXPATHLEN];
00211 
00212         struct dirent *f;
00213         struct stat s;
00214 
00215         sprintf(buf, "%s/.db", cpath);
00216         // Exception Directories
00217         if (strcmp(buf, "./.artSpool") == 0)
00218                 return;
00219         if (strcmp(buf, "./.badArticles") == 0)
00220                 return;
00221         if (stat(buf, &s) == 0) {
00222                 dbatime = MAX(s.st_atime, s.st_mtime);
00223                 pvector.push_back( new Entry (buf, dbatime, s.st_blocks) );
00224                 _blocks += s.st_blocks;
00225                 --dbatime;
00226         } else {
00227                 dbatime = 0;
00228         }
00229 
00230         if ((d = opendir(cpath)) == NULL) {
00231                 slog.p(Logger::Error) << "cannot open " << cpath << "\n";
00232                 return;
00233         }
00234         while ((f = readdir(d)) != NULL) {
00235                 if (strcmp(f->d_name, ".") == 0)
00236                         continue;
00237                 if (strcmp(f->d_name, "..") == 0)
00238                         continue;
00239                 sprintf(buf, "%s/%s", cpath, f->d_name);
00240                 if (stat(buf, &s) == 0) {
00241                         if (S_ISDIR(s.st_mode))
00242                                 clean(buf);
00243                 } else {
00244                         slog.
00245                             p(Logger::
00246                               Error) << "cannot stat " << buf << "\n";
00247                 }
00248         }
00249         closedir(d);
00250 
00251         if ((d = opendir(cpath)) == NULL) {
00252                 slog.p(Logger::Error) << "cannot reopen " << cpath << "\n";
00253                 return;
00254         }
00255         string ngname (cpath);
00256         // ./be/comp/os/unix -> be.comp.os.unix
00257         ngname.replace (0, 2, "");
00258         int i;
00259         while ((i=ngname.find ("/")) != -1) {
00260                 ngname[i] = '.';
00261         }
00262         NVNewsgroup *ng;
00263         OverviewFmt *fmt = new OverviewFmt ();
00264         int firstnr;
00265         int lastnr;
00266         try {
00267                 string dbname = cpath;
00268                 dbname += "/.db";
00269                 struct stat s;
00270                 if (stat (dbname.c_str(), &s) == 0) {
00271                         ng = new NVNewsgroup (fmt,
00272                                 (const char *) Cfg.SpoolDirectory,
00273                                 ngname.c_str());
00274                 } else {
00275                         ng = NULL;
00276                 }
00277         } catch (NoSuchGroupError e) {
00278                 ng = NULL;
00279         }
00280         NC_CATCH_ALL ("Error, please report bug!");
00281         if (ng != NULL) {
00282                 firstnr = ng->firstnbr ();
00283                 lastnr = ng->lastnbr ();
00284                 delete ng;
00285         }
00286         string art;
00287         int nr;
00288         while ((f = readdir(d)) != NULL) {
00289                 sprintf(buf, "%s/%s", cpath, f->d_name);
00290                 if (stat(buf, &s) == 0) {
00291                         if (S_ISREG(s.st_mode) && dbatime != 0 &&
00292                             strncmp(f->d_name, ".art", 4) == 0) {
00293                                 time_t at = MAX(s.st_atime, s.st_mtime);
00294                                 if (dbatime <= at)
00295                                         at = dbatime;
00296                                 art = f->d_name;
00297                                 art.replace (0,4, "");
00298                                 if (sscanf (art.c_str(), "%d", &nr) != 1) {
00299                                         slog.p(Logger::Error) << "error "
00300                                                 << "parsing " << f->d_name;
00301                                 } else if ( ng == NULL | nr < firstnr || nr > lastnr) {
00302                                         at = 0;
00303                                 }
00304                                 pvector.push_back (new Entry(buf, at, 
00305                                         s.st_blocks) );
00306                                 _blocks += s.st_blocks;
00307                         }
00308                 } else {
00309                         slog.
00310                             p(Logger::
00311                               Error) << "cannot stat " << buf << "\n";
00312                 }
00313         }
00314         closedir(d);
00315         return;
00316 }

int main int  argc,
char **  argv
 

Definition at line 339 of file NewsCacheClean.cc.

References _blocks, Cfg, clean(), cmnd, Config::Groupname, Config::LogDirectory, Config::NiceServer, Logger::open(), Logger::p(), PACKAGE, pvector, Config::read(), remove_elements(), setugid(), slog, sort_entries(), Config::SpoolDirectory, Config::SpoolSize, USAGE, and Config::Username.

00340 {
00341 #ifndef WITH_SYSLOG
00342         char logfile[MAXPATHLEN];
00343         time_t t;
00344         pid_t p;
00345 #endif
00346         char conffile[MAXPATHLEN];
00347         int opt_config = 0;
00348         int c, aerr = 0;
00349         struct cache_statistic Stat;
00350         int nice;
00351         int stat=0;
00352         int try_flag = 0;
00353         char p_flag=0;
00354         vector<Entry *>::iterator begin, end;
00355 
00356         memset ((void *) &Stat, 0, sizeof (struct cache_statistic));
00357 
00358         sprintf(conffile, "%s/newscache.conf", SYSCONFDIR);
00359 
00360         cmnd = argv[0];
00361         while (1) {
00362                 int option_index = 0;
00363                 static struct option long_options[] = {
00364                         {"version", 0, 0, 'v'},
00365                         {"help", 0, 0, 'h'},
00366                         {"configuration", 1, 0, 'c'},
00367                         {"statistic", 0, 0, 's'},
00368                         {"try", 0, 0, 't'},
00369                         {"print-purgetable", 0, 0, 'p'},
00370                         {0, 0, 0, 0}
00371                 };
00372 
00373                 c = getopt_long (argc, argv, "vhc:stp", long_options,
00374                                 &option_index);
00375 
00376                 if (c == -1)
00377                         break;
00378 
00379                 switch (c) {
00380                         case 'v':
00381                                 cout << PACKAGE << " " << VERSION << endl;
00382                                 exit (0);
00383                                 break;
00384 
00385                         case 'h':
00386                                 cout << "Usage: " << cmnd << endl;
00387                                 cout << USAGE << endl;
00388                                 exit (0);
00389                                 break;
00390 
00391                         case 'c':
00392                                 strcpy (conffile, optarg);
00393                                 ++opt_config;
00394                                 break;
00395 
00396                         case 's':
00397                                 stat = 1;
00398                                 break;
00399 
00400                         case 't':
00401                                 try_flag = 1;
00402                                 break;
00403                         
00404                         case 'p':
00405                                 p_flag = 1;
00406                                 break;
00407 
00408                         default:
00409                                 aerr = 1;
00410                                 break;
00411                 }
00412         }
00413 
00414         if (aerr || optind != argc) {
00415                 cerr << "Usage: " << cmnd << " [options]\n" << USAGE;
00416                 exit(1);
00417         }
00418 
00419         try {
00420                 Cfg.read(conffile);
00421 //    strcpy(nntp_hostname,Cfg.Hostname);
00422         }
00423         catch(IOError & io) {
00424                 cerr << "unexpected EOF in " << conffile << "\n";
00425                 exit(2);
00426         }
00427         catch(SyntaxError & se) {
00428                 cerr << se._errtext << "\n";
00429                 exit(2);
00430         }
00431 
00432 #ifdef WITH_SYSLOG
00433         slog.open(PACKAGE, LOG_NDELAY | LOG_PID, LOG_NEWS);
00434 #else
00435         sprintf (logfile, "%s/newscache_newscacheclean.log", Cfg.LogDirectory);
00436         slog.open (logfile);
00437 #endif
00438         slog.p(Logger::Info) << "cleaning spool directory\n";
00439 
00440 
00441         /* set nice value for master server */
00442 #ifdef HAVE_SETPRIORITY
00443         errno = 0;
00444         nice = Cfg.NiceServer;
00445         nice += getpriority(PRIO_PROCESS, 0);
00446         if (nice == -1 && errno != 0) {
00447                 slog.
00448                     p(Logger::
00449                       Error) << "getpriority failed: " << strerror(errno)
00450                     << "\n";
00451         } else {
00452                 if (setpriority(PRIO_PROCESS, 0, nice) == -1)
00453                         slog.
00454                             p(Logger::
00455                               Error) << "setpriority failed: " <<
00456                             strerror(errno) << "\n";
00457         }
00458 #endif
00459 
00460         if (chdir(Cfg.SpoolDirectory) < 0) {
00461                 slog.
00462                     p(Logger::
00463                       Error) <<
00464                     "cannot change to spool directory -- exiting\n";
00465                 exit(1);
00466         }
00467         if (getuid() == CONF_UIDROOT)
00468                 setugid(Cfg.Username, Cfg.Groupname);
00469         clean(".");
00470         sort (pvector.begin(), pvector.end(), sort_entries);
00471         if (p_flag) {
00472                 cout << "---------------- Purge table ----------------" << endl;
00473                 for (begin=pvector.begin(), end=pvector.end();
00474                      begin != end; begin++) {
00475                         (*begin)->print (cout);
00476                 }
00477                 cout << "---------------- Purge table ----------------" << endl;
00478         }
00479         if (!try_flag) {
00480                 remove_elements(Cfg.SpoolSize * 2, &Stat);
00481         }
00482         if (stat) {
00483                 print_statistic(cout, &Stat);
00484         }
00485 
00486         slog.p(Logger::Info) << "|SpoolDirectory|="
00487             << (unsigned int) (_blocks / 2) << "K\n";
00488         return 0;
00489 }

void remove_elements long  max_blocks,
struct cache_statistic pS
 

Definition at line 144 of file NewsCacheClean.cc.

References _blocks, Logger::Error, Logger::p(), pvector, slog, cache_statistic::stArtCnt, cache_statistic::stArtSize, cache_statistic::stDbCnt, cache_statistic::stDbSize, cache_statistic::stOutArtCnt, cache_statistic::stOutArtSize, cache_statistic::stPurgedArtCnt, cache_statistic::stPurgedArtSize, cache_statistic::stPurgedDbCnt, cache_statistic::stPurgedDbSize, cache_statistic::stPurgedDirCnt, cache_statistic::stPurgedOutArtCnt, and cache_statistic::stPurgedOutArtSize.

Referenced by main().

00145 {
00146         int isDb;
00147         char cBuffer[MAXPATHLEN];
00148         vector<Entry *>::iterator begin, end;
00149 
00150         for (begin=pvector.begin(), end=pvector.end();
00151              begin != end; begin++) {
00152                 (*begin)->Path.length();
00153                 if (strcmp((*begin)->Path.c_str() + (*begin)->Path.length() - 3, ".db") == 0) {
00154                         isDb = 1;
00155                         pS->stDbCnt++;
00156                         pS->stDbSize += (*begin)->blocks;
00157                 } else {
00158                         isDb = 0;
00159                         if ((*begin)->atime != 0) {
00160                                 pS->stArtCnt++;
00161                                 pS->stArtSize += (*begin)->blocks;
00162                         } else {
00163                                 pS->stOutArtCnt++;
00164                                 pS->stOutArtSize += (*begin)->blocks;
00165                         }
00166                 }
00167                 if ((*begin)->atime != 0 && _blocks <= max_blocks)
00168                         continue;
00169                 if (unlink((*begin)->Path.c_str()) == 0) {
00170                         _blocks -= (*begin)->blocks;
00171                         if (!isDb) {
00172                                 if ((*begin)->atime != 0) {
00173                                         pS->stPurgedArtCnt++;
00174                                         pS->stPurgedArtSize += (*begin)->blocks;
00175                                 } else {
00176                                         pS->stPurgedOutArtCnt++;
00177                                         pS->stPurgedOutArtSize += (*begin)->blocks;
00178                                 }
00179                         } else {
00180                                 pS->stPurgedDbCnt++;
00181                                 pS->stPurgedDbSize += (*begin)->blocks;
00182                                 strcpy(cBuffer, (*begin)->Path.c_str());
00183                                 cBuffer[strlen(cBuffer) - 3] = '\0';
00184                                 if (rmdir(cBuffer) == 0) {
00185                                         pS->stPurgedDirCnt++;
00186                                 } else if (errno == ENOTEMPTY) {
00187                                         slog.p(Logger::Debug) 
00188                                                 << "Error rmdir "
00189                                                 << "(Directory not empty) "
00190                                                 << (*begin)->Path << "\n";
00191                                 } else {
00192                                         slog.p(Logger::Error) 
00193                                                 << "Error rmdir "
00194                                                 << (*begin)->Path << "\n";
00195                                 }
00196                         }
00197                 } else {
00198                         slog.
00199                             p(Logger::
00200                               Error) << "Error unlink " << (*begin)->Path << "\n";
00201                 }
00202         }
00203 }

bool sort_entries const Entry l,
const Entry r
 

Definition at line 135 of file NewsCacheClean.cc.

References Entry::atime.

Referenced by main().

00136 {
00137         if (l->atime < r->atime)
00138                 return 1;
00139         else
00140                 return 0;
00141 }


Variable Documentation

long _blocks = 0
 

Definition at line 111 of file NewsCacheClean.cc.

Referenced by clean(), main(), and remove_elements().

Config Cfg
 

Definition at line 71 of file NewsCacheClean.cc.

const char* cmnd
 

Definition at line 70 of file NewsCacheClean.cc.

vector<Entry*> pvector
 

Definition at line 88 of file NewsCacheClean.cc.

Referenced by clean(), main(), and remove_elements().

Logger slog
 

Definition at line 69 of file NewsCacheClean.cc.


Generated on Fri Aug 20 10:58:09 2004 for NewsCache by doxygen 1.3.6-20040222