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

NVcontainer Class Reference

#include <NVcontainer.h>

Inheritance diagram for NVcontainer:

NVArray NVlist NVNewsgroup NVHash NVList CNewsgroup NVActiveDB List of all members.

Public Types

enum  { UnLock = F_UNLCK, ShrdLock = F_RDLCK, ExclLock = F_WRLCK }
enum  { Block = 0x0, NoBlock = 0x1 }

Public Member Functions

int lock (int command, int block=Block)
int get_lock (void)
virtual void open (const char *dbname, int flags=0)
virtual int is_open (void)
virtual void close (void)
void setmtime (nvtime_t tm, int force=0)
void getmtime (nvtime_t *tm)

Protected Member Functions

 NVcontainer (void)
 NVcontainer (const char *dbname, int flags=0)
virtual ~NVcontainer (void)
virtual void make_current (void)
virtual int is_current (void)
virtual size_t resize (size_t nsz)
nvoff_t getdata ()
nvoff_t getdatap ()
void setdata (nvoff_t d)
nvoff_t nvalloc (size_t rsz)
void nvfree (nvoff_t f)

Protected Attributes

char * mem_p
size_t mem_sz

Private Member Functions

FreeListo2fl (nvoff_t o)
nvoff_t fl2o (FreeList *r)

Private Attributes

int lck_stack [NVcontainer_LOCKSTACKSIZE]
int lck_stackp
char mem_fn [MAXPATHLEN]
int mem_fd
Headermem_hdr

Detailed Description

Author:
Thomas Gschwind How should we define a uniform interface to access data stored within an NVcontainer? Two kinds of accesses exist: shared access ... uses NVcontainer's data copy copy access ... copies the data at each request The second version is easier to use, but reduces the performance.

Bug:
Documentation is missing.

Definition at line 29 of file NVcontainer.h.


Member Enumeration Documentation

anonymous enum
 

Enumeration values:
UnLock 
ShrdLock 
ExclLock 

Definition at line 87 of file NVcontainer.h.

00087              {
00088                 UnLock = F_UNLCK,
00089                 ShrdLock = F_RDLCK,
00090                 ExclLock = F_WRLCK
00091         };

anonymous enum
 

Enumeration values:
Block 
NoBlock 

Definition at line 92 of file NVcontainer.h.

00092              {
00093                 Block = 0x0,
00094                 NoBlock = 0x1
00095         };


Constructor & Destructor Documentation

NVcontainer::NVcontainer void   )  [protected]
 

Definition at line 96 of file NVcontainer.cc.

References lck_stackp, mem_fd, mem_fn, mem_hdr, mem_p, and NVcontainer_LOCKSTACKSIZE.

00097 {
00098         lck_stackp = NVcontainer_LOCKSTACKSIZE;
00099         mem_fn[0] = '\0';
00100         mem_fd = -1;
00101         mem_p = NULL;
00102         mem_hdr = (Header *) mem_p;
00103 }

NVcontainer::NVcontainer const char *  dbname,
int  flags = 0
[protected]
 

Definition at line 105 of file NVcontainer.cc.

References lck_stackp, mem_fd, NVcontainer_LOCKSTACKSIZE, and open().

00106 {
00107         lck_stackp = NVcontainer_LOCKSTACKSIZE;
00108         mem_fd = -1;
00109         open(dbname, flags);
00110 }

NVcontainer::~NVcontainer void   )  [protected, virtual]
 

Definition at line 112 of file NVcontainer.cc.

References close().

00113 {
00114         close();
00115 }


Member Function Documentation

void NVcontainer::close void   )  [virtual]
 

Reimplemented in NVActiveDB.

Definition at line 637 of file NVcontainer.cc.

References lck_stackp, mem_fd, mem_fn, mem_hdr, mem_p, mem_sz, NVcontainer_LOCKSTACKSIZE, slog, and VERB.

Referenced by NVActiveDB::close(), make_current(), nvfree(), open(), and ~NVcontainer().

00638 {
00639         if (mem_fd < 0)
00640                 return;
00641         munmap(mem_p, mem_sz);
00642         ::close(mem_fd);
00643         if (lck_stackp != NVcontainer_LOCKSTACKSIZE) {
00644                 VERB(slog.
00645                      p(Logger::
00646                        Critical) <<
00647                      "NVcontainer::close: Forgot to unlock the container before closing it!\n");
00648                 lck_stackp = NVcontainer_LOCKSTACKSIZE;
00649         }
00650         mem_fn[0] = '\0';
00651         mem_fd = -1;
00652         mem_p = NULL;
00653         mem_hdr = (Header *) mem_p;
00654 }

