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
00272 for( SourceMap::iterator it = _deleted_sources.begin(); it != _deleted_sources.end(); it++)
00273 {
00274 MIL << "Deleting source " << it->second << " from persistent store" << endl;
00275 store.deleteSource( it->second.alias() );
00276 filesystem::recursive_rmdir( it->second.cacheDir() );
00277 }
00278
00279 _deleted_sources.clear();
00280
00281 for( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00282 {
00283 storage::PersistentStorage::SourceData descr;
00284
00285 descr.url = it->second.url().asCompleteString();
00286 descr.enabled = it->second.enabled();
00287 descr.alias = it->second.alias();
00288 descr.autorefresh = it->second.autorefresh();
00289 descr.type = it->second.type();
00290 descr.product_dir = it->second.path();
00291
00292 descr.cache_dir = it->second.cacheDir();
00293
00294 if( metadata_cache && descr.cache_dir.empty() )
00295 {
00296 if( descr.cache_dir.empty() )
00297 {
00298 filesystem::TmpDir newCache( root_r / ZYPP_METADATA_PREFIX, "Source." );
00299 descr.cache_dir = ZYPP_METADATA_PREFIX + newCache.path().basename();
00300 }
00301
00302 filesystem::assert_dir ( root_r.asString() + descr.cache_dir );
00303
00304 MIL << "Storing metadata to (" << root_r.asString() << ")/" << descr.cache_dir << endl;
00305
00306 try {
00307 it->second.storeMetadata( root_r.asString() + descr.cache_dir );
00308 }
00309 catch(const Exception &excp) {
00310 WAR << "Creating local metadata cache failed, not using cache" << endl;
00311 descr.cache_dir = "";
00312 }
00313 }
00314
00315 store.storeSource( descr );
00316 }
00317
00318 MIL << "SourceManager store done." << endl;
00319 }
00320
00324 bool SourceManager::restore( Pathname root_r, bool use_caches )
00325 {
00326 MIL << "SourceManager restore '" << root_r << ( use_caches ? "' (use_caches)" : "'" )
00327 << " ..." << endl;
00328
00329 if (! _sources.empty() )
00330 ZYPP_THROW(SourcesAlreadyRestoredException());
00331
00332
00333 FailedSourcesRestoreException report;
00334
00335 storage::PersistentStorage store;
00336 store.init( root_r );
00337
00338 std::list<storage::PersistentStorage::SourceData> new_sources = store.storedSources();
00339
00340 MIL << "Found sources: " << new_sources.size() << endl;
00341
00342 for( std::list<storage::PersistentStorage::SourceData>::iterator it = new_sources.begin();
00343 it != new_sources.end(); ++it)
00344 {
00345
00346 MIL << "Restoring source: url:[" << Url(it->url).asString() << "] product_dir:[" << it->product_dir << "] alias:[" << it->alias << "] cache_dir:[" << it->cache_dir << "]" << endl;
00347
00348 SourceId id = 0;
00349
00350 try {
00351 id = addSource( SourceFactory().createFrom(it->type, it->url, it->product_dir, it->alias, it->cache_dir) );
00352 }
00353 catch (const Exception &expt )
00354 {
00355
00356 ERR << "Unable to restore source from " << Url(it->url).asString()
00357 << endl;
00358
00359 id = 0;
00360 Url url2;
00361 try {
00362 url2 = it->url;
00363 std::string scheme( url2.getScheme());
00364
00365 if( (scheme == "cd" || scheme == "dvd") &&
00366 !url2.getQueryParam("devices").empty())
00367 {
00368 url2.setQueryParam("devices", "");
00369
00370 DBG << "CD/DVD devices changed - try again without a devices list"
00371 << std::endl;
00372
00373 id = addSource( SourceFactory().createFrom(url2, it->product_dir, it->alias, it->cache_dir) );
00374
00375
00376
00377 }
00378 }
00379 catch (const Exception &e2)
00380 {
00381
00382 ERR << "Unable to restore source from " << url2.asString()
00383 << endl;
00384 id = 0;
00385 ZYPP_CAUGHT(e2);
00386 }
00387
00388 if( id == 0)
00389 {
00390 report.append( it->url.asString() + it->product_dir.asString(), it->alias, expt );
00391 continue;
00392 }
00393 }
00394
00395 DBG << "Added source as id " << id << endl;
00396
00397 Source_Ref src = findSource( id );
00398
00399 if ( it->enabled ) {
00400 DBG << "enable source" << endl;
00401 src.enable();
00402 }
00403 else {
00404 DBG << "disable source" << endl;
00405 src.disable();
00406 }
00407 src.setAutorefresh ( it->autorefresh );
00408 }
00409
00410 if( !report.empty() )
00411 {
00412 ZYPP_THROW(report);
00413 }
00414
00415 MIL << "SourceManager restore done." << endl;
00416 dumpSourceTableOn( DBG );
00417 return true;
00418 }
00419
00420 void SourceManager::disableSourcesAt( const Pathname & root_r )
00421 {
00422 storage::PersistentStorage store;
00423 store.init( root_r );
00424
00425 std::list<storage::PersistentStorage::SourceData> new_sources = store.storedSources();
00426
00427 MIL << "Disabling all sources in store at " << root_r << endl;
00428
00429 for( std::list<storage::PersistentStorage::SourceData>::iterator it = new_sources.begin();
00430 it != new_sources.end(); ++it)
00431 {
00432 MIL << "Disabling source " << it->alias << endl;
00433 it->enabled = false;
00434 store.storeSource( *it );
00435 }
00436 }
00437
00438
00439
00440
00441
00442
00443
00444 std::ostream & operator<<( std::ostream & str, const SourceManager & obj )
00445 {
00446 return dumpSourceTableOn( str, false );
00447 }
00448
00449 Source_Ref SourceManager::findSource(SourceId id)
00450 {
00451 SourceMap::iterator it = _sources.find(id);
00452 if (it == _sources.end())
00453 {
00454 ZYPP_THROW(Exception("Unknown source ID"));
00455 }
00456 return it->second;
00457 }
00458
00459 Source_Ref SourceManager::findSource(const std::string & alias_r)
00460 {
00461 SourceMap::iterator it;
00462 for (it = _sources.begin(); it != _sources.end(); ++it)
00463 {
00464 if (it->second.alias() == alias_r) {
00465 return it->second;
00466 }
00467 }
00468 ZYPP_THROW(Exception("Unknown source name '"+alias_r+"'"));
00469
00470 return it->second;
00471 }
00472
00473 Source_Ref SourceManager::findSourceByUrl(const Url & url_r)
00474 {
00475 SourceMap::iterator it;
00476 for (it = _sources.begin(); it != _sources.end(); ++it)
00477 {
00478 if (it->second.url().asCompleteString() == url_r.asCompleteString()) {
00479 return it->second;
00480 }
00481 }
00482 ZYPP_THROW(Exception("Unknown source URL '"+url_r.asString()+"'"));
00483
00484 return it->second;
00485 }
00486
00488
00490
00491 std::ostream & FailedSourcesRestoreException::dumpOn( std::ostream & str ) const
00492 {
00493 return str << _summary;
00494 }
00495
00496 std::ostream & FailedSourcesRestoreException::dumpOnTranslated( std::ostream & str ) const
00497 {
00498 return str << Exception::asUserString() << endl << _translatedSummary;
00499 }
00500
00501 bool FailedSourcesRestoreException::empty () const
00502 {
00503 return _summary.empty();
00504 }
00505
00506 std::set<std::string> FailedSourcesRestoreException::aliases () const
00507 {
00508 return _aliases;
00509 }
00510
00511 void FailedSourcesRestoreException::append( std::string source, std::string alias, const Exception& expt)
00512 {
00513 _summary = _summary + "\n" + source + ": " + expt.asString();
00514 _translatedSummary = _translatedSummary + "\n" + source + ": " + expt.asUserString();
00515 _aliases.insert( alias );
00516 }
00517
00519 }