00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013
00014 #include "zypp/base/Logger.h"
00015 #include "zypp/base/Exception.h"
00016 #include "zypp/PathInfo.h"
00017 #include "zypp/target/CommitPackageCacheReadAhead.h"
00018
00019 using std::endl;
00020
00022 namespace zypp
00023 {
00024
00025 namespace target
00026 {
00027
00029
00030
00031
00033
00034 std::ostream & operator<<( std::ostream & str, const IMediaKey & obj )
00035 {
00036 return str << "[S" << obj._repository.numericId() << ":" << obj._mediaNr << "]"
00037 << " " << obj._repository.info().alias();
00038 }
00039
00041
00042
00043
00045
00047
00048
00049
00050
00051 CommitPackageCacheReadAhead::CommitPackageCacheReadAhead( const_iterator begin_r,
00052 const_iterator end_r,
00053 const Pathname & rootDir_r,
00054 const PackageProvider & packageProvider_r )
00055 : CommitPackageCache::Impl( packageProvider_r )
00056 , _commitListEnd( end_r )
00057 , _rootDir( rootDir_r )
00058 {}
00059
00061
00062
00063
00064
00065 bool CommitPackageCacheReadAhead::onInteractiveMedia( const PoolItem & pi ) const
00066 {
00067 if ( pi->mediaNr() == 0 )
00068 return false;
00069 if ( pi->repository().info().baseUrlsEmpty() )
00070 return false;
00071 std::string scheme( pi->repository().info().baseUrlsBegin()->getScheme() );
00072 return ( scheme == "dvd" || scheme == "cd" );
00073 }
00074
00076
00077
00078
00079
00080 void CommitPackageCacheReadAhead::cacheLastInteractive( const_iterator citem_r )
00081 {
00082
00083 try
00084 {
00085 doCacheLastInteractive( citem_r );
00086 }
00087 catch ( const Exception & excpt_r )
00088 {
00089 ZYPP_CAUGHT( excpt_r );
00090 WAR << "Failed to cache " << _lastInteractive << endl;
00091 }
00092 }
00093
00095
00096
00097
00098
00099 void CommitPackageCacheReadAhead::doCacheLastInteractive( const_iterator citem_r )
00100 {
00101 CacheMap addToCache;
00102 ByteCount addSize;
00103
00104
00105
00106 for ( const_iterator it = citem_r; it != _commitListEnd; ++it )
00107 {
00108 if ( IMediaKey( *it ) == _lastInteractive
00109 && isKind<Package>(it->resolvable())
00110 && it->status().isToBeInstalled() )
00111 {
00112 if ( _cacheMap.find( *it ) == _cacheMap.end() )
00113 {
00114 addToCache[*it];
00115 addSize += it->resolvable()->downloadSize();
00116 }
00117 }
00118 }
00119
00120 if ( addToCache.empty() )
00121 return;
00122 MIL << "could cache " << _lastInteractive << ": " << addToCache.size() << " items: " << addSize << endl;
00123
00124
00125
00126
00127 if ( ! _cacheDir )
00128 {
00129 _cacheDir.reset( new filesystem::TmpDir( _rootDir, "commitCache." ) );
00130 PathInfo pi( _cacheDir->path() );
00131 if ( ! pi.isDir() )
00132 {
00133 ERR << "Can not initialize cache dir " << pi << endl;
00134 return;
00135 }
00136 }
00137
00138
00139
00140 ByteCount df( filesystem::df( _cacheDir->path() ) );
00141 MIL << "available disk space in " << _cacheDir->path() << ": " << df << endl;
00142
00143 if ( df / 10 < addSize )
00144 {
00145 WAR << "cache would require more than 10% of the available " << df << " disk space " << endl;
00146 WAR << "not caching " << _lastInteractive << endl;
00147 return;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156 for ( CacheMap::iterator it = addToCache.begin(); it != addToCache.end(); ++it )
00157 {
00158
00159 ManagedFile fromSource( sourceProvidePackage( it->first ) );
00160
00161
00162 std::string destName( str::form( "S%lu_%u_%s",
00163 it->first->repository().numericId(),
00164 it->first->mediaNr(),
00165 fromSource.value().basename().c_str() ) );
00166
00167 ManagedFile fileInCache( _cacheDir->path() / destName,
00168 filesystem::unlink );
00169
00170 if ( filesystem::copy( fromSource.value(), fileInCache ) != 0 )
00171 {
00172
00173 ERR << "Copy to cache failed on " << fromSource.value() << endl;
00174 ZYPP_THROW( Exception("Copy to cache failed.") );
00175 }
00176
00177
00178 it->second = fileInCache;
00179 }
00180
00181
00182
00183 _cacheMap.insert( addToCache.begin(), addToCache.end() );
00184 return;
00185 }
00186
00188
00189
00190
00191
00192 ManagedFile CommitPackageCacheReadAhead::get( const_iterator citem_r )
00193 {
00194
00195 if ( ! onInteractiveMedia( *citem_r ) )
00196 {
00197 return sourceProvidePackage( *citem_r );
00198 }
00199
00200
00201 CacheMap::iterator it = _cacheMap.find( *citem_r );
00202 if ( it != _cacheMap.end() )
00203 {
00204
00205
00206
00207 ManagedFile cacheHit( it->second );
00208 _cacheMap.erase( it );
00209
00210
00211 PathInfo pi( cacheHit.value() );
00212 if ( pi.isFile() )
00213 {
00214 MIL << "Cache package provide " << cacheHit << endl;
00215 return cacheHit;
00216 }
00217
00218 WAR << "Cached file vanished: " << pi << endl;
00219 }
00220
00221
00222
00223
00224
00225 IMediaKey current( *citem_r );
00226 if ( current != _lastInteractive )
00227 {
00228 if ( _lastInteractive != IMediaKey() )
00229 {
00230 cacheLastInteractive( citem_r );
00231 }
00232
00233 DBG << "Interactive change [" << ++_dbgChanges << "] from " << _lastInteractive
00234 << " to " << current << endl;
00235 _lastInteractive = current;
00236 }
00237
00238
00239 return sourceProvidePackage( *citem_r );
00240 }
00241
00242
00244 }
00247 }