nvoff_t NVcontainer::fl2o FreeList r  )  [inline, private]
 

Definition at line 62 of file NVcontainer.h.

References mem_p, and nvoff_t.

Referenced by nvalloc(), and nvfree().

00062                                    {
00063                 return r ? (char *) r - mem_p : 0;
00064         }

int NVcontainer::get_lock void   ) 
 

Reimplemented in NVActiveDB.

Definition at line 557 of file NVcontainer.cc.

References lck_stack, lck_stackp, NVcontainer_LOCKSTACKSIZE, and UnLock.

Referenced by NVActiveDB::get_lock().

00558 {
00559         return lck_stackp <
00560             NVcontainer_LOCKSTACKSIZE ? lck_stack[lck_stackp] : UnLock;
00561 }

nvoff_t NVcontainer::getdata  )  [protected]
 

Definition at line 188 of file NVcontainer.cc.

References mem_hdr, nvoff_t, and NVcontainer::Header::userdata.

Referenced by NVListIter::attach(), NVHash::make_current(), NVArray::make_current(), NVList::remove(), and NVArray::ssetsize().

00189 {
00190         return mem_hdr->userdata;
00191 }

nvoff_t NVcontainer::getdatap  )  [protected]
 

Definition at line 193 of file NVcontainer.cc.

References mem_hdr, mem_p, nvoff_t, and NVcontainer::Header::userdata.

Referenced by NVList::append(), NVList::clear(), NVList::is_empty(), NVList::prepend(), NVList::print(), and NVList::remove().

00194 {
00195         return ((char *) &mem_hdr->userdata - mem_p);
00196 }

void NVcontainer::getmtime nvtime_t tm  ) 
 

Definition at line 665 of file NVcontainer.cc.

References lock(), mem_hdr, NVcontainer::Header::mtime, nvtime_t, ShrdLock, and UnLock.

Referenced by NVActiveDB::getmtime(), and CNewsgroup::updateOverview().

00666 {
00667         lock(ShrdLock);
00668         (*tm) = mem_hdr->mtime;
00669         lock(UnLock);
00670 }

virtual int NVcontainer::is_current void   )  [inline, protected, virtual]
 

Definition at line 75 of file NVcontainer.h.

References mem_hdr, mem_sz, and NVcontainer::Header::size.

Referenced by NVHash::make_current(), make_current(), and NVArray::make_current().

00075                                      {
00076                 return mem_sz == mem_hdr->size;
00077         }

int NVcontainer::is_open void   )  [virtual]
 

Reimplemented in NVActiveDB.

Definition at line 632 of file NVcontainer.cc.

References mem_fd.

Referenced by NVActiveDB::is_open().

00633 {
00634         return mem_fd >= 0;
00635 }

int NVcontainer::lock int  command,
int  block = Block
 

Reimplemented in NVActiveDB.

Definition at line 504 of file NVcontainer.cc.

References ERROR_LOCATION, ExclLock, lck_stack, lck_stackp, make_current(), mem_fd, NoBlock, NVcontainer_LOCKSTACKSIZE, nvflock(), and UnLock.

Referenced by NVHash::add(), NVList::append(), NVListIter::attach(), NVHashIter::attach(), NVList::clear(), NVHash::clear(), NVArray::clear(), NVArray::del(), NVListIter::detach(), NVHashIter::detach(), NVArray::get(), NVNewsgroup::getarticle(), getmtime(), NVNewsgroup::getover(), NVArray::has_element(), NVList::is_empty(), NVHash::is_empty(), NVArray::is_empty(), NVActiveDB::lock(), nvalloc(), nvfree(), NVHash::open(), CNewsgroup::prefetchGroup(), CNewsgroup::prefetchOverview(), NVList::prepend(), NVList::print(), NVHash::print(), NVArray::print(), NVNewsgroup::printarticle(), NVNewsgroup::printheaderdb(), NVNewsgroup::printlistgroup(), NVNewsgroup::printover(), NVNewsgroup::printoverdb(), NVNewsgroup::readoverdb(), NVList::remove(), resize(), NVArray::set(), NVNewsgroup::setarticle(), setmtime(), NVNewsgroup::setover(), NVNewsgroup::setsize(), NVArray::setsize(), CNewsgroup::setsize(), and CNewsgroup::updateOverview().

