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"
22 ///////////////////////////////////////////////////////////////////
24 { /////////////////////////////////////////////////////////////////
28 FetcherJob( const OnMediaLocation &loc )
34 OnMediaLocation location;
37 ///////////////////////////////////////////////////////////////////
39 // CLASS NAME : Fetcher::Impl
41 /** Fetcher implementation. */
47 void enqueue( const OnMediaLocation &resource );
48 void addCachePath( const Pathname &cache_dir );
50 void start( const Pathname &dest_dir, MediaSetAccess &media );
52 /** Offer default Impl. */
53 static shared_ptr<Impl> nullimpl()
55 static shared_ptr<Impl> _nullimpl( new Impl );
60 friend Impl * rwcowClone<Impl>( const Impl * rhs );
61 /** clone for RWCOW_pointer */
63 { return new Impl( *this ); }
65 std::list<FetcherJob> _resources;
66 std::list<Pathname> _caches;
68 ///////////////////////////////////////////////////////////////////
71 void Fetcher::Impl::enqueue( const OnMediaLocation &resource )
73 _resources.push_back(FetcherJob(resource));
76 void Fetcher::Impl::reset()
82 void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
84 _caches.push_back(cache_dir);
87 void Fetcher::Impl::start( const Pathname &dest_dir, MediaSetAccess &media )
89 for ( list<FetcherJob>::const_iterator it_res = _resources.begin(); it_res != _resources.end(); ++it_res )
91 bool got_from_cache = false;
92 for ( list<Pathname>::const_iterator it_cache = _caches.begin(); it_cache != _caches.end(); ++it_cache )
94 // Pathinfos could be cached to avoid too many stats?
95 PathInfo info(*it_cache);
98 // does the current file exists in the current cache?
99 Pathname cached_file = *it_cache + (*it_res).location.filename();
100 if ( PathInfo( cached_file ).isExist() )
102 // check the checksum
103 if ( is_checksum( cached_file, (*it_res).location.checksum() ) )
106 MIL << "file " << (*it_res).location.filename() << " found in previous cache. Using cached copy." << endl;
107 // checksum is already checked.
108 // we could later implement double failover and try to download if file copy fails.
110 // replicate the complete path in the target directory
111 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
112 if ( assert_dir( dest_full_path.dirname() ) != 0 )
113 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
115 if ( filesystem::copy(cached_file, dest_full_path ) != 0 )
117 //ZYPP_THROW(SourceIOException("Can't copy " + cached_file.asString() + " to " + destination.asString()));
118 ERR << "Can't copy " << cached_file + " to " + dest_dir << endl;
123 got_from_cache = true;
129 // File exists in cache but with a different checksum
130 // so just try next cache
136 // skip bad cache directory and try with next one
137 ERR << "Skipping cache : " << *it_cache << endl;
142 if ( ! got_from_cache )
144 // try to get the file from the net
147 Pathname tmp_file = media.provideFile((*it_res).location);
148 Pathname dest_full_path = dest_dir + (*it_res).location.filename();
149 if ( assert_dir( dest_full_path.dirname() ) != 0 )
150 ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
151 if ( filesystem::copy(tmp_file, dest_full_path ) != 0 )
153 ZYPP_THROW( Exception("Can't copy " + tmp_file.asString() + " to " + dest_dir.asString()));
156 catch (const Exception & excpt_r)
158 ZYPP_CAUGHT(excpt_r);
159 ZYPP_THROW(Exception("Can't provide " + (*it_res).location.filename().asString() + " : " + excpt_r.msg() ));
164 // We got the file from cache
165 // continue with next file
171 /** \relates Fetcher::Impl Stream output */
172 inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
174 return str << "Fetcher::Impl";
177 ///////////////////////////////////////////////////////////////////
179 // CLASS NAME : Fetcher
181 ///////////////////////////////////////////////////////////////////
183 ///////////////////////////////////////////////////////////////////
185 // METHOD NAME : Fetcher::Fetcher
186 // METHOD TYPE : Ctor
189 : _pimpl( Impl::nullimpl() )
192 ///////////////////////////////////////////////////////////////////
194 // METHOD NAME : Fetcher::~Fetcher
195 // METHOD TYPE : Dtor
200 void Fetcher::enqueue( const OnMediaLocation &resource )
202 _pimpl->enqueue(resource);
205 void Fetcher::addCachePath( const Pathname &cache_dir )
207 _pimpl->addCachePath(cache_dir);
210 void Fetcher::reset()
215 void Fetcher::start( const Pathname &dest_dir, MediaSetAccess &media )
217 _pimpl->start(dest_dir, media);
221 /******************************************************************
223 ** FUNCTION NAME : operator<<
224 ** FUNCTION TYPE : std::ostream &
226 std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
228 return str << *obj._pimpl;
231 /////////////////////////////////////////////////////////////////
233 ///////////////////////////////////////////////////////////////////
235 // callback::SendReport<DigestReport> report;
236 // if ( checksum.empty() )
238 // MIL << "File " << file_url << " has no checksum available." << std::endl;
239 // if ( report->askUserToAcceptNoDigest(file_to_download) )
241 // MIL << "User accepted " << file_url << " with no checksum." << std::endl;
246 // ZYPP_THROW(SourceMetadataException( file_url.asString() + " " + N_(" miss checksum.") ));
251 // if (! is_checksum( destination, checksum))
252 // ZYPP_THROW(SourceMetadataException( file_url.asString() + " " + N_(" fails checksum verification.") ));