| 1 | // -*- mode: cpp; mode: fold -*- |
| 2 | // Description /*{{{*/ |
| 3 | // $Id: filelist.h,v 1.2 2001/02/20 07:03:16 jgg Exp $ |
| 4 | /* ###################################################################### |
| 5 | |
| 6 | File Listing - Manages a Cache of File -> Package names. |
| 7 | |
| 8 | This is identical to the Package cache, except that the generator |
| 9 | (which is much simpler) is integrated directly into the main class, |
| 10 | and it has been designed to handle live updates. |
| 11 | |
| 12 | The storage content of the class is maintained in a memory map and is |
| 13 | written directly to the file system. Performance is traded against |
| 14 | space to give something that performs well and remains small. |
| 15 | The average per file usage is 32 bytes which yeilds about a meg every |
| 16 | 36k files. Directory paths are collected into a binary tree and stored |
| 17 | only once, this offsets the cost of the hash nodes enough to keep |
| 18 | memory usage slightly less than the sum of the filenames. |
| 19 | |
| 20 | The file names are stored into a fixed size chained hash table that is |
| 21 | linked to the package name and to the directory component. |
| 22 | |
| 23 | Each file node has a set of associated flags that indicate the current |
| 24 | state of the file. |
| 25 | |
| 26 | ##################################################################### */ |
| 27 | /*}}}*/ |
| 28 | #ifndef PKGLIB_FILELIST_H |
| 29 | #define PKGLIB_FILELIST_H |
| 30 | |
| 31 | |
| 32 | #include <cstring> |
| 33 | #include <apt-pkg/mmap.h> |
| 34 | |
| 35 | class pkgFLCache |
| 36 | { |
| 37 | public: |
| 38 | struct Header; |
| 39 | struct Node; |
| 40 | struct Directory; |
| 41 | struct Package; |
| 42 | struct Diversion; |
| 43 | struct ConfFile; |
| 44 | |
| 45 | class NodeIterator; |
| 46 | class DirIterator; |
| 47 | class PkgIterator; |
| 48 | class DiverIterator; |
| 49 | |
| 50 | protected: |
| 51 | string CacheFile; |
| 52 | DynamicMMap ⤅ |
| 53 | map_ptrloc LastTreeLookup; |
| 54 | unsigned long LastLookupSize; |
| 55 | |
| 56 | // Helpers for the addition algorithms |
| 57 | map_ptrloc TreeLookup(map_ptrloc *Base,const char *Text,const char *TextEnd, |
| 58 | unsigned long Size,unsigned int *Count = 0, |
| 59 | bool Insert = false); |
| 60 | |
| 61 | public: |
| 62 | |
| 63 | // Pointers to the arrays of items |
| 64 | Header *HeaderP; |
| 65 | Node *NodeP; |
| 66 | Directory *DirP; |
| 67 | Package *PkgP; |
| 68 | Diversion *DiverP; |
| 69 | ConfFile *ConfP; |
| 70 | char *StrP; |
| 71 | unsigned char *AnyP; |
| 72 | |
| 73 | // Quick accessors |
| 74 | Node *FileHash; |
| 75 | |
| 76 | // Accessors |
| 77 | Header &Head() {return *HeaderP;}; |
| 78 | void PrintTree(map_ptrloc Base,unsigned long Size); |
| 79 | |
| 80 | // Add/Find things |
| 81 | PkgIterator GetPkg(const char *Name,const char *End,bool Insert); |
| 82 | inline PkgIterator GetPkg(const char *Name,bool Insert); |
| 83 | NodeIterator GetNode(const char *Name, |
| 84 | const char *NameEnd, |
| 85 | map_ptrloc Loc, |
| 86 | bool Insert,bool Divert); |
| 87 | Node *HashNode(NodeIterator const &N); |
| 88 | void DropNode(map_ptrloc Node); |
| 89 | |
| 90 | inline DiverIterator DiverBegin(); |
| 91 | |
| 92 | // Diversion control |
| 93 | void BeginDiverLoad(); |
| 94 | void FinishDiverLoad(); |
| 95 | bool AddDiversion(PkgIterator const &Owner,const char *From, |
| 96 | const char *To); |
| 97 | bool AddConfFile(const char *Name,const char *NameEnd, |
| 98 | PkgIterator const &Owner,const unsigned char *Sum); |
| 99 | |
| 100 | pkgFLCache(DynamicMMap &Map); |
| 101 | // ~pkgFLCache(); |
| 102 | }; |
| 103 | |
| 104 | struct pkgFLCache::Header |
| 105 | { |
| 106 | // Signature information |
| 107 | unsigned long Signature; |
| 108 | short MajorVersion; |
| 109 | short MinorVersion; |
| 110 | bool Dirty; |
| 111 | |
| 112 | // Size of structure values |
| 113 | unsigned HeaderSz; |
| 114 | unsigned NodeSz; |
| 115 | unsigned DirSz; |
| 116 | unsigned PackageSz; |
| 117 | unsigned DiversionSz; |
| 118 | unsigned ConfFileSz; |
| 119 | |
| 120 | // Structure Counts; |
| 121 | unsigned int NodeCount; |
| 122 | unsigned int DirCount; |
| 123 | unsigned int PackageCount; |
| 124 | unsigned int DiversionCount; |
| 125 | unsigned int ConfFileCount; |
| 126 | unsigned int HashSize; |
| 127 | unsigned long UniqNodes; |
| 128 | |
| 129 | // Offsets |
| 130 | map_ptrloc FileHash; |
| 131 | map_ptrloc DirTree; |
| 132 | map_ptrloc Packages; |
| 133 | map_ptrloc Diversions; |
| 134 | |
| 135 | /* Allocation pools, there should be one of these for each structure |
| 136 | excluding the header */ |
| 137 | DynamicMMap::Pool Pools[5]; |
| 138 | |
| 139 | bool CheckSizes(Header &Against) const; |
| 140 | Header(); |
| 141 | }; |
| 142 | |
| 143 | /* The bit field is used to advoid incurring an extra 4 bytes x 40000, |
| 144 | Pointer is the most infrequently used member of the structure */ |
| 145 | struct pkgFLCache::Node |
| 146 | { |
| 147 | map_ptrloc Dir; // Dir |
| 148 | map_ptrloc File; // String |
| 149 | unsigned Pointer:24; // Package/Diversion/ConfFile |
| 150 | unsigned Flags:8; // Package |
| 151 | map_ptrloc Next; // Node |
| 152 | map_ptrloc NextPkg; // Node |
| 153 | |
| 154 | enum Flags {Diversion = (1<<0),ConfFile = (1<<1), |
| 155 | NewConfFile = (1<<2),NewFile = (1<<3), |
| 156 | Unpacked = (1<<4),Replaced = (1<<5)}; |
| 157 | }; |
| 158 | |
| 159 | struct pkgFLCache::Directory |
| 160 | { |
| 161 | map_ptrloc Left; // Directory |
| 162 | map_ptrloc Right; // Directory |
| 163 | map_ptrloc Name; // String |
| 164 | }; |
| 165 | |
| 166 | struct pkgFLCache::Package |
| 167 | { |
| 168 | map_ptrloc Left; // Package |
| 169 | map_ptrloc Right; // Package |
| 170 | map_ptrloc Name; // String |
| 171 | map_ptrloc Files; // Node |
| 172 | }; |
| 173 | |
| 174 | struct pkgFLCache::Diversion |
| 175 | { |
| 176 | map_ptrloc OwnerPkg; // Package |
| 177 | map_ptrloc DivertFrom; // Node |
| 178 | map_ptrloc DivertTo; // String |
| 179 | |
| 180 | map_ptrloc Next; // Diversion |
| 181 | unsigned long Flags; |
| 182 | |
| 183 | enum Flags {Touched = (1<<0)}; |
| 184 | }; |
| 185 | |
| 186 | struct pkgFLCache::ConfFile |
| 187 | { |
| 188 | map_ptrloc OwnerPkg; // Package |
| 189 | unsigned char MD5[16]; |
| 190 | }; |
| 191 | |
| 192 | class pkgFLCache::PkgIterator |
| 193 | { |
| 194 | Package *Pkg; |
| 195 | pkgFLCache *Owner; |
| 196 | |
| 197 | public: |
| 198 | |
| 199 | inline bool end() const {return Owner == 0 || Pkg == Owner->PkgP?true:false;} |
| 200 | |
| 201 | // Accessors |
| 202 | inline Package *operator ->() {return Pkg;}; |
| 203 | inline Package const *operator ->() const {return Pkg;}; |
| 204 | inline Package const &operator *() const {return *Pkg;}; |
| 205 | inline operator Package *() {return Pkg == Owner->PkgP?0:Pkg;}; |
| 206 | inline operator Package const *() const {return Pkg == Owner->PkgP?0:Pkg;}; |
| 207 | |
| 208 | inline unsigned long Offset() const {return Pkg - Owner->PkgP;}; |
| 209 | inline const char *Name() const {return Pkg->Name == 0?0:Owner->StrP + Pkg->Name;}; |
| 210 | inline pkgFLCache::NodeIterator Files() const; |
| 211 | |
| 212 | PkgIterator() : Pkg(0), Owner(0) {}; |
| 213 | PkgIterator(pkgFLCache &Owner,Package *Trg) : Pkg(Trg), Owner(&Owner) {}; |
| 214 | }; |
| 215 | |
| 216 | class pkgFLCache::DirIterator |
| 217 | { |
| 218 | Directory *Dir; |
| 219 | pkgFLCache *Owner; |
| 220 | |
| 221 | public: |
| 222 | |
| 223 | // Accessors |
| 224 | inline Directory *operator ->() {return Dir;}; |
| 225 | inline Directory const *operator ->() const {return Dir;}; |
| 226 | inline Directory const &operator *() const {return *Dir;}; |
| 227 | inline operator Directory *() {return Dir == Owner->DirP?0:Dir;}; |
| 228 | inline operator Directory const *() const {return Dir == Owner->DirP?0:Dir;}; |
| 229 | |
| 230 | inline const char *Name() const {return Dir->Name == 0?0:Owner->StrP + Dir->Name;}; |
| 231 | |
| 232 | DirIterator() : Dir(0), Owner(0) {}; |
| 233 | DirIterator(pkgFLCache &Owner,Directory *Trg) : Dir(Trg), Owner(&Owner) {}; |
| 234 | }; |
| 235 | |
| 236 | class pkgFLCache::DiverIterator |
| 237 | { |
| 238 | Diversion *Diver; |
| 239 | pkgFLCache *Owner; |
| 240 | |
| 241 | public: |
| 242 | |
| 243 | // Iteration |
| 244 | void operator ++(int) {if (Diver != Owner->DiverP) Diver = Owner->DiverP + Diver->Next;}; |
| 245 | inline void operator ++() {operator ++(0);}; |
| 246 | inline bool end() const {return Owner == 0 || Diver == Owner->DiverP;}; |
| 247 | |
| 248 | // Accessors |
| 249 | inline Diversion *operator ->() {return Diver;}; |
| 250 | inline Diversion const *operator ->() const {return Diver;}; |
| 251 | inline Diversion const &operator *() const {return *Diver;}; |
| 252 | inline operator Diversion *() {return Diver == Owner->DiverP?0:Diver;}; |
| 253 | inline operator Diversion const *() const {return Diver == Owner->DiverP?0:Diver;}; |
| 254 | |
| 255 | inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Diver->OwnerPkg);}; |
| 256 | inline NodeIterator DivertFrom() const; |
| 257 | inline NodeIterator DivertTo() const; |
| 258 | |
| 259 | DiverIterator() : Diver(0), Owner(0) {}; |
| 260 | DiverIterator(pkgFLCache &Owner,Diversion *Trg) : Diver(Trg), Owner(&Owner) {}; |
| 261 | }; |
| 262 | |
| 263 | class pkgFLCache::NodeIterator |
| 264 | { |
| 265 | Node *Nde; |
| 266 | enum {NdePkg, NdeHash} Type; |
| 267 | pkgFLCache *Owner; |
| 268 | |
| 269 | public: |
| 270 | |
| 271 | // Iteration |
| 272 | void operator ++(int) {if (Nde != Owner->NodeP) Nde = Owner->NodeP + |
| 273 | (Type == NdePkg?Nde->NextPkg:Nde->Next);}; |
| 274 | inline void operator ++() {operator ++(0);}; |
| 275 | inline bool end() const {return Owner == 0 || Nde == Owner->NodeP;}; |
| 276 | |
| 277 | // Accessors |
| 278 | inline Node *operator ->() {return Nde;}; |
| 279 | inline Node const *operator ->() const {return Nde;}; |
| 280 | inline Node const &operator *() const {return *Nde;}; |
| 281 | inline operator Node *() {return Nde == Owner->NodeP?0:Nde;}; |
| 282 | inline operator Node const *() const {return Nde == Owner->NodeP?0:Nde;}; |
| 283 | inline unsigned long Offset() const {return Nde - Owner->NodeP;}; |
| 284 | inline DirIterator Dir() const {return DirIterator(*Owner,Owner->DirP + Nde->Dir);}; |
| 285 | inline DiverIterator Diversion() const {return DiverIterator(*Owner,Owner->DiverP + Nde->Pointer);}; |
| 286 | inline const char *File() const {return Nde->File == 0?0:Owner->StrP + Nde->File;}; |
| 287 | inline const char *DirN() const {return Owner->StrP + Owner->DirP[Nde->Dir].Name;}; |
| 288 | Package *RealPackage() const; |
| 289 | |
| 290 | NodeIterator() : Nde(0), Type(NdeHash), Owner(0) {}; |
| 291 | NodeIterator(pkgFLCache &Owner) : Nde(Owner.NodeP), Type(NdeHash), Owner(&Owner) {}; |
| 292 | NodeIterator(pkgFLCache &Owner,Node *Trg) : Nde(Trg), Type(NdeHash), Owner(&Owner) {}; |
| 293 | NodeIterator(pkgFLCache &Owner,Node *Trg,Package *) : Nde(Trg), Type(NdePkg), Owner(&Owner) {}; |
| 294 | }; |
| 295 | |
| 296 | /* Inlines with forward references that cannot be included directly in their |
| 297 | respsective classes */ |
| 298 | inline pkgFLCache::NodeIterator pkgFLCache::DiverIterator::DivertFrom() const |
| 299 | {return NodeIterator(*Owner,Owner->NodeP + Diver->DivertFrom);}; |
| 300 | inline pkgFLCache::NodeIterator pkgFLCache::DiverIterator::DivertTo() const |
| 301 | {return NodeIterator(*Owner,Owner->NodeP + Diver->DivertTo);}; |
| 302 | |
| 303 | inline pkgFLCache::NodeIterator pkgFLCache::PkgIterator::Files() const |
| 304 | {return NodeIterator(*Owner,Owner->NodeP + Pkg->Files,Pkg);}; |
| 305 | |
| 306 | inline pkgFLCache::DiverIterator pkgFLCache::DiverBegin() |
| 307 | {return DiverIterator(*this,DiverP + HeaderP->Diversions);}; |
| 308 | |
| 309 | inline pkgFLCache::PkgIterator pkgFLCache::GetPkg(const char *Name,bool Insert) |
| 310 | {return GetPkg(Name,Name+strlen(Name),Insert);}; |
| 311 | |
| 312 | #endif |