00505 {
00506         int res;
00507         int curLock = UnLock;
00508 
00509         if (lck_stackp < NVcontainer_LOCKSTACKSIZE) {
00510                 curLock = lck_stack[lck_stackp];
00511         }
00512         if (command == UnLock) {
00513                 // Unlock container 
00514                 if (lck_stackp >= NVcontainer_LOCKSTACKSIZE) {
00515                         throw
00516                             Error
00517                             ("NVContainer(14364): Lock Stack underflow",
00518                              ERROR_LOCATION);
00519                 }
00520                 lck_stackp++;
00521                 command =
00522                     lck_stackp <
00523                     NVcontainer_LOCKSTACKSIZE ? lck_stack[lck_stackp] :
00524                     UnLock;
00525         } else {
00526                 // Lock container
00527                 if (lck_stackp == 0) {
00528                         throw
00529                             Error
00530                             ("NVContainer(24929): Lock Stack overflow",
00531                              ERROR_LOCATION);
00532                 }
00533                 // Is already locked with excl => new lock must be excl
00534                 if (curLock == ExclLock)
00535                         command = ExclLock;
00536                 lck_stack[--lck_stackp] = command;
00537         }
00538         // Relock if lock state changed
00539         if (curLock != command) {
00540                 if ((res = nvflock(mem_fd, command, block)) < 0) {
00541                         if (errno == EWOULDBLOCK && block == NoBlock) {
00542                                 lck_stackp++;
00543                                 return -1;
00544                         }
00545                         throw
00546                             SystemError("NVContainer(8402): flock failed",
00547                                         errno, ERROR_LOCATION);
00548                 }
00549                 // Adapt to the new size if somebody changed the container's 
00550                 // size
00551                 if (command != UnLock)
00552                         make_current();
00553         }
00554         return 0;
00555 }

void NVcontainer::make_current void   )  [protected, virtual]
 

Reimplemented in NVArray, and NVHash.

Definition at line 117 of file NVcontainer.cc.

References close(), ERROR_LOCATION, NVcontainer::Header::hlen, is_current(), mem_fd, mem_hdr, mem_p, mem_sz, nvoff_t, NVcontainer::Header::size, slog, VERB, and NVcontainer::Header::version.

Referenced by lock(), NVHash::make_current(), NVArray::make_current(), open(), and resize().

00118 {
00119         struct stat st;
00120 
00121         if (mem_p) {
00122                 if (is_current())
00123                         return;
00124                 munmap(mem_p, mem_sz);
00125         }
00126 
00127         if (fstat(mem_fd, &st) < 0) {
00128                 throw SystemError("NVContainer(20801): fstat failed",
00129                                   errno, ERROR_LOCATION);
00130         }
00131 
00132         if ((nvoff_t) st.st_size <=
00133             (nvoff_t) sizeof(Header) + (nvoff_t) sizeof(FreeList)) {
00134                 throw Error("NVConatiner(19603): info-record shrunk",
00135                             ERROR_LOCATION);
00136         }
00137 
00138         mem_sz = st.st_size;
00139         mem_p = (char *) mmap(NULL, mem_sz,
00140                               PROT_READ | PROT_WRITE, MAP_SHARED,
00141                               mem_fd, 0);
00142         if (mem_p == (char *) -1) {
00143                 mem_p = NULL;
00144                 throw SystemError("NVContainer(13784): mmap failed", errno,
00145                                   ERROR_LOCATION);
00146         }
00147         mem_hdr = (Header *) mem_p;
00148         //Do some sanity checks on the database
00149         if (mem_hdr->hlen != sizeof(Header) || mem_hdr->version != 2) {
00150                 close();
00151                 throw Error("NVContainer(28196): no nvcontainer",
00152                             ERROR_LOCATION);
00153         }
00154         if (mem_sz != mem_hdr->size) {
00155                 VERB(slog.
00156                      p(Logger::
00157                        Critical) <<
00158                      "NVcontainer: wrong database size stored in db-header - may be a hazard\n");
00159         }
00160 }

nvoff_t NVcontainer::nvalloc size_t  rsz  )  [protected]
 

Definition at line 203 of file NVcontainer.cc.

