libzypp 17.37.17
downloadwf.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9
10#include "downloadwf.h"
12
13#include <utility>
14#include <zypp/ng/Context>
17
18
20#include <zypp-core/zyppng/pipelines/Algorithm>
21
22#include <zypp-media/ng/Provide>
23#include <zypp-media/ng/ProvideSpec>
24
25namespace zyppng {
26
27 template<typename ZyppContextRefType>
29 : _zyppContext( std::move(zyppContext) )
30 , _destDir( std::move(destDir) )
31 { }
32
33
34 template<typename ZyppContextRefType>
41 template<typename ZyppContextRefType>
43 {
44 return _destDir;
45 }
46
47 template<typename ZyppContextRefType>
52
53 template<typename ZyppContextRefType>
54 const std::vector<zypp::Pathname> &CacheProviderContext<ZyppContextRefType>::cacheDirs() const
55 {
56 return _cacheDirs;
57 }
58
59
62
63
64 namespace {
65
66 using namespace zyppng::operators;
67
68 class CacheMissException : public zypp::Exception
69 {
70 public:
71 CacheMissException( const zypp::Pathname &filename )
72 : zypp::Exception( zypp::str::Str() << filename << " not found in target cache" ) { }
73 };
74
75 template <class T>
76 struct showme;
77
78 template <class Executor, class OpType>
79 struct ProvideFromCacheOrMediumLogic : public LogicBase<Executor, OpType> {
80 protected:
81
82 ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
83
84 using CacheProviderContextRefType = std::conditional_t<detail::is_async_op_v<OpType>, AsyncCacheProviderContextRef, SyncCacheProviderContextRef>;
86 using ProvideType = typename ContextType::ProvideType;
87 using MediaHandle = typename ProvideType::MediaHandle;
88 using ProvideRes = typename ProvideType::Res;
89
90 public:
91 ProvideFromCacheOrMediumLogic( CacheProviderContextRefType cacheContext, MediaHandle &&medium, zypp::Pathname &&file, ProvideFileSpec &&filespec )
92 : _ctx( std::move(cacheContext) )
93 , _medium( std::move(medium) )
94 , _file(std::move( file ))
95 , _filespec( std::move(filespec) ) {}
96
97 MaybeAsyncRef<expected<zypp::ManagedFile>> execute() {
98
99 return findFileInCache( )
100 | [this]( expected<zypp::ManagedFile> cached ) -> MaybeAsyncRef<expected<zypp::ManagedFile>> {
101 if ( !cached ) {
102 MIL << "Didn't find " << _file << " in the caches, providing from medium" << std::endl;
103
104 // we didn't find it in the caches or the lookup failed, lets provide and check it
105 std::shared_ptr<ProvideType> provider = _ctx->zyppContext()->provider();
106 return provider->provide( _medium, _file, _filespec )
107 | and_then( [this]( ProvideRes res ) {
108 return verifyFile( res.file() )
109 | and_then( [res = res]() {
110 return expected<ProvideRes>::success( std::move(res) );
111 });
112 })
113 | and_then( ProvideType::copyResultToDest( _ctx->zyppContext()->provider(), _ctx->destDir() / _file ) )
114 | and_then( []( zypp::ManagedFile &&file ){
115 file.resetDispose ();
116 return make_expected_success (std::move(file));
117 }) ;
118
119 } else {
120
121 return verifyFile ( cached.get() )
122 | and_then([ this, cachedFile = cached.get() ]() mutable {
123 if ( cachedFile == _ctx->destDir() / _file ) {
124 cachedFile.resetDispose(); // make sure dispose is reset
125 return makeReadyResult( expected<zypp::ManagedFile>::success(std::move(cachedFile) ));
126 }
127
128 const auto &targetPath = _ctx->destDir() / _file;
129 zypp::filesystem::assert_dir( targetPath.dirname () );
130
131 return _ctx->zyppContext()->provider()->copyFile( cachedFile, _ctx->destDir() / _file )
132 | and_then( [cachedFile]( zypp::ManagedFile &&f) { f.resetDispose(); return make_expected_success (std::move(f)); });
133 });
134 }
135 };
136 }
137
138 protected:
143 MaybeAsyncRef<expected<zypp::ManagedFile>> findFileInCache( ) {
144
145 // No checksum - no match
146 if ( _filespec.checksum().empty() )
147 return makeReadyResult( expected<zypp::ManagedFile>::error(std::make_exception_ptr( CacheMissException(_file) )) );
148
149 const auto &confDirs = _ctx->cacheDirs();
150 const auto targetFile = _ctx->destDir() / _file ;
151 std::vector<zypp::Pathname> caches;
152 caches.push_back( _ctx->destDir() );
153 caches.insert( caches.end(), confDirs.begin(), confDirs.end() );
154
155 auto makeSearchPipeline = [this, targetFile]( zypp::Pathname cachePath ){
156 zypp::Pathname cacheFilePath( cachePath / _file );
157 zypp::PathInfo cacheFileInfo( cacheFilePath );
158 if ( !cacheFileInfo.isExist () ) {
159 return makeReadyResult(expected<zypp::ManagedFile>::error( std::make_exception_ptr (CacheMissException(_file)) ));
160 } else {
161 auto provider = _ctx->zyppContext()->provider();
162
163 // calc checksum, but do not use the workflow. Here we don't want to ask the user if a wrong checksum should
164 // be accepted
165 return provider->checksumForFile( cacheFilePath, _filespec.checksum().type() )
166 | and_then([this, cacheFilePath, targetFile]( zypp::CheckSum sum ) {
167
168 auto mgdFile = zypp::ManagedFile( cacheFilePath );
169
170 // if the file is in the target dir, make sure to release it if its not used
171 if ( cacheFilePath == targetFile )
172 mgdFile.setDispose ( zypp::filesystem::unlink );
173
174 if ( sum == _filespec.checksum () ) {
175 // we found the file!
176 return expected<zypp::ManagedFile>::success( std::move(mgdFile) );
177 }
178
179 return expected<zypp::ManagedFile>::error( std::make_exception_ptr (CacheMissException(_file)) );
180 });
181 }
182 };
183
184 auto defVal = expected<zypp::ManagedFile>::error( std::make_exception_ptr (CacheMissException(_file) ) );
185 return std::move(caches) | firstOf( std::move(makeSearchPipeline), std::move(defVal), detail::ContinueUntilValidPredicate() );
186 }
187
188 MaybeAsyncRef<expected<void>> verifyFile ( const zypp::Pathname &dlFilePath ) {
189
190 return zypp::Pathname( dlFilePath )
191 | [this]( zypp::Pathname &&dlFilePath ) {
192 if ( !_filespec.checksum().empty () ) {
193 return CheckSumWorkflow::verifyChecksum( _ctx->zyppContext(), _filespec.checksum (), std::move(dlFilePath) );
194 }
196 };
197 // add other verifier here via and_then(), like a signature based one
198 }
199
200 CacheProviderContextRefType _ctx;
201 MediaHandle _medium;
203 ProvideFileSpec _filespec;
204 };
205 }
206
208
209 AsyncOpRef<expected<zypp::ManagedFile> > provideToCacheDir( AsyncCacheProviderContextRef cacheContext, ProvideMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec )
210 {
211 return SimpleExecutor<ProvideFromCacheOrMediumLogic, AsyncOp<expected<zypp::ManagedFile>>>::run( std::move(cacheContext), std::move(medium), std::move(file), std::move(filespec) );
212 }
213
214 expected<zypp::ManagedFile> provideToCacheDir(SyncCacheProviderContextRef cacheContext, SyncMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec )
215 {
216 return SimpleExecutor<ProvideFromCacheOrMediumLogic, SyncOp<expected<zypp::ManagedFile>>>::run( std::move(cacheContext), std::move(medium), std::move(file), std::move(filespec) );
217 }
218
219 }
220
221}
Base class for Exception.
Definition Exception.h:153
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const zypp::Pathname & destDir() const
Definition downloadwf.cc:42
const ContextRefType & zyppContext() const
Definition downloadwf.cc:35
ContextRefType _zyppContext
Definition downloadwf.h:47
std::vector< zypp::Pathname > _cacheDirs
Definition downloadwf.h:49
ZyppContextRefType ContextRefType
Definition downloadwf.h:32
void addCacheDir(const zypp::Pathname &p)
Definition downloadwf.cc:48
const std::vector< zypp::Pathname > & cacheDirs() const
Definition downloadwf.cc:54
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
Definition provideres.h:36
const zypp::Pathname file() const
Definition provideres.cc:21
static expected success(ConsParams &&...params)
Definition expected.h:115
static expected error(ConsParams &&...params)
Definition expected.h:126
#define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType)
Definition Arch.h:364
typename conditional< B, T, F >::type conditional_t
Definition TypeTraits.h:39
String related utilities and Regular expression matching.
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:705
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:324
Easy-to use interface to the ZYPP dependency resolver.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
Pathname _file
expected< void > verifyChecksum(SyncContextRef zyppCtx, zypp::CheckSum checksum, zypp::Pathname file)
AsyncOpRef< expected< zypp::ManagedFile > > provideToCacheDir(AsyncCacheProviderContextRef cacheContext, ProvideMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec)
auto and_then(Fun &&function)
Definition expected.h:623
std::conditional_t< isAsync, AsyncOpRef< T >, T > makeReadyResult(T &&result)
Definition asyncop.h:297
std::shared_ptr< AsyncOp< T > > AsyncOpRef
Definition asyncop.h:255
typename remove_smart_ptr< T >::type remove_smart_ptr_t
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition expected.h:397
auto firstOf(Transformation &&transformFunc, DefaultType &&def, Predicate &&predicate=detail::ContinueUntilValidPredicate())
Definition algorithm.h:149
#define MIL
Definition Logger.h:100
#define ZYPP_PRIVATE_CONSTR_ARG
Definition zyppglobal.h:160