1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Fetcher.cc
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/DefaultIntegral.h"
17 #include "zypp/Fetcher.h"
18 #include "zypp/base/UserRequestException.h"
22 ///////////////////////////////////////////////////////////////////
24 { /////////////////////////////////////////////////////////////////
27 * Class to encapsulate the \ref OnMediaLocation object
28 * and the \ref FileChecker together
32 FetcherJob( const OnMediaLocation &loc )
38 OnMediaLocation location;
39 CompositeFileChecker checkers;
42 ///////////////////////////////////////////////////////////////////
44 // CLASS NAME : Fetcher::Impl
46 /** Fetcher implementation. */
52 void enqueue( const OnMediaLocation &resource, const FileChecker &checker );
53 void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker );
54 void addCachePath( const Pathname &cache_dir );
56 void start( const Pathname &dest_dir,
57 MediaSetAccess &media,
58 const ProgressData::ReceiverFnc & progress_receiver );
60 /** Offer default Impl. */
61 static shared_ptr<Impl> nullimpl()
63 static shared_ptr<Impl> _nullimpl( new Impl );
68 friend Impl * rwcowClone<Impl>( const Impl * rhs );
69 /** clone for RWCOW_pointer */
71 { return new Impl( *this ); }
73 std::list<FetcherJob> _resources;
74 std::list<Pathname> _caches;
76 ///////////////////////////////////////////////////////////////////
79 void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
81 CompositeFileChecker composite;
82 composite.add(ChecksumFileChecker(resource.checksum()));
83 composite.add(checker);
84 FetcherJob job(resource);
85 job.checkers = composite;
86 _resources.push_back(job);
89 void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
91 FetcherJob job(resource);
92 job.checkers.add(checker);
93 _resources.push_back(job);
96 void Fetcher::Impl::reset()
102 void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
104 PathInfo info(cache_dir);
107 _caches.push_back(cache_dir);
111 // don't add bad cache directory, just log the error
112 ERR << "Not adding cache: '" << cache_dir << "'. Not a direcotry." << endl;
116 void Fetcher::Impl::start( const Pathname &dest_dir,
117 MediaSetAccess &media,
118 const ProgressData::ReceiverFnc & progress_receiver )
120 ProgressData progress(_resources.size());
121 progress.sendTo(progress_receiver);
123 for ( list<FetcherJob>::const_iterator it_res = _resources.begin(); it_res != _resources.end(); ++it_res )
125 bool got_from_cache = false;
126 for ( list<Pathname>::const_iterator it_cache = _caches.begin(); it_cache != _caches.end(); ++it_cache )
128 // does the current file exists in the current cache?
129 Pathname cached_file = *it_cache + (*it_res).location.filename();
130 if ( PathInfo( cached_file ).isExist() )
132 // check the checksum
133 if ( is_checksum( cached_file, (*it_res).location.checksum() ) && (! (*it_res).location.checksum().empty() ) )
136 MIL << "file " << (*it_res).location.filename() << " found in previous cache. Using cached copy." << endl;
137 // checksum is already checked.
138 // we could later implement double failover and try to download if file copy fails.
140 // replicate the complete path in the target directory
141 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
142 if ( assert_dir( dest_full_path.dirname() ) != 0 )
143 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
145 if ( filesystem::copy(cached_file, dest_full_path ) != 0 )
147 //ZYPP_THROW(SourceIOException("Can't copy " + cached_file.asString() + " to " + destination.asString()));
148 ERR << "Can't copy " << cached_file + " to " + dest_dir << endl;
153 got_from_cache = true;
159 if ( ! got_from_cache )
161 // try to get the file from the net
164 Pathname tmp_file = media.provideFile((*it_res).location);
165 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
166 if ( assert_dir( dest_full_path.dirname() ) != 0 )
167 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
168 if ( filesystem::copy(tmp_file, dest_full_path ) != 0 )
170 ZYPP_THROW( Exception("Can't copy " + tmp_file.asString() + " to " + dest_dir.asString()));
175 catch (const Exception & excpt_r)
177 ZYPP_CAUGHT(excpt_r);
178 Exception nexcpt("Can't provide " + (*it_res).location.filename().asString() + " : " + excpt_r.msg());
179 nexcpt.remember(excpt_r);
185 // We got the file from cache
186 // continue with next file
190 // no matter where did we got the file, try to validate it:
191 Pathname localfile = dest_dir + (*it_res).location.filename();
192 // call the checker function
194 MIL << "Checking " << localfile << endl;
195 (*it_res).checkers(localfile);
197 catch ( const FileCheckException &e )
201 catch ( const Exception &e )
207 ZYPP_THROW(Exception("Unknown error while validating " + (*it_res).location.filename().asString()));
210 if ( ! progress.incr() )
211 ZYPP_THROW(AbortRequestException());
215 /** \relates Fetcher::Impl Stream output */
216 inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
218 return str << "Fetcher::Impl";
221 ///////////////////////////////////////////////////////////////////
223 // CLASS NAME : Fetcher
225 ///////////////////////////////////////////////////////////////////
227 ///////////////////////////////////////////////////////////////////
229 // METHOD NAME : Fetcher::Fetcher
230 // METHOD TYPE : Ctor
233 : _pimpl( Impl::nullimpl() )
236 ///////////////////////////////////////////////////////////////////
238 // METHOD NAME : Fetcher::~Fetcher
239 // METHOD TYPE : Dtor
244 void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
246 _pimpl->enqueue(resource, checker);
249 void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
251 _pimpl->enqueue(resource, checker);
254 void Fetcher::addCachePath( const Pathname &cache_dir )
256 _pimpl->addCachePath(cache_dir);
259 void Fetcher::reset()
264 void Fetcher::start( const Pathname &dest_dir,
265 MediaSetAccess &media,
266 const ProgressData::ReceiverFnc & progress_receiver )
268 _pimpl->start(dest_dir, media, progress_receiver);
272 /******************************************************************
274 ** FUNCTION NAME : operator<<
275 ** FUNCTION TYPE : std::ostream &
277 std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
279 return str << *obj._pimpl;
282 /////////////////////////////////////////////////////////////////
284 ///////////////////////////////////////////////////////////////////