if (Config->SingleInstance == true || QueueMode == QueueAccess)
return U.Access;
- string AccessSchema = U.Access + ':',
- FullQueueName = AccessSchema + U.Host;
+ string AccessSchema = U.Access + ':';
+ string FullQueueName;
+
+ if (U.Host.empty())
+ {
+ long existing = 0;
+ // check how many queues exist already and reuse empty ones
+ for (Queue const *I = Queues; I != 0; I = I->Next)
+ if (I->Name.compare(0, AccessSchema.length(), AccessSchema) == 0)
+ {
+ if (I->Items == nullptr)
+ return I->Name;
+ ++existing;
+ }
+
+#ifdef _SC_NPROCESSORS_ONLN
+ long cpuCount = sysconf(_SC_NPROCESSORS_ONLN) * 2;
+#else
+ long cpuCount = 10;
+#endif
+ cpuCount = _config->FindI("Acquire::QueueHost::Limit", cpuCount);
+
+ if (cpuCount <= 0 || existing < cpuCount)
+ strprintf(FullQueueName, "%s%ld", AccessSchema.c_str(), existing);
+ else
+ {
+ long const randomQueue = random() % cpuCount;
+ strprintf(FullQueueName, "%s%ld", AccessSchema.c_str(), randomQueue);
+ }
+
+ if (Debug)
+ clog << "Chose random queue " << FullQueueName << " for " << Uri << endl;
+ } else
+ {
+ FullQueueName = AccessSchema + U.Host;
+ }
unsigned int Instances = 0, SchemaLength = AccessSchema.length();
Queue *I = Queues;
}
}
/*}}}*/
-// Acquire::RunFds - Deal with active FDs /*{{{*/
+// Acquire::RunFds - compatibility remove on next abi/api break /*{{{*/
+void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet)
+{
+ RunFdsSane(RSet, WSet);
+}
+ /*}}}*/
+// Acquire::RunFdsSane - Deal with active FDs /*{{{*/
// ---------------------------------------------------------------------
/* Dispatch active FDs over to the proper workers. It is very important
that a worker never be erased while this is running! The queue class
should never erase a worker except during shutdown processing. */
-void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet)
+bool pkgAcquire::RunFdsSane(fd_set *RSet,fd_set *WSet)
{
+ bool Res = true;
+
for (Worker *I = Workers; I != 0; I = I->NextAcquire)
{
if (I->InFd >= 0 && FD_ISSET(I->InFd,RSet) != 0)
- I->InFdReady();
+ Res &= I->InFdReady();
if (I->OutFd >= 0 && FD_ISSET(I->OutFd,WSet) != 0)
- I->OutFdReady();
+ Res &= I->OutFdReady();
}
+
+ return Res;
}
/*}}}*/
// Acquire::Run - Run the fetch sequence /*{{{*/
struct passwd const * const pw = getpwnam(SandboxUser.c_str());
if (pw == NULL)
+ {
+ _error->Warning(_("No sandbox user '%s' on the system, can not drop privileges"), SandboxUser.c_str());
+ _config->Set("APT::Sandbox::User", "");
return;
+ }
gid_t const old_euid = geteuid();
gid_t const old_egid = getegid();
I != Fetcher.ItemsEnd(); ++I)
{
// no need to drop privileges for a complete file
- if ((*I)->Complete == true)
+ if ((*I)->Complete == true || (*I)->Status != pkgAcquire::Item::StatIdle)
continue;
// if destination file is inaccessible all hope is lost for privilege dropping
break;
}
- RunFds(&RFds,&WFds);
+ if(RunFdsSane(&RFds,&WFds) == false)
+ break;
// Timeout, notify the log class
if (Res == 0 || (Log != 0 && Log->Update == true))
/* This is the total number of bytes needed */
APT_PURE unsigned long long pkgAcquire::TotalNeeded()
{
- return std::accumulate(ItemsBegin(), ItemsEnd(), 0,
+ return std::accumulate(ItemsBegin(), ItemsEnd(), 0llu,
[](unsigned long long const T, Item const * const I) {
return T + I->FileSize;
});
/* This is the number of bytes that is not local */
APT_PURE unsigned long long pkgAcquire::FetchNeeded()
{
- return std::accumulate(ItemsBegin(), ItemsEnd(), 0,
+ return std::accumulate(ItemsBegin(), ItemsEnd(), 0llu,
[](unsigned long long const T, Item const * const I) {
if (I->Local == false)
return T + I->FileSize;
/* This is the number of bytes that is not local */
APT_PURE unsigned long long pkgAcquire::PartialPresent()
{
- return std::accumulate(ItemsBegin(), ItemsEnd(), 0,
+ return std::accumulate(ItemsBegin(), ItemsEnd(), 0llu,
[](unsigned long long const T, Item const * const I) {
if (I->Local == false)
return T + I->PartialSize;
{
QItem **I = &Items;
// move to the end of the queue and check for duplicates here
- HashStringList const hsl = Item.Owner->GetExpectedHashes();
for (; *I != 0; I = &(*I)->Next)
- if (Item.URI == (*I)->URI || hsl == (*I)->Owner->GetExpectedHashes())
+ if (Item.URI == (*I)->URI)
{
if (_config->FindB("Debug::pkgAcquire::Worker",false) == true)
std::cerr << " @ Queue: Action combined for " << Item.URI << " and " << (*I)->URI << std::endl;
CurrentBytes = 0;
TotalItems = 0;
CurrentItems = 0;
-
+
// Compute the total number of bytes to fetch
unsigned int Unknown = 0;
unsigned int Count = 0;
- bool UnfetchedReleaseFiles = false;
+ bool ExpectAdditionalItems = false;
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;
-
- // see if the method tells us to expect more
- TotalItems += (*I)->ExpectedAdditionalItems;
- // check if there are unfetched Release files
- if ((*I)->Complete == false && (*I)->ExpectedAdditionalItems > 0)
- UnfetchedReleaseFiles = true;
+ // do we expect to acquire more files than we know of yet?
+ if ((*I)->ExpectedAdditionalItems > 0)
+ ExpectAdditionalItems = true;
TotalBytes += (*I)->FileSize;
if ((*I)->Complete == true)
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;
if (CurrentBytes > TotalBytes)
CurrentBytes = TotalBytes;
- // debug
- if (_config->FindB("Debug::acquire::progress", false) == true)
- std::clog << " Bytes: "
- << SizeToStr(CurrentBytes) << " / " << SizeToStr(TotalBytes)
- << std::endl;
-
// Compute the CPS
struct timeval NewTime;
gettimeofday(&NewTime,0);
double const OldPercent = Percent;
// calculate the percentage, if we have too little data assume 1%
- if (TotalBytes > 0 && UnfetchedReleaseFiles)
+ if (ExpectAdditionalItems)
Percent = 0;
else
// use both files and bytes because bytes can be unreliable
Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) +
0.2 * (CurrentItems/float(TotalItems)*100.0));
+
+ // debug
+ if (_config->FindB("Debug::acquire::progress", false) == true)
+ {
+ std::clog
+ << "["
+ << std::setw(5) << std::setprecision(4) << std::showpoint << Percent
+ << "]"
+ << " Bytes: "
+ << SizeToStr(CurrentBytes) << " / " << SizeToStr(TotalBytes)
+ << " # Files: "
+ << CurrentItems << " / " << TotalItems
+ << std::endl;
+ }
+
double const DiffPercent = Percent - OldPercent;
if (DiffPercent < 0.001 && _config->FindB("Acquire::Progress::Diffpercent", false) == true)
return true;
snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems);
// build the status str
- status << "dlstatus:" << i
- << ":" << std::setprecision(3) << Percent
- << ":" << msg
- << endl;
-
- std::string const dlstatus = status.str();
- FileFd::Write(fd, dlstatus.c_str(), dlstatus.size());
+ std::ostringstream str;
+ str.imbue(std::locale("C.UTF-8"));
+ str.precision(4);
+ str << "dlstatus" << ':' << std::fixed << i << ':' << Percent << ':' << msg << '\n';
+ auto const dlstatus = str.str();
+ FileFd::Write(fd, dlstatus.data(), dlstatus.size());
}
return true;