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
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._source.numericId() << ":" << obj._mediaNr << "]"
00037 << " " << obj._source.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->sourceMediaNr() == 0 )
00068 return false;
00069 std::string scheme( pi->source().url().getScheme() );
00070 return ( scheme == "dvd" || scheme == "cd" );
00071 }
00072
00074
00075
00076
00077
00078 void CommitPackageCacheReadAhead::cacheLastInteractive( const_iterator citem_r )
00079 {
00080
00081 try
00082 {
00083 doCacheLastInteractive( citem_r );
00084 }
00085 catch ( const Exception & excpt_r )
00086 {
00087 ZYPP_CAUGHT( excpt_r );
00088 WAR << "Failed to cache " << _lastInteractive << endl;
00089 }
00090 }
00091
00093
00094
00095
00096
00097 void CommitPackageCacheReadAhead::doCacheLastInteractive( const_iterator citem_r )
00098 {
00099 CacheMap addToCache;
00100 ByteCount addSize;
00101
00102
00103
00104 for ( const_iterator it = citem_r; it != _commitListEnd; ++it )
00105 {
00106 if ( IMediaKey( *it ) == _lastInteractive
00107 && isKind<Package>(it->resolvable())
00108 && it->status().isToBeInstalled() )
00109 {
00110 if ( _cacheMap.find( *it ) == _cacheMap.end() )
00111 {
00112 addToCache[*it];
00113 addSize += it->resolvable()->archivesize();
00114 }
00115 }
00116 }
00117
00118 if ( addToCache.empty() )
00119 return;
00120 MIL << "could cache " << _lastInteractive << ": " << addToCache.size() << " items: " << addSize << endl;
00121
00122
00123
00124
00125 if ( ! _cacheDir )
00126 {
00127 _cacheDir.reset( new filesystem::TmpDir( _rootDir, "commitCache." ) );
00128 PathInfo pi( _cacheDir->path() );
00129 if ( ! pi.isDir() )
00130 {
00131 ERR << "Can not initialize cache dir " << pi << endl;
00132 return;
00133 }
00134 }
00135
00136
00137
00138 ByteCount df( filesystem::df( _cacheDir->path() ) );
00139 MIL << "available disk space in " << _cacheDir->path() << ": " << df << endl;
00140
00141 if ( df / 10 < addSize )
00142 {
00143 WAR << "cache would require more than 10% of the available " << df << " disk space " << endl;
00144 WAR << "not caching " << _lastInteractive << endl;
00145 return;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 for ( CacheMap::iterator it = addToCache.begin(); it != addToCache.end(); ++it )
00155 {
00156
00157 ManagedFile fromSource( sourceProvidePackage( it->first ) );
00158
00159
00160 std::string destName( str::form( "S%lu_%u_%s",
00161 it->first->source().numericId(),
00162 it->first->sourceMediaNr(),
00163 fromSource.value().basename().c_str() ) );
00164
00165 ManagedFile fileInCache( _cacheDir->path() / destName,
00166 filesystem::unlink );
00167
00168 if ( filesystem::copy( fromSource.value(), fileInCache ) != 0 )
00169 {
00170
00171 ERR << "Copy to cache failed on " << fromSource.value() << endl;
00172 ZYPP_THROW( Exception("Copy to cache failed.") );
00173 }
00174
00175
00176 it->second = fileInCache;
00177 }
00178
00179
00180
00181 _cacheMap.insert( addToCache.begin(), addToCache.end() );
00182 return;
00183 }
00184
00186
00187
00188
00189
00190 ManagedFile CommitPackageCacheReadAhead::get( const_iterator citem_r )
00191 {
00192
00193 if ( ! onInteractiveMedia( *citem_r ) )
00194 {
00195 return sourceProvidePackage( *citem_r );
00196 }
00197
00198
00199 CacheMap::iterator it = _cacheMap.find( *citem_r );
00200 if ( it != _cacheMap.end() )
00201 {
00202
00203
00204
00205 ManagedFile cacheHit( it->second );
00206 _cacheMap.erase( it );
00207
00208
00209 PathInfo pi( cacheHit.value() );
00210 if ( pi.isFile() )
00211 {
00212 MIL << "Cache package provide " << cacheHit << endl;
00213 return cacheHit;
00214 }
00215
00216 WAR << "Cached file vanished: " << pi << endl;
00217 }
00218
00219
00220
00221
00222
00223 IMediaKey current( *citem_r );
00224 if ( current != _lastInteractive )
00225 {
00226 if ( _lastInteractive != IMediaKey() )
00227 {
00228 cacheLastInteractive( citem_r );
00229 }
00230
00231 DBG << "Interactive change [" << ++_dbgChanges << "] from " << _lastInteractive
00232 << " to " << current << endl;
00233 _lastInteractive = current;
00234 }
00235
00236
00237 return sourceProvidePackage( *citem_r );
00238 }
00239
00240
00242 }
00245 }