]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire.cc,v 1.10 1998/11/09 01:09:25 jgg Exp $
4 /* ######################################################################
6 Acquire - File Acquiration
8 The core element for the schedual system is the concept of a named
9 queue. Each queue is unique and each queue has a name derived from the
10 URI. The degree of paralization can be controled by how the queue
11 name is derived from the URI.
13 ##################################################################### */
15 // Include Files /*{{{*/
17 #pragma implementation "apt-pkg/acquire.h"
19 #include <apt-pkg/acquire.h>
20 #include <apt-pkg/acquire-item.h>
21 #include <apt-pkg/acquire-worker.h>
22 #include <apt-pkg/configuration.h>
23 #include <apt-pkg/error.h>
29 // Acquire::pkgAcquire - Constructor /*{{{*/
30 // ---------------------------------------------------------------------
31 /* We grab some runtime state from the configuration space */
32 pkgAcquire::pkgAcquire(pkgAcquireStatus
*Log
) : Log(Log
)
40 string Mode
= _config
->Find("Acquire::Queue-Mode","host");
41 if (strcasecmp(Mode
.c_str(),"host") == 0)
42 QueueMode
= QueueHost
;
43 if (strcasecmp(Mode
.c_str(),"access") == 0)
44 QueueMode
= QueueAccess
;
46 Debug
= _config
->FindB("Debug::pkgAcquire",false);
49 // Acquire::~pkgAcquire - Destructor /*{{{*/
50 // ---------------------------------------------------------------------
51 /* Free our memory, clean up the queues (destroy the workers) */
52 pkgAcquire::~pkgAcquire()
54 while (Items
.size() != 0)
59 MethodConfig
*Jnk
= Configs
;
60 Configs
= Configs
->Next
;
67 Queues
= Queues
->Next
;
72 // Acquire::Add - Add a new item /*{{{*/
73 // ---------------------------------------------------------------------
74 /* This puts an item on the acquire list. This list is mainly for tracking
76 void pkgAcquire::Add(Item
*Itm
)
81 // Acquire::Remove - Remove a item /*{{{*/
82 // ---------------------------------------------------------------------
83 /* Remove an item from the acquire list. This is usually not used.. */
84 void pkgAcquire::Remove(Item
*Itm
)
86 for (vector
<Item
*>::iterator I
= Items
.begin(); I
< Items
.end(); I
++)
93 // Acquire::Add - Add a worker /*{{{*/
94 // ---------------------------------------------------------------------
95 /* A list of workers is kept so that the select loop can direct their FD
97 void pkgAcquire::Add(Worker
*Work
)
99 Work
->NextAcquire
= Workers
;
103 // Acquire::Remove - Remove a worker /*{{{*/
104 // ---------------------------------------------------------------------
105 /* A worker has died. This can not be done while the select loop is running
106 as it would require that RunFds could handling a changing list state and
108 void pkgAcquire::Remove(Worker
*Work
)
113 Worker
**I
= &Workers
;
117 *I
= (*I
)->NextAcquire
;
119 I
= &(*I
)->NextAcquire
;
123 // Acquire::Enqueue - Queue an URI for fetching /*{{{*/
124 // ---------------------------------------------------------------------
125 /* This is the entry point for an item. An item calls this function when
126 it is construction which creates a queue (based on the current queue
127 mode) and puts the item in that queue. If the system is running then
128 the queue might be started. */
129 void pkgAcquire::Enqueue(ItemDesc
&Item
)
131 // Determine which queue to put the item in
132 string Name
= QueueName(Item
.URI
);
133 if (Name
.empty() == true)
136 // Find the queue structure
138 for (; I
!= 0 && I
->Name
!= Name
; I
= I
->Next
);
141 I
= new Queue(Name
,this);
149 Item
.Owner
->Status
= Item::StatIdle
;
151 // Queue it into the named queue
158 clog
<< "Fetching " << Item
.URI
<< endl
;
159 clog
<< " to " << Item
.Owner
->DestFile
<< endl
;
160 clog
<< " Queue is: " << QueueName(Item
.URI
) << endl
;
164 // Acquire::Dequeue - Remove an item from all queues /*{{{*/
165 // ---------------------------------------------------------------------
166 /* This is called when an item is finished being fetched. It removes it
167 from all the queues */
168 void pkgAcquire::Dequeue(Item
*Itm
)
172 for (; I
!= 0; I
= I
->Next
)
173 Res
|= I
->Dequeue(Itm
);
176 clog
<< "Dequeuing " << Itm
->DestFile
<< endl
;
181 // Acquire::QueueName - Return the name of the queue for this URI /*{{{*/
182 // ---------------------------------------------------------------------
183 /* The string returned depends on the configuration settings and the
184 method parameters. Given something like http://foo.org/bar it can
185 return http://foo.org or http */
186 string
pkgAcquire::QueueName(string Uri
)
190 const MethodConfig
*Config
= GetConfig(U
.Access
);
194 /* Single-Instance methods get exactly one queue per URI. This is
195 also used for the Access queue method */
196 if (Config
->SingleInstance
== true || QueueMode
== QueueAccess
)
199 return U
.Access
+ ':' + U
.Host
;
202 // Acquire::GetConfig - Fetch the configuration information /*{{{*/
203 // ---------------------------------------------------------------------
204 /* This locates the configuration structure for an access method. If
205 a config structure cannot be found a Worker will be created to
207 pkgAcquire::MethodConfig
*pkgAcquire::GetConfig(string Access
)
209 // Search for an existing config
211 for (Conf
= Configs
; Conf
!= 0; Conf
= Conf
->Next
)
212 if (Conf
->Access
== Access
)
215 // Create the new config class
216 Conf
= new MethodConfig
;
217 Conf
->Access
= Access
;
218 Conf
->Next
= Configs
;
221 // Create the worker to fetch the configuration
223 if (Work
.Start() == false)
229 // Acquire::SetFds - Deal with readable FDs /*{{{*/
230 // ---------------------------------------------------------------------
231 /* Collect FDs that have activity monitors into the fd sets */
232 void pkgAcquire::SetFds(int &Fd
,fd_set
*RSet
,fd_set
*WSet
)
234 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
236 if (I
->InReady
== true && I
->InFd
>= 0)
240 FD_SET(I
->InFd
,RSet
);
242 if (I
->OutReady
== true && I
->OutFd
>= 0)
246 FD_SET(I
->OutFd
,WSet
);
251 // Acquire::RunFds - Deal with active FDs /*{{{*/
252 // ---------------------------------------------------------------------
253 /* Dispatch active FDs over to the proper workers. It is very important
254 that a worker never be erased while this is running! The queue class
255 should never erase a worker except during shutdown processing. */
256 void pkgAcquire::RunFds(fd_set
*RSet
,fd_set
*WSet
)
258 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
260 if (I
->InFd
>= 0 && FD_ISSET(I
->InFd
,RSet
) != 0)
262 if (I
->OutFd
>= 0 && FD_ISSET(I
->OutFd
,WSet
) != 0)
267 // Acquire::Run - Run the fetch sequence /*{{{*/
268 // ---------------------------------------------------------------------
269 /* This runs the queues. It manages a select loop for all of the
270 Worker tasks. The workers interact with the queues and items to
271 manage the actual fetch. */
272 bool pkgAcquire::Run()
276 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
279 // Run till all things have been acquired
290 SetFds(Highest
,&RFds
,&WFds
);
292 int Res
= select(Highest
+1,&RFds
,&WFds
,0,&tv
);
295 _error
->Errno("select","Select has failed");
300 if (_error
->PendingError() == true)
303 // Timeout, notify the log class
304 if (Res
== 0 || (Log
!= 0 && Log
->Update
== true))
307 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
314 // Shut down the acquire bits
316 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
319 return _error
->PendingError();
322 // Acquire::Bump - Called when an item is dequeued /*{{{*/
323 // ---------------------------------------------------------------------
324 /* This routine bumps idle queues in hopes that they will be able to fetch
326 void pkgAcquire::Bump()
328 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
332 // Acquire::WorkerStep - Step to the next worker /*{{{*/
333 // ---------------------------------------------------------------------
334 /* Not inlined to advoid including acquire-worker.h */
335 pkgAcquire::Worker
*pkgAcquire::WorkerStep(Worker
*I
)
337 return I
->NextAcquire
;
341 // Acquire::MethodConfig::MethodConfig - Constructor /*{{{*/
342 // ---------------------------------------------------------------------
344 pkgAcquire::MethodConfig::MethodConfig()
346 SingleInstance
= false;
354 // Queue::Queue - Constructor /*{{{*/
355 // ---------------------------------------------------------------------
357 pkgAcquire::Queue::Queue(string Name
,pkgAcquire
*Owner
) : Name(Name
),
365 // Queue::~Queue - Destructor /*{{{*/
366 // ---------------------------------------------------------------------
368 pkgAcquire::Queue::~Queue()
380 // Queue::Enqueue - Queue an item to the queue /*{{{*/
381 // ---------------------------------------------------------------------
383 void pkgAcquire::Queue::Enqueue(ItemDesc
&Item
)
386 QItem
*I
= new QItem
;
391 Item
.Owner
->QueueCounter
++;
392 if (Items
->Next
== 0)
396 // Queue::Dequeue - Remove an item from the queue /*{{{*/
397 // ---------------------------------------------------------------------
398 /* We return true if we hit something*/
399 bool pkgAcquire::Queue::Dequeue(Item
*Owner
)
406 if ((*I
)->Owner
== Owner
)
410 Owner
->QueueCounter
--;
421 // Queue::Startup - Start the worker processes /*{{{*/
422 // ---------------------------------------------------------------------
424 bool pkgAcquire::Queue::Startup()
429 pkgAcquire::MethodConfig
*Cnf
= Owner
->GetConfig(U
.Access
);
433 Workers
= new Worker(this,Cnf
,Owner
->Log
);
435 if (Workers
->Start() == false)
441 // Queue::Shutdown - Shutdown the worker processes /*{{{*/
442 // ---------------------------------------------------------------------
444 bool pkgAcquire::Queue::Shutdown()
446 // Delete all of the workers
449 pkgAcquire::Worker
*Jnk
= Workers
;
450 Workers
= Workers
->NextQueue
;
458 // Queue::Finditem - Find a URI in the item list /*{{{*/
459 // ---------------------------------------------------------------------
461 pkgAcquire::Queue::QItem
*pkgAcquire::Queue::FindItem(string URI
,pkgAcquire::Worker
*Owner
)
463 for (QItem
*I
= Items
; I
!= 0; I
= I
->Next
)
464 if (I
->URI
== URI
&& I
->Worker
== Owner
)
469 // Queue::ItemDone - Item has been completed /*{{{*/
470 // ---------------------------------------------------------------------
471 /* The worker signals this which causes the item to be removed from the
472 queue. If this is the last queue instance then it is removed from the
474 bool pkgAcquire::Queue::ItemDone(QItem
*Itm
)
476 if (Itm
->Owner
->QueueCounter
<= 1)
477 Owner
->Dequeue(Itm
->Owner
);
487 // Queue::Cycle - Queue new items into the method /*{{{*/
488 // ---------------------------------------------------------------------
489 /* This locates a new idle item and sends it to the worker */
490 bool pkgAcquire::Queue::Cycle()
492 if (Items
== 0 || Workers
== 0)
495 // Look for a queable item
497 for (; I
!= 0; I
= I
->Next
)
498 if (I
->Owner
->Status
== pkgAcquire::Item::StatIdle
)
501 // Nothing to do, queue is idle.
506 I
->Owner
->Status
= pkgAcquire::Item::StatFetching
;
507 return Workers
->QueueItem(I
);
510 // Queue::Bump - Fetch any pending objects if we are idle /*{{{*/
511 // ---------------------------------------------------------------------
513 void pkgAcquire::Queue::Bump()