llmediadataclient.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /**
  2. * @file llmediadataclient.h
  3. * @brief class for queueing up requests to the media service
  4. *
  5. * $LicenseInfo:firstyear=2010&license=viewergpl$
  6. *
  7. * Copyright (c) 2010, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_LLMEDIADATACLIENT_H
  33. #define LL_LLMEDIADATACLIENT_H
  34. #include <list>
  35. #include <memory>
  36. #include <set>
  37. #include "llcorehttputil.h"
  38. #include "lleventtimer.h"
  39. #include "llhttpsdhandler.h"
  40. #include "llpointer.h"
  41. #include "llrefcount.h"
  42. // Link seam for LLVOVolume
  43. class LLMediaDataClientObject : public LLRefCount
  44. {
  45. public:
  46. // Get the number of media data items
  47. virtual U8 getMediaDataCount() const = 0;
  48. // Get the media data at index, as an LLSD
  49. virtual LLSD getMediaDataLLSD(U8 index) const = 0;
  50. // Return true if the current URL for the face in the media data matches
  51. // the specified URL.
  52. virtual bool isCurrentMediaUrl(U8 index, const std::string& url) const = 0;
  53. // Get this object's UUID
  54. virtual LLUUID getID() const = 0;
  55. // Navigate back to previous URL
  56. virtual void mediaNavigateBounceBack(U8 index) = 0;
  57. // Does this object have media?
  58. virtual bool hasMedia() const = 0;
  59. // Update the object's media data to the given array
  60. virtual void updateObjectMediaData(LLSD const& media_data_array,
  61. const std::string& version_string) = 0;
  62. // Return the total "interest" of the media (on-screen area)
  63. virtual F64 getMediaInterest() const = 0;
  64. // Return the given cap url
  65. virtual const std::string& getCapabilityUrl(const char* name) const = 0;
  66. // Return whether the object has been marked dead
  67. virtual bool isDead() const = 0;
  68. // Returns a media version number for the object
  69. virtual U32 getMediaVersion() const = 0;
  70. // Returns whether the object is "interesting enough" to fetch
  71. virtual bool isInterestingEnough() const = 0;
  72. // Returns whether we've seen this object yet or not
  73. virtual bool isNew() const = 0;
  74. // Smart pointer type
  75. typedef LLPointer<LLMediaDataClientObject> ptr_t;
  76. };
  77. // This class creates a priority queue for requests and abstracts the cap URL,
  78. // the request, and the handler.
  79. class LLMediaDataClient : public LLRefCount
  80. {
  81. friend class PredicateMatchRequest;
  82. protected:
  83. LOG_CLASS(LLMediaDataClient);
  84. public:
  85. static constexpr F32 QUEUE_TIMER_DELAY = 1.f; // Seconds
  86. static constexpr F32 UNAVAILABLE_RETRY_TIMER_DELAY = 5.f; // Seconds
  87. static constexpr U32 MAX_RETRIES = 4;
  88. static constexpr U32 MAX_SORTED_QUEUE_SIZE = 10000;
  89. static constexpr U32 MAX_ROUND_ROBIN_QUEUE_SIZE = 10000;
  90. LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
  91. F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
  92. U32 max_retries = MAX_RETRIES,
  93. U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
  94. U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE);
  95. LL_INLINE F32 getRetryTimerDelay() const { return mRetryTimerDelay; }
  96. // Returns true if the queue is empty
  97. virtual bool isEmpty() const;
  98. // Returns true if the given object is in the queue
  99. virtual bool isInQueue(const LLMediaDataClientObject::ptr_t& object);
  100. // Removes the given object from the queue. Returns true if the given
  101. // object is removed.
  102. virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t& object);
  103. // Called only by the Queue timer and tests (potentially)
  104. virtual bool processQueueTimer();
  105. protected:
  106. ~LLMediaDataClient() override; // Use unref
  107. // Request (pure virtual base class for requests in the queue)
  108. class Request : public std::enable_shared_from_this<Request>
  109. {
  110. public:
  111. typedef std::shared_ptr<Request> ptr_t;
  112. // Subclasses must implement this to build a payload for their request
  113. // type...
  114. virtual LLSD getPayload() const = 0;
  115. // ... and must create the correct type of handler.
  116. virtual LLCore::HttpHandler::ptr_t createHandler() = 0;
  117. LL_INLINE virtual std::string getURL() { return ""; }
  118. enum Type { GET, UPDATE, NAVIGATE, ANY };
  119. virtual ~Request() {}
  120. protected:
  121. // The only way to create one of these is through a subclass.
  122. Request(Type in_type, LLMediaDataClientObject* obj,
  123. LLMediaDataClient* mdc, S32 face = -1);
  124. public:
  125. LL_INLINE LLMediaDataClientObject* getObject() const
  126. {
  127. return mObject;
  128. }
  129. LL_INLINE U32 getNum() const { return mNum; }
  130. LL_INLINE U32 getRetryCount() const { return mRetryCount; }
  131. LL_INLINE void incRetryCount() { ++mRetryCount; }
  132. LL_INLINE Type getType() const { return mType; }
  133. LL_INLINE F64 getScore() const { return mScore; }
  134. // Note: may return an empty string !
  135. const std::string& getCapability() const;
  136. const char* getCapName() const;
  137. const char* getTypeAsString() const;
  138. // Re-enqueue thyself
  139. void reEnqueue();
  140. F32 getRetryTimerDelay() const;
  141. U32 getMaxNumRetries() const;
  142. LL_INLINE bool isObjectValid() const
  143. {
  144. return mObject.notNull() && !mObject->isDead();
  145. }
  146. LL_INLINE bool isNew() const
  147. {
  148. return isObjectValid() && mObject->isNew();
  149. }
  150. void updateScore();
  151. void markDead();
  152. bool isDead();
  153. void startTracking();
  154. void stopTracking();
  155. friend std::ostream& operator<<(std::ostream& s, const Request& q);
  156. LL_INLINE const LLUUID& getID() const { return mObjectID; }
  157. LL_INLINE S32 getFace() const { return mFace; }
  158. LL_INLINE bool isMatch(const Request::ptr_t& other,
  159. Type match_type = ANY) const
  160. {
  161. return (match_type == ANY || mType == other->mType) &&
  162. mFace == other->mFace && mObjectID == other->mObjectID;
  163. }
  164. protected:
  165. LLMediaDataClientObject::ptr_t mObject;
  166. private:
  167. // Back pointer to the MDC...not a ref !
  168. LLMediaDataClient* mMDC;
  169. LLUUID mObjectID;
  170. Type mType;
  171. // Simple tracking
  172. U32 mNum;
  173. U32 mRetryCount;
  174. F64 mScore;
  175. S32 mFace;
  176. static U32 sNum;
  177. };
  178. class Handler : public LLHttpSDHandler
  179. {
  180. protected:
  181. LOG_CLASS(LLMediaDataClient::Handler);
  182. virtual void onSuccess(LLCore::HttpResponse* response,
  183. const LLSD& content);
  184. virtual void onFailure(LLCore::HttpResponse* response,
  185. LLCore::HttpStatus status);
  186. public:
  187. Handler(const Request::ptr_t& request);
  188. LL_INLINE Request::ptr_t getRequest() { return mRequest; }
  189. private:
  190. Request::ptr_t mRequest;
  191. };
  192. class RetryTimer : public LLEventTimer
  193. {
  194. public:
  195. RetryTimer(F32 time, Request::ptr_t);
  196. virtual bool tick();
  197. private:
  198. // Back-pointer
  199. Request::ptr_t mRequest;
  200. };
  201. protected:
  202. typedef std::list<Request::ptr_t> request_queue_t;
  203. typedef std::set<Request::ptr_t> request_set_t;
  204. // Subclasses must override to return a cap name
  205. virtual const char* getCapabilityName() const = 0;
  206. // Puts the request into a queue, appropriately handling duplicates, etc.
  207. virtual void enqueue(Request::ptr_t) = 0;
  208. virtual void serviceQueue();
  209. LL_INLINE virtual void serviceHttp() { mHttpRequest->update(0); }
  210. LL_INLINE virtual request_queue_t* getQueue() { return &mQueue; }
  211. // Gets the next request, removing it from the queue
  212. virtual Request::ptr_t dequeue();
  213. LL_INLINE virtual bool canServiceRequest(Request::ptr_t)
  214. {
  215. return true;
  216. }
  217. // Returns a request to the head of the queue (should only be used for
  218. // requests that came from dequeue
  219. virtual void pushBack(Request::ptr_t request);
  220. void trackRequest(Request::ptr_t request);
  221. void stopTrackingRequest(Request::ptr_t request);
  222. LL_INLINE bool isDoneProcessing() const
  223. {
  224. return isEmpty() && mUnQueuedRequests.empty();
  225. }
  226. void startQueueTimer();
  227. LL_INLINE void stopQueueTimer() { mQueueTimerIsRunning = false; }
  228. private:
  229. static F64 getObjectScore(const LLMediaDataClientObject::ptr_t& obj);
  230. friend std::ostream& operator<<(std::ostream& s, const Request& q);
  231. friend std::ostream& operator<<(std::ostream& s, const request_queue_t& q);
  232. class QueueTimer : public LLEventTimer
  233. {
  234. public:
  235. QueueTimer(F32 time, LLMediaDataClient* mdc);
  236. virtual bool tick();
  237. private:
  238. // back-pointer
  239. LLPointer<LLMediaDataClient> mMDC;
  240. };
  241. LL_INLINE void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
  242. protected:
  243. request_queue_t mQueue;
  244. // Set for keeping track of requests that are not in either queue. This
  245. // includes:
  246. // - Requests that have been sent and are awaiting a response (pointer
  247. // held by the handler)
  248. // - Requests that are waiting for their retry timers to fire (pointer
  249. // held by the retry timer)
  250. request_set_t mUnQueuedRequests;
  251. LLCore::HttpRequest::ptr_t mHttpRequest;
  252. LLCore::HttpHeaders::ptr_t mHttpHeaders;
  253. LLCore::HttpOptions::ptr_t mHttpOpts;
  254. LLCore::HttpRequest::policy_t mHttpPolicy;
  255. const F32 mQueueTimerDelay;
  256. const F32 mRetryTimerDelay;
  257. const U32 mMaxNumRetries;
  258. const U32 mMaxSortedQueueSize;
  259. const U32 mMaxRoundRobinQueueSize;
  260. private:
  261. bool mQueueTimerIsRunning;
  262. };
  263. // MediaDataClient specific for the ObjectMedia cap
  264. class LLObjectMediaDataClient final : public LLMediaDataClient
  265. {
  266. protected:
  267. LOG_CLASS(LLObjectMediaDataClient);
  268. public:
  269. LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
  270. F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
  271. U32 max_retries = MAX_RETRIES,
  272. U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
  273. U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
  274. : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries),
  275. mCurrentQueueIsTheSortedQueue(true)
  276. {
  277. }
  278. void fetchMedia(LLMediaDataClientObject* object);
  279. void updateMedia(LLMediaDataClientObject* object);
  280. class RequestGet final : public Request
  281. {
  282. public:
  283. RequestGet(LLMediaDataClientObject* obj, LLMediaDataClient* mdc);
  284. LLSD getPayload() const override;
  285. LLCore::HttpHandler::ptr_t createHandler() override;
  286. };
  287. class RequestUpdate final : public Request
  288. {
  289. public:
  290. RequestUpdate(LLMediaDataClientObject* obj, LLMediaDataClient* mdc);
  291. LLSD getPayload() const override;
  292. LLCore::HttpHandler::ptr_t createHandler() override;
  293. };
  294. // Returns true if the queue is empty
  295. virtual bool isEmpty() const;
  296. // Returns true if the given object is in the queue
  297. virtual bool isInQueue(const LLMediaDataClientObject::ptr_t& object);
  298. // Removes the given object from the queue. Returns true if the given
  299. // object is removed.
  300. virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t& object);
  301. virtual bool processQueueTimer();
  302. virtual bool canServiceRequest(Request::ptr_t request);
  303. protected:
  304. // Subclasses must override to return a cap name
  305. virtual const char* getCapabilityName() const;
  306. virtual request_queue_t* getQueue();
  307. // Puts the request into the appropriate queue
  308. virtual void enqueue(Request::ptr_t);
  309. class Handler : public LLMediaDataClient::Handler
  310. {
  311. protected:
  312. LOG_CLASS(LLObjectMediaDataClient::Handler);
  313. virtual void onSuccess(LLCore::HttpResponse* response,
  314. const LLSD& content);
  315. public:
  316. Handler(const Request::ptr_t& request)
  317. : LLMediaDataClient::Handler(request)
  318. {
  319. }
  320. };
  321. private:
  322. // The Get/Update data client needs a second queue to avoid object updates
  323. // starving load-ins.
  324. void swapCurrentQueue();
  325. request_queue_t mRoundRobinQueue;
  326. bool mCurrentQueueIsTheSortedQueue;
  327. // Comparator for sorting
  328. static bool compareRequestScores(const Request::ptr_t& o1,
  329. const Request::ptr_t& o2);
  330. void sortQueue();
  331. };
  332. // MediaDataClient specific for the ObjectMediaNavigate cap
  333. class LLObjectMediaNavigateClient final : public LLMediaDataClient
  334. {
  335. protected:
  336. LOG_CLASS(LLObjectMediaNavigateClient);
  337. public:
  338. // NOTE: from llmediaservice.h
  339. static const int ERROR_PERMISSION_DENIED_CODE = 8002;
  340. LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
  341. F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
  342. U32 max_retries = MAX_RETRIES,
  343. U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
  344. U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
  345. : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
  346. {
  347. }
  348. void navigate(LLMediaDataClientObject* object, U8 texture_index,
  349. const std::string& url);
  350. // Puts the request into the appropriate queue
  351. void enqueue(Request::ptr_t req) override;
  352. class RequestNavigate final : public Request
  353. {
  354. public:
  355. RequestNavigate(LLMediaDataClientObject* obj, LLMediaDataClient* mdc,
  356. U8 texture_index, const std::string& url);
  357. LLSD getPayload() const override;
  358. LLCore::HttpHandler::ptr_t createHandler() override;
  359. LL_INLINE std::string getURL() override { return mURL; }
  360. private:
  361. std::string mURL;
  362. };
  363. protected:
  364. // Subclasses must override to return a cap name
  365. const char* getCapabilityName() const override;
  366. class Handler final : public LLMediaDataClient::Handler
  367. {
  368. protected:
  369. LOG_CLASS(LLObjectMediaNavigateClient::Handler);
  370. void onSuccess(LLCore::HttpResponse* response,
  371. const LLSD& content) override;
  372. void onFailure(LLCore::HttpResponse* response,
  373. LLCore::HttpStatus status) override;
  374. public:
  375. Handler(const Request::ptr_t& request)
  376. : LLMediaDataClient::Handler(request)
  377. {
  378. }
  379. private:
  380. void mediaNavigateBounceBack();
  381. };
  382. };
  383. #endif // LL_LLMEDIADATACLIENT_H