References ASSERT, NVcontainer::Header::bytes_free, ERROR_LOCATION, ExclLock, fl2o(), NVcontainer::Header::freelist, lock(), mem_hdr, mem_p, mem_sz, NVcontainer::FreeList::next, nvoff_t, o2fl(), Logger::p(), resize(), NVcontainer::FreeList::size, slog, UnLock, and VERB.

Referenced by NVHash::open(), NVlist::sappend(), NVNewsgroup::setarticle(), NVNewsgroup::setover(), NVlist::sprepend(), NVArray::sset(), and NVArray::ssetsize().

00204 {
00205         lock(ExclLock);
00206         FreeList *flhead = o2fl(mem_hdr->freelist);
00207         FreeList *cur, *prv, *res;
00208 
00209         // The allocated memory block has to meet several requirements
00210         // * aligned on 16 Byte boundary
00211         // * size has to be a multiple of 16 (simplifies the alignment)
00212         // * the allocated block has to hold its size
00213         //   the memory after the size indicator will be returned
00214         rsz = (rsz + sizeof(unsigned long) + 0xf) & (~0xf);
00215         if (flhead == NULL) {
00216                 throw
00217                     Error
00218                     ("NVContainer(5946): Database file corrupted (freelist==NULL)",
00219                      ERROR_LOCATION);
00220         }
00221         // flhead points to the last free memory block available in the database
00222         prv = flhead;
00223         cur = o2fl(prv->next);
00224         // find the first suitable memory block in the database
00225         while (cur->size < rsz && cur != flhead) {
00226                 prv = cur;
00227                 cur = o2fl(cur->next);
00228         }
00229 
00230         if (cur == flhead) {
00231                 // Special care has to be taken for the last free memory block
00232                 // It must always be present! So we have to resize it, if its
00233                 // memory is smaller than the requested size plus the size 
00234                 // necessary to maintain the last block of free memory.
00235                 if (flhead->size < rsz + sizeof(FreeList)) {
00236                         nvoff_t prvoff = fl2o(prv);
00237                         // Since it is very likely that the mapped region will change
00238                         // during the resize operation, we will have to save the
00239                         // currently used pointers
00240                         int needsz = rsz + sizeof(FreeList) - flhead->size;
00241                         resize(mem_sz + needsz);
00242                         cur = flhead = o2fl(mem_hdr->freelist);
00243                         prv = o2fl(prvoff);
00244                         ASSERT(if (cur->size < rsz + sizeof(FreeList)) {
00245                                throw
00246                                AssertionError
00247                                ("NVContainer::nvalloc: resize failed",
00248                                 ERROR_LOCATION);}
00249                         );
00250                 }
00251         }
00252         ASSERT(if (cur->size < rsz) {
00253                throw
00254                AssertionError
00255                ("NVContainer::nvalloc: did not find a large enough free memory block",
00256                 ERROR_LOCATION);}
00257         );
00258 
00259         res = cur;
00260 
00261         if (cur->size < rsz + sizeof(FreeList)) {
00262                 // The available space is too small to split?
00263                 // This may only occur if cur _is_not_ the tail of the free blocks
00264                 ASSERT(if (res == flhead) {
00265                        throw
00266                        AssertionError
00267                        ("NVContainer::nvalloc: Cannot split block of free memory at tail of database",
00268                         ERROR_LOCATION);}
00269                 );
00270                 prv->next = cur->next;
00271                 rsz = cur->size;
00272         } else {
00273                 // Split the space into two parts
00274                 cur = (FreeList *) ((char *) cur + rsz);
00275                 cur->size = res->size - rsz;
00276                 if (prv != res) {
00277                         // list contains at least two blocks
00278                         cur->next = res->next;
00279                         prv->next = fl2o(cur);
00280                         if (res == flhead) {
00281                                 mem_hdr->freelist = fl2o(cur);
00282                         }
00283                 } else {
00284                         // list contains only one block pointing to itself
00285                         // this must be the free memory block at the tail
00286                         ASSERT(if (res != flhead) {
00287                                throw
00288                                AssertionError
00289                                ("NVList::nvalloc: Lost block of free memory at tail of database",
00290                                 ERROR_LOCATION);}
00291                         );
00292                         mem_hdr->freelist = cur->next = fl2o(cur);
00293                 }
00294         }
00295         mem_hdr->bytes_free -= rsz;
00296         lock(UnLock);
00297 
00298         *(unsigned long *) res = rsz;
00299 #ifdef FREELIST_ASSERT_ON
00300         char buf[256];
00301         int i = 10000;
00302         prv = flhead = o2fl(mem_hdr->freelist);;
00303         cur = o2fl(prv->next);
00304 
00305         VERB(sprintf
00306              (buf, "nvalloc: checking freelist flhead=%p\n", flhead);
00307              slog.p(Logger::Debug) << buf);
00308         while (cur != flhead && i) {
00309                 VERB(sprintf
00310                      (buf, "nvalloc: elem(%lu)={%lu,%lu}\n",
00311                       (nvoff_t) ((char *) cur - mem_p), cur->next,
00312                       cur->size); slog.p(Logger::Debug) << buf);
00313                 prv = cur;
00314                 cur = o2fl(cur->next);
00315                 ASSERT(if (prv >= cur) {
00316                        throw
00317                        AssertionError
00318                        ("NVContainer::nvalloc: freelist out of order!",
00319                         ERROR_LOCATION);}
00320                 );
00321                 i--;
00322         }
00323         VERB(sprintf
00324              (buf, "nvfree: tail(%lu)={%lu,%lu}\n",
00325               (nvoff_t) ((char *) cur - mem_p), cur->next, cur->size);
00326              slog.p(Logger::Debug) << buf);
00327         if (!i)
00328                 VERB(slog.
00329                      p(Logger::
00330                        Debug) <<
00331                      "nvalloc: more than 10000 free blocks!\n");
00332 #endif
00333         return (nvoff_t) ((char *) res - mem_p) + sizeof(unsigned long);
00334 }

