00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <list>
00014
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/base/PtrTypes.h"
00017 #include "zypp/base/DefaultIntegral.h"
00018 #include "zypp/Fetcher.h"
00019 #include "zypp/base/UserRequestException.h"
00020
00021 using namespace std;
00022
00024 namespace zypp
00025 {
00026
00031 struct FetcherJob
00032 {
00033 FetcherJob( const OnMediaLocation &loc )
00034 : location(loc)
00035 {
00036
00037 }
00038
00039 ~FetcherJob()
00040 {
00041
00042 }
00043
00044 OnMediaLocation location;
00045
00046 list<FileChecker> checkers;
00047 };
00048
00049 typedef shared_ptr<FetcherJob> FetcherJob_Ptr;
00050
00052
00053
00054
00056 struct Fetcher::Impl
00057 {
00058
00059 public:
00060
00061 void enqueue( const OnMediaLocation &resource, const FileChecker &checker );
00062 void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker );
00063 void addCachePath( const Pathname &cache_dir );
00064 void reset();
00065 void start( const Pathname &dest_dir,
00066 MediaSetAccess &media,
00067 const ProgressData::ReceiverFnc & progress_receiver );
00068
00070 static shared_ptr<Impl> nullimpl()
00071 {
00072 static shared_ptr<Impl> _nullimpl( new Impl );
00073 return _nullimpl;
00074 }
00075
00076 private:
00077 friend Impl * rwcowClone<Impl>( const Impl * rhs );
00079 Impl * clone() const
00080 { return new Impl( *this ); }
00081
00082 std::list<FetcherJob_Ptr> _resources;
00083 std::list<Pathname> _caches;
00084 };
00086
00087
00088 void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
00089 {
00090 FetcherJob_Ptr job;
00091 job.reset(new FetcherJob(resource));
00092 ChecksumFileChecker digest_check(resource.checksum());
00093 job->checkers.push_back(digest_check);
00094 if ( checker )
00095 job->checkers.push_back(checker);
00096 _resources.push_back(job);
00097 }
00098
00099 void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
00100 {
00101 FetcherJob_Ptr job;
00102 job.reset(new FetcherJob(resource));
00103 if ( checker )
00104 job->checkers.push_back(checker);
00105 _resources.push_back(job);
00106 }
00107
00108 void Fetcher::Impl::reset()
00109 {
00110 _resources.clear();
00111 }
00112
00113 void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
00114 {
00115 PathInfo info(cache_dir);
00116 if ( info.isDir() )
00117 {
00118 _caches.push_back(cache_dir);
00119 }
00120 else
00121 {
00122
00123 ERR << "Not adding cache: '" << cache_dir << "'. Not a direcotry." << endl;
00124 }
00125 }
00126
00127 void Fetcher::Impl::start( const Pathname &dest_dir,
00128 MediaSetAccess &media,
00129 const ProgressData::ReceiverFnc & progress_receiver )
00130 {
00131 ProgressData progress(_resources.size());
00132 progress.sendTo(progress_receiver);
00133
00134 for ( list<FetcherJob_Ptr>::const_iterator it_res = _resources.begin(); it_res != _resources.end(); ++it_res )
00135 {
00136 bool got_from_cache = false;
00137 for ( list<Pathname>::const_iterator it_cache = _caches.begin(); it_cache != _caches.end(); ++it_cache )
00138 {
00139
00140 Pathname cached_file = *it_cache + (*it_res)->location.filename();
00141 if ( PathInfo( cached_file ).isExist() )
00142 {
00143
00144 if ( is_checksum( cached_file, (*it_res)->location.checksum() ) && (! (*it_res)->location.checksum().empty() ) )
00145 {
00146
00147 MIL << "file " << (*it_res)->location.filename() << " found in previous cache. Using cached copy." << endl;
00148
00149
00150
00151
00152 Pathname dest_full_path = dest_dir + (*it_res)->location.filename();
00153 if ( assert_dir( dest_full_path.dirname() ) != 0 )
00154 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
00155
00156 if ( filesystem::copy(cached_file, dest_full_path ) != 0 )
00157 {
00158
00159 ERR << "Can't copy " << cached_file + " to " + dest_dir << endl;
00160
00161 continue;
00162 }
00163
00164 got_from_cache = true;
00165 break;
00166 }
00167 }
00168 }
00169
00170 if ( ! got_from_cache )
00171 {
00172
00173 try
00174 {
00175 Pathname tmp_file = media.provideFile((*it_res)->location);
00176 Pathname dest_full_path = dest_dir + (*it_res)->location.filename();
00177 if ( assert_dir( dest_full_path.dirname() ) != 0 )
00178 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
00179 if ( filesystem::copy(tmp_file, dest_full_path ) != 0 )
00180 {
00181 ZYPP_THROW( Exception("Can't copy " + tmp_file.asString() + " to " + dest_dir.asString()));
00182 }
00183
00184
00185 }
00186 catch (const Exception & excpt_r)
00187 {
00188 ZYPP_CAUGHT(excpt_r);
00189 Exception nexcpt("Can't provide " + (*it_res)->location.filename().asString() + " : " + excpt_r.msg());
00190 nexcpt.remember(excpt_r);
00191 ZYPP_THROW(nexcpt);
00192 }
00193 }
00194 else
00195 {
00196
00197
00198 continue;
00199 }
00200
00201
00202 Pathname localfile = dest_dir + (*it_res)->location.filename();
00203
00204 try {
00205 MIL << "Checking job [" << localfile << "] (" << (*it_res)->checkers.size() << " checkers )" << endl;
00206 for ( list<FileChecker>::const_iterator it = (*it_res)->checkers.begin();
00207 it != (*it_res)->checkers.end();
00208 ++it )
00209 {
00210 if (*it)
00211 {
00212 (*it)(localfile);
00213 }
00214 else
00215 {
00216 ERR << "Invalid checker for '" << localfile << "'" << endl;
00217 }
00218 }
00219
00220 }
00221 catch ( const FileCheckException &e )
00222 {
00223 ZYPP_RETHROW(e);
00224 }
00225 catch ( const Exception &e )
00226 {
00227 ZYPP_RETHROW(e);
00228 }
00229 catch (...)
00230 {
00231 ZYPP_THROW(Exception("Unknown error while validating " + (*it_res)->location.filename().asString()));
00232 }
00233
00234 if ( ! progress.incr() )
00235 ZYPP_THROW(AbortRequestException());
00236 }
00237 }
00238
00240 inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
00241 {
00242 return str << "Fetcher::Impl";
00243 }
00244
00246
00247
00248
00250
00252
00253
00254
00255
00256 Fetcher::Fetcher()
00257 : _pimpl( Impl::nullimpl() )
00258 {}
00259
00261
00262
00263
00264
00265 Fetcher::~Fetcher()
00266 {}
00267
00268 void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
00269 {
00270 _pimpl->enqueueDigested(resource, checker);
00271 }
00272
00273 void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
00274 {
00275 _pimpl->enqueue(resource, checker);
00276 }
00277
00278 void Fetcher::addCachePath( const Pathname &cache_dir )
00279 {
00280 _pimpl->addCachePath(cache_dir);
00281 }
00282
00283 void Fetcher::reset()
00284 {
00285 _pimpl->reset();
00286 }
00287
00288 void Fetcher::start( const Pathname &dest_dir,
00289 MediaSetAccess &media,
00290 const ProgressData::ReceiverFnc & progress_receiver )
00291 {
00292 _pimpl->start(dest_dir, media, progress_receiver);
00293 }
00294
00295
00296
00297
00298
00299
00300
00301 std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
00302 {
00303 return str << *obj._pimpl;
00304 }
00305
00307 }
00309