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"
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       // release all media of this source, not needed anymore (#159754)
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           // Not worth an Exception. Request to add noSource, adds no Source,
00114           // and returns the noSource Id.
00115           WAR << "SourceManager does not add Source::noSource" << endl;
00116         }
00117       return source_r.numericId();
00118     }
00119 
00120   }
00121 
00123   //
00124   //    METHOD NAME : SourceManager::SourceManager
00125   //    METHOD TYPE : Ctor
00126   //
00127   SourceManager::SourceManager()
00128   {
00129     MIL << "Created SourceManager Singleton." << endl;
00130   }
00131 
00133   //
00134   //    METHOD NAME : SourceManager::~SourceManager
00135   //    METHOD TYPE : Dtor
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       ; // empty body
00185 
00186     if ( ! sourceTableRemove( it ) )
00187       {
00188         WAR << "SourceManager remove: no source with alias " << alias_r << endl;
00189       }
00190   }
00191 
00192   void SourceManager::removeSourceByUrl( const Url & url_r )
00193   {
00194     SourceMap::iterator it = _sources.begin();
00195     for ( ; it != _sources.end() && it->second.url().asString() != url_r.asString(); ++it )
00196       ; // empty body
00197 
00198     if ( ! sourceTableRemove( it ) )
00199       {
00200         WAR << "SourceManager remove: no source with Url " << url_r << endl;
00201       }
00202   }
00203 
00204   void SourceManager::releaseAllSources()
00205   {
00206     MIL << "SourceManager releasing all sources ..." << endl;
00207     for (SourceMap::iterator it = _sources.begin();
00208          it != _sources.end(); it++)
00209     {
00210       it->second.release();
00211     }
00212     MIL << "SourceManager releasing all sources done." << endl;
00213   }
00214 
00215   void SourceManager::reattachSources(const Pathname &attach_point)
00216   {
00217     MIL << "SourceManager reattach all sources to '" << attach_point << " ..." << endl;
00218     for (SourceMap::iterator it = _sources.begin();
00219          it != _sources.end(); it++)
00220     {
00221       it->second.reattach(attach_point);
00222     }
00223     MIL << "SourceManager reattach all sources to '" << attach_point << " done." << endl;
00224   }
00225 
00226 
00227   void SourceManager::disableAllSources()
00228   {
00229     MIL << "SourceManager disable all sources ..." << endl;
00230     for( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00231     {
00232         it->second.disable();
00233     }
00234     MIL << "SourceManager disable all sources done." << endl;
00235   }
00236 
00237   std::list<SourceManager::SourceId> SourceManager::enabledSources() const
00238   {
00239     std::list<SourceManager::SourceId> res;
00240 
00241     for( SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); it++)
00242     {
00243         if( it->second.enabled() )
00244             res.push_back(it->first);
00245     }
00246 
00247     return res;
00248   }
00249 
00250   std::list<SourceManager::SourceId> SourceManager::allSources() const
00251   {
00252     std::list<SourceManager::SourceId> res;
00253 
00254     for( SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); it++)
00255     {
00256         res.push_back(it->first);
00257     }
00258 
00259     return res;
00260   }
00261 
00262   void SourceManager::store(Pathname root_r, bool metadata_cache )
00263   {
00264     MIL << "SourceManager store '" << root_r << ( metadata_cache ? "' (metadata_cache)" : "'" )
00265         << " ..." << endl;
00266 
00267     storage::PersistentStorage store;
00268     store.init( root_r );
00269 
00270 
00271     // make sure to create the source metadata cache
00272     if( metadata_cache )
00273     {
00274         // make sure our root exists
00275 
00276         filesystem::assert_dir( root_r / getZYpp()->homePath() );
00277         Pathname topdir( root_r / ZYPP_METADATA_PREFIX );
00278         filesystem::assert_dir( topdir );
00279         MIL << "Created..." << topdir << std::endl;
00280     }
00281 
00282     // delete before modifying and creating
00283     // so that we can recreate a deleted one (#174295)
00284     for( SourceMap::iterator it = _deleted_sources.begin(); it != _deleted_sources.end(); it++)
00285     {
00286         MIL << "Deleting source " << it->second << " from persistent store" << endl;
00287         store.deleteSource( it->second.alias() );
00288         filesystem::recursive_rmdir( it->second.cacheDir() );
00289     }
00290 
00291     _deleted_sources.clear();
00292 
00293     for( SourceMap::iterator it = _sources.begin(); it != _sources.end(); it++)
00294     {
00295         storage::PersistentStorage::SourceData descr;
00296 
00297         descr.url = it->second.url().asCompleteString();
00298         descr.enabled = it->second.enabled();
00299         descr.alias = it->second.alias();
00300         descr.autorefresh = it->second.autorefresh();
00301         descr.type = it->second.type();
00302         descr.product_dir = it->second.path();
00303 
00304         descr.cache_dir = it->second.cacheDir();
00305 
00306         if( metadata_cache && descr.cache_dir.empty() )
00307         {
00308             if( descr.cache_dir.empty() )
00309             {
00310               filesystem::TmpDir newCache( root_r /  ZYPP_METADATA_PREFIX, "Source." );
00311               descr.cache_dir = ZYPP_METADATA_PREFIX + newCache.path().basename();
00312             }
00313 
00314             filesystem::assert_dir ( root_r.asString() + descr.cache_dir );
00315 
00316             MIL << "Storing metadata to (" << root_r.asString() << ")/" << descr.cache_dir << endl;
00317 
00318             try {
00319                 it->second.storeMetadata( root_r.asString() + descr.cache_dir );
00320             }
00321             catch(const Exception &excp) {
00322                 WAR << "Creating local metadata cache failed, not using cache" << endl;
00323                 descr.cache_dir = "";
00324             }
00325         }
00326 
00327         store.storeSource( descr );
00328     }
00329 
00330     MIL << "SourceManager store done." << endl;
00331   }
00332 
00336   bool SourceManager::restore( Pathname root_r, bool use_caches, const std::string &alias_filter, const std::string &url_filter )
00337   {
00338     MIL << "SourceManager restore ('" << root_r << ( use_caches ? "' (use_caches)" : "'" )
00339         << ", alias_filter '" << alias_filter
00340         << ", url_filter '" << url_filter << "')" << endl;
00341 
00342     if (! _sources.empty() ) {
00343 
00344         // if we've already restored sources and this is an unfiltered call, reject it.
00345 
00346         if (alias_filter.empty()
00347             && url_filter.empty())
00348         {
00349             ZYPP_THROW(SourcesAlreadyRestoredException());
00350             //Exception ( N_("At least one source already registered, cannot restore sources from persistent store.") ) );
00351         }
00352 
00353         // check filters against already restore sources and check for duplicates.
00354         //
00355         for (SourceMap::const_iterator it = _sources.begin(); it != _sources.end(); ++it) {
00356             if (!alias_filter.empty()
00357                 && (alias_filter == it->second.alias()) )
00358             {
00359                 MIL << "Source with alias '" << alias_filter << "' already restored.";
00360                 return true;
00361             }
00362             if (!url_filter.empty()
00363                 && (url_filter == it->second.url().asString()) )
00364             {
00365                 MIL << "Source with url '" << url_filter << "' already restored.";
00366                 return true;
00367             }
00368         }
00369     }
00370 
00371     FailedSourcesRestoreException report;
00372 
00373     storage::PersistentStorage store;
00374     store.init( root_r );
00375 
00376     std::list<storage::PersistentStorage::SourceData> new_sources = store.storedSources();
00377 
00378     MIL << "Found sources: " << new_sources.size() << endl;
00379 
00380     for( std::list<storage::PersistentStorage::SourceData>::iterator it = new_sources.begin(); it != new_sources.end(); ++it)
00381     {
00382         if ( !alias_filter.empty()                      // check alias filter, if set
00383             && (alias_filter != it->alias) )
00384         {
00385             continue;
00386         }
00387 
00388         if ( !url_filter.empty()                        // check url filter, if set
00389             && (url_filter != it->url.asString()) )
00390         {
00391             continue;
00392         }
00393 
00394         // Note: Url(it->url).asString() to hide password in logs
00395         MIL << "Restoring source: url:[" << Url(it->url).asString() << "] product_dir:[" << it->product_dir << "] alias:[" << it->alias << "] cache_dir:[" << it->cache_dir << "]" << endl;
00396   
00397           SourceId id = 0;
00398   
00399           try {
00400             id = addSource( SourceFactory().createFrom(it->type, it->url, it->product_dir, it->alias, it->cache_dir, false, it->autorefresh) );
00401           }
00402           catch (const Exception &expt )
00403           {
00404               // Note: Url(it->url).asString() to hide password in logs
00405               ERR << "Unable to restore source from " << Url(it->url).asString()
00406                   << endl;
00407   
00408               id = 0;
00409               Url url2;
00410               try {
00411                   url2 = it->url;
00412                   std::string scheme( url2.getScheme());
00413   
00414                   if( (scheme == "cd" || scheme == "dvd") &&
00415                       !url2.getQueryParam("devices").empty())
00416                   {
00417                       url2.setQueryParam("devices", "");
00418   
00419                       DBG << "CD/DVD devices changed - try again without a devices list"
00420                           << std::endl;
00421   
00422                       id = addSource( SourceFactory().createFrom(url2, it->product_dir, it->alias, it->cache_dir, false) );
00423   
00424                       // This worked ... update it->url ?
00425                       //it->url = url2.asCompleteString();
00426                   }
00427               }
00428               catch (const Exception &e2)
00429               {
00430                   // Note: Url(it->url).asString() to hide password in logs
00431                   ERR << "Unable to restore source from " << url2.asString()
00432                       << endl;
00433                   id = 0;
00434                   ZYPP_CAUGHT(e2);
00435               }
00436   
00437               if( id == 0)
00438               {
00439                 report.append( it->url.asString() + it->product_dir.asString(), it->alias, expt );
00440                   continue;
00441               }
00442           }
00443   
00444           DBG << "Added source as id " << id << endl;
00445           // should not throw, we've just created the source
00446           Source_Ref src = findSource( id );
00447   
00448           if ( it->enabled ) {
00449               DBG << "enable source" << endl;
00450               src.enable();
00451           }
00452           else {
00453               DBG << "disable source" << endl;
00454               src.disable();
00455           }
00456     }
00457 
00458     if( !report.empty() )
00459     {
00460         ZYPP_THROW(report);
00461     }
00462 
00463     MIL << "SourceManager restore done." << endl;
00464     dumpSourceTableOn( DBG );
00465     return true;
00466   }
00467 
00468   void SourceManager::disableSourcesAt( const Pathname & root_r )
00469   {
00470     storage::PersistentStorage store;
00471     store.init( root_r );
00472 
00473     std::list<storage::PersistentStorage::SourceData> new_sources = store.storedSources();
00474 
00475     MIL << "Disabling all sources in store at " << root_r << endl;
00476 
00477     for( std::list<storage::PersistentStorage::SourceData>::iterator it = new_sources.begin();
00478         it != new_sources.end(); ++it)
00479     {
00480         MIL << "Disabling source " << it->alias << endl;
00481         it->enabled = false;
00482         store.storeSource( *it );
00483     }
00484   }
00485 
00486   SourceManager::SourceInfoList SourceManager::knownSourceInfos(const Pathname &root_r)
00487   {
00488     storage::PersistentStorage store;
00489     SourceInfoList result;
00490     store.init( root_r );
00491 
00492     std::list<storage::PersistentStorage::SourceData> sources = store.storedSources();
00493 
00494     MIL << "Found sources: " << sources.size() << endl;
00495 
00496     for( std::list<storage::PersistentStorage::SourceData>::iterator it = sources.begin();
00497          it != sources.end(); ++it)
00498     {
00499       SourceInfo info = { it->alias, it->url, it->type, it->autorefresh };
00500       result.push_back( info );
00501     }
00502     return result;
00503   }
00504     
00505   /******************************************************************
00506   **
00507   **    FUNCTION NAME : operator<<
00508   **    FUNCTION TYPE : std::ostream &
00509   */
00510   std::ostream & operator<<( std::ostream & str, const SourceManager & obj )
00511   {
00512     return dumpSourceTableOn( str, /*tailingENDL*/false );
00513   }
00514 
00515   Source_Ref SourceManager::findSource(SourceId id)
00516   {
00517     SourceMap::iterator it = _sources.find(id);
00518     if (it == _sources.end())
00519     {
00520       ZYPP_THROW(Exception("Unknown source ID"));
00521     }
00522     return it->second;
00523   }
00524 
00525   Source_Ref SourceManager::findSource(const std::string & alias_r)
00526   {
00527     SourceMap::iterator it;
00528     for (it = _sources.begin(); it != _sources.end(); ++it)
00529     {
00530         if (it->second.alias() == alias_r) {
00531             return it->second;
00532         }
00533     }
00534     ZYPP_THROW(Exception("Unknown source name '"+alias_r+"'"));
00535     /*NOTREACHED*/
00536     return it->second; // just to keep gcc happy
00537   }
00538 
00539   Source_Ref SourceManager::findSourceByUrl(const Url & url_r)
00540   {
00541     SourceMap::iterator it;
00542     for (it = _sources.begin(); it != _sources.end(); ++it)
00543     {
00544         if (it->second.url().asCompleteString() == url_r.asCompleteString()) {
00545             return it->second;
00546         }
00547     }
00548     ZYPP_THROW(Exception("Unknown source URL '"+url_r.asString()+"'"));
00549     /*NOTREACHED*/
00550     return it->second; // just to keep gcc happy
00551   }
00552 
00554   // FailedSourcesRestoreException
00556 
00557   std::ostream & FailedSourcesRestoreException::dumpOn( std::ostream & str ) const
00558   {
00559         return str << _summary;
00560   }
00561 
00562   std::ostream & FailedSourcesRestoreException::dumpOnTranslated( std::ostream & str ) const
00563   {
00564         return str << Exception::asUserString() << endl << _translatedSummary;
00565   }
00566 
00567   bool FailedSourcesRestoreException::empty () const
00568   {
00569         return _summary.empty();
00570   }
00571 
00572   std::set<std::string> FailedSourcesRestoreException::aliases () const
00573   {
00574         return _aliases;
00575   }
00576 
00577   void FailedSourcesRestoreException::append( std::string source, std::string alias, const Exception& expt)
00578   {
00579         _summary = _summary + "\n" + source + ": " + expt.asString();
00580         _translatedSummary = _translatedSummary + "\n" + source + ": " + expt.asUserString();
00581         _aliases.insert( alias );
00582   }
00583 
00585 } // namespace zypp

Generated on Thu Jul 6 00:07:26 2006 for zypp by  doxygen 1.4.6