void NVcontainer::nvfree nvoff_t  f  )  [protected]
 

Definition at line 336 of file NVcontainer.cc.

References ASSERT, NVcontainer::Header::bytes_free, close(), ERROR_LOCATION, ExclLock, fl2o(), NVcontainer::Header::freelist, lock(), mem_hdr, mem_p, mem_sz, NVcontainer::FreeList::next, nvoff_t, o2fl(), Logger::p(), NVcontainer::FreeList::size, slog, UnLock, and VERB.

Referenced by CNewsgroup::prefetchGroup(), NVArray::sclear(), NVArray::sdel(), NVNewsgroup::setarticle(), NVNewsgroup::setsize(), NVArray::setsize(), NVlist::sremove(), NVArray::sset(), NVArray::ssetsize(), and CNewsgroup::sUpdateOverview().

00337 {
00338 #ifdef FREELIST_ASSERT_ON
00339         VERB(char buf[256];
00340              sprintf(buf, "NVcontainer::nvfree(%lu)\n", p);
00341              slog.p(Logger::Debug) << buf);
00342 #endif
00343         lock(ExclLock);
00344 
00345         FreeList *pb, *pe;
00346         int psz;
00347 #ifdef FREELIST_ASSERT_ON
00348         FreeList *flhead;
00349         FreeList *cur, *prv;
00350         int i = 10000;
00351         prv = flhead = o2fl(mem_hdr->freelist);;
00352         cur = o2fl(prv->next);
00353 
00354         VERB(sprintf(buf, "nvfree: checking freelist flhead=%p\n", flhead);
00355              slog.p(Logger::Debug) << buf);
00356         while (cur != flhead && i) {
00357                 VERB(sprintf
00358                      (buf, "nvfree: elem(%lu)={%lu,%lu}\n",
00359                       (nvoff_t) ((char *) cur - mem_p), cur->next,
00360                       cur->size); slog.p(Logger::Debug) << buf);
00361                 prv = cur;
00362                 cur = o2fl(cur->next);
00363                 ASSERT(if (prv >= cur) {
00364                        throw
00365                        AssertionError
00366                        ("NVContainer::nvfree: freelist out of order!",
00367                         ERROR_LOCATION);}
00368                 );
00369                 i--;
00370         }
00371         VERB(sprintf
00372              (buf, "nvfree: tail(%lu)={%lu,%lu}\n",
00373               (nvoff_t) ((char *) cur - mem_p), cur->next, cur->size);
00374              slog.p(Logger::Debug) << buf);
00375         if (!i)
00376                 VERB(slog.
00377                      p(Logger::
00378                        Debug) << "nvfree: more than 10000 free blocks!\n");
00379 #else
00380         FreeList *flhead = o2fl(mem_hdr->freelist);
00381         FreeList *cur = NULL, *prv = NULL;
00382 #endif
00383 
00384         pb = o2fl(p - sizeof(unsigned long));
00385         psz = *(unsigned long *) pb;
00386         pe = (FreeList *) ((char *) pb + psz);
00387 
00388 //  ASSERT(memset(pb,255,psz));
00389         ASSERT(if ((char *) pb < mem_p || mem_p + mem_sz < (char *) pe) {
00390                char buf[1024];
00391                close();
00392                sprintf(buf,
00393                        "NVcontainer::nvfree: tried to free illegal memory block ([%p,%p])!\nNVcontainer mapped from [%p,%p]",
00394                        pb, pe, mem_p, mem_p + mem_sz);
00395                throw AssertionError(buf, ERROR_LOCATION);});
00396 
00397         // flhead points to the last free memory block available in the database
00398         prv = flhead;
00399         cur = o2fl(prv->next);
00400         while (cur < pb && cur != flhead) {
00401                 prv = cur;
00402                 cur = o2fl(cur->next);
00403                 ASSERT(if (prv >= cur) {
00404                        throw
00405                        AssertionError
00406                        ("NVContainer::nvfree: freelist out of order!",
00407                         ERROR_LOCATION);}
00408                 );
00409         }
00410         ASSERT(if (cur < pb) {
00411                char buf[1024];
00412                close();
00413                sprintf(buf,
00414                        "NVcontainer::nvfree: tried to free unallocated memory block ([%p,%p])!\n Address must be smaller than flhead (%p)!\nNVcontainer mapped from[%p,%p]",
00415                        pb, pe, flhead, mem_p, mem_p + mem_sz);
00416                throw AssertionError(buf, ERROR_LOCATION);});
00417 
00418         if ((char *) prv + prv->size == (char *) pb) {
00419 #ifdef FREELIST_ASSERT_ON
00420                 VERB(slog.
00421                      p(Logger::Debug) << "nvfree: adjacent to previous\n");
00422 #endif
00423                 // The freed block is adjacent to the previous free block
00424                 prv->size += psz;
00425                 if (pe == cur) {
00426 #ifdef FREELIST_ASSERT_ON
00427                         VERB(slog.
00428                              p(Logger::
00429                                Debug) <<
00430                              "nvfree: adjacent to next---cool\n");
00431 #endif
00432                         // The freed block is adjacent to the next free block too, cool :)
00433                         if (cur == flhead)
00434                                 mem_hdr->freelist = fl2o(prv);
00435                         prv->size += cur->size;
00436                         prv->next = cur->next;
00437                 }
00438         } else if (pe == cur) {
00439 #ifdef FREELIST_ASSERT_ON
00440                 VERB(slog.
00441                      p(Logger::Debug) << "nvfree: adjacent to next\n");
00442 #endif
00443                 // The freed block is adjacent to the next free block
00444                 if (cur->next == fl2o(cur)) {
00445                         // Only one block of free memory left
00446                         ASSERT(if (flhead != cur) {
00447                                throw
00448                                AssertionError
00449                                ("NVContainer::nvfree: flhead lost trailing block of free memory",
00450                                 ERROR_LOCATION);}
00451                         );
00452                         mem_hdr->freelist = pb->next = fl2o(pb);
00453                         pb->size = psz + cur->size;
00454                 } else {
00455                         pb->next = cur->next;
00456                         pb->size = psz + cur->size;
00457                         prv->next = fl2o(pb);
00458                         if (cur == flhead)
00459                                 mem_hdr->freelist = fl2o(pb);
00460                 }
00461         } else {
00462                 VERB(slog.p(Logger::Debug) << "nvfree: not adjacent\n");
00463                 // The freed block neither is adjacent to the previous nor to the 
00464                 // next free block
00465                 pb->next = fl2o(cur);
00466                 pb->size = psz;
00467                 prv->next = fl2o(pb);
00468         }
00469         mem_hdr->bytes_free += psz;
00470 #ifdef FREELIST_ASSERT_ON
00471         i = 10000;
00472         prv = flhead = o2fl(mem_hdr->freelist);;
00473         cur = o2fl(prv->next);
00474 
00475         VERB(sprintf(buf, "nvfree: checking freelist flhead=%p\n", flhead);
00476              slog.p(Logger::Debug) << buf);
00477         while (cur != flhead && i) {
00478                 VERB(sprintf
00479                      (buf, "nvfree: elem(%lu)={%lu,%lu}\n",
00480                       (nvoff_t) ((char *) cur - mem_p), cur->next,
00481                       cur->size); slog.p(Logger::Debug) << buf);
00482                 prv = cur;
00483                 cur = o2fl(cur->next);
00484                 ASSERT(if (prv >= cur) {
00485                        throw
00486                        AssertionError
00487                        ("NVContainer::nvfree: freelist out of order!",
00488                         ERROR_LOCATION);}
00489                 );
00490                 i--;
00491         }
00492         VERB(sprintf
00493              (buf, "nvfree: tail(%lu)={%lu,%lu}\n",
00494               (nvoff_t) ((char *) cur - mem_p), cur->next, cur->size);
00495              slog.p(Logger::Debug) << buf);
00496         if (!i)
00497                 VERB(slog.
00498                      p(Logger::
00499                        Debug) << "nvfree: more than 10000 free blocks!\n");
00500 #endif
00501         lock(UnLock);
00502 }

