PageRenderTime 41ms CodeModel.GetById 2ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llmediadataclient.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 412 lines | 249 code | 83 blank | 80 comment | 9 complexity | 63971ec2a7f2b7dff3801efa2ace8d73 MD5 | raw file
  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