libzypp 17.32.5
mediafacade.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9#include "mediafacade.h"
10#include <zypp-core/TriBool.h>
11#include <utility>
12#include <zypp-media/ng/ProvideSpec>
14
15namespace zyppng {
16
18 {
19
20 public:
21
23
25 const ProvideMediaSpec &spec() const;
26 const zypp::Url &url() const;
27 const std::optional<zypp::Pathname> &rootPath() const;
28 MediaSyncFacadeRef parent() const;
29
33 bool isSameMedium ( const std::vector<zypp::Url> &urls, const ProvideMediaSpec &spec );
34
35 // ReferenceCounted interface
36 protected:
37 void unref_to(unsigned int) const override;
38
39 private:
43 MediaSyncFacadeRef _parent;
44 std::optional<zypp::Pathname> _localPath;
45 };
46
48
50 : _id( mediaId )
51 , _attachedUrl(std::move( baseUrl ))
52 , _spec(std::move( mediaSpec ))
53 , _parent(std::move( parentRef ))
54 , _localPath( locPath )
55 {}
56
61
63 {
64 return _spec;
65 }
66
68 {
69 return _attachedUrl;
70 }
71
72 const std::optional<zypp::Pathname> &AttachedSyncMediaInfo::rootPath() const
73 {
74 return _localPath;
75 }
76
77 MediaSyncFacadeRef AttachedSyncMediaInfo::parent() const
78 {
79 return _parent;
80 }
81
82 bool AttachedSyncMediaInfo::isSameMedium(const std::vector<zypp::Url> &urls, const ProvideMediaSpec &spec) {
83
84 const auto check = _spec.isSameMedium(spec);
85 if ( !zypp::indeterminate (check) )
86 return (bool)check;
87
88 // let the URL rule
89 return ( std::find( urls.begin(), urls.end(), _attachedUrl ) != urls.end() );
90 }
91
92 void AttachedSyncMediaInfo::unref_to( unsigned int count ) const
93 {
94 // once count reaches 1 only the MediaSyncFacade holds a reference,
95 // time to release the medium
96 if ( count == 1 ) {
97 _parent->releaseMedium ( this );
98 // !!!! careful from here on out 'this' is most likely invalid !!!!
99 return;
100 }
101 }
102
103
105
106 SyncMediaHandle::SyncMediaHandle(AttachedSyncMediaInfo_Ptr dataPtr) : _data( std::move(dataPtr) )
107 { }
108
109 MediaSyncFacadeRef SyncMediaHandle::parent() const
110 {
111 return _data->parent();
112 }
113
115 {
116 return _data.get() != nullptr;
117 }
118
120 {
122 if ( !_data )
123 return invalidHandle;
124 return _data->url();
125 }
126
127 const std::optional<zypp::Pathname> &SyncMediaHandle::localPath() const
128 {
129 static std::optional<zypp::Pathname> invalidPath;
130 if ( !_data )
131 return invalidPath;
132 return _data->rootPath();
133 }
134
136 {
137 return *_data;
138 }
139
141 : _res( std::move(file) )
142 , _provideHandle( std::move (hdl) )
143 { }
144
146 return _res;
147 }
148
150
152 {
153 // rewrite and sanitize the urls if required
154 std::vector<zypp::Url> useableUrls = urls;
155
156 // first try and find a already attached medium
157 auto i = std::find_if( _attachedMedia.begin (), _attachedMedia.end(), [&]( const AttachedSyncMediaInfo_Ptr &medium ) {
158 return medium->isSameMedium( useableUrls, request );
159 });
160
161 if ( i != _attachedMedia.end() ) {
163 }
164
165 // nothing attached, make a new one
167 std::exception_ptr lastError;
168 for ( const auto &url : useableUrls ) {
169 std::optional<zypp::media::MediaAccessId> attachId;
170 try {
171
172 attachId = mgr.open( url );
173 if ( !request.mediaFile().empty() ) {
174 mgr.addVerifier( *attachId, zypp::media::MediaVerifierRef( new zypp::repo::SUSEMediaVerifier( request.mediaFile(), request.medianr() ) ) );
175 }
176
177 // attach the medium
178 mgr.attach( *attachId );
179
180 auto locPath = mgr.localPath( *attachId, "/" );
181 auto attachInfo = AttachedSyncMediaInfo_Ptr( new AttachedSyncMediaInfo( shared_this<MediaSyncFacade>(), *attachId, url, request, locPath ) );
182 _attachedMedia.push_back( attachInfo );
184
185 } catch ( const zypp::Exception &e ) {
186 lastError = std::current_exception();
187 ZYPP_CAUGHT(e);
188 } catch (...) {
189 // didn't work -> clean up
190 lastError = std::current_exception();
191 }
192
193 // this URL wasn't the one, prepare to try a new one
194 if ( attachId )
195 mgr.close ( *attachId );
196
197 attachId.reset();
198 }
199
200 // if we have a error stored, return that one
201 if ( lastError ) {
203 }
204
206 }
207
209 {
210 // this should never happen because every handle has a reference to the media manager, but still add a debug output
211 // so we know in case we have weird behavior.
212 if ( _attachedMedia.size () ) {
213 WAR << "Releasing zyppng::MediaSyncFacade with still valid MediaHandles, this is a bug!" << std::endl;
214 }
215 }
216
218 {
219 return attachMedia( std::vector<zypp::Url>{url}, request );
220 }
221
223 {
224 using namespace zyppng::operators;
225
226 if ( !urls.size() )
227 return expected<MediaSyncFacade::Res>::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("Can not provide a file without a URL.") ));
228
229 std::optional<expected<MediaSyncFacade::Res>> lastErr;
230 for ( const zypp::Url& file_url : urls ) {
231
232 zypp::Url url(file_url);
234 url.setPathName ("/");
235
237 | and_then( [&, this]( const MediaSyncFacade::MediaHandle& handle ) {
238 return provide( handle, fileName, request.asOnMediaLocation(fileName, 1));
239 });
240
241 if ( res )
242 return res;
243
244 lastErr = res;
245 }
246
247 // we always should have a last error, except if the URLs are empty
248 if ( lastErr )
249 return *lastErr;
250
251 // we should not get here, but if we do simply use the first entry to make a not found error
252 zypp::Url url( urls.front() );
254 url.setPathName ("/");
256
257 }
258
260 {
261 return provide( std::vector<zypp::Url>{url}, request );
262 }
263
265 {
267 const auto &handleInfo = attachHandle.info();
268
269 try {
270 if ( request.checkExistsOnly() ) {
271 if ( !mgr.doesFileExist ( handleInfo.mediaId (), fileName ) ) {
273 }
274
275 // we return a result pointing to a non existant file, since the code just asked us to check if the file exists
277
278 } else {
279 mgr.provideFile( handleInfo.mediaId (), request.asOnMediaLocation( fileName, handleInfo.spec().medianr()) );
280
281 zypp::ManagedFile locFile( mgr.localPath( handleInfo.mediaId(), fileName ) );
282
283 // do not clean up files for now, they are cleaned up anyways on detach
284#if 0
285 // if the file is downloaded we want to clean it up again
286 if ( handleInfo.url().schemeIsDownloading() )
288#endif
289
291 }
292 } catch ( const zypp::Exception &e ) {
293 ZYPP_CAUGHT(e);
294 return expected<MediaSyncFacade::Res>::error(std::current_exception());
295 } catch (...) {
296 return expected<MediaSyncFacade::Res>::error(std::current_exception());
297 }
298 }
299
301 {
302 try {
304 } catch(...) {
305 return expected<zypp::CheckSum>::error ( std::current_exception () );
306 }
307 }
308
310 {
311 try {
312 // do what Provide would do and make a URL
313 zypp::Url url("copy:///");
314 url.setPathName( source );
315
316 auto sourcePi = zypp::PathInfo(source);
317 if ( !sourcePi.isExist() ) {
319 }
320 if ( !sourcePi.isFile () )
322
323 auto res = zypp::filesystem::hardlinkCopy( source, target.asString() );
324 if ( res == 0 ) {
326 } else {
327 return expected<zypp::ManagedFile>::error ( ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Failed to create file " << target << " errno: " << res ) ) );
328 }
329 } catch(...) {
330 return expected<zypp::ManagedFile>::error ( std::current_exception () );
331 }
332 }
333
335 {
336 // not much to do here, since this will block until the file has been copied we do not need to remember the ProvideRes
337 return copyFile( source.file(), target );
338 }
339
341 {
342 if ( !ptr ) return;
343
344 auto i = std::find_if(_attachedMedia.begin (), _attachedMedia.end(), [&]( const auto &p ) { return p.get() == ptr; } );
345
346 try {
348 mgr.close ( ptr->mediaId() );
349 } catch ( const zypp::Exception & e ) {
350 ZYPP_CAUGHT(e);
351 }
352
353 if ( i != _attachedMedia.end() ) {
354 _attachedMedia.erase(i);
355 } else {
356 ERR << "Releasing unknown medium " << ptr->mediaId () << " should not happen";
357 }
358 }
359
360
361}
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
void reset()
Reset to default Ctor values.
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Base class for Exception.
Definition Exception.h:147
Url manipulation class.
Definition Url.h:92
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition Url.cc:608
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition Url.cc:768
Base class for reference counted objects.
Wrapper class for stat/lstat.
Definition PathInfo.h:222
const std::string & asString() const
String representation.
Definition Pathname.h:91
Just inherits Exception to separate media exceptions.
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees,...
Implementation of the traditional SUSE media verifier.
zypp::media::MediaAccessId _id
MediaSyncFacadeRef _parent
std::optional< zypp::Pathname > _localPath
AttachedSyncMediaInfo(MediaSyncFacadeRef parentRef, zypp::media::MediaAccessId mediaId, zypp::Url baseUrl, ProvideMediaSpec mediaSpec, const zypp::Pathname &locPath)
const zypp::Url & url() const
MediaSyncFacadeRef parent() const
bool isSameMedium(const std::vector< zypp::Url > &urls, const ProvideMediaSpec &spec)
const std::optional< zypp::Pathname > & rootPath() const
zypp::media::MediaAccessId mediaId() const
void unref_to(unsigned int) const override
const ProvideMediaSpec & spec() const
Res(MediaHandle hdl, zypp::ManagedFile file)
const zypp::Pathname file() const
expected< Res > provide(const std::vector< zypp::Url > &urls, const ProvideFileSpec &request)
expected< MediaHandle > attachMedia(const std::vector< zypp::Url > &urls, const ProvideMediaSpec &request)
friend class AttachedSyncMediaInfo
Definition mediafacade.h:52
expected< zypp::CheckSum > checksumForFile(const zypp::Pathname &p, const std::string &algorithm)
expected< zypp::ManagedFile > copyFile(const zypp::Pathname &source, const zypp::Pathname &target)
std::vector< AttachedSyncMediaInfo_Ptr > _attachedMedia
void releaseMedium(const AttachedSyncMediaInfo *ptr)
zypp::TriBool isSameMedium(const ProvideMediaSpec &other)
const std::optional< zypp::Pathname > & localPath() const
const AttachedSyncMediaInfo & info() const
MediaSyncFacadeRef parent() const
const zypp::Url & baseUrl() const
AttachedSyncMediaInfo_Ptr _data
Definition mediafacade.h:39
static expected success(ConsParams &&...params)
Definition expected.h:115
Definition Arch.h:364
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
std::string checksum(const Pathname &file, const std::string &algorithm)
Compute a files checksum.
Definition PathInfo.cc:1052
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:701
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition PathInfo.cc:884
unsigned int MediaAccessId
Media manager access Id type.
Definition MediaSource.h:30
ResultType and_then(const expected< T, E > &exp, Function &&f)
Definition expected.h:367
Wrapper for const correct access via Smart pointer types.
Definition PtrTypes.h:292
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:212
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:437
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition Exception.h:433
#define ERR
Definition Logger.h:98
#define WAR
Definition Logger.h:97
#define IMPL_PTR_TYPE(NAME)
#define ZYPP_IMPL_PRIVATE_CONSTR(Class)
Definition zyppglobal.h:213