]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-worker.cc
a02c6bc0414b77467210cb51be04ea104cdcc18c
   1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: acquire-worker.cc,v 1.9 1998/11/01 05:27:33 jgg Exp $ 
   4 /* ###################################################################### 
   8    The worker process can startup either as a Configuration prober 
   9    or as a queue runner. As a configuration prober it only reads the 
  10    configuration message and  
  12    ##################################################################### */ 
  14 // Include Files                                                        /*{{{*/ 
  16 #pragma implementation "apt-pkg/acquire-worker.h" 
  18 #include <apt-pkg/acquire-worker.h> 
  19 #include <apt-pkg/acquire-item.h> 
  20 #include <apt-pkg/configuration.h> 
  21 #include <apt-pkg/error.h> 
  22 #include <apt-pkg/fileutl.h> 
  30 // Worker::Worker - Constructor for Queue startup                       /*{{{*/ 
  31 // --------------------------------------------------------------------- 
  33 pkgAcquire::Worker::Worker(Queue 
*Q
,MethodConfig 
*Cnf
) 
  43 // Worker::Worker - Constructor for method config startup               /*{{{*/ 
  44 // --------------------------------------------------------------------- 
  46 pkgAcquire::Worker::Worker(MethodConfig 
*Cnf
) 
  56 // Worker::Construct - Constructor helper                               /*{{{*/ 
  57 // --------------------------------------------------------------------- 
  59 void pkgAcquire::Worker::Construct() 
  68    Debug 
= _config
->FindB("Debug::pkgAcquire::Worker",false); 
  71 // Worker::~Worker - Destructor                                         /*{{{*/ 
  72 // --------------------------------------------------------------------- 
  74 pkgAcquire::Worker::~Worker() 
  82       if (waitpid(Process
,0,0) != Process
) 
  83          _error
->Warning("I waited but nothing was there!"); 
  87 // Worker::Start - Start the worker process                             /*{{{*/ 
  88 // --------------------------------------------------------------------- 
  89 /* This forks the method and inits the communication channel */ 
  90 bool pkgAcquire::Worker::Start() 
  92    // Get the method path 
  93    string Method 
= _config
->FindDir("Dir::Bin::Methods") + Access
; 
  94    if (FileExists(Method
) == false) 
  95       return _error
->Error("The method driver %s could not be found.",Method
.c_str()); 
  98       clog 
<< "Starting method '" << Method 
<< '\'' << endl
; 
 101    int Pipes
[4] = {-1,-1,-1,-1}; 
 102    if (pipe(Pipes
) != 0 || pipe(Pipes
+2) != 0) 
 104       _error
->Errno("pipe","Failed to create IPC pipe to subprocess"); 
 105       for (int I 
= 0; I 
!= 4; I
++) 
 109    for (int I 
= 0; I 
!= 4; I
++) 
 110       SetCloseExec(Pipes
[0],true); 
 112    // Fork off the process 
 116       cerr 
<< "FATAL -> Failed to fork." << endl
; 
 120    // Spawn the subprocess 
 124       dup2(Pipes
[1],STDOUT_FILENO
); 
 125       dup2(Pipes
[2],STDIN_FILENO
); 
 126       dup2(((filebuf 
*)clog
.rdbuf())->fd(),STDERR_FILENO
); 
 127       SetCloseExec(STDOUT_FILENO
,false); 
 128       SetCloseExec(STDIN_FILENO
,false);       
 129       SetCloseExec(STDERR_FILENO
,false); 
 132       Args
[0] = Method
.c_str(); 
 134       execv(Args
[0],(char **)Args
); 
 135       cerr 
<< "Failed to exec method " << Args
[0] << endl
; 
 142    SetNonBlock(Pipes
[0],true); 
 143    SetNonBlock(Pipes
[3],true); 
 149    // Read the configuration data 
 150    if (WaitFd(InFd
) == false || 
 151        ReadMessages() == false) 
 152       return _error
->Error("Method %s did not start correctly",Method
.c_str()); 
 161 // Worker::ReadMessages - Read all pending messages into the list       /*{{{*/ 
 162 // --------------------------------------------------------------------- 
 164 bool pkgAcquire::Worker::ReadMessages() 
 166    if (::ReadMessages(InFd
,MessageQueue
) == false) 
 167       return MethodFailure(); 
 171 // Worker::RunMessage - Empty the message queue                         /*{{{*/ 
 172 // --------------------------------------------------------------------- 
 173 /* This takes the messages from the message queue and runs them through 
 174    the parsers in order. */ 
 175 bool pkgAcquire::Worker::RunMessages() 
 177    while (MessageQueue
.empty() == false) 
 179       string Message 
= MessageQueue
.front(); 
 180       MessageQueue
.erase(MessageQueue
.begin()); 
 183          clog 
<< " <- " << Access 
<< ':' << QuoteString(Message
,"\n") << endl
; 
 185       // Fetch the message number 
 187       int Number 
= strtol(Message
.c_str(),&End
,10); 
 188       if (End 
== Message
.c_str()) 
 189          return _error
->Error("Invalid message from method %s: %s",Access
.c_str(),Message
.c_str()); 
 191       string URI 
= LookupTag(Message
,"URI"); 
 192       pkgAcquire::Queue::QItem 
*Itm 
= 0; 
 193       if (URI
.empty() == false) 
 194          Itm 
