00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <map>
00014
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/base/Algorithm.h"
00017 #include "zypp/base/Gettext.h"
00018
00019 #include "zypp/ZYpp.h"
00020 #include "zypp/ZYppFactory.h"
00021 #include "zypp/SourceManager.h"
00022 #include "zypp/SourceFactory.h"
00023 #include "zypp/Source.h"
00024 #include "zypp/source/SourceImpl.h"
00025 #include "zypp/target/store/PersistentStorage.h"
00026 #include "zypp/TmpPath.h"
00027 #include "zypp/Pathname.h"
00028 #include "zypp/PathInfo.h"
00029
00031 #undef ZYPP_BASE_LOGGER_LOGGROUP
00032 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::SourceManager"
00034
00035 #define ZYPP_METADATA_PREFIX ( getZYpp()->homePath().asString()+"/cache/" )
00036
00037 using std::endl;
00038
00040 namespace zypp
00041 {
00042
00043 IMPL_PTR_TYPE(SourceManager)
00044
00045 SourceManager_Ptr SourceManager::sourceManager()
00046 {
00047 static SourceManager_Ptr _source_manager( new SourceManager );
00048 return _source_manager;
00049 }
00050
00051 namespace
00052 {
00053 typedef std::map<SourceManager::SourceId, Source_Ref> SourceMap;
00054
00055 static SourceMap _sources;
00056 static SourceMap _deleted_sources;
00057 static std::set<std::string> _renamed_sources;
00058
00059 struct PrintSourceMapEntry
00060 {
00061 void operator()( const SourceMap::value_type & el ) const
00062 {
00063 _str << endl << " - " << el.second;
00064 }
00065 PrintSourceMapEntry( std::ostream & str )
00066 : _str( str )
00067 {}
00068 std::ostream & _str;
00069 };
00070
00071 inline std::ostream & dumpSourceTableOn( std::ostream & str, bool trailingENDL = true )
00072 {
00073 str << "SourceManager: =========================" << endl
00074 << " known Sources " << _sources.size();
00075 std::for_each( _sources.begin(), _sources.end(), PrintSourceMapEntry(str) );
00076
00077 str << endl
00078 << " deleted Sources " << _deleted_sources.size();
00079 std::for_each( _deleted_sources.begin(), _deleted_sources.end(), PrintSourceMapEntry(str) );
00080 str << endl
00081 << "========================================";
00082 if ( trailingENDL )
00083 str << endl;
00084 return str;
00085 }
00086
00087 inline bool sourceTableRemove( SourceMap::iterator it )
00088 {
00089 if ( it == _sources.end() )
00090 return false;
00091
00092 MIL << "SourceManager remove " << it->second << endl;
00093 _deleted_sources[it->second.numericId()] = it->second;
00094 _sources.erase(it);
00095
00096
00097 it->second.release();
00098
00099 dumpSourceTableOn( DBG );
00100 return true;
00101 }
00102
00103 inline SourceManager::SourceId sourceTableAdd( Source_Ref source_r )
00104 {
00105 if ( source_r.numericId() )
00106 {
00107 MIL << "SourceManager add " << source_r << endl;
00108 _sources[source_r.numericId()] = source_r;
00109
00110 dumpSourceTableOn( DBG );
00111 }
00112 else
00113 {
00114
00115
00116 WAR << "SourceManager does not add Source::noSource" << endl;
00117 }
00118 return source_r.numericId();
00119 }
00120
00121 }
00122
00124
00125
00126
00127
00128 SourceManager::SourceManager()
00129 {
00130 MIL << "Created SourceManager Singleton." << endl;
00131 }
00132
00134
00135
00136
00137
00138 SourceManager::~SourceManager()
00139 {
00140 MIL << "Deleted SourceManager Singleton." << endl;
00141 }
00142
00143 SourceManager::const_iterator SourceManager::begin() const
00144 {
00145 return _sources.begin();
00146 }
00147
00148 SourceManager::const_iterator SourceManager::end() const
00149 {
00150 return _sources.end();
00151 }
00152
00153 SourceManager::SourceId_const_iterator SourceManager::SourceId_begin() const
00154 {
00155 return make_map_key_begin( _sources );
00156 }
00157
00158 SourceManager::SourceId_const_iterator SourceManager::SourceId_end() const
00159 {
00160 return make_map_key_end( _sources );
00161 }
00162
00163 SourceManager::Source_const_iterator SourceManager::Source_begin() const
00164 {
00165 return make_map_value_begin( _sources );
00166 }
00167
00168 SourceManager::Source_const_iterator SourceManager::Source_end() const
00169 {
00170 return make_map_value_end( _sources );
00171 }
00172
00173 void SourceManager::reset()
00174 {
00175 MIL << "SourceManager reset (forget all sources)" << endl;
00176 _sources.clear();
00177 _deleted_sources.clear();
00178 }
00179
00180 SourceManager::SourceId SourceManager::addSource( Source_Ref source_r )
00181 {
00182 return sourceTableAdd( source_r );
00183 }
00184
00185 void SourceManager::renameSource( SourceId id, const std::string & new_alias_r )
00186 {
00187 Source_Ref src = findSource(id);
00188
00189 if ( src )
00190 {
00191
00192
00193
00194 _renamed_sources.insert(src.alias());
00195
00196 src.setAlias( new_alias_r );
00197 }
00198
00199 }
00200
00201 void SourceManager::removeSource(SourceManager::SourceId id)
00202 {
00203 if ( ! sourceTableRemove( _sources.find(id) ) )
00204 {
00205 WAR << "SourceManager remove: no source with SourceId " << id << endl;
00206 }
00207 }
00208
00209 void SourceManager::removeSource( const std::string & alias_r )
00210 {
00211 SourceMap::iterator it = _sources.begin();
00212 for ( ; it != _sources.end() && it->second.alias() != alias_r; ++it )
00213 ;
00214
00215 if ( ! sourceTableRemove( it ) )
00216 {
00217 WAR << "SourceManager remove: no source with alias " << alias_r << endl;
00218 }
00219 }
00220
00221 void SourceManager::removeSourceByUrl( const Url & url_r )
00222 {
00223 SourceMap::iterator it = _sources.begin();
00224 for ( ; it != _sources.end() && it->second.url().asString() != url_r.asString(); ++it )
00225 ;
00226
00227 if ( ! sourceTableRemove( it ) )
00228 {
00229 WAR << "SourceManager remove: no source with Url " << url_r << endl;
00230 }
00231 }
00232
00233 void SourceManager::releaseAllSources()
00234 {
00235 MIL << "SourceManager releasing all sources ..." << endl;
00236 for (SourceMap::iterator it = _sources.begin();
00237 it != _sources.end(); it++)
00238 {
00239 it->second.release();
00240 }
00241 MIL << "SourceManager releasing all sources done." << endl;
00242 }
00243
00244 void SourceManager::reattachSources(const Pathname &attach_point)
00245 {
00246 MIL << "SourceManager reattach all sources to '" << attach_point << " ..." << endl;
00247 for (SourceMap::iterator it = _sources.begin();
00248 it != _sources.end(); it++)
00249 {
00250 it->second.reattach(attach_point);
00251 }
00252 MIL << "SourceManager reattach all sources to '" << attach_point << " done." << endl;
00253 }
00254
00255
00256 void SourceManager::disableAllSources()
00257 {
00258 MIL << "SourceManager disable all sources ..." << endl;
00259 for ( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00260 {
00261 it->second.disable();
00262 }
00263 MIL << "SourceManager disable all sources done." << endl;
00264 }
00265
00266 std::list<SourceManager::SourceId> SourceManager::enabledSources() const
00267 {
00268 std::list<SourceManager::SourceId> res;
00269
00270 for ( SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); it++)
00271 {
00272 if ( it->second.enabled() )
00273 res.push_back(it->first);
00274 }
00275
00276 return res;
00277 }
00278
00279 std::list<SourceManager::SourceId> SourceManager::allSources() const
00280 {
00281 std::list<SourceManager::SourceId> res;
00282
00283 for ( SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); it++)
00284 {
00285 res.push_back(it->first);
00286 }
00287
00288 return res;
00289 }
00290
00291 void SourceManager::store(Pathname root_r, bool metadata_cache )
00292 {
00293 MIL << "SourceManager store '" << root_r << ( metadata_cache ? "' (metadata_cache)" : "'" )
00294 << " ..." << endl;
00295
00296 storage::PersistentStorage store;
00297 store.init( root_r );
00298
00299
00300
00301 if ( metadata_cache )
00302 {
00303
00304
00305 filesystem::assert_dir( root_r / getZYpp()->homePath() );
00306 Pathname topdir( root_r / ZYPP_METADATA_PREFIX );
00307 filesystem::assert_dir( topdir );
00308 MIL << "Created..." << topdir << std::endl;
00309 }
00310
00311
00312 for ( std::set<std::string>::const_iterator it = _renamed_sources.begin(); it != _renamed_sources.end(); it++)
00313 {
00314 MIL << "removing source entry " << *it << " (renamed) from persistent store" << endl;
00315 store.deleteSource( *it );
00316 }
00317
00318 _renamed_sources.clear();
00319
00320
00321
00322 for ( SourceMap::iterator it = _deleted_sources.begin(); it != _deleted_sources.end(); it++)
00323 {
00324 MIL << "Deleting source " << it->second << " from persistent store" << endl;
00325 store.deleteSource( it->second.alias() );
00326 filesystem::recursive_rmdir( it->second.cacheDir() );
00327 }
00328
00329 _deleted_sources.clear();
00330
00331 for ( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00332 {
00333 source::SourceInfo descr;
00334
00335 descr.setUrl(it->second.url());
00336 descr.setEnabled( it->second.enabled() );
00337 descr.setAlias( it->second.alias() );
00338 descr.setAutorefresh( it->second.autorefresh() );
00339 descr.setType( it->second.type() );
00340 descr.setPath( it->second.path() );
00341
00342 descr.setCacheDir( it->second.cacheDir() );
00343
00344 if ( metadata_cache && descr.cacheDir().empty() )
00345 {
00346 if ( descr.cacheDir().empty() )
00347 {
00348 filesystem::TmpDir newCache( root_r / ZYPP_METADATA_PREFIX, "Source." );
00349 descr.setCacheDir( ZYPP_METADATA_PREFIX + newCache.path().basename() );
00350 }
00351
00352 filesystem::assert_dir ( root_r.asString() + descr.cacheDir() );
00353
00354 MIL << "Storing metadata to (" << root_r.asString() << ")/" << descr.cacheDir() << endl;
00355
00356 try
00357 {
00358 it->second.storeMetadata( root_r.asString() + descr.cacheDir() );
00359 }
00360 catch (const Exception &excp)
00361 {
00362 WAR << "Creating local metadata cache failed, not using cache" << endl;
00363 descr.setCacheDir("");
00364 }
00365 }
00366
00367 store.storeSource( descr );
00368 }
00369
00370 MIL << "SourceManager store done." << endl;
00371 }
00372
00376 bool SourceManager::restore( Pathname root_r, bool use_caches, const std::string &alias_filter, const std::string &url_filter )
00377 {
00378 MIL << "SourceManager restore ('" << root_r << ( use_caches ? "' (use_caches)" : "'" ) << ", alias_filter '" << alias_filter << ", url_filter '" << url_filter << "')" << endl;
00379
00380 if (! _sources.empty() )
00381 {
00382
00383
00384
00385 if (alias_filter.empty()
00386 && url_filter.empty())
00387 {
00388 ZYPP_THROW(SourcesAlreadyRestoredException());
00389
00390 }
00391
00392
00393
00394 for (SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); ++it)
00395 {
00396 if (!alias_filter.empty() && (alias_filter == it->second.alias()) )
00397 {
00398 MIL << "Source with alias '" << alias_filter << "' already restored.";
00399 return true;
00400 }
00401
00402 if (!url_filter.empty() && (url_filter == it->second.url().asString()) )
00403 {
00404 MIL << "Source with url '" << url_filter << "' already restored.";
00405 return true;
00406 }
00407 }
00408 }
00409
00410 FailedSourcesRestoreException report;
00411
00412 storage::PersistentStorage store;
00413 store.init( root_r );
00414
00415 std::list<source::SourceInfo> new_sources = store.storedSources();
00416
00417 MIL << "Found sources: " << new_sources.size() << endl;
00418
00419 for ( std::list<source::SourceInfo>::iterator it = new_sources.begin(); it != new_sources.end(); ++it)
00420 {
00421 if ( !alias_filter.empty()
00422 && (alias_filter != it->alias()) )
00423 {
00424 continue;
00425 }
00426
00427 if ( !url_filter.empty()
00428 && (url_filter != it->url().asString()) )
00429 {
00430 continue;
00431 }
00432
00433
00434 MIL << "Restoring source: url:[" << it->url().asString() << "] product_dir:[" << it->path() << "] alias:[" << it->alias() << "] cache_dir:[" << it->cacheDir() << "] auto_refresh:[ " << it->autorefresh() << "]" << endl;
00435
00436 SourceId id = 0;
00437
00438 try
00439 {
00440 Source_Ref src = SourceFactory().createFrom(it->type(), it->url(), it->path(), it->alias(), it->cacheDir(), false, it->autorefresh());
00441 id = addSource(src);
00442 }
00443 catch (const Exception &expt )
00444 {
00445
00446 ERR << "Unable to restore source from " << it->url().asString() << endl;
00447
00448 id = 0;
00449 Url url2;
00450 try
00451 {
00452 url2 = it->url();
00453 std::string scheme( url2.getScheme());
00454
00455 if ( (scheme == "cd" || scheme == "dvd") && !url2.getQueryParam("devices").empty())
00456 {
00457 url2.setQueryParam("devices", "");
00458 DBG << "CD/DVD devices changed - try again without a devices list" << std::endl;
00459
00460 id = addSource( SourceFactory().createFrom(url2, it->path(), it->alias(), it->cacheDir(), false ) );
00461
00462
00463
00464 }
00465 }
00466 catch (const Exception &e2)
00467 {
00468
00469 ERR << "Unable to restore source from " << url2.asString()
00470 << endl;
00471 id = 0;
00472 ZYPP_CAUGHT(e2);
00473 }
00474
00475 if ( id == 0)
00476 {
00477 report.append( it->url().asString() + it->path().asString(), it->alias(), expt );
00478 continue;
00479 }
00480 }
00481
00482 DBG << "Added source as id " << id << endl;
00483
00484 Source_Ref src = findSource( id );
00485
00486 if ( it->enabled() )
00487 {
00488 DBG << "enable source" << endl;
00489 src.enable();
00490 }
00491 else
00492 {
00493 DBG << "disable source" << endl;
00494 src.disable();
00495 }
00496 }
00497
00498 if ( !report.empty() )
00499 {
00500 ZYPP_THROW(report);
00501 }
00502
00503 MIL << "SourceManager restore done." << endl;
00504 dumpSourceTableOn( DBG );
00505 return true;
00506 }
00507
00508 void SourceManager::disableSourcesAt( const Pathname & root_r )
00509 {
00510 storage::PersistentStorage store;
00511 store.init( root_r );
00512
00513 std::list<source::SourceInfo> new_sources = store.storedSources();
00514
00515 MIL << "Disabling all sources in store at " << root_r << endl;
00516
00517 for ( std::list<source::SourceInfo>::iterator it = new_sources.begin();
00518 it != new_sources.end(); ++it)
00519 {
00520 MIL << "Disabling source " << it->alias() << endl;
00521 it->setEnabled(false);
00522 store.storeSource( *it );
00523 }
00524 }
00525
00526 source::SourceInfoList SourceManager::knownSourceInfos(const Pathname &root_r)
00527 {
00528 storage::PersistentStorage store;
00529 SourceInfoList result;
00530 store.init( root_r );
00531
00532 source::SourceInfoList sources = store.storedSources();
00533 MIL << "Found sources: " << sources.size() << endl;
00534 return sources;
00535 }
00536
00537
00538
00539
00540
00541
00542 std::ostream & operator<<( std::ostream & str, const SourceManager & obj )
00543 {
00544 return dumpSourceTableOn( str, false );
00545 }
00546
00547 Source_Ref SourceManager::findSource(SourceId id)
00548 {
00549 SourceMap::iterator it = _sources.find(id);
00550 if (it == _sources.end())
00551 {
00552 ZYPP_THROW(Exception("Unknown source ID"));
00553 }
00554 return it->second;
00555 }
00556
00557 Source_Ref SourceManager::findSource(const std::string & alias_r)
00558 {
00559 SourceMap::iterator it;
00560 for (it = _sources.begin(); it != _sources.end(); ++it)
00561 {
00562 if (it->second.alias() == alias_r)
00563 {
00564 return it->second;
00565 }
00566 }
00567 ZYPP_THROW(Exception("Unknown source name '"+alias_r+"'"));
00568
00569 return it->second;
00570 }
00571
00572 Source_Ref SourceManager::findSourceByUrl(const Url & url_r)
00573 {
00574 SourceMap::iterator it;
00575 for (it = _sources.begin(); it != _sources.end(); ++it)
00576 {
00577 if (it->second.url().asCompleteString() == url_r.asCompleteString())
00578 {
00579 return it->second;
00580 }
00581 }
00582 ZYPP_THROW(Exception("Unknown source URL '"+url_r.asString()+"'"));
00583
00584 return it->second;
00585 }
00586
00588
00590
00591 std::ostream & FailedSourcesRestoreException::dumpOn( std::ostream & str ) const
00592 {
00593 return str << _summary;
00594 }
00595
00596 std::ostream & FailedSourcesRestoreException::dumpOnTranslated( std::ostream & str ) const
00597 {
00598 return str << Exception::asUserString() << endl << _translatedSummary;
00599 }
00600
00601 bool FailedSourcesRestoreException::empty () const
00602 {
00603 return _summary.empty();
00604 }
00605
00606 std::set<std::string> FailedSourcesRestoreException::aliases () const
00607 {
00608 return _aliases;
00609 }
00610
00611 void FailedSourcesRestoreException::append( std::string source, std::string alias, const Exception& expt)
00612 {
00613 _summary = _summary + "\n" + source + ": " + expt.asString();
00614 _translatedSummary = _translatedSummary + "\n" + source + ": " + expt.asUserString();
00615 _aliases.insert( alias );
00616 }
00617
00619 }