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"
00033
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
00058 struct PrintSourceMapEntry
00059 {
00060 void operator()( const SourceMap::value_type & el ) const
00061 {
00062 _str << endl << " - " << el.second;
00063 }
00064 PrintSourceMapEntry( std::ostream & str )
00065 : _str( str )
00066 {}
00067 std::ostream & _str;
00068 };
00069
00070 inline std::ostream & dumpSourceTableOn( std::ostream & str, bool trailingENDL = true )
00071 {
00072 str << "SourceManager: =========================" << endl
00073 << " known Sources " << _sources.size();
00074 std::for_each( _sources.begin(), _sources.end(), PrintSourceMapEntry(str) );
00075
00076 str << endl
00077 << " deleted Sources " << _deleted_sources.size();
00078 std::for_each( _deleted_sources.begin(), _deleted_sources.end(), PrintSourceMapEntry(str) );
00079 str << endl
00080 << "========================================";
00081 if ( trailingENDL )
00082 str << endl;
00083 return str;
00084 }
00085
00086 inline bool sourceTableRemove( SourceMap::iterator it )
00087 {
00088 if ( it == _sources.end() )
00089 return false;
00090
00091 MIL << "SourceManager remove " << it->second << endl;
00092 _deleted_sources[it->second.numericId()] = it->second;
00093 _sources.erase(it);
00094
00095
00096 it->second.release();
00097
00098 dumpSourceTableOn( DBG );
00099 return true;
00100 }
00101
00102 inline SourceManager::SourceId sourceTableAdd( Source_Ref source_r )
00103 {
00104 if ( source_r.numericId() )
00105 {
00106 MIL << "SourceManager add " << source_r << endl;
00107 _sources[source_r.numericId()] = source_r;
00108
00109 dumpSourceTableOn( DBG );
00110 }
00111 else
00112 {
00113
00114
00115 WAR << "SourceManager does not add Source::noSource" << endl;
00116 }
00117 return source_r.numericId();
00118 }
00119
00120 }
00121
00123
00124
00125
00126
00127 SourceManager::SourceManager()
00128 {
00129 MIL << "Created SourceManager Singleton." << endl;
00130 }
00131
00133
00134
00135
00136
00137 SourceManager::~SourceManager()
00138 {
00139 MIL << "Deleted SourceManager Singleton." << endl;
00140 }
00141
00142 SourceManager::const_iterator SourceManager::begin() const
00143 { return _sources.begin(); }
00144
00145 SourceManager::const_iterator SourceManager::end() const
00146 { return _sources.end(); }
00147
00148 SourceManager::SourceId_const_iterator SourceManager::SourceId_begin() const
00149 { return make_map_key_begin( _sources ); }
00150
00151 SourceManager::SourceId_const_iterator SourceManager::SourceId_end() const
00152 { return make_map_key_end( _sources ); }
00153
00154 SourceManager::Source_const_iterator SourceManager::Source_begin() const
00155 { return make_map_value_begin( _sources ); }
00156
00157 SourceManager::Source_const_iterator SourceManager::Source_end() const
00158 { return make_map_value_end( _sources ); }
00159
00160 void SourceManager::reset()
00161 {
00162 MIL << "SourceManager reset (forget all sources)" << endl;
00163 _sources.clear();
00164 _deleted_sources.clear();
00165 }
00166
00167 SourceManager::SourceId SourceManager::addSource( Source_Ref source_r )
00168 {
00169 return sourceTableAdd( source_r );
00170 }
00171
00172 void SourceManager::removeSource(SourceManager::SourceId id)
00173 {
00174 if ( ! sourceTableRemove( _sources.find(id) ) )
00175 {
00176 WAR << "SourceManager remove: no source with SourceId " << id << endl;
00177 }
00178 }
00179
00180 void SourceManager::removeSource( const std::string & alias_r )
00181 {
00182 SourceMap::iterator it = _sources.begin();
00183 for ( ; it != _sources.end() && it->second.alias() != alias_r; ++it )
00184 ;
00185
00186 if ( ! sourceTableRemove( it ) )
00187 {
00188 WAR << "SourceManager remove: no source with alias " << alias_r << endl;
00189 }
00190 }
00191
00192 void SourceManager::releaseAllSources()
00193 {
00194 MIL << "SourceManager releasing all sources ..." << endl;
00195 for (SourceMap::iterator it = _sources.begin();
00196 it != _sources.end(); it++)
00197 {
00198 it->second.release();
00199 }
00200 MIL << "SourceManager releasing all sources done." << endl;
00201 }
00202
00203 void SourceManager::reattachSources(const Pathname &attach_point)
00204 {
00205 MIL << "SourceManager reattach all sources to '" << attach_point << " ..." << endl;
00206 for (SourceMap::iterator it = _sources.begin();
00207 it != _sources.end(); it++)
00208 {
00209 it->second.reattach(attach_point);
00210 }
00211 MIL << "SourceManager reattach all sources to '" << attach_point << " done." << endl;
00212 }
00213
00214
00215 void SourceManager::disableAllSources()
00216 {
00217 MIL << "SourceManager disable all sources ..." << endl;
00218 for( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00219 {
00220 it->second.disable();
00221 }
00222 MIL << "SourceManager disable all sources done." << endl;
00223 }
00224
00225 std::list<SourceManager::SourceId> SourceManager::enabledSources() const
00226 {
00227 std::list<SourceManager::SourceId> res;
00228
00229 for( SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); it++)
00230 {
00231 if( it->second.enabled() )
00232 res.push_back(it->first);
00233 }
00234
00235 return res;
00236 }
00237
00238 std::list<SourceManager::SourceId> SourceManager::allSources() const
00239 {
00240 std::list<SourceManager::SourceId> res;
00241
00242 for( SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); it++)
00243 {
00244 res.push_back(it->first);
00245 }
00246
00247 return res;
00248 }
00249
00250 void SourceManager::store(Pathname root_r, bool metadata_cache )
00251 {
00252 MIL << "SourceManager store '" << root_r << ( metadata_cache ? "' (metadata_cache)" : "'" )
00253 << " ..." << endl;
00254
00255 storage::PersistentStorage store;
00256 store.init( root_r );
00257
00258
00259
00260 if( metadata_cache )
00261 {
00262
00263
00264 filesystem::assert_dir( root_r / getZYpp()->homePath() );
00265 Pathname topdir( root_r / ZYPP_METADATA_PREFIX );
00266 filesystem::assert_dir( topdir );
00267 MIL << "Created..." << topdir << std::endl;
00268 }
00269
00270
00271 std::set<std::string> known_caches;
00272 for( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00273 {
00274 if( ! it->second.cacheDir().empty() )
00275 known_caches.insert( it->second.cacheDir().asString() );
00276 }
00277
00278 for( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00279 {
00280 storage::PersistentStorage::SourceData descr;
00281
00282 descr.url = it->second.url().asCompleteString();
00283 descr.enabled = it->second.enabled();
00284 descr.alias = it->second.alias();
00285 descr.autorefresh = it->second.autorefresh();
00286 descr.type = it->second.type();
00287 descr.product_dir = it->second.path();
00288
00289 descr.cache_dir = it->second.cacheDir();
00290
00291 if( metadata_cache && descr.cache_dir.empty() )
00292 {
00293 if( descr.cache_dir.empty() )
00294 {
00295 filesystem::TmpDir newCache( root_r / ZYPP_METADATA_PREFIX, "Source." );
00296 descr.cache_dir = ZYPP_METADATA_PREFIX + newCache.path().basename();
00297 known_caches.insert( descr.cache_dir.asString() );
00298 }
00299
00300 filesystem::assert_dir ( root_r.asString() + descr.cache_dir );
00301
00302 MIL << "Storing metadata to (" << root_r.asString() << ")/" << descr.cache_dir << endl;
00303
00304 try {
00305 it->second.storeMetadata( root_r.asString() + descr.cache_dir );
00306 }
00307 catch(const Exception &excp) {
00308 WAR << "Creating local metadata cache failed, not using cache" << endl;
00309 descr.cache_dir = "";
00310 }
00311 }
00312
00313 store.storeSource( descr );
00314 }
00315
00316 for( SourceMap::iterator it = _deleted_sources.begin(); it != _deleted_sources.end(); it++)
00317 {
00318 MIL << "Deleting source " << it->second << " from persistent store" << endl;
00319 store.deleteSource( it->second.alias() );
00320 filesystem::recursive_rmdir( it->second.cacheDir() );
00321 }
00322
00323 _deleted_sources.clear();
00324
00325 MIL << "SourceManager store done." << endl;
00326 }
00327
00331 bool SourceManager::restore( Pathname root_r, bool use_caches )
00332 {
00333 MIL << "SourceManager restore '" << root_r << ( use_caches ? "' (use_caches)" : "'" )
00334 << " ..." << endl;
00335
00336 if (! _sources.empty() )
00337 ZYPP_THROW(SourcesAlreadyRestoredException());
00338
00339
00340 FailedSourcesRestoreException report;
00341
00342 storage::PersistentStorage store;
00343 store.init( root_r );
00344
00345 std::list<storage::PersistentStorage::SourceData> new_sources = store.storedSources();
00346
00347 MIL << "Found sources: " << new_sources.size() << endl;
00348
00349 for( std::list<storage::PersistentStorage::SourceData>::iterator it = new_sources.begin();
00350 it != new_sources.end(); ++it)
00351 {
00352
00353 MIL << "Restoring source: url:[" << Url(it->url).asString() << "] product_dir:[" << it->product_dir << "] alias:[" << it->alias << "] cache_dir:[" << it->cache_dir << "]" << endl;
00354
00355 SourceId id = 0;
00356
00357 try {
00358 id = addSource( SourceFactory().createFrom(it->type, it->url, it->product_dir, it->alias, it->cache_dir) );
00359 }
00360 catch (const Exception &expt )
00361 {
00362
00363 ERR << "Unable to restore source from " << Url(it->url).asString()
00364 << endl;
00365
00366 id = 0;
00367 Url url2;
00368 try {
00369 url2 = it->url;
00370 std::string scheme( url2.getScheme());
00371
00372 if( (scheme == "cd" || scheme == "dvd") &&
00373 !url2.getQueryParam("devices").empty())
00374 {
00375 url2.setQueryParam("devices", "");
00376
00377 DBG << "CD/DVD devices changed - try again without a devices list"
00378 << std::endl;
00379
00380 id = addSource( SourceFactory().createFrom(url2, it->product_dir, it->alias, it->cache_dir) );
00381
00382
00383
00384 }
00385 }
00386 catch (const Exception &e2)
00387 {
00388
00389 ERR << "Unable to restore source from " << url2.asString()
00390 << endl;
00391 id = 0;
00392 ZYPP_CAUGHT(e2);
00393 }
00394
00395 if( id == 0)
00396 {
00397 report.append( it->url.asString() + it->product_dir.asString(), it->alias, expt );
00398 continue;
00399 }
00400 }
00401
00402 DBG << "Added source as id " << id << endl;
00403
00404 Source_Ref src = findSource( id );
00405
00406 if ( it->enabled ) {
00407 DBG << "enable source" << endl;
00408 src.enable();
00409 }
00410 else {
00411 DBG << "disable source" << endl;
00412 src.disable();
00413 }
00414 src.setAutorefresh ( it->autorefresh );
00415 }
00416
00417 if( !report.empty() )
00418 {
00419 ZYPP_THROW(report);
00420 }
00421
00422 MIL << "SourceManager restore done." << endl;
00423 dumpSourceTableOn( DBG );
00424 return true;
00425 }
00426
00427 void SourceManager::disableSourcesAt( const Pathname & root_r )
00428 {
00429 storage::PersistentStorage store;
00430 store.init( root_r );
00431
00432 std::list<storage::PersistentStorage::SourceData> new_sources = store.storedSources();
00433
00434 MIL << "Disabling all sources in store at " << root_r << endl;
00435
00436 for( std::list<storage::PersistentStorage::SourceData>::iterator it = new_sources.begin();
00437 it != new_sources.end(); ++it)
00438 {
00439 MIL << "Disabling source " << it->alias << endl;
00440 it->enabled = false;
00441 store.storeSource( *it );
00442 }
00443 }
00444
00445
00446
00447
00448
00449
00450
00451 std::ostream & operator<<( std::ostream & str, const SourceManager & obj )
00452 {
00453 return dumpSourceTableOn( str, false );
00454 }
00455
00456 Source_Ref SourceManager::findSource(SourceId id)
00457 {
00458 SourceMap::iterator it = _sources.find(id);
00459 if (it == _sources.end())
00460 {
00461 ZYPP_THROW(Exception("Unknown source ID"));
00462 }
00463 return it->second;
00464 }
00465
00466 Source_Ref SourceManager::findSource(const std::string & alias_r)
00467 {
00468 SourceMap::iterator it;
00469 for (it = _sources.begin(); it != _sources.end(); ++it)
00470 {
00471 if (it->second.alias() == alias_r) {
00472 return it->second;
00473 break;
00474 }
00475
00476 }
00477 ZYPP_THROW(Exception("Unknown source name '"+alias_r+"'"));
00478
00479 return it->second;
00480 }
00481
00483
00485
00486 std::ostream & FailedSourcesRestoreException::dumpOn( std::ostream & str ) const
00487 {
00488 return str << _summary;
00489 }
00490
00491 std::ostream & FailedSourcesRestoreException::dumpOnTranslated( std::ostream & str ) const
00492 {
00493 return str << Exception::asUserString() << endl << _translatedSummary;
00494 }
00495
00496 bool FailedSourcesRestoreException::empty () const
00497 {
00498 return _summary.empty();
00499 }
00500
00501 std::set<std::string> FailedSourcesRestoreException::aliases () const
00502 {
00503 return _aliases;
00504 }
00505
00506 void FailedSourcesRestoreException::append( std::string source, std::string alias, const Exception& expt)
00507 {
00508 _summary = _summary + "\n" + source + ": " + expt.asString();
00509 _translatedSummary = _translatedSummary + "\n" + source + ": " + expt.asUserString();
00510 _aliases.insert( alias );
00511 }
00512
00514 }