AlexaClientSDK  3.0.0
A cross-platform, modular SDK for interacting with the Alexa Voice Service
DavsHandler.h
Go to the documentation of this file.
1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  * http://aws.amazon.com/apache2.0/
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #ifndef ACSDKDAVSCLIENT_DAVSHANDLER_H_
17 #define ACSDKDAVSCLIENT_DAVSHANDLER_H_
18 
23 
24 #include <chrono>
25 #include <future>
26 #include <mutex>
27 
33 
34 namespace alexaClientSDK {
35 namespace acsdkAssets {
36 namespace davs {
37 
40  , public std::enable_shared_from_this<DavsHandler> {
41 public:
58  static std::shared_ptr<DavsHandler> create(
59  std::shared_ptr<commonInterfaces::DavsRequest> artifactRequest,
60  const std::shared_ptr<davsInterfaces::DavsDownloadCallbackInterface>& downloadRequester,
61  const std::shared_ptr<davsInterfaces::DavsCheckCallbackInterface>& checkRequester,
62  std::string workingDirectory,
63  std::chrono::milliseconds baseBackOffTime,
64  std::chrono::milliseconds maxBackOffTime,
65  std::shared_ptr<alexaClientSDK::avsCommon::sdkInterfaces::AuthDelegateInterface> authDelegate,
66  std::shared_ptr<davsInterfaces::DavsEndpointHandlerInterface> davsEndpointHandler,
67  std::shared_ptr<alexaClientSDK::avsCommon::utils::power::PowerResource> powerResource = nullptr,
68  std::chrono::seconds forcedUpdateInterval = std::chrono::seconds(0));
72  ~DavsHandler() override;
73 
77  inline bool isRelevant() {
78  return !m_checkRequester.expired() && !m_downloadRequester.expired();
79  }
80 
85  void requestAndDownload(bool isUserInitiated);
86 
90  void cancel();
91 
96  inline void enableUpdate(bool enable) {
97  std::lock_guard<std::mutex> lock(m_eventMutex);
98  m_updateEnabled = enable;
99  handleUpdateLocked();
100  }
101 
106  inline bool isUpdateEnabled() {
107  return m_updateEnabled;
108  }
109 
110  /***
111  * Expose the inside ArtifactRequest containing type and key to DavsClient check then update
112  * @return ArtifactRequest
113  */
114  inline std::shared_ptr<commonInterfaces::DavsRequest> getDavsRequest() {
115  return m_artifactRequest;
116  }
117 
121  inline void setFirstBackOff(std::chrono::milliseconds firstBackOffTime) {
122  m_firstBackOffTime = firstBackOffTime;
123  }
124 
130  std::chrono::milliseconds getBackOffTime(std::chrono::milliseconds prevBackOffTime);
131 
139  static std::string parseFileFromLink(const std::string& url, const std::string& defaultValue);
140 
141  bool isThrottled() const;
142 
143  void setThrottled(bool throttle);
144 
145  void setConnectionState(bool connected);
146 
147 private:
148  DavsHandler(
149  std::shared_ptr<commonInterfaces::DavsRequest> artifactRequest,
150  const std::shared_ptr<davsInterfaces::DavsDownloadCallbackInterface>& downloadRequester,
151  const std::shared_ptr<davsInterfaces::DavsCheckCallbackInterface>& checkRequester,
152  std::string workingDirectory,
153  std::chrono::milliseconds baseBackOffTime,
154  std::chrono::milliseconds maxBackOffTime,
155  std::shared_ptr<alexaClientSDK::avsCommon::sdkInterfaces::AuthDelegateInterface> authDelegate,
156  std::shared_ptr<davsInterfaces::DavsEndpointHandlerInterface> davsEndpointHandler,
157  std::shared_ptr<alexaClientSDK::avsCommon::utils::power::PowerResource> powerResource,
158  std::chrono::seconds forcedUpdateInterval);
159 
164  void runner(bool isUserInitiated);
165 
172  commonInterfaces::ResultCode checkArtifact(std::shared_ptr<commonInterfaces::VendableArtifact>& artifact);
173 
182  commonInterfaces::ResultCode downloadArtifact(
183  const std::shared_ptr<commonInterfaces::VendableArtifact>& artifact,
184  bool isUserInitiated,
185  std::string& path);
192  commonInterfaces::ResultCode checkWithRetryLoop(std::shared_ptr<commonInterfaces::VendableArtifact>& artifact);
193 
200  void downloadWithRetryLoop(
201  const std::shared_ptr<commonInterfaces::VendableArtifact>& artifact,
202  bool isUserInitiated);
203 
211  bool waitForRetry(std::chrono::milliseconds& waitTime);
212 
218  bool waitForNetworkConnection();
219 
223  void handleUpdateLocked();
224 
228  inline std::string getTmpParentDirectory() const {
229  return m_workingDirectory + "/" + m_artifactRequest->getSummary();
230  }
231 
232  inline std::shared_ptr<davsInterfaces::DavsCheckCallbackInterface> getChecker() {
233  auto checker = m_checkRequester.lock();
234  if (checker == nullptr) {
236  .m("Check requester is no longer available")
237  .d("request", m_artifactRequest->getSummary()));
238  s_metrics().addCounter(METRIC_PREFIX_ERROR("checkRequesterNotAvailable"));
239  return nullptr;
240  }
241  return checker;
242  }
243 
244  inline std::shared_ptr<davsInterfaces::DavsDownloadCallbackInterface> getDownloader() {
245  auto downloader = m_downloadRequester.lock();
246  if (downloader == nullptr) {
247  ACSDK_WARN(alexaClientSDK::avsCommon::utils::logger::LogEntry("DavsHandler", "getDownloader")
248  .m("Download requester is no longer available")
249  .d("request", m_artifactRequest->getSummary()));
250  s_metrics().addCounter(METRIC_PREFIX_ERROR("downloadRequesterNotAvailable"));
251  return nullptr;
252  }
253  return downloader;
254  }
255 
256  inline void sendOnCheckFailure(commonInterfaces::ResultCode resultCode) {
257  auto checker = getChecker();
258  if (checker == nullptr) {
259  return;
260  }
261  ACSDK_ERROR(alexaClientSDK::avsCommon::utils::logger::LogEntry("DavsHandler", "sendOnCheckFailure")
262  .m("Check failed")
263  .d("request", m_artifactRequest->getSummary()));
264  s_metrics().addZeroCounter("downloadCheckSuccess").addCounter(METRIC_PREFIX_ERROR("downloadCheckFailed"));
265  checker->onCheckFailure(resultCode);
266  }
267 
268  inline bool sendCheckIfOkToDownload(
269  const std::shared_ptr<commonInterfaces::VendableArtifact>& artifact,
270  size_t spaceNeeded) {
271  auto checker = getChecker();
272  if (checker == nullptr) {
273  return false;
274  }
275  s_metrics().addCounter("downloadCheckSuccess");
276  if (!checker->checkIfOkToDownload(artifact, spaceNeeded)) {
277  ACSDK_WARN(alexaClientSDK::avsCommon::utils::logger::LogEntry("DavsHandler", "sendCheckIfOkToDownload")
278  .m("Requester rejected download")
279  .d("request", m_artifactRequest->getSummary()));
280  s_metrics().addCounter("downloadRejected");
281  return false;
282  }
283  return true;
284  }
285 
286  inline bool sendOnStartAndCheckIfAvailable() {
287  auto downloader = getDownloader();
288  if (downloader == nullptr) {
289  return false;
290  }
291  ACSDK_INFO(alexaClientSDK::avsCommon::utils::logger::LogEntry("DavsHandler", "sendOnStartAndCheckIfAvailable")
292  .m("Download started")
293  .d("request", m_artifactRequest->getSummary()));
294  downloader->onStart();
295  return true;
296  }
297 
298  inline void sendOnDownloadFailure(commonInterfaces::ResultCode resultCode) {
299  auto downloader = getDownloader();
300  if (downloader == nullptr) {
301  return;
302  }
303  ACSDK_ERROR(alexaClientSDK::avsCommon::utils::logger::LogEntry("DavsHandler", "sendOnDownloadFailure")
304  .m("Download utterly failed")
305  .d("request", m_artifactRequest->getSummary()));
306  s_metrics().addZeroCounter("downloadSuccess").addCounter(METRIC_PREFIX_ERROR("downloadFailed"));
307  downloader->onDownloadFailure(resultCode);
308  }
309 
310  inline void sendOnArtifactDownloaded(
311  const std::shared_ptr<commonInterfaces::VendableArtifact>& artifact,
312  const std::string& path) {
313  auto downloader = m_downloadRequester.lock();
314  if (downloader == nullptr) {
315  return;
316  }
317  ACSDK_INFO(alexaClientSDK::avsCommon::utils::logger::LogEntry("DavsHandler", "sendOnArtifactDownloaded")
318  .m("Download succeeded")
319  .d("request", m_artifactRequest->getSummary()));
320  s_metrics().addCounter("downloadSuccess");
321  downloader->onArtifactDownloaded(artifact, path);
322  }
323 
326  bool onProgressUpdate(long dlTotal, long dlNow, long ulTotal, long ulNow) override;
328 private:
329  static const std::function<common::AmdMetricsWrapper()> s_metrics;
330 
331  const std::shared_ptr<commonInterfaces::DavsRequest> m_artifactRequest;
332  const std::weak_ptr<davsInterfaces::DavsDownloadCallbackInterface> m_downloadRequester;
333  const std::weak_ptr<davsInterfaces::DavsCheckCallbackInterface> m_checkRequester;
334  const std::string m_workingDirectory;
335 
336  // controls retry logic and how much to backoff
337  const std::chrono::milliseconds m_baseBackOffTime;
338  const std::chrono::milliseconds m_maxBackOffTime;
340  const std::shared_ptr<alexaClientSDK::avsCommon::sdkInterfaces::AuthDelegateInterface> m_authDelegate;
342  const std::shared_ptr<davsInterfaces::DavsEndpointHandlerInterface> m_davsEndpointHandler;
344  std::shared_ptr<alexaClientSDK::avsCommon::utils::power::PowerResource> m_powerResource;
346  const std::chrono::seconds m_forcedUpdateInterval;
347  std::chrono::milliseconds m_firstBackOffTime;
348 
349  // whether cancel request has been issued during DAVS download
350  std::mutex m_eventMutex;
351  std::condition_variable m_eventTrigger;
352  bool m_shutdown;
353  std::atomic_flag m_running;
354  std::future<void> m_taskFuture;
356 
357  bool m_updateEnabled;
359 
360  bool m_throttled;
361  bool m_networkConnected;
362 
364  bool m_unpack;
365 };
366 
367 } // namespace davs
368 } // namespace acsdkAssets
369 } // namespace alexaClientSDK
370 
371 #endif // ACSDKDAVSCLIENT_DAVSHANDLER_H_
void setFirstBackOff(std::chrono::milliseconds firstBackOffTime)
Definition: DavsHandler.h:121
::std::string string
Definition: gtest-port.h:1097
Definition: CurlProgressCallbackInterface.h:23
std::chrono::system_clock::time_point TimeEpoch
Definition: VendableArtifact.h:29
std::mutex m
Definition: AlexaPresentationTest.cpp:91
Timer to schedule task for delayed and periodic execution.
Definition: Timer.h:39
std::shared_ptr< commonInterfaces::DavsRequest > getDavsRequest()
Definition: DavsHandler.h:114
static std::shared_ptr< DavsHandler > create(std::shared_ptr< commonInterfaces::DavsRequest > artifactRequest, const std::shared_ptr< davsInterfaces::DavsDownloadCallbackInterface > &downloadRequester, const std::shared_ptr< davsInterfaces::DavsCheckCallbackInterface > &checkRequester, std::string workingDirectory, std::chrono::milliseconds baseBackOffTime, std::chrono::milliseconds maxBackOffTime, std::shared_ptr< alexaClientSDK::avsCommon::sdkInterfaces::AuthDelegateInterface > authDelegate, std::shared_ptr< davsInterfaces::DavsEndpointHandlerInterface > davsEndpointHandler, std::shared_ptr< alexaClientSDK::avsCommon::utils::power::PowerResource > powerResource=nullptr, std::chrono::seconds forcedUpdateInterval=std::chrono::seconds(0))
#define ACSDK_ERROR(entry)
Definition: Logger.h:481
#define ACSDK_WARN(entry)
Definition: Logger.h:472
Whether or not curl logs should be emitted.
Definition: AVSConnectionManager.h:36
std::chrono::milliseconds getBackOffTime(std::chrono::milliseconds prevBackOffTime)
void requestAndDownload(bool isUserInitiated)
#define ACSDK_INFO(entry)
Definition: Logger.h:463
#define METRIC_PREFIX_ERROR(str)
Definition: AmdMetricWrapper.h:25
bool isRelevant()
Definition: DavsHandler.h:77
static std::string parseFileFromLink(const std::string &url, const std::string &defaultValue)
void enableUpdate(bool enable)
Definition: DavsHandler.h:96
bool isUpdateEnabled()
Definition: DavsHandler.h:106
LogEntry is used to compile the log entry text to log via Logger.
Definition: LogEntry.h:33

AlexaClientSDK 3.0.0 - Copyright 2016-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0