1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire.cc,v 1.5 1998/10/26 07:11:47 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 // ---------------------------------------------------------------------
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 // ---------------------------------------------------------------------
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 // ---------------------------------------------------------------------
73 void pkgAcquire::Add(Item
*Itm
)
78 // Acquire::Remove - Remove a item /*{{{*/
79 // ---------------------------------------------------------------------
81 void pkgAcquire::Remove(Item
*Itm
)
83 for (vector
<Item
*>::iterator I
= Items
.begin(); I
< Items
.end(); I
++)
90 // Acquire::Add - Add a worker /*{{{*/
91 // ---------------------------------------------------------------------
93 void pkgAcquire::Add(Worker
*Work
)
95 Work
->NextAcquire
= Workers
;
99 // Acquire::Remove - Remove a worker /*{{{*/
100 // ---------------------------------------------------------------------
102 void pkgAcquire::Remove(Worker
*Work
)
104 Worker
**I
= &Workers
;
108 *I
= (*I
)->NextAcquire
;
110 I
= &(*I
)->NextAcquire
;
114 // Acquire::Enqueue - Queue an URI for fetching /*{{{*/
115 // ---------------------------------------------------------------------
117 void pkgAcquire::Enqueue(Item
*Itm
,string URI
,string Description
)
119 // Determine which queue to put the item in
120 string Name
= QueueName(URI
);
121 if (Name
.empty() == true)
124 // Find the queue structure
126 for (; I
!= 0 && I
->Name
!= Name
; I
= I
->Next
);
129 I
= new Queue(Name
,this);
134 // Queue it into the named queue
135 I
->Enqueue(Itm
,URI
,Description
);
144 clog
<< "Fetching " << URI
<< endl
;
145 clog
<< " to " << Itm
->DestFile
<< endl
;
146 clog
<< " Queue is: " << QueueName(URI
) << endl
;
150 // Acquire::Dequeue - Remove an item from all queues /*{{{*/
151 // ---------------------------------------------------------------------
153 void pkgAcquire::Dequeue(Item
*Itm
)
156 for (; I
!= 0; I
= I
->Next
)
161 // Acquire::QueueName - Return the name of the queue for this URI /*{{{*/
162 // ---------------------------------------------------------------------
163 /* The string returned depends on the configuration settings and the
164 method parameters. Given something like http://foo.org/bar it can
165 return http://foo.org or http */
166 string
pkgAcquire::QueueName(string URI
)
168 const MethodConfig
*Config
= GetConfig(URIAccess(URI
));
172 /* Single-Instance methods get exactly one queue per URI. This is
173 also used for the Access queue method */
174 if (Config
->SingleInstance
== true || QueueMode
== QueueAccess
)
175 return URIAccess(URI
);
178 string::iterator I
= URI
.begin();
179 for (; I
< URI
.end() && *I
!= ':'; I
++);
180 for (; I
< URI
.end() && (*I
== '/' || *I
== ':'); I
++);
181 for (; I
< URI
.end() && *I
!= '/'; I
++);
183 return string(URI
,0,I
- URI
.begin());
186 // Acquire::GetConfig - Fetch the configuration information /*{{{*/
187 // ---------------------------------------------------------------------
188 /* This locates the configuration structure for an access method. If
189 a config structure cannot be found a Worker will be created to
191 pkgAcquire::MethodConfig
*pkgAcquire::GetConfig(string Access
)
193 // Search for an existing config
195 for (Conf
= Configs
; Conf
!= 0; Conf
= Conf
->Next
)
196 if (Conf
->Access
== Access
)
199 // Create the new config class
200 Conf
= new MethodConfig
;
201 Conf
->Access
= Access
;
202 Conf
->Next
= Configs
;
205 // Create the worker to fetch the configuration
207 if (Work
.Start() == false)
213 // Acquire::SetFds - Deal with readable FDs /*{{{*/
214 // ---------------------------------------------------------------------
215 /* Collect FDs that have activity monitors into the fd sets */
216 void pkgAcquire::SetFds(int &Fd
,fd_set
*RSet
,fd_set
*WSet
)
218 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
220 if (I
->InReady
== true && I
->InFd
>= 0)
224 FD_SET(I
->InFd
,RSet
);
226 if (I
->OutReady
== true && I
->OutFd
>= 0)
230 FD_SET(I
->OutFd
,WSet
);
235 // Acquire::RunFds - Deal with active FDs /*{{{*/
236 // ---------------------------------------------------------------------
237 /* Dispatch active FDs over to the proper workers */
238 void pkgAcquire::RunFds(fd_set
*RSet
,fd_set
*WSet
)
240 for (Worker
*I
= Workers
; I
!= 0; I
= I
->NextAcquire
)
242 if (I
->InFd
>= 0 && FD_ISSET(I
->InFd
,RSet
) != 0)
244 if (I
->OutFd
>= 0 && FD_ISSET(I
->OutFd
,WSet
) != 0)
249 // Acquire::Run - Run the fetch sequence /*{{{*/
250 // ---------------------------------------------------------------------
251 /* This runs the queues. It manages a select loop for all of the
252 Worker tasks. The workers interact with the queues and items to
253 manage the actual fetch. */
254 bool pkgAcquire::Run()
258 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
261 // Run till all things have been acquired
269 SetFds(Highest
,&RFds
,&WFds
);
271 if (select(Highest
+1,&RFds
,&WFds
,0,0) <= 0)
274 return _error
->Errno("select","Select has failed");
280 for (Queue
*I
= Queues
; I
!= 0; I
= I
->Next
)
288 // Acquire::MethodConfig::MethodConfig - Constructor /*{{{*/
289 // ---------------------------------------------------------------------
291 pkgAcquire::MethodConfig::MethodConfig()
293 SingleInstance
= false;
301 // Queue::Queue - Constructor /*{{{*/
302 // ---------------------------------------------------------------------
304 pkgAcquire::Queue::Queue(string Name
,pkgAcquire
*Owner
) : Name(Name
),
312 // Queue::~Queue - Destructor /*{{{*/
313 // ---------------------------------------------------------------------
315 pkgAcquire::Queue::~Queue()
327 // Queue::Enqueue - Queue an item to the queue /*{{{*/
328 // ---------------------------------------------------------------------
330 void pkgAcquire::Queue::Enqueue(Item
*Owner
,string URI
,string Description
)
333 QItem
*I
= new QItem
;
338 Items
->Owner
= Owner
;
340 Items
->Description
= Description
;
341 Owner
->QueueCounter
++;
344 // Queue::Dequeue - Remove an item from the queue /*{{{*/
345 // ---------------------------------------------------------------------
347 void pkgAcquire::Queue::Dequeue(Item
*Owner
)
352 if ((*I
)->Owner
== Owner
)
356 Owner
->QueueCounter
--;
364 // Queue::Startup - Start the worker processes /*{{{*/
365 // ---------------------------------------------------------------------
367 bool pkgAcquire::Queue::Startup()
371 pkgAcquire::MethodConfig
*Cnf
= Owner
->GetConfig(URIAccess(Name
));
375 Workers
= new Worker(this,Cnf
);
377 if (Workers
->Start() == false)
380 Items
->Worker
= Workers
;
381 Workers
->QueueItem(Items
);
386 // Queue::Shutdown - Shutdown the worker processes /*{{{*/
387 // ---------------------------------------------------------------------
389 bool pkgAcquire::Queue::Shutdown()
391 // Delete all of the workers
394 pkgAcquire::Worker
*Jnk
= Workers
;
395 Workers
= Workers
->NextQueue
;
403 // Queue::Finditem - Find a URI in the item list /*{{{*/
404 // ---------------------------------------------------------------------
406 pkgAcquire::Queue::QItem
*pkgAcquire::Queue::FindItem(string URI
,pkgAcquire::Worker
*Owner
)
408 for (QItem
*I
= Items
; I
!= 0; I
= I
->Next
)
409 if (I
->URI
== URI
&& I
->Worker
== Owner
)
414 // Queue::ItemDone - Item has been completed /*{{{*/
415 // ---------------------------------------------------------------------
416 /* The worker signals this which causes the item to be removed from the
418 bool pkgAcquire::Queue::ItemDone(QItem
*Itm
)
425 Items
->Worker
= Workers
;
426 Items
->Owner
->Status
= pkgAcquire::Item::StatFetching
;
427 return Workers
->QueueItem(Items
);