SET(LIBZYPP_MAJOR "16")
SET(LIBZYPP_COMPATMINOR "0")
SET(LIBZYPP_MINOR "4")
-SET(LIBZYPP_PATCH "0")
+SET(LIBZYPP_PATCH "1")
#
-# LAST RELEASED: 16.4.0 (0)
+# LAST RELEASED: 16.4.1 (0)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
-------------------------------------------------------------------
+Fri Feb 3 13:40:04 CET 2017 - ma@suse.de
+
+- MediaMultiCurl: Trigger aliveCallback when downloading metalink
+ files (bsc#1021291)
+- version 16.4.1 (0)
+
+-------------------------------------------------------------------
Thu Jan 26 13:03:37 CET 2017 - ma@suse.de
- Add API for updating the AutoInstalled db
CapMatch Capability::_doMatch( sat::detail::IdType lhs, sat::detail::IdType rhs )
{
-#warning MIGRATE TO SAT
-#warning TESTCASE
if ( lhs == rhs )
return CapMatch::yes;
case VendorSupportUnsupported:
case VendorSupportACC:
return true;
+
+ case VendorSupportLevel1:
+ case VendorSupportLevel2:
+ case VendorSupportLevel3:
+ break; // intentionally no default:
}
return false;
}
{ return Date( lookupNumAttribute( sat::SolvAttr::productEndOfLife ) );}
bool Product::hasEndOfLife() const
- { return( lookupNumAttribute( sat::SolvAttr::productEndOfLife, -1 ) != -1 ); }
+ { return( lookupNumAttribute( sat::SolvAttr::productEndOfLife, -1 ) != (unsigned long long)(-1) ); }
bool Product::hasEndOfLife( Date & value ) const
{
namespace {
struct ProgressData
{
- ProgressData(CURL *_curl, const long _timeout, const zypp::Url &_url = zypp::Url(),
- callback::SendReport<DownloadProgressReport> *_report=NULL)
- : curl(_curl)
- , timeout(_timeout)
- , reached(false)
- , report(_report)
- , drate_period(-1)
- , dload_period(0)
- , secs(0)
- , drate_avg(-1)
- , ltime( time(NULL))
- , dload( 0)
- , uload( 0)
- , url(_url)
+ ProgressData( CURL *_curl, time_t _timeout = 0, const Url & _url = Url(),
+ callback::SendReport<DownloadProgressReport> *_report = nullptr )
+ : curl( _curl )
+ , url( _url )
+ , timeout( _timeout )
+ , reached( false )
+ , report( _report )
{}
- CURL *curl;
- long timeout;
- bool reached;
+
+ CURL *curl;
+ Url url;
+ time_t timeout;
+ bool reached;
callback::SendReport<DownloadProgressReport> *report;
+
+ time_t _timeStart = 0; ///< Start total stats
+ time_t _timeLast = 0; ///< Start last period(~1sec)
+ time_t _timeRcv = 0; ///< Start of no-data timeout
+ time_t _timeNow = 0; ///< Now
+
+ double _dnlTotal = 0.0; ///< Bytes to download or 0 if unknown
+ double _dnlLast = 0.0; ///< Bytes downloaded at period start
+ double _dnlNow = 0.0; ///< Bytes downloaded now
+
+ int _dnlPercent= 0; ///< Percent completed or 0 if _dnlTotal is unknown
+
+ double _drateTotal= 0.0; ///< Download rate so far
+ double _drateLast = 0.0; ///< Download rate in last period
+
+ void updateStats( double dltotal = 0.0, double dlnow = 0.0 )
+ {
+ time_t now = _timeNow = time(0);
+
+ // If called without args (0.0), recompute based on the last values seen
+ if ( dltotal && dltotal != _dnlTotal )
+ _dnlTotal = dltotal;
+
+ if ( dlnow && dlnow != _dnlNow )
+ {
+ _timeRcv = now;
+ _dnlNow = dlnow;
+ }
+ else if ( !_dnlNow && !_dnlTotal )
+ {
+ // Start time counting as soon as first data arrives.
+ // Skip the connection / redirection time at begin.
+ return;
+ }
+
+ // init or reset if time jumps back
+ if ( !_timeStart || _timeStart > now )
+ _timeStart = _timeLast = _timeRcv = now;
+
+ // timeout condition
+ if ( timeout )
+ reached = ( (now - _timeRcv) > timeout );
+
+ // percentage:
+ if ( _dnlTotal )
+ _dnlPercent = int(_dnlNow * 100 / _dnlTotal);
+
+ // download rates:
+ _drateTotal = _dnlNow / std::max( int(now - _timeStart), 1 );
+
+ if ( _timeLast < now )
+ {
+ _drateLast = (_dnlNow - _dnlLast) / int(now - _timeLast);
+ // start new period
+ _timeLast = now;
+ _dnlLast = _dnlNow;
+ }
+ else if ( _timeStart == _timeLast )
+ _drateLast = _drateTotal;
+ }
+
+ int reportProgress() const
+ {
+ if ( reached )
+ return 1; // no-data timeout
+ if ( report && !(*report)->progress( _dnlPercent, url, _drateTotal, _drateLast ) )
+ return 1; // user requested abort
+ return 0;
+ }
+
+
// download rate of the last period (cca 1 sec)
double drate_period;
// bytes downloaded at the start of the last period
double dload;
// bytes uploaded at the moment the progress was last reported
double uload;
- zypp::Url url;
};
///////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////
+//
+int MediaCurl::aliveCallback( void *clientp, double /*dltotal*/, double dlnow, double /*ultotal*/, double /*ulnow*/ )
+{
+ ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
+ if( pdata )
+ {
+ // Do not propagate dltotal in alive callbacks. MultiCurl uses this to
+ // prevent a percentage raise while downloading a metalink file. Download
+ // activity however is indicated by propagating the download rate (via dlnow).
+ pdata->updateStats( 0.0, dlnow );
+ return pdata->reportProgress();
+ }
+ return 0;
+}
-int MediaCurl::progressCallback( void *clientp,
- double dltotal, double dlnow,
- double ultotal, double ulnow)
+int MediaCurl::progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
{
- ProgressData *pdata = reinterpret_cast<ProgressData *>(clientp);
- if( pdata)
+ ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
+ if( pdata )
{
// work around curl bug that gives us old data
long httpReturnCode = 0;
- if (curl_easy_getinfo(pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode) != CURLE_OK || httpReturnCode == 0)
- return 0;
-
- time_t now = time(NULL);
- if( now > 0)
- {
- // reset time of last change in case initial time()
- // failed or the time was adjusted (goes backward)
- if( pdata->ltime <= 0 || pdata->ltime > now)
- {
- pdata->ltime = now;
- }
-
- // start time counting as soon as first data arrives
- // (skip the connection / redirection time at begin)
- time_t dif = 0;
- if (dlnow > 0 || ulnow > 0)
- {
- dif = (now - pdata->ltime);
- dif = dif > 0 ? dif : 0;
-
- pdata->secs += dif;
- }
-
- // update the drate_avg and drate_period only after a second has passed
- // (this callback is called much more often than a second)
- // otherwise the values would be far from accurate when measuring
- // the time in seconds
- //! \todo more accurate download rate computationn, e.g. compute average value from last 5 seconds, or work with milliseconds instead of seconds
-
- if ( pdata->secs > 1 && (dif > 0 || dlnow == dltotal ))
- pdata->drate_avg = (dlnow / pdata->secs);
-
- if ( dif > 0 )
- {
- pdata->drate_period = ((dlnow - pdata->dload_period) / dif);
- pdata->dload_period = dlnow;
- }
- }
-
- // send progress report first, abort transfer if requested
- if( pdata->report)
- {
- if (!(*(pdata->report))->progress(int( dltotal ? dlnow * 100 / dltotal : 0 ),
- pdata->url,
- pdata->drate_avg,
- pdata->drate_period))
- {
- return 1; // abort transfer
- }
- }
-
- // check if we there is a timeout set
- if( pdata->timeout > 0)
- {
- if( now > 0)
- {
- bool progress = false;
-
- // update download data if changed, mark progress
- if( dlnow != pdata->dload)
- {
- progress = true;
- pdata->dload = dlnow;
- pdata->ltime = now;
- }
- // update upload data if changed, mark progress
- if( ulnow != pdata->uload)
- {
- progress = true;
- pdata->uload = ulnow;
- pdata->ltime = now;
- }
+ if ( curl_easy_getinfo( pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0 )
+ return aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow );
- if( !progress && (now >= (pdata->ltime + pdata->timeout)))
- {
- pdata->reached = true;
- return 1; // aborts transfer
- }
- }
- }
+ pdata->updateStats( dltotal, dlnow );
+ return pdata->reportProgress();
}
return 0;
}
};
protected:
-
- static int progressCallback( void *clientp, double dltotal, double dlnow,
- double ultotal, double ulnow );
+// /** Callback sending just an alive trigger to the UI, without stats (e.g. during metalink download). */
+ static int aliveCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow );
+ /** Callback reporting download progress. */
+ static int progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow );
static CURL *progressCallback_getcurl( void *clientp );
/**
* check the url is supported by the curl library
}
// here we try to suppress all progress coming from a metalink download
+// bsc#1021291: Nevertheless send alive trigger (without stats), so UIs
+// are able to abort a hanging metalink download via callback response.
int MediaMultiCurl::progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{
CURL *_curl = MediaCurl::progressCallback_getcurl(clientp);
if (!_curl)
- return 0;
+ return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
+
// work around curl bug that gives us old data
long httpReturnCode = 0;
if (curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0)
- return 0;
+ return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
char *ptr = NULL;
bool ismetalink = false;
}
if (!ismetalink && dlnow < 256)
{
- // can't tell yet, suppress callback
- return 0;
+ // can't tell yet, ...
+ return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
}
if (!ismetalink)
{
FILE *fp = 0;
- if (curl_easy_getinfo(_curl, CURLINFO_PRIVATE, &fp) != CURLE_OK)
- return 0;
- if (!fp)
- return 0; /* hmm */
+ if (curl_easy_getinfo(_curl, CURLINFO_PRIVATE, &fp) != CURLE_OK || !fp)
+ return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
fflush(fp);
ismetalink = looks_like_metalink_fd(fileno(fp));
DBG << "looks_like_metalink_fd: " << ismetalink << endl;
}
if (ismetalink)
{
- // we're downloading the metalink file. no progress please.
- curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, 1L);
- return 0;
+ // we're downloading the metalink file. Just trigger aliveCallbacks
+ curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, &MediaCurl::aliveCallback);
+ return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
}
curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, &MediaCurl::progressCallback);
return MediaCurl::progressCallback(clientp, dltotal, dlnow, ultotal, ulnow);
public:
/** Ctro taking a ProcessResource2 callback */
Impl(const Pathname &repomd_file, const ProcessResource2 & callback )
- : _tag( tag_NONE )
+ : _callback( callback )
+ , _tag( tag_NONE )
, _type( ResourceType::NONE_e )
- , _callback( callback )
{
Reader reader( repomd_file );
MIL << "Reading " << repomd_file << endl;
///////////////////////////////////////////////////////////////////
namespace zypp
-{ /////////////////////////////////////////////////////////////////
+{
///////////////////////////////////////////////////////////////////
namespace repo
- { /////////////////////////////////////////////////////////////////
+ {
- ///////////////////////////////////////////////////////////////////
- namespace
- { /////////////////////////////////////////////////////////////////
-
- typedef std::string (SrcPackage::*inlined)() const;
- typedef OnMediaLocation (SrcPackage::*location)() const;
-
- /** Provide a SrcPackage in a local file. */
- ManagedFile doProvideSrcPackage( repo::RepoMediaAccess & access_r,
- const SrcPackage & script_r,
- inlined inlined_r, location location_r )
- {
- ManagedFile ret;
-
- // 1st try inlined
- std::string inlined( (script_r.*inlined_r)() );
- if ( ! inlined.empty() )
- {
- // Take care the TmpFile goes out of scope BEFORE the
- // ofstream opens the file again.
- ret = ManagedFile( filesystem::TmpFile( filesystem::TmpPath::defaultLocation(),
- "zypp-script-"+script_r.name() ),
- filesystem::unlink );
- std::ofstream str( ret.value().c_str() );
- str << inlined << endl;
- }
- else
- {
- // otherwise try download
- OnMediaLocation location( (script_r.*location_r)() );
- if ( ! location.filename().empty() )
- {
- ret = access_r.provideFile( script_r.repoInfo(), location );
- }
- else
- {
- // no script
- return ManagedFile();
- }
- }
-
- // HERE: got the script
- filesystem::chmod( ret, 0700 );
- return ret;
- }
-
- /////////////////////////////////////////////////////////////////
- } // namespace
- ///////////////////////////////////////////////////////////////////
-
- ///////////////////////////////////////////////////////////////////
- //
- // METHOD NAME : SrcPackageProvider::SrcPackageProvider
- // METHOD TYPE : Ctor
- //
SrcPackageProvider::SrcPackageProvider( repo::RepoMediaAccess & access_r )
: _access( access_r )
{}
- ///////////////////////////////////////////////////////////////////
- //
- // METHOD NAME : SrcPackageProvider::~SrcPackageProvider
- // METHOD TYPE : Dtor
- //
SrcPackageProvider::~SrcPackageProvider()
{}
ManagedFile SrcPackageProvider::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ) const
- {
- return _access.provideFile( srcPackage_r->repoInfo(), srcPackage_r->location() );
- }
+ { return _access.provideFile( srcPackage_r->repoInfo(), srcPackage_r->location() ); }
- /////////////////////////////////////////////////////////////////
} // namespace repo
///////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////