+pair<bool,DOMElement*> XMLMetadataProvider::background_load()
+{
+ try {
+ return load(false);
+ }
+ catch (long& ex) {
+ if (ex == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED) {
+ // Unchanged document, so re-establish previous refresh interval.
+ m_reloadInterval = computeNextRefresh();
+ m_log.info("remote resource (%s) unchanged, adjusted reload interval to %u seconds", m_source.c_str(), m_reloadInterval);
+ }
+ else {
+ // Any other status code, just treat as an error.
+ m_reloadInterval = m_minRefreshDelay * m_backoffFactor++;
+ if (m_reloadInterval > m_maxRefreshDelay)
+ m_reloadInterval = m_maxRefreshDelay;
+ m_log.warn("adjusted reload interval to %u seconds", m_reloadInterval);
+ }
+ if (!m_loaded && !m_backing.empty())
+ return load(true);
+ throw;
+ }
+ catch (std::exception& ex) {
+ if (!m_local) {
+ m_reloadInterval = m_minRefreshDelay * m_backoffFactor++;
+ if (m_reloadInterval > m_maxRefreshDelay)
+ m_reloadInterval = m_maxRefreshDelay;
+ m_log.warn("adjusted reload interval to %u seconds", m_reloadInterval);
+ if (!m_loaded && !m_backing.empty()) {
+ m_log.warn("trying backup file, exception loading remote resource: %s", ex.what());
+ return load(true);
+ }
+ }
+ throw;
+ }
+}
+
+time_t XMLMetadataProvider::computeNextRefresh()
+{
+ time_t now = time(nullptr);
+
+ // If some or all of the metadata is already expired, reload after the minimum.
+ if (m_lastValidUntil < now) {
+ return m_minRefreshDelay;
+ }
+ else {
+ // Compute the smaller of the validUntil / cacheDuration constraints.
+ time_t ret = m_lastValidUntil - now;
+ const CacheableSAMLObject* cacheable = dynamic_cast<const CacheableSAMLObject*>(m_object.get());
+ if (cacheable && cacheable->getCacheDuration())
+ ret = min(ret, cacheable->getCacheDurationEpoch());
+
+ // Adjust for the delay factor.
+ ret *= m_refreshDelayFactor;
+
+ // Bound by max and min.
+ if (ret > m_maxRefreshDelay)
+ return m_maxRefreshDelay;
+ else if (ret < m_minRefreshDelay)
+ return m_minRefreshDelay;
+
+ return ret;
+ }
+}
+
+void XMLMetadataProvider::index(time_t& validUntil)