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"
21 ///////////////////////////////////////////////////////////////////
23 { /////////////////////////////////////////////////////////////////
26 * Class to encapsulate the \ref OnMediaLocation object
27 * and the \ref FileChcker together
31 FetcherJob( const OnMediaLocation &loc )
37 OnMediaLocation location;
38 CompositeFileChecker checkers;
41 ///////////////////////////////////////////////////////////////////
43 // CLASS NAME : Fetcher::Impl
45 /** Fetcher implementation. */
51 void enqueue( const OnMediaLocation &resource, const FileChecker &checker );
52 void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker );
53 void addCachePath( const Pathname &cache_dir );
55 void start( const Pathname &dest_dir, MediaSetAccess &media );
57 /** Offer default Impl. */
58 static shared_ptr<Impl> nullimpl()
60 static shared_ptr<Impl> _nullimpl( new Impl );
65 friend Impl * rwcowClone<Impl>( const Impl * rhs );
66 /** clone for RWCOW_pointer */
68 { return new Impl( *this ); }
70 std::list<FetcherJob> _resources;
71 std::list<Pathname> _caches;
73 ///////////////////////////////////////////////////////////////////
76 void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
78 CompositeFileChecker composite;
79 composite.add(ChecksumFileChecker(resource.checksum()));
80 composite.add(checker);
81 enqueue(resource, composite);
84 void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
86 FetcherJob job(resource);
87 job.checkers.add(checker);
88 _resources.push_back(resource);
91 void Fetcher::Impl::reset()
97 void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
99 _caches.push_back(cache_dir);
102 void Fetcher::Impl::start( const Pathname &dest_dir, MediaSetAccess &media )
104 for ( list<FetcherJob>::const_iterator it_res = _resources.begin(); it_res != _resources.end(); ++it_res )
106 bool got_from_cache = false;
107 for ( list<Pathname>::const_iterator it_cache = _caches.begin(); it_cache != _caches.end(); ++it_cache )
109 // Pathinfos could be cached to avoid too many stats?
110 PathInfo info(*it_cache);
113 // does the current file exists in the current cache?
114 Pathname cached_file = *it_cache + (*it_res).location.filename();
115 if ( PathInfo( cached_file ).isExist() )
117 // check the checksum
118 if ( is_checksum( cached_file, (*it_res).location.checksum() ) )
121 MIL << "file " << (*it_res).location.filename() << " found in previous cache. Using cached copy." << endl;
122 // checksum is already checked.
123 // we could later implement double failover and try to download if file copy fails.
125 // replicate the complete path in the target directory
126 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
127 if ( assert_dir( dest_full_path.dirname() ) != 0 )
128 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
130 if ( filesystem::copy(cached_file, dest_full_path ) != 0 )
132 //ZYPP_THROW(SourceIOException("Can't copy " + cached_file.asString() + " to " + destination.asString()));
133 ERR << "Can't copy " << cached_file + " to " + dest_dir << endl;
138 got_from_cache = true;
144 // File exists in cache but with a different checksum
145 // so just try next cache
151 // skip bad cache directory and try with next one
152 ERR << "Skipping cache : " << *it_cache << endl;
157 if ( ! got_from_cache )
159 // try to get the file from the net
162 Pathname tmp_file = media.provideFile((*it_res).location);
163 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
164 if ( assert_dir( dest_full_path.dirname() ) != 0 )
165 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
166 if ( filesystem::copy(tmp_file, dest_full_path ) != 0 )
168 ZYPP_THROW( Exception("Can't copy " + tmp_file.asString() + " to " + dest_dir.asString()));
173 catch (const Exception & excpt_r)
175 ZYPP_CAUGHT(excpt_r);
176 ZYPP_THROW(Exception("Can't provide " + (*it_res).location.filename().asString() + " : " + excpt_r.msg() ));
181 // We got the file from cache
182 // continue with next file
186 // no matter where did we got the file, try to validate it:
187 Pathname localfile = dest_dir + (*it_res).location.filename();
188 // call the checker function
190 (*it_res).checkers(localfile);
192 catch ( const FileCheckException &e )
196 catch ( const Exception &e )
202 ZYPP_THROW(Exception("Unknown error while validating " + (*it_res).location.filename().asString()));
207 /** \relates Fetcher::Impl Stream output */
208 inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
210 return str << "Fetcher::Impl";
213 ///////////////////////////////////////////////////////////////////
215 // CLASS NAME : Fetcher
217 ///////////////////////////////////////////////////////////////////
219 ///////////////////////////////////////////////////////////////////
221 // METHOD NAME : Fetcher::Fetcher
222 // METHOD TYPE : Ctor
225 : _pimpl( Impl::nullimpl() )
228 ///////////////////////////////////////////////////////////////////
230 // METHOD NAME : Fetcher::~Fetcher
231 // METHOD TYPE : Dtor
236 void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
238 _pimpl->enqueue(resource, checker);
241 void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
243 _pimpl->enqueue(resource, checker);
246 void Fetcher::addCachePath( const Pathname &cache_dir )
248 _pimpl->addCachePath(cache_dir);
251 void Fetcher::reset()
256 void Fetcher::start( const Pathname &dest_dir, MediaSetAccess &media )
258 _pimpl->start(dest_dir, media);
262 /******************************************************************
264 ** FUNCTION NAME : operator<<
265 ** FUNCTION TYPE : std::ostream &
267 std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
269 return str << *obj._pimpl;
272 /////////////////////////////////////////////////////////////////
274 ///////////////////////////////////////////////////////////////////