summaryrefslogtreecommitdiff
path: root/indra/newview/llmediadataclient.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmediadataclient.h')
-rw-r--r--indra/newview/llmediadataclient.h412
1 files changed, 412 insertions, 0 deletions
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
new file mode 100644
index 0000000000..ab90915c55
--- /dev/null
+++ b/indra/newview/llmediadataclient.h
@@ -0,0 +1,412 @@
+/**
+ * @file llmediadataclient.h
+ * @brief class for queueing up requests to the media service
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMEDIADATACLIENT_H
+#define LL_LLMEDIADATACLIENT_H
+
+#include "llhttpclient.h"
+#include <set>
+#include "llrefcount.h"
+#include "llpointer.h"
+#include "lleventtimer.h"
+
+
+// Link seam for LLVOVolume
+class LLMediaDataClientObject : public LLRefCount
+{
+public:
+ // Get the number of media data items
+ virtual U8 getMediaDataCount() const = 0;
+ // Get the media data at index, as an LLSD
+ virtual LLSD getMediaDataLLSD(U8 index) const = 0;
+ // Return true if the current URL for the face in the media data matches the specified URL.
+ virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const = 0;
+ // Get this object's UUID
+ virtual LLUUID getID() const = 0;
+ // Navigate back to previous URL
+ virtual void mediaNavigateBounceBack(U8 index) = 0;
+ // Does this object have media?
+ virtual bool hasMedia() const = 0;
+ // Update the object's media data to the given array
+ virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0;
+ // Return the total "interest" of the media (on-screen area)
+ virtual F64 getMediaInterest() const = 0;
+ // Return the given cap url
+ virtual std::string getCapabilityUrl(const std::string &name) const = 0;
+ // Return whether the object has been marked dead
+ virtual bool isDead() const = 0;
+ // Returns a media version number for the object
+ virtual U32 getMediaVersion() const = 0;
+ // Returns whether the object is "interesting enough" to fetch
+ virtual bool isInterestingEnough() const = 0;
+ // Returns whether we've seen this object yet or not
+ virtual bool isNew() const = 0;
+
+ // smart pointer
+ typedef LLPointer<LLMediaDataClientObject> ptr_t;
+};
+
+
+// This object creates a priority queue for requests.
+// Abstracts the Cap URL, the request, and the responder
+class LLMediaDataClient : public LLRefCount
+{
+public:
+ LOG_CLASS(LLMediaDataClient);
+
+ const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
+ const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
+ const static U32 MAX_RETRIES;// = 4;
+ const static U32 MAX_SORTED_QUEUE_SIZE;// = 10000;
+ const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000;
+
+ // Constructor
+ LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES,
+ U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+ U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE);
+
+ F32 getRetryTimerDelay() const { return mRetryTimerDelay; }
+
+ // Returns true iff the queue is empty
+ virtual bool isEmpty() const;
+
+ // Returns true iff the given object is in the queue
+ virtual bool isInQueue(const LLMediaDataClientObject::ptr_t &object);
+
+ // Remove the given object from the queue. Returns true iff the given object is removed.
+ virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t &object);
+
+ // Called only by the Queue timer and tests (potentially)
+ virtual bool processQueueTimer();
+
+protected:
+ // Destructor
+ virtual ~LLMediaDataClient(); // use unref
+
+ class Responder;
+
+ // Request (pure virtual base class for requests in the queue)
+ class Request : public LLRefCount
+ {
+ public:
+ // Subclasses must implement this to build a payload for their request type.
+ virtual LLSD getPayload() const = 0;
+ // and must create the correct type of responder.
+ virtual Responder *createResponder() = 0;
+
+ virtual std::string getURL() { return ""; }
+
+ enum Type {
+ GET,
+ UPDATE,
+ NAVIGATE,
+ ANY
+ };
+
+ protected:
+ // The only way to create one of these is through a subclass.
+ Request(Type in_type, LLMediaDataClientObject *obj, LLMediaDataClient *mdc, S32 face = -1);
+ public:
+ LLMediaDataClientObject *getObject() const { return mObject; }
+
+ U32 getNum() const { return mNum; }
+ U32 getRetryCount() const { return mRetryCount; }
+ void incRetryCount() { mRetryCount++; }
+ Type getType() const { return mType; }
+ F64 getScore() const { return mScore; }
+
+ // Note: may return empty string!
+ std::string getCapability() const;
+ const char *getCapName() const;
+ const char *getTypeAsString() const;
+
+ // Re-enqueue thyself
+ void reEnqueue();
+
+ F32 getRetryTimerDelay() const;
+ U32 getMaxNumRetries() const;
+
+ bool isObjectValid() const { return mObject.notNull() && (!mObject->isDead()); }
+ bool isNew() const { return isObjectValid() && mObject->isNew(); }
+ void updateScore();
+
+ void markDead();
+ bool isDead();
+ void startTracking();
+ void stopTracking();
+
+ friend std::ostream& operator<<(std::ostream &s, const Request &q);
+
+ const LLUUID &getID() const { return mObjectID; }
+ S32 getFace() const { return mFace; }
+
+ bool isMatch (const Request* other, Type match_type = ANY) const
+ {
+ return ((match_type == ANY) || (mType == other->mType)) &&
+ (mFace == other->mFace) &&
+ (mObjectID == other->mObjectID);
+ }
+ protected:
+ LLMediaDataClientObject::ptr_t mObject;
+ private:
+ Type mType;
+ // Simple tracking
+ U32 mNum;
+ static U32 sNum;
+ U32 mRetryCount;
+ F64 mScore;
+
+ LLUUID mObjectID;
+ S32 mFace;
+
+ // Back pointer to the MDC...not a ref!
+ LLMediaDataClient *mMDC;
+ };
+ typedef LLPointer<Request> request_ptr_t;
+
+ // Responder
+ class Responder : public LLHTTPClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request);
+ //If we get back an error (not found, etc...), handle it here
+ virtual void error(U32 status, const std::string& reason);
+ //If we get back a normal response, handle it here. Default just logs it.
+ virtual void result(const LLSD& content);
+
+ request_ptr_t &getRequest() { return mRequest; }
+
+ private:
+ request_ptr_t mRequest;
+ };
+
+ class RetryTimer : public LLEventTimer
+ {
+ public:
+ RetryTimer(F32 time, request_ptr_t);
+ virtual BOOL tick();
+ private:
+ // back-pointer
+ request_ptr_t mRequest;
+ };
+
+
+protected:
+ typedef std::list<request_ptr_t> request_queue_t;
+ typedef std::set<request_ptr_t> request_set_t;
+
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const = 0;
+
+ // Puts the request into a queue, appropriately handling duplicates, etc.
+ virtual void enqueue(Request*) = 0;
+
+ virtual void serviceQueue();
+
+ virtual request_queue_t *getQueue() { return &mQueue; };
+
+ // Gets the next request, removing it from the queue
+ virtual request_ptr_t dequeue();
+
+ virtual bool canServiceRequest(request_ptr_t request) { return true; };
+
+ // Returns a request to the head of the queue (should only be used for requests that came from dequeue
+ virtual void pushBack(request_ptr_t request);
+
+ void trackRequest(request_ptr_t request);
+ void stopTrackingRequest(request_ptr_t request);
+
+ request_queue_t mQueue;
+
+ const F32 mQueueTimerDelay;
+ const F32 mRetryTimerDelay;
+ const U32 mMaxNumRetries;
+ const U32 mMaxSortedQueueSize;
+ const U32 mMaxRoundRobinQueueSize;
+
+ // Set for keeping track of requests that aren't in either queue. This includes:
+ // Requests that have been sent and are awaiting a response (pointer held by the Responder)
+ // Requests that are waiting for their retry timers to fire (pointer held by the retry timer)
+ request_set_t mUnQueuedRequests;
+
+ void startQueueTimer();
+ void stopQueueTimer();
+
+private:
+
+ static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj);
+
+ friend std::ostream& operator<<(std::ostream &s, const Request &q);
+ friend std::ostream& operator<<(std::ostream &s, const request_queue_t &q);
+
+ class QueueTimer : public LLEventTimer
+ {
+ public:
+ QueueTimer(F32 time, LLMediaDataClient *mdc);
+ virtual BOOL tick();
+ private:
+ // back-pointer
+ LLPointer<LLMediaDataClient> mMDC;
+ };
+
+ void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
+
+ bool mQueueTimerIsRunning;
+
+ template <typename T> friend typename T::iterator find_matching_request(T &c, const LLMediaDataClient::Request *request, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY);
+ template <typename T> friend typename T::iterator find_matching_request(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY);
+ template <typename T> friend void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY);
+
+};
+
+// MediaDataClient specific for the ObjectMedia cap
+class LLObjectMediaDataClient : public LLMediaDataClient
+{
+public:
+ LOG_CLASS(LLObjectMediaDataClient);
+ LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES,
+ U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+ U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries),
+ mCurrentQueueIsTheSortedQueue(true)
+ {}
+
+ void fetchMedia(LLMediaDataClientObject *object);
+ void updateMedia(LLMediaDataClientObject *object);
+
+ class RequestGet: public Request
+ {
+ public:
+ RequestGet(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
+ /*virtual*/ LLSD getPayload() const;
+ /*virtual*/ Responder *createResponder();
+ };
+
+ class RequestUpdate: public Request
+ {
+ public:
+ RequestUpdate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
+ /*virtual*/ LLSD getPayload() const;
+ /*virtual*/ Responder *createResponder();
+ };
+
+ // Returns true iff the queue is empty
+ virtual bool isEmpty() const;
+
+ // Returns true iff the given object is in the queue
+ virtual bool isInQueue(const LLMediaDataClientObject::ptr_t &object);
+
+ // Remove the given object from the queue. Returns true iff the given object is removed.
+ virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t &object);
+
+ virtual bool processQueueTimer();
+
+ virtual bool canServiceRequest(request_ptr_t request);
+
+protected:
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const;
+
+ virtual request_queue_t *getQueue();
+
+ // Puts the request into the appropriate queue
+ virtual void enqueue(Request*);
+
+ class Responder : public LLMediaDataClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request)
+ : LLMediaDataClient::Responder(request) {}
+ virtual void result(const LLSD &content);
+ };
+private:
+ // The Get/Update data client needs a second queue to avoid object updates starving load-ins.
+ void swapCurrentQueue();
+
+ request_queue_t mRoundRobinQueue;
+ bool mCurrentQueueIsTheSortedQueue;
+
+ // Comparator for sorting
+ static bool compareRequestScores(const request_ptr_t &o1, const request_ptr_t &o2);
+ void sortQueue();
+};
+
+
+// MediaDataClient specific for the ObjectMediaNavigate cap
+class LLObjectMediaNavigateClient : public LLMediaDataClient
+{
+public:
+ LOG_CLASS(LLObjectMediaNavigateClient);
+ // NOTE: from llmediaservice.h
+ static const int ERROR_PERMISSION_DENIED_CODE = 8002;
+
+ LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES,
+ U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+ U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+ {}
+
+ void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
+
+ // Puts the request into the appropriate queue
+ virtual void enqueue(Request*);
+
+ class RequestNavigate: public Request
+ {
+ public:
+ RequestNavigate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc, U8 texture_index, const std::string &url);
+ /*virtual*/ LLSD getPayload() const;
+ /*virtual*/ Responder *createResponder();
+ /*virtual*/ std::string getURL() { return mURL; }
+ private:
+ std::string mURL;
+ };
+
+protected:
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const;
+
+ class Responder : public LLMediaDataClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request)
+ : LLMediaDataClient::Responder(request) {}
+ virtual void error(U32 status, const std::string& reason);
+ virtual void result(const LLSD &content);
+ private:
+ void mediaNavigateBounceBack();
+ };
+
+};
+
+
+#endif // LL_LLMEDIADATACLIENT_H