| 1 | // -*- mode: cpp; mode: fold -*- |
| 2 | // Description /*{{{*/ |
| 3 | // $Id: acquire.h,v 1.29.2.1 2003/12/24 23:09:17 mdz 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 | |
| 33 | /** \defgroup acquire Acquire system {{{ |
| 34 | * |
| 35 | * \brief The Acquire system is responsible for retrieving files from |
| 36 | * local or remote URIs and postprocessing them (for instance, |
| 37 | * verifying their authenticity). The core class in this system is |
| 38 | * pkgAcquire, which is responsible for managing the download queues |
| 39 | * during the download. There is at least one download queue for |
| 40 | * each supported protocol; protocols such as http may provide one |
| 41 | * queue per host. |
| 42 | * |
| 43 | * Each file to download is represented by a subclass of |
| 44 | * pkgAcquire::Item. The files add themselves to the download |
| 45 | * queue(s) by providing their URI information to |
| 46 | * pkgAcquire::Item::QueueURI, which calls pkgAcquire::Enqueue. |
| 47 | * |
| 48 | * Once the system is set up, the Run method will spawn subprocesses |
| 49 | * to handle the enqueued URIs; the scheduler will then take items |
| 50 | * from the queues and feed them into the handlers until the queues |
| 51 | * are empty. |
| 52 | * |
| 53 | * \todo Acquire supports inserting an object into several queues at |
| 54 | * once, but it is not clear what its behavior in this case is, and |
| 55 | * no subclass of pkgAcquire::Item seems to actually use this |
| 56 | * capability. |
| 57 | */ /*}}}*/ |
| 58 | |
| 59 | /** \addtogroup acquire |
| 60 | * |
| 61 | * @{ |
| 62 | * |
| 63 | * \file acquire.h |
| 64 | */ |
| 65 | |
| 66 | #ifndef PKGLIB_ACQUIRE_H |
| 67 | #define PKGLIB_ACQUIRE_H |
| 68 | |
| 69 | #include <apt-pkg/macros.h> |
| 70 | #include <apt-pkg/weakptr.h> |
| 71 | |
| 72 | #include <vector> |
| 73 | #include <string> |
| 74 | |
| 75 | #include <stddef.h> |
| 76 | #include <sys/time.h> |
| 77 | #include <sys/select.h> |
| 78 | |
| 79 | #ifndef APT_10_CLEANER_HEADERS |
| 80 | #include <unistd.h> |
| 81 | #endif |
| 82 | |
| 83 | #ifndef APT_8_CLEANER_HEADERS |
| 84 | using std::vector; |
| 85 | using std::string; |
| 86 | #endif |
| 87 | |
| 88 | class pkgAcquireStatus; |
| 89 | |
| 90 | /** \brief The core download scheduler. {{{ |
| 91 | * |
| 92 | * This class represents an ongoing download. It manages the lists |
| 93 | * of active and pending downloads and handles setting up and tearing |
| 94 | * down download-related structures. |
| 95 | * |
| 96 | * \todo Why all the protected data items and methods? |
| 97 | */ |
| 98 | class pkgAcquire |
| 99 | { |
| 100 | private: |
| 101 | /** \brief FD of the Lock file we acquire in Setup (if any) */ |
| 102 | int LockFD; |
| 103 | /** \brief dpointer placeholder (for later in case we need it) */ |
| 104 | void *d; |
| 105 | |
| 106 | public: |
| 107 | |
| 108 | class Item; |
| 109 | class Queue; |
| 110 | class Worker; |
| 111 | struct MethodConfig; |
| 112 | struct ItemDesc; |
| 113 | friend class Item; |
| 114 | friend class Queue; |
| 115 | |
| 116 | typedef std::vector<Item *>::iterator ItemIterator; |
| 117 | typedef std::vector<Item *>::const_iterator ItemCIterator; |
| 118 | |
| 119 | protected: |
| 120 | |
| 121 | /** \brief A list of items to download. |
| 122 | * |
| 123 | * This is built monotonically as items are created and only |
| 124 | * emptied when the download shuts down. |
| 125 | */ |
| 126 | std::vector<Item *> Items; |
| 127 | |
| 128 | /** \brief The head of the list of active queues. |
| 129 | * |
| 130 | * \todo why a hand-managed list of queues instead of std::list or |
| 131 | * std::set? |
| 132 | */ |
| 133 | Queue *Queues; |
| 134 | |
| 135 | /** \brief The head of the list of active workers. |
| 136 | * |
| 137 | * \todo why a hand-managed list of workers instead of std::list |
| 138 | * or std::set? |
| 139 | */ |
| 140 | Worker *Workers; |
| 141 | |
| 142 | /** \brief The head of the list of acquire method configurations. |
| 143 | * |
| 144 | * Each protocol (http, ftp, gzip, etc) via which files can be |
| 145 | * fetched can have a representation in this list. The |
| 146 | * configuration data is filled in by parsing the 100 Capabilities |
| 147 | * string output by a method on startup (see |
| 148 | * pkgAcqMethod::pkgAcqMethod and pkgAcquire::GetConfig). |
| 149 | * |
| 150 | * \todo why a hand-managed config dictionary instead of std::map? |
| 151 | */ |
| 152 | MethodConfig *Configs; |
| 153 | |
| 154 | /** \brief The progress indicator for this download. */ |
| 155 | pkgAcquireStatus *Log; |
| 156 | |
| 157 | /** \brief The number of files which are to be fetched. */ |
| 158 | unsigned long ToFetch; |
| 159 | |
| 160 | // Configurable parameters for the scheduler |
| 161 | |
| 162 | /** \brief Represents the queuing strategy for remote URIs. */ |
| 163 | enum QueueStrategy { |
| 164 | /** \brief Generate one queue for each protocol/host combination; downloads from |
| 165 | * multiple hosts can proceed in parallel. |
| 166 | */ |
| 167 | QueueHost, |
| 168 | /** \brief Generate a single queue for each protocol; serialize |
| 169 | * downloads from multiple hosts. |
| 170 | */ |
| 171 | QueueAccess} QueueMode; |
| 172 | |
| 173 | /** \brief If \b true, debugging information will be dumped to std::clog. */ |
| 174 | bool const Debug; |
| 175 | /** \brief If \b true, a download is currently in progress. */ |
| 176 | bool Running; |
| 177 | |
| 178 | /** \brief Add the given item to the list of items. */ |
| 179 | void Add(Item *Item); |
| 180 | |
| 181 | /** \brief Remove the given item from the list of items. */ |
| 182 | void Remove(Item *Item); |
| 183 | |
| 184 | /** \brief Add the given worker to the list of workers. */ |
| 185 | void Add(Worker *Work); |
| 186 | |
| 187 | /** \brief Remove the given worker from the list of workers. */ |
| 188 | void Remove(Worker *Work); |
| 189 | |
| 190 | /** \brief Insert the given fetch request into the appropriate queue. |
| 191 | * |
| 192 | * \param Item The URI to download and the item to download it |
| 193 | * for. Copied by value into the queue; no reference to Item is |
| 194 | * retained. |
| 195 | */ |
| 196 | void Enqueue(ItemDesc &Item); |
| 197 | |
| 198 | /** \brief Remove all fetch requests for this item from all queues. */ |
| 199 | void Dequeue(Item *Item); |
| 200 | |
| 201 | /** \brief Determine the fetch method and queue of a URI. |
| 202 | * |
| 203 | * \param URI The URI to fetch. |
| 204 | * |
| 205 | * \param[out] Config A location in which to place the method via |
| 206 | * which the URI is to be fetched. |
| 207 | * |
| 208 | * \return the string-name of the queue in which a fetch request |
| 209 | * for the given URI should be placed. |
| 210 | */ |
| 211 | std::string QueueName(std::string URI,MethodConfig const *&Config); |
| 212 | |
| 213 | /** \brief Build up the set of file descriptors upon which select() should |
| 214 | * block. |
| 215 | * |
| 216 | * The default implementation inserts the file descriptors |
| 217 | * corresponding to active downloads. |
| 218 | * |
| 219 | * \param[out] Fd The largest file descriptor in the generated sets. |
| 220 | * |
| 221 | * \param[out] RSet The set of file descriptors that should be |
| 222 | * watched for input. |
| 223 | * |
| 224 | * \param[out] WSet The set of file descriptors that should be |
| 225 | * watched for output. |
| 226 | */ |
| 227 | virtual void SetFds(int &Fd,fd_set *RSet,fd_set *WSet); |
| 228 | |
| 229 | /** Handle input from and output to file descriptors which select() |
| 230 | * has determined are ready. The default implementation |
| 231 | * dispatches to all active downloads. |
| 232 | * |
| 233 | * \param RSet The set of file descriptors that are ready for |
| 234 | * input. |
| 235 | * |
| 236 | * \param WSet The set of file descriptors that are ready for |
| 237 | * output. |
| 238 | */ |
| 239 | virtual void RunFds(fd_set *RSet,fd_set *WSet); |
| 240 | |
| 241 | /** \brief Check for idle queues with ready-to-fetch items. |
| 242 | * |
| 243 | * Called by pkgAcquire::Queue::Done each time an item is dequeued |
| 244 | * but remains on some queues; i.e., another queue should start |
| 245 | * fetching it. |
| 246 | */ |
| 247 | void Bump(); |
| 248 | |
| 249 | public: |
| 250 | |
| 251 | /** \brief Retrieve information about a fetch method by name. |
| 252 | * |
| 253 | * \param Access The name of the method to look up. |
| 254 | * |
| 255 | * \return the method whose name is Access, or \b NULL if no such method exists. |
| 256 | */ |
| 257 | MethodConfig *GetConfig(std::string Access); |
| 258 | |
| 259 | /** \brief Provides information on how a download terminated. */ |
| 260 | enum RunResult { |
| 261 | /** \brief All files were fetched successfully. */ |
| 262 | Continue, |
| 263 | |
| 264 | /** \brief Some files failed to download. */ |
| 265 | Failed, |
| 266 | |
| 267 | /** \brief The download was cancelled by the user (i.e., #Log's |
| 268 | * pkgAcquireStatus::Pulse() method returned \b false). |
| 269 | */ |
| 270 | Cancelled}; |
| 271 | |
| 272 | /** \brief Download all the items that have been Add()ed to this |
| 273 | * download process. |
| 274 | * |
| 275 | * This method will block until the download completes, invoking |
| 276 | * methods on #Log to report on the progress of the download. |
| 277 | * |
| 278 | * \param PulseInterval The method pkgAcquireStatus::Pulse will be |
| 279 | * invoked on #Log at intervals of PulseInterval milliseconds. |
| 280 | * |
| 281 | * \return the result of the download. |
| 282 | */ |
| 283 | RunResult Run(int PulseInterval=500000); |
| 284 | |
| 285 | /** \brief Remove all items from this download process, terminate |
| 286 | * all download workers, and empty all queues. |
| 287 | */ |
| 288 | void Shutdown(); |
| 289 | |
| 290 | /** \brief Get the first Worker object. |
| 291 | * |
| 292 | * \return the first active worker in this download process. |
| 293 | */ |
| 294 | inline Worker *WorkersBegin() {return Workers;}; |
| 295 | |
| 296 | /** \brief Advance to the next Worker object. |
| 297 | * |
| 298 | * \return the worker immediately following I, or \b NULL if none |
| 299 | * exists. |
| 300 | */ |
| 301 | Worker *WorkerStep(Worker *I) APT_PURE; |
| 302 | |
| 303 | /** \brief Get the head of the list of items. */ |
| 304 | inline ItemIterator ItemsBegin() {return Items.begin();}; |
| 305 | |
| 306 | /** \brief Get the end iterator of the list of items. */ |
| 307 | inline ItemIterator ItemsEnd() {return Items.end();}; |
| 308 | |
| 309 | // Iterate over queued Item URIs |
| 310 | class UriIterator; |
| 311 | /** \brief Get the head of the list of enqueued item URIs. |
| 312 | * |
| 313 | * This iterator will step over every element of every active |
| 314 | * queue. |
| 315 | */ |
| 316 | UriIterator UriBegin(); |
| 317 | /** \brief Get the end iterator of the list of enqueued item URIs. */ |
| 318 | UriIterator UriEnd(); |
| 319 | |
| 320 | /** Deletes each entry in the given directory that is not being |
| 321 | * downloaded by this object. For instance, when downloading new |
| 322 | * list files, calling Clean() will delete the old ones. |
| 323 | * |
| 324 | * \param Dir The directory to be cleaned out. |
| 325 | * |
| 326 | * \return \b true if the directory exists and is readable. |
| 327 | */ |
| 328 | bool Clean(std::string Dir); |
| 329 | |
| 330 | /** \return the total size in bytes of all the items included in |
| 331 | * this download. |
| 332 | */ |
| 333 | unsigned long long TotalNeeded(); |
| 334 | |
| 335 | /** \return the size in bytes of all non-local items included in |
| 336 | * this download. |
| 337 | */ |
| 338 | unsigned long long FetchNeeded(); |
| 339 | |
| 340 | /** \return the amount of data to be fetched that is already |
| 341 | * present on the filesystem. |
| 342 | */ |
| 343 | unsigned long long PartialPresent(); |
| 344 | |
| 345 | /** \brief Delayed constructor |
| 346 | * |
| 347 | * \param Progress indicator associated with this download or |
| 348 | * \b NULL for none. This object is not owned by the |
| 349 | * download process and will not be deleted when the pkgAcquire |
| 350 | * object is destroyed. Naturally, it should live for at least as |
| 351 | * long as the pkgAcquire object does. |
| 352 | * \param Lock defines a lock file that should be acquired to ensure |
| 353 | * only one Acquire class is in action at the time or an empty string |
| 354 | * if no lock file should be used. |
| 355 | */ |
| 356 | bool Setup(pkgAcquireStatus *Progress = NULL, std::string const &Lock = ""); |
| 357 | |
| 358 | void SetLog(pkgAcquireStatus *Progress) { Log = Progress; } |
| 359 | |
| 360 | /** \brief Construct a new pkgAcquire. */ |
| 361 | pkgAcquire(pkgAcquireStatus *Log) APT_DEPRECATED; |
| 362 | pkgAcquire(); |
| 363 | |
| 364 | /** \brief Destroy this pkgAcquire object. |
| 365 | * |
| 366 | * Destroys all queue, method, and item objects associated with |
| 367 | * this download. |
| 368 | */ |
| 369 | virtual ~pkgAcquire(); |
| 370 | |
| 371 | }; |
| 372 | |
| 373 | /** \brief Represents a single download source from which an item |
| 374 | * should be downloaded. |
| 375 | * |
| 376 | * An item may have several assocated ItemDescs over its lifetime. |
| 377 | */ |
| 378 | struct pkgAcquire::ItemDesc : public WeakPointable |
| 379 | { |
| 380 | /** \brief The URI from which to download this item. */ |
| 381 | std::string URI; |
| 382 | /** brief A description of this item. */ |
| 383 | std::string Description; |
| 384 | /** brief A shorter description of this item. */ |
| 385 | std::string ShortDesc; |
| 386 | /** brief The underlying item which is to be downloaded. */ |
| 387 | Item *Owner; |
| 388 | }; |
| 389 | /*}}}*/ |
| 390 | /** \brief A single download queue in a pkgAcquire object. {{{ |
| 391 | * |
| 392 | * \todo Why so many protected values? |
| 393 | */ |
| 394 | class pkgAcquire::Queue |
| 395 | { |
| 396 | friend class pkgAcquire; |
| 397 | friend class pkgAcquire::UriIterator; |
| 398 | friend class pkgAcquire::Worker; |
| 399 | |
| 400 | /** \brief dpointer placeholder (for later in case we need it) */ |
| 401 | void *d; |
| 402 | |
| 403 | /** \brief The next queue in the pkgAcquire object's list of queues. */ |
| 404 | Queue *Next; |
| 405 | |
| 406 | protected: |
| 407 | |
| 408 | /** \brief A single item placed in this queue. */ |
| 409 | struct QItem : pkgAcquire::ItemDesc |
| 410 | { |
| 411 | /** \brief The next item in the queue. */ |
| 412 | QItem *Next; |
| 413 | /** \brief The worker associated with this item, if any. */ |
| 414 | pkgAcquire::Worker *Worker; |
| 415 | |
| 416 | /** \brief Assign the ItemDesc portion of this QItem from |
| 417 | * another ItemDesc |
| 418 | */ |
| 419 | void operator =(pkgAcquire::ItemDesc const &I) |
| 420 | { |
| 421 | URI = I.URI; |
| 422 | Description = I.Description; |
| 423 | ShortDesc = I.ShortDesc; |
| 424 | Owner = I.Owner; |
| 425 | }; |
| 426 | }; |
| 427 | |
| 428 | /** \brief The name of this queue. */ |
| 429 | std::string Name; |
| 430 | |
| 431 | /** \brief The head of the list of items contained in this queue. |
| 432 | * |
| 433 | * \todo why a by-hand list instead of an STL structure? |
| 434 | */ |
| 435 | QItem *Items; |
| 436 | |
| 437 | /** \brief The head of the list of workers associated with this queue. |
| 438 | * |
| 439 | * \todo This is plural because support exists in Queue for |
| 440 | * multiple workers. However, it does not appear that there is |
| 441 | * any way to actually associate more than one worker with a |
| 442 | * queue. |
| 443 | * |
| 444 | * \todo Why not just use a std::set? |
| 445 | */ |
| 446 | pkgAcquire::Worker *Workers; |
| 447 | |
| 448 | /** \brief the download scheduler with which this queue is associated. */ |
| 449 | pkgAcquire *Owner; |
| 450 | |
| 451 | /** \brief The number of entries in this queue that are currently |
| 452 | * being downloaded. |
| 453 | */ |
| 454 | signed long PipeDepth; |
| 455 | |
| 456 | /** \brief The maximum number of entries that this queue will |
| 457 | * attempt to download at once. |
| 458 | */ |
| 459 | unsigned long MaxPipeDepth; |
| 460 | |
| 461 | public: |
| 462 | |
| 463 | /** \brief Insert the given fetch request into this queue. |
| 464 | * |
| 465 | * \return \b true if the queuing was successful. May return |
| 466 | * \b false if the Item is already in the queue |
| 467 | */ |
| 468 | bool Enqueue(ItemDesc &Item); |
| 469 | |
| 470 | /** \brief Remove all fetch requests for the given item from this queue. |
| 471 | * |
| 472 | * \return \b true if at least one request was removed from the queue. |
| 473 | */ |
| 474 | bool Dequeue(Item *Owner); |
| 475 | |
| 476 | /** \brief Locate an item in this queue. |
| 477 | * |
| 478 | * \param URI A URI to match against. |
| 479 | * \param Owner A pkgAcquire::Worker to match against. |
| 480 | * |
| 481 | * \return the first item in the queue whose URI is #URI and that |
| 482 | * is being downloaded by #Owner. |
| 483 | */ |
| 484 | QItem *FindItem(std::string URI,pkgAcquire::Worker *Owner) APT_PURE; |
| 485 | |
| 486 | /** Presumably this should start downloading an item? |
| 487 | * |
| 488 | * \todo Unimplemented. Implement it or remove? |
| 489 | */ |
| 490 | bool ItemStart(QItem *Itm,unsigned long long Size); |
| 491 | |
| 492 | /** \brief Remove the given item from this queue and set its state |
| 493 | * to pkgAcquire::Item::StatDone. |
| 494 | * |
| 495 | * If this is the only queue containing the item, the item is also |
| 496 | * removed from the main queue by calling pkgAcquire::Dequeue. |
| 497 | * |
| 498 | * \param Itm The item to remove. |
| 499 | * |
| 500 | * \return \b true if no errors are encountered. |
| 501 | */ |
| 502 | bool ItemDone(QItem *Itm); |
| 503 | |
| 504 | /** \brief Start the worker process associated with this queue. |
| 505 | * |
| 506 | * If a worker process is already associated with this queue, |
| 507 | * this is equivalent to calling Cycle(). |
| 508 | * |
| 509 | * \return \b true if the startup was successful. |
| 510 | */ |
| 511 | bool Startup(); |
| 512 | |
| 513 | /** \brief Shut down the worker process associated with this queue. |
| 514 | * |
| 515 | * \param Final If \b true, then the process is stopped unconditionally. |
| 516 | * Otherwise, it is only stopped if it does not need cleanup |
| 517 | * as indicated by the pkgAcqMethod::NeedsCleanup member of |
| 518 | * its configuration. |
| 519 | * |
| 520 | * \return \b true. |
| 521 | */ |
| 522 | bool Shutdown(bool Final); |
| 523 | |
| 524 | /** \brief Send idle items to the worker process. |
| 525 | * |
| 526 | * Fills up the pipeline by inserting idle items into the worker's queue. |
| 527 | */ |
| 528 | bool Cycle(); |
| 529 | |
| 530 | /** \brief Check for items that could be enqueued. |
| 531 | * |
| 532 | * Call this after an item placed in multiple queues has gone from |
| 533 | * the pkgAcquire::Item::StatFetching state to the |
| 534 | * pkgAcquire::Item::StatIdle state, to possibly refill an empty queue. |
| 535 | * This is an alias for Cycle(). |
| 536 | * |
| 537 | * \todo Why both this and Cycle()? Are they expected to be |
| 538 | * different someday? |
| 539 | */ |
| 540 | void Bump(); |
| 541 | |
| 542 | /** \brief Create a new Queue. |
| 543 | * |
| 544 | * \param Name The name of the new queue. |
| 545 | * \param Owner The download process that owns the new queue. |
| 546 | */ |
| 547 | Queue(std::string Name,pkgAcquire *Owner); |
| 548 | |
| 549 | /** Shut down all the worker processes associated with this queue |
| 550 | * and empty the queue. |
| 551 | */ |
| 552 | virtual ~Queue(); |
| 553 | }; |
| 554 | /*}}}*/ |
| 555 | /** \brief Iterates over all the URIs being fetched by a pkgAcquire object. {{{*/ |
| 556 | class pkgAcquire::UriIterator |
| 557 | { |
| 558 | /** \brief dpointer placeholder (for later in case we need it) */ |
| 559 | void *d; |
| 560 | |
| 561 | /** The next queue to iterate over. */ |
| 562 | pkgAcquire::Queue *CurQ; |
| 563 | /** The item that we currently point at. */ |
| 564 | pkgAcquire::Queue::QItem *CurItem; |
| 565 | |
| 566 | public: |
| 567 | |
| 568 | inline void operator ++() {operator ++(0);}; |
| 569 | |
| 570 | void operator ++(int) |
| 571 | { |
| 572 | CurItem = CurItem->Next; |
| 573 | while (CurItem == 0 && CurQ != 0) |
| 574 | { |
| 575 | CurItem = CurQ->Items; |
| 576 | CurQ = CurQ->Next; |
| 577 | } |
| 578 | }; |
| 579 | |
| 580 | inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;}; |
| 581 | inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;}; |
| 582 | inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;}; |
| 583 | |
| 584 | /** \brief Create a new UriIterator. |
| 585 | * |
| 586 | * \param Q The queue over which this UriIterator should iterate. |
| 587 | */ |
| 588 | UriIterator(pkgAcquire::Queue *Q) : CurQ(Q), CurItem(0) |
| 589 | { |
| 590 | while (CurItem == 0 && CurQ != 0) |
| 591 | { |
| 592 | CurItem = CurQ->Items; |
| 593 | CurQ = CurQ->Next; |
| 594 | } |
| 595 | } |
| 596 | virtual ~UriIterator() {}; |
| 597 | }; |
| 598 | /*}}}*/ |
| 599 | /** \brief Information about the properties of a single acquire method. {{{*/ |
| 600 | struct pkgAcquire::MethodConfig |
| 601 | { |
| 602 | /** \brief dpointer placeholder (for later in case we need it) */ |
| 603 | void *d; |
| 604 | |
| 605 | /** \brief The next link on the acquire method list. |
| 606 | * |
| 607 | * \todo Why not an STL container? |
| 608 | */ |
| 609 | MethodConfig *Next; |
| 610 | |
| 611 | /** \brief The name of this acquire method (e.g., http). */ |
| 612 | std::string Access; |
| 613 | |
| 614 | /** \brief The implementation version of this acquire method. */ |
| 615 | std::string Version; |
| 616 | |
| 617 | /** \brief If \b true, only one download queue should be created for this |
| 618 | * method. |
| 619 | */ |
| 620 | bool SingleInstance; |
| 621 | |
| 622 | /** \brief If \b true, this method supports pipelined downloading. */ |
| 623 | bool Pipeline; |
| 624 | |
| 625 | /** \brief If \b true, the worker process should send the entire |
| 626 | * APT configuration tree to the fetch subprocess when it starts |
| 627 | * up. |
| 628 | */ |
| 629 | bool SendConfig; |
| 630 | |
| 631 | /** \brief If \b true, this fetch method does not require network access; |
| 632 | * all files are to be acquired from the local disk. |
| 633 | */ |
| 634 | bool LocalOnly; |
| 635 | |
| 636 | /** \brief If \b true, the subprocess has to carry out some cleanup |
| 637 | * actions before shutting down. |
| 638 | * |
| 639 | * For instance, the cdrom method needs to unmount the CD after it |
| 640 | * finishes. |
| 641 | */ |
| 642 | bool NeedsCleanup; |
| 643 | |
| 644 | /** \brief If \b true, this fetch method acquires files from removable media. */ |
| 645 | bool Removable; |
| 646 | |
| 647 | /** \brief Set up the default method parameters. |
| 648 | * |
| 649 | * All fields are initialized to NULL, "", or \b false as |
| 650 | * appropriate. |
| 651 | */ |
| 652 | MethodConfig(); |
| 653 | |
| 654 | /* \brief Destructor, empty currently */ |
| 655 | virtual ~MethodConfig() {}; |
| 656 | }; |
| 657 | /*}}}*/ |
| 658 | /** \brief A monitor object for downloads controlled by the pkgAcquire class. {{{ |
| 659 | * |
| 660 | * \todo Why protected members? |
| 661 | */ |
| 662 | class pkgAcquireStatus |
| 663 | { |
| 664 | /** \brief dpointer placeholder (for later in case we need it) */ |
| 665 | void *d; |
| 666 | |
| 667 | protected: |
| 668 | |
| 669 | /** \brief The last time at which this monitor object was updated. */ |
| 670 | struct timeval Time; |
| 671 | |
| 672 | /** \brief The time at which the download started. */ |
| 673 | struct timeval StartTime; |
| 674 | |
| 675 | /** \brief The number of bytes fetched as of the previous call to |
| 676 | * pkgAcquireStatus::Pulse, including local items. |
| 677 | */ |
| 678 | unsigned long long LastBytes; |
| 679 | |
| 680 | /** \brief The current rate of download as of the most recent call |
| 681 | * to pkgAcquireStatus::Pulse, in bytes per second. |
| 682 | */ |
| 683 | unsigned long long CurrentCPS; |
| 684 | |
| 685 | /** \brief The number of bytes fetched as of the most recent call |
| 686 | * to pkgAcquireStatus::Pulse, including local items. |
| 687 | */ |
| 688 | unsigned long long CurrentBytes; |
| 689 | |
| 690 | /** \brief The total number of bytes that need to be fetched. |
| 691 | * |
| 692 | * \warning This member is inaccurate, as new items might be |
| 693 | * enqueued while the download is in progress! |
| 694 | */ |
| 695 | unsigned long long TotalBytes; |
| 696 | |
| 697 | /** \brief The total number of bytes accounted for by items that |
| 698 | * were successfully fetched. |
| 699 | */ |
| 700 | unsigned long long FetchedBytes; |
| 701 | |
| 702 | /** \brief The amount of time that has elapsed since the download |
| 703 | * started. |
| 704 | */ |
| 705 | unsigned long long ElapsedTime; |
| 706 | |
| 707 | /** \brief The total number of items that need to be fetched. |
| 708 | * |
| 709 | * \warning This member is inaccurate, as new items might be |
| 710 | * enqueued while the download is in progress! |
| 711 | */ |
| 712 | unsigned long TotalItems; |
| 713 | |
| 714 | /** \brief The number of items that have been successfully downloaded. */ |
| 715 | unsigned long CurrentItems; |
| 716 | |
| 717 | public: |
| 718 | |
| 719 | /** \brief If \b true, the download scheduler should call Pulse() |
| 720 | * at the next available opportunity. |
| 721 | */ |
| 722 | bool Update; |
| 723 | |
| 724 | /** \brief If \b true, extra Pulse() invocations will be performed. |
| 725 | * |
| 726 | * With this option set, Pulse() will be called every time that a |
| 727 | * download item starts downloading, finishes downloading, or |
| 728 | * terminates with an error. |
| 729 | */ |
| 730 | bool MorePulses; |
| 731 | |
| 732 | /** \brief Invoked when a local or remote file has been completely fetched. |
| 733 | * |
| 734 | * \param Size The size of the file fetched. |
| 735 | * |
| 736 | * \param ResumePoint How much of the file was already fetched. |
| 737 | */ |
| 738 | virtual void Fetched(unsigned long long Size,unsigned long long ResumePoint); |
| 739 | |
| 740 | /** \brief Invoked when the user should be prompted to change the |
| 741 | * inserted removable media. |
| 742 | * |
| 743 | * This method should not return until the user has confirmed to |
| 744 | * the user interface that the media change is complete. |
| 745 | * |
| 746 | * \param Media The name of the media type that should be changed. |
| 747 | * |
| 748 | * \param Drive The identifying name of the drive whose media |
| 749 | * should be changed. |
| 750 | * |
| 751 | * \return \b true if the user confirms the media change, \b |
| 752 | * false if it is cancelled. |
| 753 | * |
| 754 | * \todo This is a horrible blocking monster; it should be CPSed |
| 755 | * with prejudice. |
| 756 | */ |
| 757 | virtual bool MediaChange(std::string Media,std::string Drive) = 0; |
| 758 | |
| 759 | /** \brief Invoked when an item is confirmed to be up-to-date. |
| 760 | |
| 761 | * For instance, when an HTTP download is informed that the file on |
| 762 | * the server was not modified. |
| 763 | */ |
| 764 | virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 765 | |
| 766 | /** \brief Invoked when some of an item's data is fetched. */ |
| 767 | virtual void Fetch(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 768 | |
| 769 | /** \brief Invoked when an item is successfully and completely fetched. */ |
| 770 | virtual void Done(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 771 | |
| 772 | /** \brief Invoked when the process of fetching an item encounters |
| 773 | * a fatal error. |
| 774 | */ |
| 775 | virtual void Fail(pkgAcquire::ItemDesc &/*Itm*/) {}; |
| 776 | |
| 777 | /** \brief Periodically invoked while the Acquire process is underway. |
| 778 | * |
| 779 | * Subclasses should first call pkgAcquireStatus::Pulse(), then |
| 780 | * update their status output. The download process is blocked |
| 781 | * while Pulse() is being called. |
| 782 | * |
| 783 | * \return \b false if the user asked to cancel the whole Acquire process. |
| 784 | * |
| 785 | * \see pkgAcquire::Run |
| 786 | */ |
| 787 | virtual bool Pulse(pkgAcquire *Owner); |
| 788 | |
| 789 | /** \brief Invoked when the Acquire process starts running. */ |
| 790 | virtual void Start(); |
| 791 | |
| 792 | /** \brief Invoked when the Acquire process stops running. */ |
| 793 | virtual void Stop(); |
| 794 | |
| 795 | /** \brief Initialize all counters to 0 and the time to the current time. */ |
| 796 | pkgAcquireStatus(); |
| 797 | virtual ~pkgAcquireStatus() {}; |
| 798 | }; |
| 799 | /*}}}*/ |
| 800 | /** @} */ |
| 801 | |
| 802 | #endif |