]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire.cc
ed64c5e5fdae8482e27c802e22998271be0bb162
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire.cc,v 1.9 1998/11/06 02:52:20 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>
27 // Acquire::pkgAcquire - Constructor /*{{{*/
28 // ---------------------------------------------------------------------
29 /* We grab some runtime state from the configuration space */
30 pkgAcquire::pkgAcquire()
38 string Mode
= _config
->Find("Acquire::Queue-Mode","host");
39 if (strcasecmp(Mode
.c_str(),"host") == 0)
40 QueueMode
= QueueHost
;
41 if (strcasecmp(Mode
.c_str(),"access") == 0)
42 QueueMode
= QueueAccess
;
44 Debug
= _config
->FindB("Debug::pkgAcquire",false);
47 // Acquire::~pkgAcquire - Destructor /*{{{*/
48 // ---------------------------------------------------------------------
49 /* Free our memory, clean up the queues (destroy the workers) */
50 pkgAcquire::~pkgAcquire()
52 while (Items
.size() != 0)
57 MethodConfig
*Jnk
= Configs
;
58 Configs
= Configs
->Next
;
65 Queues
= Queues
->Next
;
70 // Acquire::Add - Add a new item /*{{{*/
71 // ---------------------------------------------------------------------
72 /* This puts an item on the acquire list. This list is mainly for tracking
74 void pkgAcquire::Add(Item
*Itm
)
79 // Acquire::Remove - Remove a item /*{{{*/
80 // ---------------------------------------------------------------------
81 /* Remove an item from the acquire list. This is usually not used.. */
82 void pkgAcquire::Remove(Item
*Itm
)
84 for (vector
<Item
*>::iterator I
= Items
.begin(); I
< Items
.end(); I
++)
91 // Acquire::Add - Add a worker /*{{{*/
92 // ---------------------------------------------------------------------
93 /* A list of workers is kept so that the select loop can direct their FD
95 void pkgAcquire::Add(Worker
*Work
)
97 Work
->NextAcquire
= Workers
;
101 // Acquire::Remove - Remove a worker /*{{{*/
102 // ---------------------------------------------------------------------
103 /* A worker has died. This can not be done while the select loop is running
104 as it would require that RunFds could handling a changing list state and
106 void pkgAcquire::Remove(Worker
*Work
)
111 Worker
**I
= &Workers
;
115 *I
= (*I
)->NextAcquire
;
117 I
= &(*I
)->NextAcquire
;
121 // Acquire::Enqueue - Queue an URI for fetching /*{{{*/
122 // ---------------------------------------------------------------------
123 /* This is the entry point for an item. An item calls this function when
124 it is construction which creates a queue (based on the current queue
125 mode) and puts the item in that queue. If the system is running then
126 the queue might be started. */
127 void pkgAcquire::Enqueue(Item
*Itm
,string URI
,string Description
)
129 // Determine which queue to put the item in
130 string Name
= QueueName(URI
);
131 if (Name
.empty() == true)
134 // Find the queue structure
136 for (; I
!= 0 && I
->Name
!= Name
; I
= I
->Next
);
139 I
= new Queue(Name
,this);
147 Itm
->Status
= Item::StatIdle
;
149 // Queue it into the named queue
150 I
->Enqueue(Itm
,URI
,Description
);
156 clog
<< "Fetching " << URI
<< endl
;
157 clog
<< " to " << Itm
->DestFile
<< endl
;
158 clog
<< " Queue is: " << QueueName(URI
) << endl
;
162 // Acquire::Dequeue - Remove an item from all queues /*{{{*/
163 // ---------------------------------------------------------------------
164 /* This is called when an item is finished being fetched. It removes it
165 from all the queues */
166 void pkgAcquire::Dequeue(Item
*Itm
)
170 for (; I
!= 0; I
= I
->Next
)
171 Res
|= I
->Dequeue(Itm
);
174 clog
<< "Dequeuing " << Itm
->DestFile
<< endl
;
179 // Acquire::QueueName - Return the name of the queue for this URI /*{{{*/
180 // ---------------------------------------------------------------------
181 /* The string returned depends on the configuration settings and the
182 method parameters. Given something like http://foo.org/bar it can
183 return http://foo.org or http */
184 string
pkgAcquire::QueueName(string Uri
)
188 const MethodConfig
*Config
= GetConfig(U
.Access
);
192 /* Single-Instance methods get exactly one queue per URI. This is
193 also used for the Access queue method */
194 if (Config
->SingleInstance
== true || QueueMode
== QueueAccess
)
197 return U
.Access
+ ':' + U
.Host
;
200 // Acquire::GetConfig - Fetch the configuration information /*{{{*/
201 // ---------------------------------------------------------------------
202 /* This locates the configuration structure for an access method. If
203 a config structure cannot be found a Worker will be created to
205 pkgAcquire::MethodConfig
*pkgAcquire::GetConfig(string Access
)
207 // Search for an existing config
209 for (Conf
= Configs
; Conf
!= 0; Conf
= Conf
->Next
)
210 if (Conf
->Access
== Access
)
213 // Create the new config class
214 Conf
= new MethodConfig
;
215 Conf
->Access
= Access
;
216 Conf
->Next
= Configs
;
219 // Create the worker to fetch the configuration
221 if (Work
.Start() == false)
227 // Acquire::SetFds - Deal with readable FDs /*{{{*/
228 // ---------------------------------------------------------------------
229 /* Collect FDs that have activity monitors into the fd sets */
230 void pkgAcquire::SetFds(int &Fd
,fd_set
*RSet
,fd_set
*WSet
)
232 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
234 if (I
->InReady
== true && I
->InFd
>= 0)
238 FD_SET(I
->InFd
,RSet
);
240 if (I
->OutReady
== true && I
->OutFd
>= 0)
244 FD_SET(I
->OutFd
,WSet
);
249 // Acquire::RunFds - Deal with active FDs /*{{{*/
250 // ---------------------------------------------------------------------
251 /* Dispatch active FDs over to the proper workers. It is very important
252 that a worker never be erased while this is running! The queue class
253 should never erase a worker except during shutdown processing. */
254 void pkgAcquire::RunFds(fd_set
*RSet
,fd_set
*WSet
)
256 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
258 if (I
->InFd
>= 0 && FD_ISSET(I
->InFd
,RSet
) != 0)
260 if (I
->OutFd
>= 0 && FD_ISSET(I
->OutFd
,WSet
) != 0)
265 // Acquire::Run - Run the fetch sequence /*{{{*/
266 // ---------------------------------------------------------------------
267 /* This runs the queues. It manages a select loop for all of the
268 Worker tasks. The workers interact with the queues and items to
269 manage the actual fetch. */
270 bool pkgAcquire::Run()
274 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
277 // Run till all things have been acquired
285 SetFds(Highest
,&RFds
,&WFds
);
287 if (select(Highest
+1,&RFds
,&WFds
,0,0) <= 0)
290 return _error
->Errno("select","Select has failed");
294 if (_error
->PendingError() == true)
298 // Shut down the acquire bits
300 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
303 return _error
->PendingError();
306 // Acquire::Bump - Called when an item is dequeued /*{{{*/
307 // ---------------------------------------------------------------------
308 /* This routine bumps idle queues in hopes that they will be able to fetch
310 void pkgAcquire::Bump()
312 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
317 // Acquire::MethodConfig::MethodConfig - Constructor /*{{{*/
318 // ---------------------------------------------------------------------
320 pkgAcquire::MethodConfig::MethodConfig()
322 SingleInstance
= false;
330 // Queue::Queue - Constructor /*{{{*/
331 // ---------------------------------------------------------------------
333 pkgAcquire::Queue::Queue(string Name
,pkgAcquire
*Owner
) : Name(Name
),
341 // Queue::~Queue - Destructor /*{{{*/
342 // ---------------------------------------------------------------------
344 pkgAcquire::Queue::~Queue()
356 // Queue::Enqueue - Queue an item to the queue /*{{{*/
357 // ---------------------------------------------------------------------
359 void pkgAcquire::Queue::Enqueue(Item
*Owner
,string URI
,string Description
)
362 QItem
*I
= new QItem
;
367 Items
->Owner
= Owner
;
369 Items
->Description
= Description
;
370 Owner
->QueueCounter
++;
372 if (Items
->Next
== 0)
376 // Queue::Dequeue - Remove an item from the queue /*{{{*/
377 // ---------------------------------------------------------------------
378 /* We return true if we hit something*/
379 bool pkgAcquire::Queue::Dequeue(Item
*Owner
)
386 if ((*I
)->Owner
== Owner
)
390 Owner
->QueueCounter
--;
401 // Queue::Startup - Start the worker processes /*{{{*/
402 // ---------------------------------------------------------------------
404 bool pkgAcquire::Queue::Startup()
409 pkgAcquire::MethodConfig
*Cnf
= Owner
->GetConfig(U
.Access
);
413 Workers
= new Worker(this,Cnf
);
415 if (Workers
->Start() == false)
421 // Queue::Shutdown - Shutdown the worker processes /*{{{*/
422 // ---------------------------------------------------------------------
424 bool pkgAcquire::Queue::Shutdown()
426 // Delete all of the workers
429 pkgAcquire::Worker
*Jnk
= Workers
;
430 Workers
= Workers
->NextQueue
;
438 // Queue::Finditem - Find a URI in the item list /*{{{*/
439 // ---------------------------------------------------------------------
441 pkgAcquire::Queue::QItem
*pkgAcquire::Queue::FindItem(string URI
,pkgAcquire::Worker
*Owner
)
443 for (QItem
*I
= Items
; I
!= 0; I
= I
->Next
)
444 if (I
->URI
== URI
&& I
->Worker
== Owner
)
449 // Queue::ItemDone - Item has been completed /*{{{*/
450 // ---------------------------------------------------------------------
451 /* The worker signals this which causes the item to be removed from the
452 queue. If this is the last queue instance then it is removed from the
454 bool pkgAcquire::Queue::ItemDone(QItem
*Itm
)
456 if (Itm
->Owner
->QueueCounter
<= 1)
457 Owner
->Dequeue(Itm
->Owner
);
467 // Queue::Cycle - Queue new items into the method /*{{{*/
468 // ---------------------------------------------------------------------
469 /* This locates a new idle item and sends it to the worker */
470 bool pkgAcquire::Queue::Cycle()
472 if (Items
== 0 || Workers
== 0)
475 // Look for a queable item
477 for (; I
!= 0; I
= I
->Next
)
478 if (I
->Owner
->Status
== pkgAcquire::Item::StatIdle
)
481 // Nothing to do, queue is idle.
486 I
->Owner
->Status
= pkgAcquire::Item::StatFetching
;
487 return Workers
->QueueItem(I
);
490 // Queue::Bump - Fetch any pending objects if we are idle /*{{{*/
491 // ---------------------------------------------------------------------
493 void pkgAcquire::Queue::Bump()