FreeList* NVcontainer::o2fl nvoff_t  o  )  [inline, private]
 

Definition at line 59 of file NVcontainer.h.

References mem_p.

Referenced by nvalloc(), nvfree(), and resize().

00059                                   {
00060                 return (FreeList *) (o ? mem_p + o : NULL);
00061         }

void NVcontainer::open const char *  dbname,
int  flags = 0
[virtual]
 

Definition at line 565 of file NVcontainer.cc.

References ASSERT, Block, NVcontainer::Header::bytes_free, close(), ERROR_LOCATION, ExclLock, NVcontainer::Header::freelist, NVcontainer::Header::hlen, make_current(), mem_fd, mem_fn, NVcontainer::FreeList::next, nvflock(), NVcontainer::FreeList::size, NVcontainer::Header::size, and UnLock.

Referenced by NVArray::NVArray(), NVcontainer(), NVNewsgroup::NVNewsgroup(), and NVHash::open().

00566 {
00567         ASSERT(if (!dbname) throw
00568                AssertionError
00569                ("NVContainer(1a): open called with null-ointer\n",
00570                 ERROR_LOCATION));
00571 
00572         if (strcmp(mem_fn, dbname) == 0)
00573                 return;
00574 
00575         if (mem_fd >= 0)
00576                 close();
00577 
00578         char errbuf[MAXPATHLEN + 256];
00579         struct stat st;
00580 
00581         flags = 0;
00582         strcpy(mem_fn, dbname);
00583         if ((mem_fd =::open(mem_fn, O_RDWR | O_CREAT, 0644)) < 0) {
00584                 sprintf(errbuf,
00585                         "NVList(15485): Cannot open(%s,O_RDWR|O_CREAT)",
00586                         dbname);
00587                 throw SystemError(errbuf, errno, ERROR_LOCATION);
00588         }
00589 
00590         nvflock(mem_fd, ExclLock, Block);
00591         if (fstat(mem_fd, &st) < 0) {
00592                 throw SystemError("NVContainer(16974): fstat failed",
00593                                   errno, ERROR_LOCATION);
00594         }
00595         if (st.st_size == 0) {
00596                 Header hdr;
00597                 FreeList fl;
00598                 hdr.freelist = hdr.hlen;
00599                 hdr.size = 0x10000;
00600                 fl.next = hdr.freelist;
00601                 fl.size = hdr.bytes_free = hdr.size - hdr.hlen;
00602 
00603                 if (ftruncate(mem_fd, hdr.size) < 0) {
00604                         unlink(mem_fn);
00605                         throw
00606                             SystemError
00607                             ("NVContainer(13947): cannot create nvcontainer",
00608                              errno, ERROR_LOCATION);
00609                 }
00610                 if (write(mem_fd, &hdr, sizeof(Header)) != sizeof(Header)) {
00611                         unlink(mem_fn);
00612                         throw
00613                             SystemError
00614                             ("NVContainer(13948): write(info-record) failed",
00615                              errno, ERROR_LOCATION);
00616                 }
00617                 if (write(mem_fd, &fl, sizeof(FreeList)) !=
00618                     sizeof(FreeList)) {
00619                         unlink(mem_fn);
00620                         throw
00621                             SystemError
00622                             ("NVContainer(23367): write(free-record) failed",
00623                              errno, ERROR_LOCATION);
00624                 }
00625         }
00626         nvflock(mem_fd, UnLock, Block);
00627 
00628         //Sanity checks of an existing database will be done in 
00629         make_current();
00630 }