= OwnerQ
->FindItem(URI
,this); 
 196       // Determine the message number and dispatch 
 201          if (Capabilities(Message
) == false) 
 202             return _error
->Error("Unable to process Capabilities message from %s",Access
.c_str()); 
 208             clog 
<< " <- (log) " << LookupTag(Message
,"Message") << endl
; 
 213          Status 
= LookupTag(Message
,"Message"); 
 221                _error
->Error("Method gave invalid 200 URI Start message"); 
 226             TotalSize 
= atoi(LookupTag(Message
,"Size","0").c_str()); 
 236                _error
->Error("Method gave invalid 201 URI Done message"); 
 240             OwnerQ
->ItemDone(Itm
); 
 241             Itm
->Owner
->Done(Message
,atoi(LookupTag(Message
,"Size","0").c_str()), 
 242                                           LookupTag(Message
,"MD5-Hash")); 
 251                _error
->Error("Method gave invalid 400 URI Failure message"); 
 255             OwnerQ
->ItemDone(Itm
); 
 256             Itm
->Owner
->Failed(Message
); 
 260          // 401 General Failure 
 262          _error
->Error("Method %s General failure: %s",LookupTag(Message
,"Message").c_str()); 
 269 // Worker::Capabilities - 100 Capabilities handler                      /*{{{*/ 
 270 // --------------------------------------------------------------------- 
 271 /* This parses the capabilities message and dumps it into the configuration 
 273 bool pkgAcquire::Worker::Capabilities(string Message
) 
 278    Config
->Version 
= LookupTag(Message
,"Version"); 
 279    Config
->SingleInstance 
= StringToBool(LookupTag(Message
,"Single-Instance"),false); 
 280    Config
->PreScan 
= StringToBool(LookupTag(Message
,"Pre-Scan"),false); 
 281    Config
->Pipeline 
= StringToBool(LookupTag(Message
,"Pipeline"),false); 
 282    Config
->SendConfig 
= StringToBool(LookupTag(Message
,"Send-Config"),false); 
 287       clog 
<< "Configured access method " << Config
->Access 
<< endl
; 
 288       clog 
<< "Version:" << Config
->Version 
<< " SingleInstance:" << 
 289          Config
->SingleInstance 
<< " PreScan: " << Config
->PreScan 
<< 
 290          " Pipeline:" << Config
->Pipeline 
<< " SendConfig:" <<  
 291          Config
->SendConfig 
<< endl
; 
 297 // Worker::SendConfiguration - Send the config to the method            /*{{{*/ 
 298 // --------------------------------------------------------------------- 
 300 bool pkgAcquire::Worker::SendConfiguration() 
 302    if (Config
->SendConfig 
== false) 
 308    string Message 
= "601 Configuration\n"; 
 309    Message
.reserve(2000); 
 311    /* Write out all of the configuration directives by walking the  
 312       configuration tree */ 
 313    const Configuration::Item 
*Top 
= _config
->Tree(0); 
 316       if (Top
->Value
.empty() == false) 
 318          string Line 
= "Config-Item: " + Top
->FullTag() + "="; 
 319          Line 
+= QuoteString(Top
->Value
,"\n") + '\n'; 
 329       while (Top 
!= 0 && Top
->Next 
== 0) 
 337       clog 
<< " -> " << Access 
<< ':' << QuoteString(Message
,"\n") << endl
; 
 344 // Worker::QueueItem - Add an item to the outbound queue                /*{{{*/ 
 345 // --------------------------------------------------------------------- 
 346 /* Send a URI Acquire message to the method */ 
 347 bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem 
*Item
) 
 352    string Message 
= "600 URI Acquire\n"; 
 353    Message
.reserve(300); 
 354    Message 
+= "URI: " + Item
->URI
; 
 355    Message 
+= "\nFilename: " + Item
->Owner
->DestFile
; 
 356    Message 
+= Item
->Owner
->Custom600Headers(); 
 360       clog 
<< " -> " << Access 
<< ':' << QuoteString(Message
,"\n") << endl
; 
 367 // Worker::OutFdRead - Out bound FD is ready                            /*{{{*/ 
 368 // --------------------------------------------------------------------- 
 370 bool pkgAcquire::Worker::OutFdReady() 
 372    int Res 
= write(OutFd
,OutQueue
.begin(),OutQueue
.length()); 
 374       return MethodFailure(); 
 376    // Hmm.. this should never happen. 
 380    OutQueue
.erase(0,Res
); 
 381    if (OutQueue
.empty() == true) 
 387 // Worker::InFdRead - In bound FD is ready                              /*{{{*/ 
 388 // --------------------------------------------------------------------- 
 390 bool pkgAcquire::Worker::InFdReady() 
 392    if (ReadMessages() == false) 
 398 // Worker::MethodFailure - Called when the method fails                 /*{{{*/ 
 399 // --------------------------------------------------------------------- 
 400 /* This is called when the method is belived to have failed, probably because 
 402 bool pkgAcquire::Worker::MethodFailure() 
 404    cerr 
<< "Method " << Access 
<< " has died unexpectedly!" << endl
; 
 405    if (waitpid(Process
,0,0) != Process
) 
 406       _error
->Warning("I waited but nothing was there!"); 
 415    MessageQueue
.erase(MessageQueue
.begin(),MessageQueue
.end());