00001
00002
00003
00004
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
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
00214
00215
00216
00217
00218
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
00255
00256
00257
00258
00259
00260
00261
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
00272
00273
00274
00275
00276
00277
00278
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
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
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
00364
00365 _ticks.range( _ticks.max() + jobsize );
00366
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
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
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
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
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
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
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 }
00483 }
00484 }
00485
00486