SourceManager.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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       // release all media of this source, not needed anymore (#159754)
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         // Not worth an Exception. Request to add noSource, adds no Source,
00115         // and returns the noSource Id.
00116         WAR << "SourceManager does not add Source::noSource" << endl;
00117       }
00118       return source_r.numericId();
00119     }
00120 
00121   }
00122 
00124   //
00125   // METHOD NAME : SourceManager::SourceManager
00126   // METHOD TYPE : Ctor
00127   //
00128   SourceManager::SourceManager()
00129   {
00130     MIL << "Created SourceManager Singleton." << endl;
00131   }
00132 
00134   //
00135   // METHOD NAME : SourceManager::~SourceManager
00136   // METHOD TYPE : Dtor
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       // delete the old entry in the storage
00192       // the new entry will appear when doing
00193       // store
00194       _renamed_sources.insert(src.alias());
00195       // set the new alias
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       ; // empty body
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       ; // empty body
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     // make sure to create the source metadata cache
00301     if ( metadata_cache )
00302     {
00303       // make sure our root exists
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     // delete renamed sources entries
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     // delete before modifying and creating
00321     // so that we can recreate a deleted one (#174295)
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       // if we've already restored sources and this is an unfiltered call, reject it.
00384 
00385       if (alias_filter.empty()
00386           && url_filter.empty())
00387       {
00388         ZYPP_THROW(SourcesAlreadyRestoredException());
00389         //Exception ( N_("At least one source already registered, cannot restore sources from persistent store.") ) );
00390       }
00391 
00392       // check filters against already restore sources and check for duplicates.
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()   // check alias filter, if set
00422            && (alias_filter != it->alias()) )
00423       {
00424         continue;
00425       }
00426 
00427       if ( !url_filter.empty()   // check url filter, if set
00428            && (url_filter != it->url().asString()) )
00429       {
00430         continue;
00431       }
00432 
00433       // Note: Url(it->url).asString() to hide password in logs
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         // Note: Url(it->url).asString() to hide password in logs
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             // This worked ... update it->url ?
00463             //it->url = url2.asCompleteString();
00464           }
00465         }
00466         catch (const Exception &e2)
00467         {
00468           // Note: Url(it->url).asString() to hide password in logs
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       // should not throw, we've just created the source
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   ** FUNCTION NAME : operator<<
00540   ** FUNCTION TYPE : std::ostream &
00541   */
00542   std::ostream & operator<<( std::ostream & str, const SourceManager & obj )
00543   {
00544     return dumpSourceTableOn( str, /*tailingENDL*/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     /*NOTREACHED*/
00569     return it->second; // just to keep gcc happy
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     /*NOTREACHED*/
00584     return it->second; // just to keep gcc happy
00585   }
00586 
00588   // FailedSourcesRestoreException
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 } // namespace zypp

Generated on Tue Nov 28 16:49:33 2006 for zypp by  doxygen 1.5.0