size_t NVcontainer::resize size_t  nsz  )  [protected, virtual]
 

Definition at line 162 of file NVcontainer.cc.

References NVcontainer::Header::bytes_free, ERROR_LOCATION, ExclLock, NVcontainer::Header::freelist, lock(), make_current(), mem_fd, mem_hdr, mem_sz, o2fl(), NVcontainer::Header::size, NVcontainer::FreeList::size, slog, UnLock, and VERB.

Referenced by nvalloc().

00163 {
00164         if (nsz < mem_sz) {
00165                 VERB(slog.
00166                      p(Logger::
00167                        Warning) <<
00168                      "NVContainer: reduction of database size not supported, ignored\n");
00169                 return mem_sz;
00170         }
00171 
00172         lock(ExclLock);
00173         FreeList *flhead = o2fl(mem_hdr->freelist);
00174 
00175         nsz = (nsz + 0x10000) & (~0xffff);
00176         if (ftruncate(mem_fd, nsz) < 0) {
00177                 throw SystemError("NVList(2756): ftruncate failed", errno,
00178                                   ERROR_LOCATION);
00179         }
00180         mem_hdr->bytes_free += nsz - mem_sz;
00181         flhead->size += nsz - mem_sz;
00182         mem_hdr->size = nsz;
00183         make_current();
00184         lock(UnLock);
00185         return mem_sz;
00186 }

