ZYppImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00013 #include <sys/utsname.h>
00014 #include <unistd.h>
00015 #include <iostream>
00016 #include <fstream>
00017 #include "zypp/base/Logger.h"
00018 #include "zypp/base/String.h"
00019 
00020 #include "zypp/zypp_detail/ZYppImpl.h"
00021 #include "zypp/detail/ResImplTraits.h"
00022 #include "zypp/solver/detail/Helper.h"
00023 #include "zypp/target/TargetImpl.h"
00024 #include "zypp/ZYpp.h"
00025 #include "zypp/NVRAD.h"
00026 #include "zypp/Language.h"
00027 #include "zypp/DiskUsageCounter.h"
00028 #include "zypp/NameKindProxy.h"
00029 
00030 using std::endl;
00031 
00033 namespace zypp
00034 { 
00035 
00036   namespace zypp_detail
00037   { 
00038 
00039     inline Locale defaultTextLocale()
00040     {
00041       Locale ret( "en" );
00042       char * envlist[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
00043       for ( char ** envvar = envlist; *envvar; ++envvar )
00044         {
00045           char * envlang = getenv( *envvar );
00046           if ( envlang )
00047             {
00048               std::string envstr( envlang );
00049               if ( envstr != "POSIX" && envstr != "C" )
00050                 {
00051                   Locale lang( envlang );
00052                   if ( lang != Locale::noCode )
00053                     {
00054                       ret = lang;
00055                       break;
00056                     }
00057                 }
00058             }
00059         }
00060       return ret;
00061     }
00062 
00063     Arch defaultArchitecture()
00064     {
00065       Arch architecture;
00066 
00067       // detect the true architecture
00068       struct utsname buf;
00069       if ( uname( &buf ) < 0 )
00070         {
00071           ERR << "Can't determine system architecture" << endl;
00072         }
00073       else
00074         {
00075           architecture = Arch( buf.machine );
00076           DBG << "uname architecture is '" << buf.machine << "'" << endl;
00077 
00078           // some CPUs report i686 but dont implement cx8 and cmov
00079           // check for both flags in /proc/cpuinfo and downgrade
00080           // to i586 if either is missing (cf bug #18885)
00081 
00082           if ( architecture == Arch_i686 )
00083             {
00084               std::ifstream cpuinfo( "/proc/cpuinfo" );
00085               if ( !cpuinfo )
00086                 {
00087                   ERR << "Cant open /proc/cpuinfo" << endl;
00088                 }
00089               else
00090                 {
00091                   char infoline[1024];
00092                   while ( cpuinfo.good() )
00093                     {
00094                       if ( !cpuinfo.getline( infoline, 1024, '\n' ) )
00095                         {
00096                           if ( cpuinfo.eof() )
00097                             break;
00098                         }
00099                       if ( strncmp( infoline, "flags", 5 ) == 0 )
00100                         {
00101                           std::string flagsline( infoline );
00102                           if ( flagsline.find( "cx8" ) == std::string::npos
00103                                || flagsline.find( "cmov" ) == std::string::npos )
00104                             {
00105                               architecture = Arch_i586;
00106                               DBG << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl;
00107                             }
00108                           break;
00109                         } // flags found
00110                     } // read proc/cpuinfo
00111                 } // proc/cpuinfo opened
00112             } // i686 extra flags check
00113         }
00114 
00115       if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) )
00116       {
00117         architecture = Arch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) );
00118         WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Setting fake system architecture for test purpuses to: '" << architecture << "'" << endl;
00119       }
00120 
00121       return architecture;
00122     }
00124     //
00125     //  METHOD NAME : ZYppImpl::ZYppImpl
00126     //  METHOD TYPE : Constructor
00127     //
00128     ZYppImpl::ZYppImpl()
00129     : _textLocale( defaultTextLocale() )
00130     , _pool()
00131     , _sourceFeed( _pool )
00132     , _target(0)
00133     , _resolver( new Resolver(_pool.accessor()) )
00134     , _architecture( defaultArchitecture() )
00135     , _disk_usage()
00136     {
00137       MIL << "defaultTextLocale: '" << _textLocale << "'" << endl;
00138       MIL << "System architecture is '" << _architecture << "'" << endl;
00139 
00140       MIL << "initializing keyring..." << std::endl;
00141       //_keyring = new KeyRing(homePath() + Pathname("/keyring/all"), homePath() + Pathname("/keyring/trusted"));
00142       _keyring = new KeyRing(tmpPath());
00143     }
00144 
00146     //
00147     //  METHOD NAME : ZYppImpl::~ZYppImpl
00148     //  METHOD TYPE : Destructor
00149     //
00150     ZYppImpl::~ZYppImpl()
00151     {}
00152 
00153     //------------------------------------------------------------------------
00154     // add/remove resolvables
00155 
00156     void ZYppImpl::addResolvables (const ResStore& store, bool installed)
00157     {
00158         _pool.insert(store.begin(), store.end(), installed);
00159     }
00160 
00161     void ZYppImpl::removeResolvables (const ResStore& store)
00162     {
00163         for (ResStore::iterator it = store.begin(); it != store.end(); ++it)
00164         {
00165             _pool.erase(*it);
00166         }
00167     }
00168 
00169     void ZYppImpl::removeInstalledResolvables ()
00170     {
00171         for (ResPool::const_iterator it = pool().begin(); it != pool().end();)
00172         {
00173             ResPool::const_iterator next = it; ++next;
00174             if (it->status().isInstalled())
00175                 _pool.erase( *it );
00176             it = next;
00177         }
00178     }
00179 
00180     DiskUsageCounter::MountPointSet ZYppImpl::diskUsage()
00181     { return _disk_usage.disk_usage(pool()); }
00182 
00183     void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp)
00184     { _disk_usage.setMountPoints(mp); }
00185 
00186     //------------------------------------------------------------------------
00187     // target
00188 
00189     Target_Ptr ZYppImpl::target() const
00190     {
00191       if (! _target)
00192         ZYPP_THROW(Exception("Target not initialized."));
00193       return _target;
00194      }
00195 
00196     void ZYppImpl::initializeTarget(const Pathname & root)
00197     {
00198       MIL << "initTarget( " << root << endl;
00199       if (_target) {
00200         if (_target->root() == root) {
00201             MIL << "Repeated call to initializeTarget()" << endl;
00202             return;
00203         }
00204         removeInstalledResolvables( );
00205       }
00206       _target = new Target( root );
00207       _target->enableStorage( root );
00208     }
00209 
00210     void ZYppImpl::initTarget(const Pathname & root, bool commit_only)
00211     {
00212       MIL << "initTarget( " << root << ", " << commit_only << ")" << endl;
00213       if (_target) {
00214         if (_target->root() == root) {
00215           MIL << "Repeated call to initTarget()" << endl;
00216           return;
00217         }
00218         removeInstalledResolvables( );
00219       }
00220       _target = new Target( root );
00221       _target->enableStorage( root );
00222       if (!commit_only)
00223       {
00224         addResolvables( _target->resolvables(), true );
00225       }
00226     }
00227 
00228 
00229     void ZYppImpl::finishTarget()
00230     {
00231       if (_target)
00232         removeInstalledResolvables();
00233       _target = 0;
00234     }
00235 
00236     //------------------------------------------------------------------------
00237     // commit
00238 
00241     ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r )
00242     {
00243       if ( getenv("ZYPP_TESTSUITE_FAKE_ARCH") )
00244       {
00245         ZYPP_THROW( Exception("ZYPP_TESTSUITE_FAKE_ARCH set. Commit not allowed and disabled.") );
00246       }
00247 
00248       MIL << "Attempt to commit (" << policy_r << ")" << endl;
00249       if (! _target)
00250         ZYPP_THROW( Exception("Target not initialized.") );
00251 
00252       ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r );
00253 
00254       if (! policy_r.dryRun() ) {
00255         // Tag target data invalid, so they are reloaded on the next call to
00256         // target->resolvables(). Actually the target should do this without
00257         // foreign help.
00258         _target->reset();
00259         removeInstalledResolvables();
00260         if ( policy_r.syncPoolAfterCommit() )
00261           {
00262             // reload new status from target
00263             addResolvables( _target->resolvables(), true );
00264           }
00265       }
00266 
00267       MIL << "Commit (" << policy_r << ") returned: "
00268           << res << endl;
00269       return res;
00270     }
00271 
00272 
00273     //------------------------------------------------------------------------
00274     // locales
00275 
00277     void ZYppImpl::setRequestedLocales( const LocaleSet & locales_r )
00278     {
00279       ResPool mpool( pool() );
00280       // assert all requested are available
00281       for ( LocaleSet::const_iterator it = locales_r.begin();
00282             it != locales_r.end(); ++it )
00283         {
00284           NameKindProxy select( nameKindProxy<Language>( mpool, it->code() ) );
00285           if ( select.installedEmpty() && select.availableEmpty() )
00286             _pool.insert( Language::availableInstance( *it ) );
00287         }
00288 
00289       // now adjust status
00290       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
00291             it != mpool.byKindEnd<Language>(); ++it )
00292         {
00293           NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
00294           if ( locales_r.find( Locale( (*it)->name() ) ) != locales_r.end() )
00295             {
00296               // Language is requested
00297               if ( select.installedEmpty() )
00298                 {
00299                   if ( select.availableEmpty() )
00300                     {
00301                       // no item ==> provide available to install
00302                       _pool.insert( Language::availableInstance( Locale((*it)->name()) ) );
00303                       select = nameKindProxy<Language>( mpool, (*it)->name() );
00304                     }
00305                   // available only ==> to install
00306                   select.availableBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
00307                 }
00308               else
00309                 {
00310                   // installed ==> keep it
00311                   select.installedBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
00312                   if ( ! select.availableEmpty() )
00313                     {
00314                       // both items ==> keep
00315                       select.availableBegin()->status().resetTransact( ResStatus::USER );
00316                     }
00317                 }
00318             }
00319           else
00320             {
00321               // Language is NOT requested
00322               if ( ! select.installedEmpty() )
00323                 select.installedBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
00324               if ( ! select.availableEmpty() )
00325                 select.availableBegin()->status().resetTransact( ResStatus::USER );
00326             }
00327         }
00328     }
00329 
00331     ZYppImpl::LocaleSet ZYppImpl::getAvailableLocales() const
00332     {
00333       ZYpp::LocaleSet ret;
00334       ResPool mpool( pool() );
00335       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
00336             it != mpool.byKindEnd<Language>(); ++it )
00337         {
00338           if ( (*it).status().isUninstalled() ) // available!
00339             ret.insert( Locale( (*it)->name() ) );
00340         }
00341       return ret;
00342     }
00343 
00345     ZYppImpl::LocaleSet ZYppImpl::getRequestedLocales() const
00346     {
00347       ZYpp::LocaleSet ret;
00348       ResPool mpool( pool() );
00349       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
00350             it != mpool.byKindEnd<Language>(); ++it )
00351         {
00352           NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
00353           if ( ! select.installedEmpty()
00354                && select.installedBegin()->status().getTransactValue() != ResStatus::TRANSACT )
00355             ret.insert( Locale( (*it)->name() ) );
00356           else if ( ! select.availableEmpty()
00357                     && select.availableBegin()->status().getTransactValue() == ResStatus::TRANSACT )
00358             ret.insert( Locale( (*it)->name() ) );
00359         }
00360       return ret;
00361     }
00362 
00363     void ZYppImpl::availableLocale( const Locale & locale_r )
00364     {
00365       _pool.insert( Language::availableInstance( locale_r ) );
00366     }
00367 
00368     //------------------------------------------------------------------------
00369     // architecture
00370 
00371     void ZYppImpl::setArchitecture( const Arch & arch )
00372     {
00373         _architecture = arch;
00374         if (_resolver) _resolver->setArchitecture( arch );
00375     }
00376 
00377     //------------------------------------------------------------------------
00378     // target store path
00379 
00380     Pathname ZYppImpl::homePath() const
00381     { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; }
00382 
00383     void ZYppImpl::setHomePath( const Pathname & path )
00384     { _home_path = path; }
00385 
00386     Pathname ZYppImpl::tmpPath() const
00387     {
00388       static TmpDir zypp_tmp_dir("/var/tmp", "zypp.");
00389       return zypp_tmp_dir.path();
00390     }
00391 
00392     /******************************************************************
00393      **
00394      ** FUNCTION NAME : operator<<
00395      ** FUNCTION TYPE : std::ostream &
00396     */
00397     std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
00398     {
00399       return str << "ZYppImpl";
00400     }
00401 
00403   } // namespace zypp_detail
00406 } // namespace zypp

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