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

NVNewsgroup.cc

Go to the documentation of this file.
00001 #include<ctype.h>
00002 #include<sys/stat.h>
00003 #include<sys/types.h>
00004 #include<stdio.h>
00005 #include<utime.h>
00006 #include<unistd.h>
00007 
00008 #include"Logger.h"
00009 #include"Error.h"
00010 #include"NVNewsgroup.h"
00011 
00012 using namespace std;
00013 
00014 /* Structure of a record of the NVArray
00015  * 4 Bytes ... Size of record (s)
00016  * s Bytes ... The record itself
00017  *
00018  * Structure of a record
00019  * 1 Byte ... Type of information (overview,article,bigarticle)
00020  * n Bytes ... Article/Overviewrecord, including trailing \0
00021  */
00022 
00023 #ifdef ENABLE_ASSERTIONS
00024 void NVNewsgroup::testdb(void)
00025 {
00026         //  VERB(slog.p(Logger::Debug) << "NVNewsgroup::testdb()\n"); 
00027         char *data;
00028         size_t szdata;
00029         unsigned long f, i, l;
00030 //   Article *art=NULL;
00031         int corr = 0;
00032 
00033         NVArray::lock(NVcontainer::ShrdLock);
00034         NVArray::getsize(&f, &l);
00035         for (i = f; i <= l; i++) {
00036                 NVArray::sget(i, &data, &szdata);
00037                 if (data && *data != overview && *data != article
00038                     && *data != bigarticle) {
00039                         corr++;
00040                 }
00041         }
00042         if (corr) {
00043                 slog.
00044                     p(Logger::
00045                       Alert) << "NVNewsgroup::testdb: Oops, " << corr <<
00046                     " errors found in database!\n";
00047         }
00048         NVArray::lock(NVcontainer::UnLock);
00049 }
00050 #endif
00051 
00052 void NVNewsgroup::sprintover(ostream & os, unsigned int nbr)
00053 {
00054         char *data;
00055         size_t szdata;
00056         unsigned long f, l;
00057         string over;
00058 
00059         NVArray::getsize(&f, &l);
00060         if (f <= nbr && nbr <= l) {
00061                 NVArray::sget(nbr, &data, &szdata);
00062                 if (data) {
00063                         if (*data == article) {
00064                                 Article *art;
00065                                 //FIX! This is inefficient!
00066                                 //FIX! The article is copied and all the overview data is copied 
00067                                 //FIX! again. We should allow Articles to use externally provided 
00068                                 //FIX! memory (eg. memory from the NVNewsgroup).
00069                                 // szdata ... Size of article+1 including the trailing \0
00070                                 art =
00071                                     new Article(nbr, data + sizeof(char),
00072                                                 szdata - sizeof(char) - 1);
00073                                 _OverviewFormat->convert(*art, over);
00074                                 os << over << "\r\n";
00075                                 delete art;
00076                         } else if (*data == bigarticle
00077                                    || *data == overview) {
00078                                 os << data + sizeof(char) << "\r\n";
00079                         } else {
00080                                 // Oops, inconsistent
00081                                 VERB(slog.
00082                                      p(Logger::
00083                                        Alert) <<
00084                                      "NVN::sprintover(...): inconsistent newsgroup database!\n");
00085                         }
00086                 }
00087         }
00088 }
00089 
00090 void NVNewsgroup::setsize(unsigned int f, unsigned int l)
00091 {
00092         VERB(slog.
00093              p(Logger::
00094                Debug) << "NVNewsgroup::setsize(" << f << "," << l <<
00095              ")\n");
00096         char fn[MAXPATHLEN];
00097         long n1, n2, i;
00098 
00099         lock(NVcontainer::ShrdLock);
00100         if (f != arrfst || l != arrlst) {
00101                 lock(NVcontainer::ExclLock);
00102                 if (arrfst <= arrlst) {
00103                         // free all those elements from arrfst -> f
00104                         i = 0;
00105                         n1 = f - arrfst;
00106                         n2 = arrlst - arrfst + 1;
00107                         if (n2 < n1)
00108                                 n1 = n2;
00109                         while ((long) i < n1) {
00110                                 if (arrtab[i]) {
00111                                         if (*
00112                                             (mem_p + arrtab[i] +
00113                                              sizeof(long)) == bigarticle) {
00114                                                 // Remove article from disk
00115                                                 sprintf(fn, "%s/.art%lu",
00116                                                         _SpoolDirectory,
00117                                                         arrfst + i);
00118                                                 unlink(fn);
00119                                         }
00120                                         nvfree(arrtab[i]);
00121                                 }
00122                                 i++;
00123                         }
00124 
00125                         // free all those elements from l -> arrlst
00126                         i = l - arrfst + 1;
00127                         if (i < 0)
00128                                 i = 0;
00129                         n1 = arrlst - arrfst + 1;
00130                         while ((long) i < n1) {
00131                                 if (arrtab[i]) {
00132                                         if (*
00133                                             (mem_p + arrtab[i] +
00134                                              sizeof(long)) == bigarticle) {
00135                                                 // Remove article from disk
00136                                                 sprintf(fn, "%s/.art%lu",
00137                                                         _SpoolDirectory,
00138                                                         arrfst + i);
00139                                                 unlink(fn);
00140                                         }
00141                                         nvfree(arrtab[i]);
00142                                 }
00143                                 i++;
00144                         }
00145                 }
00146                 // resize array
00147                 NVArray::ssetsize(f, l);
00148                 lock(NVcontainer::UnLock);
00149         }
00150         lock(NVcontainer::UnLock);
00151 }
00152 
00153 Article *NVNewsgroup::getarticle(unsigned int nbr)
00154 {
00155         VERB(slog.
00156              p(Logger::
00157                Debug) << "NVNewsgroup::getarticle(" << nbr << ")\n");
00158         char *data;
00159         size_t szdata;
00160         unsigned long f, l;
00161         Article *art = NULL;
00162 
00163         NVArray::lock(NVcontainer::ShrdLock);
00164         NVArray::getsize(&f, &l);
00165         if (nbr >= f && nbr <= l) {
00166                 NVArray::sget(nbr, &data, &szdata);
00167                 if (data) {
00168                         if (*data == article) {
00169                                 // szdata ... Size of article including type and the trailing \0
00170                                 art =
00171                                     new Article(nbr, data + sizeof(char),
00172                                                 szdata - sizeof(char) - 1);
00173                         } else if (*data == bigarticle) {
00174                                 char fn[MAXPATHLEN];
00175                                 ifstream fs;
00176                                 sprintf(fn, "%s/.art%u", _SpoolDirectory,
00177                                         nbr);
00178                                 fs.open(fn);
00179                                 if (!fs.good() && errno == ENOENT) {
00180                                         if ((art =
00181                                              retrievearticle(nbr)) != NULL)
00182                                                 setarticle(art);
00183                                 } else {
00184                                         art = new Article(nbr);
00185                                         art->read(fs);
00186                                 }
00187                                 fs.close();
00188                         } else {
00189                                 // Article not available
00190                                 if ((art = retrievearticle(nbr)) != NULL)
00191                                         setarticle(art);
00192                         }
00193                 } else {
00194                         // Article not available
00195                         if ((art = retrievearticle(nbr)) != NULL)
00196                                 setarticle(art);
00197                 }
00198         }
00199         NVArray::lock(NVcontainer::UnLock);
00200         return art;
00201 }
00202 
00203 void NVNewsgroup::setarticle(Article * art)
00204 {
00205         unsigned long f, l;
00206         unsigned int nbr;
00207 
00208         VERB(char buf[1024];
00209              sprintf(buf, "NVNewsgroup::setarticle(*art(nbr=%d))\n",
00210                      art->getnbr()); slog.p(Logger::Debug) << buf);
00211         ASSERT2(testdb());
00212 
00213         nbr = art->getnbr();
00214         NVArray::lock(NVcontainer::ExclLock);
00215         NVArray::getsize(&f, &l);
00216         if (f <= nbr && nbr <= l) {
00217                 char *data;
00218                 size_t szdata;
00219                 unsigned long i;
00220 
00221                 i = nbr - arrfst;
00222                 NVArray::sget(nbr, &data, &szdata);
00223                 if (art->length() <= 15360) {
00224                         // Article smaller/equal 15k => Store article in NewsgroupDB
00225                         nvoff_t x;
00226                         if (data) {
00227                                 nvfree(arrtab[i]);
00228                         }
00229                         szdata = art->length() + 1 + sizeof(char);
00230                         x = nvalloc(szdata + sizeof(unsigned long));
00231                         arrtab[i] = x;
00232                         data = mem_p + x;
00233                         *((unsigned long *) data) = szdata;
00234                         data += sizeof(unsigned long);
00235                         *data = article;
00236 //       VERB(sprintf(buf,"NVN::setarticle: Before memcpy arrtab=%p data=%p\n",arrtab,data);
00237 //         slog.p(Logger::Debug) << buf);
00238                         ASSERT2(testdb());
00239                         memcpy(data + sizeof(char), art->c_str(),
00240                                art->length() + 1);
00241                 } else if (art->length() > 15360) {
00242                         // Article bigger 15k => Store externally
00243                         if (data && *data != overview
00244                             && *data != bigarticle) {
00245                                 nvfree(arrtab[i]);
00246                                 data = NULL;
00247                         }
00248                         if (!data) {
00249                                 string over;
00250                                 nvoff_t x;
00251                                 _OverviewFormat->convert(*art, over);
00252                                 szdata = over.length() + 1 + sizeof(char);
00253                                 x = nvalloc(szdata +
00254                                             sizeof(unsigned long));
00255                                 arrtab[i] = x;
00256                                 data = mem_p + x;
00257                                 *((unsigned long *) (data)) = szdata;
00258                                 data += sizeof(unsigned long);
00259                                 memcpy(data + sizeof(char), over.c_str(),
00260                                        over.length() + 1);
00261                         }
00262                         *data = bigarticle;
00263                         char fn[MAXPATHLEN];
00264                         ofstream fs;
00265                         sprintf(fn, "%s/.art%u", _SpoolDirectory, nbr);
00266                         fs.open(fn);
00267                         fs << *art;
00268                         fs.close();
00269                         *data = bigarticle;
00270                 } else {
00271                         VERB(slog.
00272                              p(Logger::
00273                                Debug) <<
00274                              "NVNewsgroup::setarticle: Tried to store an existing article\n");
00275                 }
00276         }                       /* if(f<=nbr<=l) */
00277         lock(NVcontainer::UnLock);
00278         ASSERT2(testdb());
00279 }
00280 
00281 void NVNewsgroup::printarticle(ostream & os, unsigned int nbr)
00282 {
00283         char *data;
00284         size_t szdata;
00285         unsigned long f, l;
00286 
00287         NVArray::lock(NVcontainer::ShrdLock);
00288         NVArray::getsize(&f, &l);
00289         if (nbr >= f && nbr <= l) {
00290                 NVArray::sget(nbr, &data, &szdata);
00291                 if (data) {
00292                         if (*data == article) {
00293                                 os << data + sizeof(char);
00294                         } else if (*data == bigarticle) {
00295                                 Article art(nbr);
00296                                 char fn[MAXPATHLEN];
00297                                 ifstream fs;
00298                                 sprintf(fn, "%s/.art%u", _SpoolDirectory,
00299                                         nbr);
00300                                 fs.open(fn);
00301                                 art.read(fs);
00302                                 fs.close();
00303                                 os << art;
00304                         } else {
00305                                 // Article not available
00306                                 Article *art;
00307                                 if ((art = retrievearticle(nbr)) != NULL)
00308                                         setarticle(art);
00309                                 os << *art;
00310                                 delete art;
00311                         }
00312                 }
00313         }
00314         NVArray::lock(NVcontainer::UnLock);
00315 }
00316 
00317 //FIX! Possibly, we should throw an exception, if the overview record
00318 //FIX! cannot be found.
00319 const char *NVNewsgroup::getover(unsigned int nbr)
00320 {
00321         //  VERB(slog.p(Logger::Debug) << "NVNewsgroup::getover(over)\n"); 
00322 
00323         char *data;
00324         size_t szdata;
00325         unsigned long f, l;
00326         static string over;
00327 
00328         over = "";
00329         NVArray::lock(NVcontainer::ShrdLock);
00330         NVArray::getsize(&f, &l);
00331         if (f <= nbr && nbr <= l) {
00332                 NVArray::sget(nbr, &data, &szdata);
00333                 if (data) {
00334                         if (*data == article) {
00335                                 Article *art;
00336                                 //FIX! This is inefficient!
00337                                 //FIX! The article is copied and all the overview data is copied 
00338                                 //FIX! again. We should allow Articles to use externally provided 
00339                                 //FIX! memory (eg. memory from the NVNewsgroup).
00340                                 // szdata ... Size of article+1 including the trailing \0
00341                                 art =
00342                                     new Article(nbr, data + sizeof(char),
00343                                                 szdata - sizeof(char) - 1);
00344                                 _OverviewFormat->convert(*art, over);
00345                                 delete art;
00346                         } else if (*data == bigarticle
00347                                    || *data == overview) {
00348                                 over = data + sizeof(char);
00349                         } else {
00350                                 // Impossible
00351                                 VERB(slog.
00352                                      p(Logger::
00353                                        Critical) <<
00354                                      "NVNewsgroup::getover. Oops, reached ?dead? code 936!!!\n");
00355                         }
00356                 }
00357         }
00358         NVArray::lock(NVcontainer::UnLock);
00359         return over.c_str();
00360 }
00361 
00362 void NVNewsgroup::setover(const string & over)
00363 {
00364         //  VERB(slog.p(Logger::Notice) << "NVNewsgroup::setover(over)\n"); 
00365 
00366         unsigned long f, l, nbr;
00367 
00368         nbr = atoi((const char *) over.c_str());
00369         NVArray::lock(NVcontainer::ExclLock);
00370         NVArray::getsize(&f, &l);
00371         if (f <= nbr && nbr <= l) {
00372                 char *data;
00373                 size_t szdata;
00374                 unsigned long i;
00375 
00376                 i = nbr - arrfst;
00377                 NVArray::sget(nbr, &data, &szdata);
00378                 if (!data) {
00379                         szdata = over.length() + 1 + sizeof(char);
00380                         nvoff_t x =
00381                             nvalloc(szdata + sizeof(unsigned long));
00382                         arrtab[i] = x;
00383                         data = mem_p + x;
00384                         *((unsigned long *) (data)) = szdata;
00385                         data += sizeof(unsigned long);
00386                         memcpy(data + sizeof(char), over.c_str(),
00387                                over.length() + 1);
00388                         *data = overview;
00389                 }
00390         }
00391         NVArray::lock(NVcontainer::UnLock);
00392         ASSERT2(testdb());
00393 }
00394 
00395 void NVNewsgroup::readoverdb(istream & is)
00396 {
00397         VERB(slog.p(Logger::Debug) << "NVNewsgroup::readoverdb(&is)\n");
00398 
00399         string line1, line2;
00400         time_t now;
00401 
00402         lock(NVcontainer::ExclLock);
00403         for (;;) {
00404                 nlreadline(is, line1, 0);
00405                 if (line1 == "." || is.eof())
00406                         break;
00407                 if (_OverviewFormat->dotrans) {
00408                         // Convert Record
00409                         _OverviewFormat->convert(line1, line2);
00410                         setover(line2);
00411                 } else {
00412                         setover(line1);
00413                 }
00414         }
00415 
00416         time(&now);
00417         setmtime(now);
00418         lock(NVcontainer::UnLock);
00419 }
00420 
00421 void NVNewsgroup::printoverdb(ostream & os, unsigned int f, unsigned int l)
00422 {
00423         VERB(slog.p(Logger::Debug) << "NVNewsgroup::printoverdb(os,"
00424              << f << "," << l << ")\n");
00425         unsigned int i;
00426         lock(NVcontainer::ShrdLock);
00427         if (f < arrfst)
00428                 f = arrfst;
00429         if (arrlst < l)
00430                 l = arrlst;
00431         for (i = f; i <= l; i++)
00432                 sprintover(os, i);
00433         lock(NVcontainer::UnLock);
00434 }
00435 
00436 void NVNewsgroup::printheaderdb(ostream & os,
00437                                 const char *header,
00438                                 unsigned int f, unsigned int l)
00439 {
00440         char *data, xheader[512], *p;
00441         string fld;
00442         const char *q;
00443         size_t szdata;
00444         unsigned long gf, i, gl;
00445 
00446         p = xheader;
00447         q = header;
00448         while ((*p++ = *q++));
00449         *(p - 1) = ':';
00450         *p = '\0';
00451         NVArray::lock(NVcontainer::ShrdLock);
00452         NVArray::getsize(&gf, &gl);
00453         if (f < gf)
00454                 f = gf;
00455         if (l > gl)
00456                 l = gl;
00457         for (i = f; i <= l; i++) {
00458                 NVArray::sget(i, &data, &szdata);
00459                 if (data) {
00460                         if (*data == article) {
00461                                 Article *art;
00462                                 //FIX! This is inefficient!
00463                                 //FIX! The article is copied and all the overview data is copied 
00464                                 //FIX! again. We should allow Articles to use externally provided 
00465                                 //FIX! memory (eg. memory from the NVNewsgroup).
00466                                 // szdata ... Size of article including the trailing \0 plus
00467                                 //            1char (= InformationTag of NVNewsgroup)
00468                                 art =
00469                                     new Article(i, data + sizeof(char),
00470                                                 szdata - sizeof(char));
00471                                 try {
00472                                         fld = art->getfield(xheader, 0);
00473                                         os << i << " " << fld << "\r\n";
00474                                 } catch(NoSuchFieldError & nfe) {
00475                                         os << i << " (none)\r\n";
00476                                 }
00477                                 delete art;
00478                         } else if (*data == bigarticle
00479                                    || *data == overview) {
00480                                 const char *over = data + sizeof(char);
00481                                 try {
00482                                         fld =
00483                                             _OverviewFormat->getfield(over,
00484                                                                       xheader,
00485                                                                       0);
00486                                         os << i << " " << fld << "\r\n";
00487                                 } catch(NoSuchFieldError & nfe) {
00488                                         os << i << " (none)\r\n";
00489                                 }
00490                         }
00491                 }               /* if(data) */
00492         }
00493         NVArray::lock(NVcontainer::UnLock);
00494 }
00495 
00496 void NVNewsgroup::printlistgroup(ostream & os)
00497 {
00498         VERB(slog.
00499              p(Logger::Debug) << "NVNewsgroup::printlistgroup(&os)\n");
00500 
00501         unsigned int i;
00502         lock(NVcontainer::ShrdLock);
00503         for (i = arrfst; i <= arrlst; i++) {
00504                 if (shas_element(i))
00505                         os << i << "\r\n";
00506         }
00507         lock(NVcontainer::UnLock);
00508 }

Generated on Sun Oct 24 21:08:19 2004 for NewsCache by doxygen 1.3.6-20040222