/************************************************************************* * * HTCd - Copyright (C) 1998-2006 Henrik Rydberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef FILEMAPH #define FILEMAPH #include #include #include #include #include ////////////////////////////////////////////// // // NOTE that filemap is MT unsafe: // it needs to be called from dbmap // // The exception is when filelocking; // that's MT safe per filemap, and hence // should not be locked further // #define HEADLOCK(fm) headlock_t headlock(fm) ////////////////////////////////////////////////////// // network byteorder class byte4 { public: byte4() {} // must be uninitialized explicit byte4(int h): n(htonl(h)) {} void set(int h) { n=htonl(h); } void add(int h) { n=htonl(ntohl(n)+h); } int get() const { return ntohl(n); } private: long n; }; ////////////////////////////////////////////////////// class filemap { public: typedef char char32[32]; static const int maxtabs=32; //////////////////////////////////////////////////// struct head_t { char32 ident; byte4 lock; byte4 minor; byte4 major; byte4 fatal; byte4 filesize; byte4 filetop; byte4 tables; byte4 index; char32 compname; char32 tabs[maxtabs]; byte4 frame; head_t(); head_t(const head_t* hd,int mem); void setcomp(int idx, const sref& cp); sref get(int col) const { return sref(tabs[col]); } void set(int col,const sref& s); void insert(int col,const sref& s); void remove(int col); }; head_t* head() { return hd; } const head_t* head() const { return hd; } /////////////////////////////////////////////////////// struct rec_t { byte4 mem; byte4 caps; }; rec_t* at(int off) { for(chunk_t* p=mem;p;p=p->next) if(p->own(off)) return p->at(off); return 0; } const rec_t* at(int off) const { for(const chunk_t* p=mem;p;p=p->next) if(p->own(off)) return p->at(off); return 0; } int recs() const { return hd->frame.get(); } int size(int off) const { if(offfiletop.get()) { for(const chunk_t* p=mem;p;p=p->next) if(p->own(off)) return p->at(off)->mem.get(); } return 0; } /////////////////////////////////////////////////////// void remap(); rec_t* add(int n); void rem(rec_t* rec); /////////////////////////////////////////////////////// filemap(filemap* p); filemap(filemap* p,const mstring& path,int update=0,int prot=0600); ~filemap(); filemap* next; /////////////////////////////////////////////////////// void open(const mstring& path,int update=0,int prot=0600) throw(merror_t); void save(const mstring& path,int prot=0600) throw(merror_t); void check() throw(merror_t); void close(); void sync(); const mstring& Pathname() const { return pathname; } time_t Lastmod() const; int reference() const { return refs; } int writable() const { return wok; } void pushref() { refs++; } void popref() { refs--; } /////////////////////////////////////////////////////// void lock(); void unlock(); /////////////////////////////////////////////////////// protected: struct chunk_t { chunk_t* next; long begin; long end; char* map; int size() const { return end-begin; } chunk_t(chunk_t* p,int fd,int wok,int off,int size); ~chunk_t(); int own(int off) const { return off>=begin&&offlock(); } ~headlock_t() { if(fm) fm->unlock(); } }; #endif