| 1 | // -*- mode: cpp; mode: fold -*- |
| 2 | // Description /*{{{*/ |
| 3 | // $Id: acquire.h,v 1.29 2001/05/22 04:17:18 jgg Exp $ |
| 4 | /* ###################################################################### |
| 5 | |
| 6 | Acquire - File Acquiration |
| 7 | |
| 8 | This module contians the Acquire system. It is responsible for bringing |
| 9 | files into the local pathname space. It deals with URIs for files and |
| 10 | URI handlers responsible for downloading or finding the URIs. |
| 11 | |
| 12 | Each file to download is represented by an Acquire::Item class subclassed |
| 13 | into a specialization. The Item class can add itself to several URI |
| 14 | acquire queues each prioritized by the download scheduler. When the |
| 15 | system is run the proper URI handlers are spawned and the the acquire |
| 16 | queues are fed into the handlers by the schedular until the queues are |
| 17 | empty. This allows for an Item to be downloaded from an alternate source |
| 18 | if the first try turns out to fail. It also alows concurrent downloading |
| 19 | of multiple items from multiple sources as well as dynamic balancing |
| 20 | of load between the sources. |
| 21 | |
| 22 | Schedualing of downloads is done on a first ask first get basis. This |
| 23 | preserves the order of the download as much as possible. And means the |
| 24 | fastest source will tend to process the largest number of files. |
| 25 | |
| 26 | Internal methods and queues for performing gzip decompression, |
| 27 | md5sum hashing and file copying are provided to allow items to apply |
| 28 | a number of transformations to the data files they are working with. |
| 29 | |
| 30 | ##################################################################### */ |
| 31 | /*}}}*/ |
| 32 | #ifndef PKGLIB_ACQUIRE_H |
| 33 | #define PKGLIB_ACQUIRE_H |
| 34 | |
| 35 | #include <vector> |
| 36 | #include <string> |
| 37 | |
| 38 | using std::vector; |
| 39 | using std::string; |
| 40 | |
| 41 | #ifdef __GNUG__ |
| 42 | #pragma interface "apt-pkg/acquire.h" |
| 43 | #endif |
| 44 | |
| 45 | #include <sys/time.h> |
| 46 | #include <unistd.h> |
| 47 | |
| 48 | class pkgAcquireStatus; |
| 49 | class pkgAcquire |
| 50 | { |
| 51 | public: |
| 52 | |
| 53 | class Item; |
| 54 | class Queue; |
| 55 | class Worker; |
| 56 | struct MethodConfig; |
| 57 | struct ItemDesc; |
| 58 | friend class Item; |
| 59 | friend class Queue; |
| 60 | |
| 61 | typedef vector<Item *>::iterator ItemIterator; |
| 62 | typedef vector<Item *>::const_iterator ItemCIterator; |
| 63 | |
| 64 | protected: |
| 65 | |
| 66 | // List of items to fetch |
| 67 | vector<Item *> Items; |
| 68 | |
| 69 | // List of active queues and fetched method configuration parameters |
| 70 | Queue *Queues; |
| 71 | Worker *Workers; |
| 72 | MethodConfig *Configs; |
| 73 | pkgAcquireStatus *Log; |
| 74 | unsigned long ToFetch; |
| 75 | |
| 76 | // Configurable parameters for the schedular |
| 77 | enum {QueueHost,QueueAccess} QueueMode; |
| 78 | bool Debug; |
| 79 | bool Running; |
| 80 | |
| 81 | void Add(Item *Item); |
| 82 | void Remove(Item *Item); |
| 83 | void Add(Worker *Work); |
| 84 | void Remove(Worker *Work); |
| 85 | |
| 86 | void Enqueue(ItemDesc &Item); |
| 87 | void Dequeue(Item *Item); |
| 88 | string QueueName(string URI,MethodConfig const *&Config); |
| 89 | |
| 90 | // FDSET managers for derived classes |
| 91 | virtual void SetFds(int &Fd,fd_set *RSet,fd_set *WSet); |
| 92 | virtual void RunFds(fd_set *RSet,fd_set *WSet); |
| 93 | |
| 94 | // A queue calls this when it dequeues an item |
| 95 | void Bump(); |
| 96 | |
| 97 | public: |
| 98 | |
| 99 | MethodConfig *GetConfig(string Access); |
| 100 | |
| 101 | enum RunResult {Continue,Failed,Cancelled}; |
| 102 | |
| 103 | RunResult Run(); |
| 104 | void Shutdown(); |
| 105 | |
| 106 | // Simple iteration mechanism |
| 107 | inline Worker *WorkersBegin() {return Workers;}; |
| 108 | Worker *WorkerStep(Worker *I); |
| 109 | inline ItemIterator ItemsBegin() {return Items.begin();}; |
| 110 | inline ItemIterator ItemsEnd() {return Items.end();}; |
| 111 | |
| 112 | // Iterate over queued Item URIs |
| 113 | class UriIterator; |
| 114 | UriIterator UriBegin(); |
| 115 | UriIterator UriEnd(); |
| 116 | |
| 117 | // Cleans out the download dir |
| 118 | bool Clean(string Dir); |
| 119 | |
| 120 | // Returns the size of the total download set |
| 121 | double TotalNeeded(); |
| 122 | double FetchNeeded(); |
| 123 | double PartialPresent(); |
| 124 | |
| 125 | pkgAcquire(pkgAcquireStatus *Log = 0); |
| 126 | virtual ~pkgAcquire(); |
| 127 | }; |
| 128 | |
| 129 | // Description of an Item+URI |
| 130 | struct pkgAcquire::ItemDesc |
| 131 | { |
| 132 | string URI; |
| 133 | string Description; |
| 134 | string ShortDesc; |
| 135 | Item *Owner; |
| 136 | }; |
| 137 | |
| 138 | // List of possible items queued for download. |
| 139 | class pkgAcquire::Queue |
| 140 | { |
| 141 | friend class pkgAcquire; |
| 142 | friend class pkgAcquire::UriIterator; |
| 143 | friend class pkgAcquire::Worker; |
| 144 | Queue *Next; |
| 145 | |
| 146 | protected: |
| 147 | |
| 148 | // Queued item |
| 149 | struct QItem : pkgAcquire::ItemDesc |
| 150 | { |
| 151 | QItem *Next; |
| 152 | pkgAcquire::Worker *Worker; |
| 153 | |
| 154 | void operator =(pkgAcquire::ItemDesc const &I) |
| 155 | { |
| 156 | URI = I.URI; |
| 157 | Description = I.Description; |
| 158 | ShortDesc = I.ShortDesc; |
| 159 | Owner = I.Owner; |
| 160 | }; |
| 161 | }; |
| 162 | |
| 163 | // Name of the queue |
| 164 | string Name; |
| 165 | |
| 166 | // Items queued into this queue |
| 167 | QItem *Items; |
| 168 | pkgAcquire::Worker *Workers; |
| 169 | pkgAcquire *Owner; |
| 170 | signed long PipeDepth; |
| 171 | unsigned long MaxPipeDepth; |
| 172 | |
| 173 | public: |
| 174 | |
| 175 | // Put an item into this queue |
| 176 | void Enqueue(ItemDesc &Item); |
| 177 | bool Dequeue(Item *Owner); |
| 178 | |
| 179 | // Find a Queued item |
| 180 | QItem *FindItem(string URI,pkgAcquire::Worker *Owner); |
| 181 | bool ItemStart(QItem *Itm,unsigned long Size); |
| 182 | bool ItemDone(QItem *Itm); |
| 183 | |
| 184 | bool Startup(); |
| 185 | bool Shutdown(bool Final); |
| 186 | bool Cycle(); |
| 187 | void Bump(); |
| 188 | |
| 189 | Queue(string Name,pkgAcquire *Owner); |
| 190 | ~Queue(); |
| 191 | }; |
| 192 | |
| 193 | class pkgAcquire::UriIterator |
| 194 | { |
| 195 | pkgAcquire::Queue *CurQ; |
| 196 | pkgAcquire::Queue::QItem *CurItem; |
| 197 | |
| 198 | public: |
| 199 | |
| 200 | // Advance to the next item |
| 201 | inline void operator ++() {operator ++();}; |
| 202 | void operator ++(int) |
| 203 | { |
| 204 | CurItem = CurItem->Next; |
| 205 | while (CurItem == 0 && CurQ != 0) |
| 206 | { |
| 207 | CurItem = CurQ->Items; |
| 208 | CurQ = CurQ->Next; |
| 209 | } |
| 210 | }; |
| 211 | |
| 212 | // Accessors |
| 213 | inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;}; |
| 214 | inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;}; |
| 215 | inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;}; |
| 216 | |
| 217 | UriIterator(pkgAcquire::Queue *Q) : CurQ(Q), CurItem(0) |
| 218 | { |
| 219 | while (CurItem == 0 && CurQ != 0) |
| 220 | { |
| 221 | CurItem = CurQ->Items; |
| 222 | CurQ = CurQ->Next; |
| 223 | } |
| 224 | } |
| 225 | }; |
| 226 | |
| 227 | // Configuration information from each method |
| 228 | struct pkgAcquire::MethodConfig |
| 229 | { |
| 230 | MethodConfig *Next; |
| 231 | |
| 232 | string Access; |
| 233 | |
| 234 | string Version; |
| 235 | bool SingleInstance; |
| 236 | bool Pipeline; |
| 237 | bool SendConfig; |
| 238 | bool LocalOnly; |
| 239 | bool NeedsCleanup; |
| 240 | bool Removable; |
| 241 | |
| 242 | MethodConfig(); |
| 243 | }; |
| 244 | |
| 245 | class pkgAcquireStatus |
| 246 | { |
| 247 | protected: |
| 248 | |
| 249 | struct timeval Time; |
| 250 | struct timeval StartTime; |
| 251 | double LastBytes; |
| 252 | double CurrentCPS; |
| 253 | double CurrentBytes; |
| 254 | double TotalBytes; |
| 255 | double FetchedBytes; |
| 256 | unsigned long ElapsedTime; |
| 257 | unsigned long TotalItems; |
| 258 | unsigned long CurrentItems; |
| 259 | |
| 260 | public: |
| 261 | |
| 262 | bool Update; |
| 263 | bool MorePulses; |
| 264 | |
| 265 | // Called by items when they have finished a real download |
| 266 | virtual void Fetched(unsigned long Size,unsigned long ResumePoint); |
| 267 | |
| 268 | // Called to change media |
| 269 | virtual bool MediaChange(string Media,string Drive) = 0; |
| 270 | |
| 271 | // Each of these is called by the workers when an event occures |
| 272 | virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 273 | virtual void Fetch(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 274 | virtual void Done(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 275 | virtual void Fail(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 276 | virtual bool Pulse(pkgAcquire *Owner); // returns false on user cancel |
| 277 | virtual void Start(); |
| 278 | virtual void Stop(); |
| 279 | |
| 280 | pkgAcquireStatus(); |
| 281 | virtual ~pkgAcquireStatus() {}; |
| 282 | }; |
| 283 | |
| 284 | #endif |