RepoParser.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 
00014 #include "zypp/ZConfig.h"
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/PathInfo.h"
00017 #include "zypp/base/UserRequestException.h"
00018 #include "zypp/repo/yum/ResourceType.h"
00019 #include "zypp/data/ResolvableData.h"
00020 
00021 #include "zypp/parser/yum/RepomdFileReader.h"
00022 #include "zypp/parser/yum/PrimaryFileReader.h"
00023 #include "zypp/parser/yum/PatchesFileReader.h"
00024 #include "zypp/parser/yum/PatchFileReader.h"
00025 #include "zypp/parser/yum/PatternFileReader.h"
00026 #include "zypp/parser/yum/ProductFileReader.h"
00027 #include "zypp/parser/yum/OtherFileReader.h"
00028 #include "zypp/parser/yum/FilelistsFileReader.h"
00029 
00030 #include "zypp/parser/yum/RepoParser.h"
00031 
00032 
00033 #undef ZYPP_BASE_LOGGER_LOGGROUP
00034 #define ZYPP_BASE_LOGGER_LOGGROUP "parser::yum"
00035 
00036 using namespace std;
00037 using zypp::repo::yum::ResourceType;
00038 
00039 namespace zypp
00040 {
00041   namespace parser
00042   {
00043     namespace yum
00044     {
00045 
00049   struct RepoParserJob
00050   {
00051     RepoParserJob(const Pathname & filename, const ResourceType & type)
00052       : _filename(filename), _type(type) {}
00053 
00054     const Pathname & filename() const { return _filename; }
00055     const ResourceType & type() const { return _type; }
00056 
00057   private:
00059     Pathname _filename;
00061     ResourceType _type;
00062   };
00063 
00064 
00066   //
00067   //  CLASS NAME : RepoParser::Impl
00068   //
00069   class RepoParser::Impl : private base::NonCopyable
00070   {
00071   public:
00073     Impl(
00074       const data::RecordId & repository_id,
00075       data::ResolvableDataConsumer & consumer,
00076       const RepoParserOpts & options = RepoParserOpts(),
00077       const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc()
00078     );
00079 
00081     void parse(const Pathname &cache_dir);
00082 
00089     void doJobs(const Pathname & path);
00090 
00098     bool repomd_CB(const OnMediaLocation & loc, const ResourceType & dtype);
00099 
00106     bool primary_CB(const data::Packagebase_Ptr & package_r); 
00107 
00115     bool patches_CB(const OnMediaLocation &loc, const std::string & patch_id);
00116 
00123     bool patch_CB(const data::Patch_Ptr & patch);
00124 
00132     bool other_CB(const data::Resolvable_Ptr & res_ptr, const Changelog & changelog);
00133 
00141     bool filelist_CB(const data::Resolvable_Ptr & res_ptr, const data::Filenames & filenames);
00142 
00149     bool pattern_CB(const data::Pattern_Ptr & pattern_ptr);
00150 
00157     bool product_CB(const data::Product_Ptr & product_ptr);
00158 
00159   private:
00161     data::RecordId _repository_id;
00162 
00164     data::ResolvableDataConsumer & _consumer;
00165 
00167     std::list<RepoParserJob> _jobs;
00168 
00170     ProgressData _ticks;
00171 
00173     const RepoParserOpts & _options;
00174   };
00176 
00177 
00178   RepoParser::Impl::Impl(
00179       const data::RecordId & repository_id,
00180       data::ResolvableDataConsumer & consumer,
00181       const RepoParserOpts & options,
00182       const ProgressData::ReceiverFnc & progress)
00183     :
00184       _repository_id(repository_id), _consumer(consumer), _options(options)
00185   {
00186     _ticks.name("YUM RepoParser");
00187     _ticks.sendTo(progress);
00188   }
00189 
00190   // -------------------------------------------------------------------------
00191 
00192   bool RepoParser::Impl::repomd_CB(
00193     const OnMediaLocation & loc, const ResourceType & dtype)
00194   {
00195     DBG << "Adding " << dtype
00196         << " (" << loc.filename() << ") to RepoParser jobs " << endl;
00197 
00198     _jobs.push_back(RepoParserJob(loc.filename(), dtype));
00199 
00200     return true;
00201   }
00202 
00203   // -------------------------------------------------------------------------
00204 
00205   bool RepoParser::Impl::primary_CB(const data::Packagebase_Ptr & package_r)
00206   {
00207     data::Package_Ptr pkg = dynamic_pointer_cast<data::Package>(package_r);
00208     if (pkg)
00209       _consumer.consumePackage(_repository_id, pkg);
00210     else
00211       _consumer.consumeSourcePackage(_repository_id, dynamic_pointer_cast<data::SrcPackage>(package_r));
00212 
00213 /*    MIL << "got package "
00214       << package.name << package.edition << " "
00215       << package.arch
00216       << endl;
00217     MIL << "checksum: " << package.checksum << endl;
00218     MIL << "summary: " << package.summary << endl;*/
00219 
00220     return true;
00221   }
00222 
00223   // -------------------------------------------------------------------------
00224 
00225   bool RepoParser::Impl::patches_CB(
00226     const OnMediaLocation & loc, const string & patch_id)
00227   {
00228     DBG << "Adding patch " << loc.filename() << " to RepoParser jobs " << endl;
00229 
00230     _jobs.push_back(RepoParserJob(loc.filename(), ResourceType::PATCH));
00231 
00232     return true;
00233   }
00234 
00235   // -------------------------------------------------------------------------
00236 
00237   bool RepoParser::Impl::patch_CB(const data::Patch_Ptr & patch)
00238   {
00239     _consumer.consumePatch( _repository_id, patch );
00240 
00241     MIL << "got patch "
00242       << patch->name << patch->edition << " "
00243       << patch->arch
00244       << endl;
00245 
00246     return true;
00247   }
00248 
00249   // -------------------------------------------------------------------------
00250 
00251   bool RepoParser::Impl::other_CB(
00252     const data::Resolvable_Ptr & res_ptr, const Changelog & changelog)
00253   {
00254     //_consumer.consumeChangelog(_repository_id, res_ptr, changelog);
00255 /*
00256     DBG << "got changelog for "
00257       << res_ptr->name << res_ptr->edition << " "
00258       << res_ptr->arch
00259       << endl;
00260 
00261     DBG << "last entry: " << changelog.front() << endl;
00262 */
00263     return true;
00264   }
00265 
00266   // -------------------------------------------------------------------------
00267 
00268   bool RepoParser::Impl::filelist_CB(
00269     const data::Resolvable_Ptr & res_ptr, const data::Filenames & filenames)
00270   {
00271     //_consumer.consumeFilelist(_repository_id, res_ptr, filenames);
00272 /*
00273     DBG << "got filelist for "
00274       << res_ptr->name << res_ptr->edition << " "
00275       << res_ptr->arch
00276       << endl;
00277 
00278     DBG << "last entry: " << filenames.front() << endl;
00279 */
00280     return true;
00281   }
00282 
00283   // --------------------------------------------------------------------------
00284 
00285   bool RepoParser::Impl::pattern_CB(const data::Pattern_Ptr & product_ptr)
00286   {
00287     _consumer.consumePattern(_repository_id, product_ptr);
00288 
00289     MIL << "got pattern " << product_ptr->name << endl;
00290 
00291     return true;
00292   }
00293 
00294   // --------------------------------------------------------------------------
00295 
00296   bool RepoParser::Impl::product_CB(const data::Product_Ptr & product_ptr)
00297   {
00298     _consumer.consumeProduct(_repository_id, product_ptr);
00299 
00300     MIL << "got product " << product_ptr->name
00301         << "-" << product_ptr->edition << endl;
00302 
00303     return true;
00304   }
00305 
00306   // --------------------------------------------------------------------------
00307 
00308   void RepoParser::Impl::parse(const Pathname &cache_dir)
00309   {
00310     zypp::parser::yum::RepomdFileReader(
00311         cache_dir + "/repodata/repomd.xml",
00312         bind(&RepoParser::Impl::repomd_CB, this, _1, _2));
00313 
00314      long long totalsize = 0;
00315      for(list<RepoParserJob>::const_iterator it = _jobs.begin();
00316          it != _jobs.end(); ++it)
00317      {
00318        RepoParserJob job = *it;
00319        totalsize += PathInfo(cache_dir + job.filename()).size();
00320      }
00321 
00322      MIL << "Total files size: " << totalsize << endl;
00323     _ticks.range(totalsize);
00324     _ticks.toMin();
00325     
00326     doJobs(cache_dir);
00327 
00328     _ticks.toMax();
00329   }
00330 
00331   // --------------------------------------------------------------------------
00332 
00333   void RepoParser::Impl::doJobs(const Pathname &cache_dir)
00334   {
00335     for(list<RepoParserJob>::const_iterator it = _jobs.begin();
00336         it != _jobs.end(); ++it)
00337     {
00338       RepoParserJob job = *it;
00339       // FIXME better way to do progress here?
00340       int jobsize = PathInfo(cache_dir + job.filename()).size();
00341     
00342       MIL << "going to parse " << job.type() << " file " 
00343           << job.filename() << " (" << jobsize << " bytes)" << endl;
00344       
00345       switch(job.type().toEnum())
00346       {
00347         // parse primary.xml.gz
00348         case ResourceType::PRIMARY_e:
00349         {
00350           CombinedProgressData jobrcv( _ticks, jobsize );
00351           PrimaryFileReader(
00352             cache_dir + job.filename(),
00353             bind(&RepoParser::Impl::primary_CB, this, _1),
00354             jobrcv);
00355           break;
00356         }
00357 
00358         case ResourceType::PATCHES_e:
00359         {
00360           PatchesFileReader(
00361             cache_dir + job.filename(),
00362             bind(&RepoParser::Impl::patches_CB, this, _1, _2));
00363           // reset progress reporter max value (number of jobs changed if
00364           // there are patches to parse)
00365           _ticks.range( _ticks.max() + jobsize );
00366           // increase in the total bytes of the file
00367           if (!_ticks.incr( jobsize ))
00368             ZYPP_THROW(AbortRequestException());
00369           break;
00370         }
00371 
00372         case ResourceType::PATCH_e:
00373         {
00374           PatchFileReader(
00375             cache_dir + job.filename(),
00376             bind(&RepoParser::Impl::patch_CB, this, _1));
00377           // increase in the total bytes of the file
00378           if (!_ticks.incr( jobsize ))
00379             ZYPP_THROW(AbortRequestException());
00380           break;
00381         }
00382 
00383         case ResourceType::OTHER_e:
00384         {
00385           if (!_options.skipOther)
00386           {
00387             CombinedProgressData jobrcv( _ticks, jobsize );
00388             OtherFileReader(
00389               cache_dir + job.filename(),
00390               bind(&RepoParser::Impl::other_CB, this, _1, _2),
00391               jobrcv);
00392           }
00393           else
00394           {
00395             MIL << "skipping other.xml.gz" << endl;
00396             // increase in the total bytes of the file
00397             if (!_ticks.incr( jobsize ))
00398               ZYPP_THROW(AbortRequestException());
00399           }
00400           break;
00401         }
00402 
00403         case ResourceType::FILELISTS_e:
00404         {
00405           if (!_options.skipFilelists)
00406           {
00407             CombinedProgressData jobrcv( _ticks, jobsize );
00408             FilelistsFileReader(
00409               cache_dir + job.filename(),
00410               bind(&RepoParser::Impl::filelist_CB, this, _1, _2),
00411               jobrcv);
00412           }
00413           else
00414           {
00415             MIL << "skipping filelists.xml.gz";
00416             // increase in the total bytes of the file
00417           if (!_ticks.incr( jobsize ))
00418             ZYPP_THROW(AbortRequestException());
00419           }
00420           break;
00421         }
00422 
00423         case ResourceType::PATTERNS_e:
00424         {
00425           PatternFileReader(
00426             cache_dir + job.filename(),
00427             bind(&RepoParser::Impl::pattern_CB, this, _1));
00428           // increase in the total bytes of the file
00429           if (!_ticks.incr( jobsize ))
00430             ZYPP_THROW(AbortRequestException());
00431           break;
00432         }
00433 
00434         case ResourceType::PRODUCTS_e:
00435         {
00436           ProductFileReader(
00437             cache_dir + job.filename(),
00438             bind(&RepoParser::Impl::product_CB, this, _1));
00439           // increase in the total bytes of the file
00440           if (!_ticks.incr( jobsize ))
00441             ZYPP_THROW(AbortRequestException());
00442           break;
00443         }
00444 
00445         default:
00446         {
00447           WAR << "Don't know how to read "
00448               << job.type() << " file "
00449               << job.filename() << endl;
00450         }
00451       }
00452     }
00453   }
00454 
00455 
00457   //
00458   //  CLASS : RepoParser
00459   //
00461 
00462   RepoParser::RepoParser(
00463       const data::RecordId & repository_id,
00464       data::ResolvableDataConsumer & consumer,
00465       const RepoParserOpts & options,
00466       const ProgressData::ReceiverFnc & progress)
00467     :
00468       _pimpl(new Impl(repository_id, consumer, options, progress))
00469   {}
00470 
00471 
00472   RepoParser::~RepoParser()
00473   {}
00474 
00475 
00476   void RepoParser::parse(const Pathname & cache_dir)
00477   {
00478     _pimpl->parse(cache_dir);
00479   }
00480 
00481 
00482     } // ns yum
00483   } // ns parser
00484 } // ns zypp
00485 
00486 // vim: set ts=2 sts=2 sw=2 et ai:

Generated on Tue Sep 25 19:23:02 2007 for libzypp by  doxygen 1.5.3