/indra/newview/llmediadataclient.h
C Header | 412 lines | 249 code | 83 blank | 80 comment | 9 complexity | 63971ec2a7f2b7dff3801efa2ace8d73 MD5 | raw file
Possible License(s): LGPL-2.1
1/** 2 * @file llmediadataclient.h 3 * @brief class for queueing up requests to the media service 4 * 5 * $LicenseInfo:firstyear=2007&license=viewerlgpl$ 6 * Second Life Viewer Source Code 7 * Copyright (C) 2010, Linden Research, Inc. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; 12 * version 2.1 of the License only. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA 24 * $/LicenseInfo$ 25 */ 26 27#ifndef LL_LLMEDIADATACLIENT_H 28#define LL_LLMEDIADATACLIENT_H 29 30#include "llhttpclient.h" 31#include <set> 32#include "llrefcount.h" 33#include "llpointer.h" 34#include "lleventtimer.h" 35 36 37// Link seam for LLVOVolume 38class LLMediaDataClientObject : public LLRefCount 39{ 40public: 41 // Get the number of media data items 42 virtual U8 getMediaDataCount() const = 0; 43 // Get the media data at index, as an LLSD 44 virtual LLSD getMediaDataLLSD(U8 index) const = 0; 45 // Return true if the current URL for the face in the media data matches the specified URL. 46 virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const = 0; 47 // Get this object's UUID 48 virtual LLUUID getID() const = 0; 49 // Navigate back to previous URL 50 virtual void mediaNavigateBounceBack(U8 index) = 0; 51 // Does this object have media? 52 virtual bool hasMedia() const = 0; 53 // Update the object's media data to the given array 54 virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0; 55 // Return the total "interest" of the media (on-screen area) 56 virtual F64 getMediaInterest() const = 0; 57 // Return the given cap url 58 virtual std::string getCapabilityUrl(const std::string &name) const = 0; 59 // Return whether the object has been marked dead 60 virtual bool isDead() const = 0; 61 // Returns a media version number for the object 62 virtual U32 getMediaVersion() const = 0; 63 // Returns whether the object is "interesting enough" to fetch 64 virtual bool isInterestingEnough() const = 0; 65 // Returns whether we've seen this object yet or not 66 virtual bool isNew() const = 0; 67 68 // smart pointer 69 typedef LLPointer<LLMediaDataClientObject> ptr_t; 70}; 71 72 73// This object creates a priority queue for requests. 74// Abstracts the Cap URL, the request, and the responder 75class LLMediaDataClient : public LLRefCount 76{ 77public: 78 LOG_CLASS(LLMediaDataClient); 79 80 const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s) 81 const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs 82 const static U32 MAX_RETRIES;// = 4; 83 const static U32 MAX_SORTED_QUEUE_SIZE;// = 10000; 84 const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000; 85 86 // Constructor 87 LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, 88 F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, 89 U32 max_retries = MAX_RETRIES, 90 U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, 91 U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE); 92 93 F32 getRetryTimerDelay() const { return mRetryTimerDelay; } 94 95 // Returns true iff the queue is empty 96 virtual bool isEmpty() const; 97 98 // Returns true iff the given object is in the queue 99 virtual bool isInQueue(const LLMediaDataClientObject::ptr_t &object); 100 101 // Remove the given object from the queue. Returns true iff the given object is removed. 102 virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t &object); 103 104 // Called only by the Queue timer and tests (potentially) 105 virtual bool processQueueTimer(); 106 107protected: 108 // Destructor 109 virtual ~LLMediaDataClient(); // use unref 110 111 class Responder; 112 113 // Request (pure virtual base class for requests in the queue) 114 class Request : public LLRefCount 115 { 116 public: 117 // Subclasses must implement this to build a payload for their request type. 118 virtual LLSD getPayload() const = 0; 119 // and must create the correct type of responder. 120 virtual Responder *createResponder() = 0; 121 122 virtual std::string getURL() { return ""; } 123 124 enum Type { 125 GET, 126 UPDATE, 127 NAVIGATE, 128 ANY 129 }; 130 131 protected: 132 // The only way to create one of these is through a subclass. 133 Request(Type in_type, LLMediaDataClientObject *obj, LLMediaDataClient *mdc, S32 face = -1); 134 public: 135 LLMediaDataClientObject *getObject() const { return mObject; } 136 137 U32 getNum() const { return mNum; } 138 U32 getRetryCount() const { return mRetryCount; } 139 void incRetryCount() { mRetryCount++; } 140 Type getType() const { return mType; } 141 F64 getScore() const { return mScore; } 142 143 // Note: may return empty string! 144 std::string getCapability() const; 145 const char *getCapName() const; 146 const char *getTypeAsString() const; 147 148 // Re-enqueue thyself 149 void reEnqueue(); 150 151 F32 getRetryTimerDelay() const; 152 U32 getMaxNumRetries() const; 153 154 bool isObjectValid() const { return mObject.notNull() && (!mObject->isDead()); } 155 bool isNew() const { return isObjectValid() && mObject->isNew(); } 156 void updateScore(); 157 158 void markDead(); 159 bool isDead(); 160 void startTracking(); 161 void stopTracking(); 162 163 friend std::ostream& operator<<(std::ostream &s, const Request &q); 164 165 const LLUUID &getID() const { return mObjectID; } 166 S32 getFace() const { return mFace; } 167 168 bool isMatch (const Request* other, Type match_type = ANY) const 169 { 170 return ((match_type == ANY) || (mType == other->mType)) && 171 (mFace == other->mFace) && 172 (mObjectID == other->mObjectID); 173 } 174 protected: 175 LLMediaDataClientObject::ptr_t mObject; 176 private: 177 Type mType; 178 // Simple tracking 179 U32 mNum; 180 static U32 sNum; 181 U32 mRetryCount; 182 F64 mScore; 183 184 LLUUID mObjectID; 185 S32 mFace; 186 187 // Back pointer to the MDC...not a ref! 188 LLMediaDataClient *mMDC; 189 }; 190 typedef LLPointer<Request> request_ptr_t; 191 192 // Responder 193 class Responder : public LLHTTPClient::Responder 194 { 195 public: 196 Responder(const request_ptr_t &request); 197 //If we get back an error (not found, etc...), handle it here 198 virtual void error(U32 status, const std::string& reason); 199 //If we get back a normal response, handle it here. Default just logs it. 200 virtual void result(const LLSD& content); 201 202 request_ptr_t &getRequest() { return mRequest; } 203 204 private: 205 request_ptr_t mRequest; 206 }; 207 208 class RetryTimer : public LLEventTimer 209 { 210 public: 211 RetryTimer(F32 time, request_ptr_t); 212 virtual BOOL tick(); 213 private: 214 // back-pointer 215 request_ptr_t mRequest; 216 }; 217 218 219protected: 220 typedef std::list<request_ptr_t> request_queue_t; 221 typedef std::set<request_ptr_t> request_set_t; 222 223 // Subclasses must override to return a cap name 224 virtual const char *getCapabilityName() const = 0; 225 226 // Puts the request into a queue, appropriately handling duplicates, etc. 227 virtual void enqueue(Request*) = 0; 228 229 virtual void serviceQueue(); 230 231 virtual request_queue_t *getQueue() { return &mQueue; }; 232 233 // Gets the next request, removing it from the queue 234 virtual request_ptr_t dequeue(); 235 236 virtual bool canServiceRequest(request_ptr_t request) { return true; }; 237 238 // Returns a request to the head of the queue (should only be used for requests that came from dequeue 239 virtual void pushBack(request_ptr_t request); 240 241 void trackRequest(request_ptr_t request); 242 void stopTrackingRequest(request_ptr_t request); 243 244 request_queue_t mQueue; 245 246 const F32 mQueueTimerDelay; 247 const F32 mRetryTimerDelay; 248 const U32 mMaxNumRetries; 249 const U32 mMaxSortedQueueSize; 250 const U32 mMaxRoundRobinQueueSize; 251 252 // Set for keeping track of requests that aren't in either queue. This includes: 253 // Requests that have been sent and are awaiting a response (pointer held by the Responder) 254 // Requests that are waiting for their retry timers to fire (pointer held by the retry timer) 255 request_set_t mUnQueuedRequests; 256 257 void startQueueTimer(); 258 void stopQueueTimer(); 259 260private: 261 262 static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj); 263 264 friend std::ostream& operator<<(std::ostream &s, const Request &q); 265 friend std::ostream& operator<<(std::ostream &s, const request_queue_t &q); 266 267 class QueueTimer : public LLEventTimer 268 { 269 public: 270 QueueTimer(F32 time, LLMediaDataClient *mdc); 271 virtual BOOL tick(); 272 private: 273 // back-pointer 274 LLPointer<LLMediaDataClient> mMDC; 275 }; 276 277 void setIsRunning(bool val) { mQueueTimerIsRunning = val; } 278 279 bool mQueueTimerIsRunning; 280 281 template <typename T> friend typename T::iterator find_matching_request(T &c, const LLMediaDataClient::Request *request, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY); 282 template <typename T> friend typename T::iterator find_matching_request(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY); 283 template <typename T> friend void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY); 284 285}; 286 287// MediaDataClient specific for the ObjectMedia cap 288class LLObjectMediaDataClient : public LLMediaDataClient 289{ 290public: 291 LOG_CLASS(LLObjectMediaDataClient); 292 LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, 293 F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, 294 U32 max_retries = MAX_RETRIES, 295 U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, 296 U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE) 297 : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries), 298 mCurrentQueueIsTheSortedQueue(true) 299 {} 300 301 void fetchMedia(LLMediaDataClientObject *object); 302 void updateMedia(LLMediaDataClientObject *object); 303 304 class RequestGet: public Request 305 { 306 public: 307 RequestGet(LLMediaDataClientObject *obj, LLMediaDataClient *mdc); 308 /*virtual*/ LLSD getPayload() const; 309 /*virtual*/ Responder *createResponder(); 310 }; 311 312 class RequestUpdate: public Request 313 { 314 public: 315 RequestUpdate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc); 316 /*virtual*/ LLSD getPayload() const; 317 /*virtual*/ Responder *createResponder(); 318 }; 319 320 // Returns true iff the queue is empty 321 virtual bool isEmpty() const; 322 323 // Returns true iff the given object is in the queue 324 virtual bool isInQueue(const LLMediaDataClientObject::ptr_t &object); 325 326 // Remove the given object from the queue. Returns true iff the given object is removed. 327 virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t &object); 328 329 virtual bool processQueueTimer(); 330 331 virtual bool canServiceRequest(request_ptr_t request); 332 333protected: 334 // Subclasses must override to return a cap name 335 virtual const char *getCapabilityName() const; 336 337 virtual request_queue_t *getQueue(); 338 339 // Puts the request into the appropriate queue 340 virtual void enqueue(Request*); 341 342 class Responder : public LLMediaDataClient::Responder 343 { 344 public: 345 Responder(const request_ptr_t &request) 346 : LLMediaDataClient::Responder(request) {} 347 virtual void result(const LLSD &content); 348 }; 349private: 350 // The Get/Update data client needs a second queue to avoid object updates starving load-ins. 351 void swapCurrentQueue(); 352 353 request_queue_t mRoundRobinQueue; 354 bool mCurrentQueueIsTheSortedQueue; 355 356 // Comparator for sorting 357 static bool compareRequestScores(const request_ptr_t &o1, const request_ptr_t &o2); 358 void sortQueue(); 359}; 360 361 362// MediaDataClient specific for the ObjectMediaNavigate cap 363class LLObjectMediaNavigateClient : public LLMediaDataClient 364{ 365public: 366 LOG_CLASS(LLObjectMediaNavigateClient); 367 // NOTE: from llmediaservice.h 368 static const int ERROR_PERMISSION_DENIED_CODE = 8002; 369 370 LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, 371 F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, 372 U32 max_retries = MAX_RETRIES, 373 U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE, 374 U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE) 375 : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries) 376 {} 377 378 void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url); 379 380 // Puts the request into the appropriate queue 381 virtual void enqueue(Request*); 382 383 class RequestNavigate: public Request 384 { 385 public: 386 RequestNavigate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc, U8 texture_index, const std::string &url); 387 /*virtual*/ LLSD getPayload() const; 388 /*virtual*/ Responder *createResponder(); 389 /*virtual*/ std::string getURL() { return mURL; } 390 private: 391 std::string mURL; 392 }; 393 394protected: 395 // Subclasses must override to return a cap name 396 virtual const char *getCapabilityName() const; 397 398 class Responder : public LLMediaDataClient::Responder 399 { 400 public: 401 Responder(const request_ptr_t &request) 402 : LLMediaDataClient::Responder(request) {} 403 virtual void error(U32 status, const std::string& reason); 404 virtual void result(const LLSD &content); 405 private: 406 void mediaNavigateBounceBack(); 407 }; 408 409}; 410 411 412#endif // LL_LLMEDIADATACLIENT_H