void NVcontainer::setdata nvoff_t  d  )  [protected]
 

Definition at line 198 of file NVcontainer.cc.

References mem_hdr, nvoff_t, and NVcontainer::Header::userdata.

Referenced by NVHash::open(), and NVArray::ssetsize().

00199 {
00200         mem_hdr->userdata = d;
00201 }

void NVcontainer::setmtime nvtime_t  tm,
int  force = 0
 

Definition at line 656 of file NVcontainer.cc.

References ExclLock, lock(), mem_hdr, NVcontainer::Header::mtime, nvtime_t, and UnLock.

Referenced by CNewsgroup::prefetchGroup(), NVNewsgroup::readoverdb(), NVActiveDB::setmtime(), CNewsgroup::setsize(), and CNewsgroup::sUpdateOverview().

00657 {
00658         lock(ExclLock);
00659         unsigned long ctm = mem_hdr->mtime;
00660         if (force || tm > ctm)
00661                 mem_hdr->mtime = tm;
00662         lock(UnLock);
00663 }


Member Data Documentation

int NVcontainer::lck_stack[NVcontainer_LOCKSTACKSIZE] [private]
 

Definition at line 52 of file NVcontainer.h.

Referenced by get_lock(), and lock().

int NVcontainer::lck_stackp [private]
 

Definition at line 53 of file NVcontainer.h.

Referenced by close(), get_lock(), lock(), and NVcontainer().

int NVcontainer::mem_fd [private]
 

Definition at line 56 of file NVcontainer.h.

Referenced by close(), is_open(), lock(), make_current(), NVcontainer(), open(), and resize().

char NVcontainer::mem_fn[MAXPATHLEN] [private]
 

Definition at line 55 of file NVcontainer.h.

Referenced by close(), NVcontainer(), and open().

Header* NVcontainer::mem_hdr [private]
 

Definition at line 57 of file NVcontainer.h.

Referenced by close(), getdata(), getdatap(), getmtime(), is_current(), make_current(), nvalloc(), NVcontainer(), nvfree(), resize(), setdata(), and setmtime().

char* NVcontainer::mem_p [protected]
 

Definition at line 71 of file NVcontainer.h.

Referenced by close(), NVListIter::data(), NVHashIter::data(), fl2o(), NVActiveDB_Iter::get(), getdatap(), make_current(), nvalloc(), NVcontainer(), nvfree(), and o2fl().

size_t NVcontainer::mem_sz [protected]
 

Definition at line 72 of file NVcontainer.h.

Referenced by close(), is_current(), make_current(), nvalloc(), nvfree(), and resize().


The documentation for this class was generated from the following files:
Generated on Fri Aug 20 10:58:11 2004 for NewsCache by doxygen 1.3.6-20040222