]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire.cc,v 1.7 1998/11/01 05:27:34 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 // Queue it into the named queue
148 I
->Enqueue(Itm
,URI
,Description
);
154 clog
<< "Fetching " << URI
<< endl
;
155 clog
<< " to " << Itm
->DestFile
<< endl
;
156 clog
<< " Queue is: " << QueueName(URI
) << endl
;
160 // Acquire::Dequeue - Remove an item from all queues /*{{{*/
161 // ---------------------------------------------------------------------
162 /* This is called when an item is finished being fetched. It removes it
163 from all the queues */
164 void pkgAcquire::Dequeue(Item
*Itm
)
167 for (; I
!= 0; I
= I
->Next
)
171 clog
<< "Dequeuing " << Itm
->DestFile
<< endl
;
175 // Acquire::QueueName - Return the name of the queue for this URI /*{{{*/
176 // ---------------------------------------------------------------------
177 /* The string returned depends on the configuration settings and the
178 method parameters. Given something like http://foo.org/bar it can
179 return http://foo.org or http */
180 string
pkgAcquire::QueueName(string Uri
)
184 const MethodConfig
*Config
= GetConfig(U
.Access
);
188 /* Single-Instance methods get exactly one queue per URI. This is
189 also used for the Access queue method */
190 if (Config
->SingleInstance
== true || QueueMode
== QueueAccess
)
193 return U
.Access
+ ':' + U
.Host
;
196 // Acquire::GetConfig - Fetch the configuration information /*{{{*/
197 // ---------------------------------------------------------------------
198 /* This locates the configuration structure for an access method. If
199 a config structure cannot be found a Worker will be created to
201 pkgAcquire::MethodConfig
*pkgAcquire::GetConfig(string Access
)
203 // Search for an existing config
205 for (Conf
= Configs
; Conf
!= 0; Conf
= Conf
->Next
)
206 if (Conf
->Access
== Access
)
209 // Create the new config class
210 Conf
= new MethodConfig
;
211 Conf
->Access
= Access
;
212 Conf
->Next
= Configs
;
215 // Create the worker to fetch the configuration
217 if (Work
.Start() == false)
223 // Acquire::SetFds - Deal with readable FDs /*{{{*/
224 // ---------------------------------------------------------------------
225 /* Collect FDs that have activity monitors into the fd sets */
226 void pkgAcquire::SetFds(int &Fd
,fd_set
*RSet
,fd_set
*WSet
)
228 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
230 if (I
->InReady
== true && I
->InFd
>= 0)
234 FD_SET(I
->InFd
,RSet
);
236 if (I
->OutReady
== true && I
->OutFd
>= 0)
240 FD_SET(I
->OutFd
,WSet
);
245 // Acquire::RunFds - Deal with active FDs /*{{{*/
246 // ---------------------------------------------------------------------
247 /* Dispatch active FDs over to the proper workers. It is very important
248 that a worker never be erased while this is running! The queue class
249 should never erase a worker except during shutdown processing. */
250 void pkgAcquire::RunFds(fd_set
*RSet
,fd_set
*WSet
)
252 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
254 if (I
->InFd
>= 0 && FD_ISSET(I
->InFd
,RSet
) != 0)
256 if (I
->OutFd
>= 0 && FD_ISSET(I
->OutFd
,WSet
) != 0)
261 // Acquire::Run - Run the fetch sequence /*{{{*/
262 // ---------------------------------------------------------------------
263 /* This runs the queues. It manages a select loop for all of the
264 Worker tasks. The workers interact with the queues and items to
265 manage the actual fetch. */
266 bool pkgAcquire::Run()
270 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
273 // Run till all things have been acquired
281 SetFds(Highest
,&RFds
,&WFds
);
283 if (select(Highest
+1,&RFds
,&WFds
,0,0) <= 0)
286 return _error
->Errno("select","Select has failed");
290 if (_error
->PendingError() == true)
294 // Shut down the acquire bits
296 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
299 return _error
->PendingError();
302 // Acquire::Bump - Called when an item is dequeued /*{{{*/
303 // ---------------------------------------------------------------------
304 /* This routine bumps idle queues in hopes that they will be able to fetch
306 void pkgAcquire::Bump()
308 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
313 // Acquire::MethodConfig::MethodConfig - Constructor /*{{{*/
314 // ---------------------------------------------------------------------
316 pkgAcquire::MethodConfig::MethodConfig()
318 SingleInstance
= false;
326 // Queue::Queue - Constructor /*{{{*/
327 // ---------------------------------------------------------------------
329 pkgAcquire::Queue::Queue(string Name
,pkgAcquire
*Owner
) : Name(Name
),
337 // Queue::~Queue - Destructor /*{{{*/
338 // ---------------------------------------------------------------------
340 pkgAcquire::Queue::~Queue()
352 // Queue::Enqueue - Queue an item to the queue /*{{{*/
353 // ---------------------------------------------------------------------
355 void pkgAcquire::Queue::Enqueue(Item
*Owner
,string URI
,string Description
)
358 QItem
*I
= new QItem
;
363 Items
->Owner
= Owner
;
365 Items
->Description
= Description
;
366 Owner
->QueueCounter
++;
368 if (Items
->Next
== 0)
372 // Queue::Dequeue - Remove an item from the queue /*{{{*/
373 // ---------------------------------------------------------------------
375 void pkgAcquire::Queue::Dequeue(Item
*Owner
)
380 if ((*I
)->Owner
== Owner
)
384 Owner
->QueueCounter
--;
392 // Queue::Startup - Start the worker processes /*{{{*/
393 // ---------------------------------------------------------------------
395 bool pkgAcquire::Queue::Startup()
400 pkgAcquire::MethodConfig
*Cnf
= Owner
->GetConfig(U
.Access
);
404 Workers
= new Worker(this,Cnf
);
406 if (Workers
->Start() == false)
412 // Queue::Shutdown - Shutdown the worker processes /*{{{*/
413 // ---------------------------------------------------------------------
415 bool pkgAcquire::Queue::Shutdown()
417 // Delete all of the workers
420 pkgAcquire::Worker
*Jnk
= Workers
;
421 Workers
= Workers
->NextQueue
;
429 // Queue::Finditem - Find a URI in the item list /*{{{*/
430 // ---------------------------------------------------------------------
432 pkgAcquire::Queue::QItem
*pkgAcquire::Queue::FindItem(string URI
,pkgAcquire::Worker
*Owner
)
434 for (QItem
*I
= Items
; I
!= 0; I
= I
->Next
)
435 if (I
->URI
== URI
&& I
->Worker
== Owner
)
440 // Queue::ItemDone - Item has been completed /*{{{*/
441 // ---------------------------------------------------------------------
442 /* The worker signals this which causes the item to be removed from the
443 queue. If this is the last queue instance then it is removed from the
445 bool pkgAcquire::Queue::ItemDone(QItem
*Itm
)
447 if (Itm
->Owner
->QueueCounter
<= 1)
448 Owner
->Dequeue(Itm
->Owner
);
458 // Queue::Cycle - Queue new items into the method /*{{{*/
459 // ---------------------------------------------------------------------
460 /* This locates a new idle item and sends it to the worker */
461 bool pkgAcquire::Queue::Cycle()
463 if (Items
== 0 || Workers
== 0)
466 // Look for a queable item
468 for (; I
!= 0; I
= I
->Next
)
469 if (I
->Owner
->Status
== pkgAcquire::Item::StatIdle
)
472 // Nothing to do, queue is idle.
477 I
->Owner
->Status
= pkgAcquire::Item::StatFetching
;
478 return Workers
->QueueItem(I
);
481 // Queue::Bump - Fetch any pending objects if we are idle /*{{{*/
482 // ---------------------------------------------------------------------
484 void pkgAcquire::Queue::Bump()