+ if (PipeDepth < 0)
+ return _error->Error("Pipedepth failure");
+
+ // Look for a queable item
+ QItem *I = Items;
+ while (PipeDepth < (signed)MaxPipeDepth)
+ {
+ for (; I != 0; I = I->Next)
+ if (I->Owner->Status == pkgAcquire::Item::StatIdle)
+ break;
+
+ // Nothing to do, queue is idle.
+ if (I == 0)
+ return true;
+
+ I->Worker = Workers;
+ I->Owner->Status = pkgAcquire::Item::StatFetching;
+ PipeDepth++;
+ if (Workers->QueueItem(I) == false)
+ return false;
+ }
+
+ return true;
+}
+ /*}}}*/
+// Queue::Bump - Fetch any pending objects if we are idle /*{{{*/
+// ---------------------------------------------------------------------
+/* This is called when an item in multiple queues is dequeued */
+void pkgAcquire::Queue::Bump()
+{
+ Cycle();
+}
+ /*}}}*/
+// AcquireStatus::pkgAcquireStatus - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Update(true), MorePulses(false)
+{
+ Start();
+}
+ /*}}}*/
+// AcquireStatus::Pulse - Called periodically /*{{{*/
+// ---------------------------------------------------------------------
+/* This computes some internal state variables for the derived classes to
+ use. It generates the current downloaded bytes and total bytes to download
+ as well as the current CPS estimate. */
+bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
+{
+ TotalBytes = 0;
+ CurrentBytes = 0;
+ TotalItems = 0;
+ CurrentItems = 0;
+
+ // Compute the total number of bytes to fetch
+ unsigned int Unknown = 0;
+ unsigned int Count = 0;
+ for (pkgAcquire::ItemCIterator I = Owner->ItemsBegin(); I != Owner->ItemsEnd();
+ ++I, ++Count)
+ {
+ TotalItems++;
+ if ((*I)->Status == pkgAcquire::Item::StatDone)
+ ++CurrentItems;
+
+ // Totally ignore local items
+ if ((*I)->Local == true)
+ continue;
+
+ TotalBytes += (*I)->FileSize;
+ if ((*I)->Complete == true)
+ CurrentBytes += (*I)->FileSize;
+ if ((*I)->FileSize == 0 && (*I)->Complete == false)
+ ++Unknown;
+ }
+
+ // Compute the current completion
+ unsigned long long ResumeSize = 0;
+ for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
+ I = Owner->WorkerStep(I))
+ if (I->CurrentItem != 0 && I->CurrentItem->Owner->Complete == false)
+ {
+ CurrentBytes += I->CurrentSize;
+ ResumeSize += I->ResumePoint;
+
+ // Files with unknown size always have 100% completion
+ if (I->CurrentItem->Owner->FileSize == 0 &&
+ I->CurrentItem->Owner->Complete == false)
+ TotalBytes += I->CurrentSize;
+ }
+
+ // Normalize the figures and account for unknown size downloads
+ if (TotalBytes <= 0)
+ TotalBytes = 1;
+ if (Unknown == Count)
+ TotalBytes = Unknown;
+
+ // Wha?! Is not supposed to happen.
+ if (CurrentBytes > TotalBytes)
+ CurrentBytes = TotalBytes;
+
+ // Compute the CPS
+ struct timeval NewTime;
+ gettimeofday(&NewTime,0);
+ if ((NewTime.tv_sec - Time.tv_sec == 6 && NewTime.tv_usec > Time.tv_usec) ||
+ NewTime.tv_sec - Time.tv_sec > 6)
+ {
+ double Delta = NewTime.tv_sec - Time.tv_sec +
+ (NewTime.tv_usec - Time.tv_usec)/1000000.0;
+
+ // Compute the CPS value
+ if (Delta < 0.01)
+ CurrentCPS = 0;
+ else
+ CurrentCPS = ((CurrentBytes - ResumeSize) - LastBytes)/Delta;
+ LastBytes = CurrentBytes - ResumeSize;
+ ElapsedTime = (unsigned long long)Delta;
+ Time = NewTime;
+ }
+
+ int fd = _config->FindI("APT::Status-Fd",-1);
+ if(fd > 0)
+ {
+ ostringstream status;
+
+ char msg[200];
+ long i = CurrentItems < TotalItems ? CurrentItems + 1 : CurrentItems;
+ unsigned long long ETA = 0;
+ if(CurrentCPS > 0)
+ ETA = (TotalBytes - CurrentBytes) / CurrentCPS;
+
+ // only show the ETA if it makes sense
+ if (ETA > 0 && ETA < 172800 /* two days */ )
+ snprintf(msg,sizeof(msg), _("Retrieving file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str());
+ else
+ snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems);
+
+
+
+ // build the status str
+ status << "dlstatus:" << i
+ << ":" << (CurrentBytes/float(TotalBytes)*100.0)
+ << ":" << msg
+ << endl;
+
+ std::string const dlstatus = status.str();
+ FileFd::Write(fd, dlstatus.c_str(), dlstatus.size());
+ }
+
+ return true;
+}
+ /*}}}*/
+// AcquireStatus::Start - Called when the download is started /*{{{*/
+// ---------------------------------------------------------------------
+/* We just reset the counters */
+void pkgAcquireStatus::Start()
+{
+ gettimeofday(&Time,0);
+ gettimeofday(&StartTime,0);
+ LastBytes = 0;
+ CurrentCPS = 0;
+ CurrentBytes = 0;
+ TotalBytes = 0;
+ FetchedBytes = 0;
+ ElapsedTime = 0;
+ TotalItems = 0;
+ CurrentItems = 0;
+}
+ /*}}}*/
+// AcquireStatus::Stop - Finished downloading /*{{{*/
+// ---------------------------------------------------------------------
+/* This accurately computes the elapsed time and the total overall CPS. */
+void pkgAcquireStatus::Stop()
+{
+ // Compute the CPS and elapsed time
+ struct timeval NewTime;
+ gettimeofday(&NewTime,0);
+
+ double Delta = NewTime.tv_sec - StartTime.tv_sec +
+ (NewTime.tv_usec - StartTime.tv_usec)/1000000.0;
+
+ // Compute the CPS value
+ if (Delta < 0.01)
+ CurrentCPS = 0;
+ else
+ CurrentCPS = FetchedBytes/Delta;
+ LastBytes = CurrentBytes;
+ ElapsedTime = (unsigned long long)Delta;
+}
+ /*}}}*/
+// AcquireStatus::Fetched - Called when a byte set has been fetched /*{{{*/
+// ---------------------------------------------------------------------
+/* This is used to get accurate final transfer rate reporting. */
+void pkgAcquireStatus::Fetched(unsigned long long Size,unsigned long long Resume)
+{
+ FetchedBytes += Size - Resume;