From 2d01d763d558a373b356ea445ddb3801e36ae457 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Thu, 10 Dec 2009 17:03:40 -0800 Subject: PARTIAL DEV-43869 - add "isInterestingEnough()" to the queue calculation This change bumps the queue sizes way up, because we think that the "isInterestingEnough()" call will prevent loading more media data than we think is necessary. Still need to implement it in LLVOVolume, though --- indra/newview/app_settings/settings.xml | 4 +- indra/newview/llmediadataclient.cpp | 124 +++++------ indra/newview/llmediadataclient.h | 10 +- indra/newview/llvovolume.cpp | 5 + indra/newview/tests/llmediadataclient_test.cpp | 285 +++++++++++++++++++------ 5 files changed, 292 insertions(+), 136 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 19efeed7f0..9ef74364ac 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5514,7 +5514,7 @@ Type U32 Value - 120 + 100000 PrimMediaMaxRoundRobinQueueSize @@ -5525,7 +5525,7 @@ Type U32 Value - 15 + 100000 ProbeHardwareOnStartup diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index fe2af36302..0a20a4a1c9 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -5,7 +5,7 @@ * $LicenseInfo:firstyear=2001&license=viewergpl$ * * Copyright (c) 2001-2009, Linden Research, Inc. - * = + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 @@ -61,8 +61,8 @@ const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s) const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs const U32 LLMediaDataClient::MAX_RETRIES = 4; -const U32 LLMediaDataClient::MAX_SORTED_QUEUE_SIZE = 60; -const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 25; +const U32 LLMediaDataClient::MAX_SORTED_QUEUE_SIZE = 10000; +const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000; ////////////////////////////////////////////////////////////////////////////////////// // @@ -273,22 +273,6 @@ bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_p return ( o1->getScore() > o2->getScore() ); } -void LLMediaDataClient::swapCurrentQueue() -{ - // Swap - mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; - // If its empty, swap back - if (getCurrentQueue()->empty()) - { - mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; - } -} - -LLMediaDataClient::request_queue_t *LLMediaDataClient::getCurrentQueue() -{ - return (mCurrentQueueIsTheSortedQueue) ? &mSortedQueue : &mRoundRobinQueue; -} - void LLMediaDataClient::serviceQueue() { request_queue_t *queue_p = getCurrentQueue(); @@ -306,60 +290,64 @@ void LLMediaDataClient::serviceQueue() request_ptr_t request = queue_p->front(); llassert(!request.isNull()); const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject(); - bool performed_request = false; - bool error = false; llassert(NULL != object); - if(request->isMarkedSent()) + // Check for conditions that would make us just pop and rapidly loop through + // the queue. + if(request.isNull() || + request->isMarkedSent() || + NULL == object || + object->isDead() || + !object->hasMedia()) { - // This object has been sent and not re-requested. Skip it. - LL_INFOS("LLMediaDataClient") << "Skipping " << *request << ": object is marked sent!" << LL_ENDL; + if (request.isNull()) + { + LL_INFOS("LLMediaDataClient") << "Skipping NULL request" << LL_ENDL; + } + else { + LL_INFOS("LLMediaDataClient") << "Skipping : " << *request << " " + << ((request->isMarkedSent()) ? " request is marked sent" : + ((NULL == object) ? " object is NULL " : + ((object->isDead()) ? "object is dead" : + ((!object->hasMedia()) ? "object has no media!" : "BADNESS!")))) << LL_ENDL; + } queue_p->pop_front(); continue; // jump back to the start of the quick retry loop } - if(object->isDead()) + // Next, ask if this is "interesting enough" to fetch. If not, just stop + // and wait for the next timer go-round. Only do this for the sorted + // queue. + if (mCurrentQueueIsTheSortedQueue && !object->isInterestingEnough()) { - // This object has been marked dead. Pop it and move on to the next item in the queue immediately. - LL_INFOS("LLMediaDataClient") << "Skipping " << *request << ": object is dead!" << LL_ENDL; - queue_p->pop_front(); - continue; // jump back to the start of the quick retry loop + LL_DEBUGS("LLMediaDataClient") << "Not fetching " << *request << ": not interesting enough" << LL_ENDL; + break; } - if (NULL != object && object->hasMedia()) + // Finally, try to send the HTTP message to the cap url + std::string url = request->getCapability(); + bool maybe_retry = false; + if (!url.empty()) { - std::string url = request->getCapability(); - if (!url.empty()) - { - const LLSD &sd_payload = request->getPayload(); - LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL; - - // Call the subclass for creating the responder - LLHTTPClient::post(url, sd_payload, createResponder(request)); - performed_request = true; - } - else { - LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL; - } + const LLSD &sd_payload = request->getPayload(); + LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL; + + // Call the subclass for creating the responder + LLHTTPClient::post(url, sd_payload, createResponder(request)); } else { - if (request.isNull()) - { - LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL; - } - else if (NULL == object) - { - LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL; - } - else if (!object->hasMedia()) - { - LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL; - } - error = true; + LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL; + maybe_retry = true; } + bool exceeded_retries = request->getRetryCount() > mMaxNumRetries; - if (performed_request || exceeded_retries || error) // Try N times before giving up + if (maybe_retry && ! exceeded_retries) // Try N times before giving up { + // We got an empty cap, but in that case we will retry again next + // timer fire. + request->incRetryCount(); + } + else { if (exceeded_retries) { LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " @@ -374,19 +362,31 @@ void LLMediaDataClient::serviceQueue() request->markSent(true); mRoundRobinQueue.push_back(request); } - if (error) continue; - } - else { - request->incRetryCount(); } - // end of quick retry loop -- any cases where we want to loop will use 'continue' to jump back to the start. + // end of quick loop -- any cases where we want to loop will use 'continue' to jump back to the start. break; } swapCurrentQueue(); } +void LLMediaDataClient::swapCurrentQueue() +{ + // Swap + mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; + // If its empty, swap back + if (getCurrentQueue()->empty()) + { + mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue; + } +} + +LLMediaDataClient::request_queue_t *LLMediaDataClient::getCurrentQueue() +{ + return (mCurrentQueueIsTheSortedQueue) ? &mSortedQueue : &mRoundRobinQueue; +} + // dump the queue std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q) { diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h index ffb8a4632b..75d32e707b 100755 --- a/indra/newview/llmediadataclient.h +++ b/indra/newview/llmediadataclient.h @@ -64,6 +64,8 @@ public: 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; @@ -81,8 +83,8 @@ public: 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;// = 60; - const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 25; + 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, @@ -274,7 +276,7 @@ public: U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE) : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries) {} - ~LLObjectMediaDataClient() {} + virtual ~LLObjectMediaDataClient() {} void fetchMedia(LLMediaDataClientObject *object); void updateMedia(LLMediaDataClientObject *object); @@ -310,7 +312,7 @@ public: U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE) : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries) {} - ~LLObjectMediaNavigateClient() {} + virtual ~LLObjectMediaNavigateClient() {} void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index ffadece615..b92d024ac9 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -136,6 +136,11 @@ public: F64 tmp = mObject->getTotalMediaInterest(); return (tmp < 0.0) ? mObject->getPixelArea() : tmp; } + virtual bool isInterestingEnough() const + { + // TODO: use performance manager to control this + return true; + } virtual std::string getCapabilityUrl(const std::string &name) const { return mObject->getRegion()->getCapability(name); } diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp index a8e199e993..33d413bd21 100644 --- a/indra/newview/tests/llmediadataclient_test.cpp +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -110,6 +110,7 @@ const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true"); "================================================================================\n" << LL_ENDL; LLSD *gPostRecords = NULL; +F64 gMinimumInterestLevel = (F64)0.0; // stubs: void LLHTTPClient::post( @@ -179,7 +180,10 @@ public: virtual F64 getMediaInterest() const { return (LLSD::Real)mRep["interest"]; } - + + virtual bool isInterestingEnough() const + { return getMediaInterest() > gMinimumInterestLevel; } + virtual std::string getCapabilityUrl(const std::string &name) const { return mRep["cap_urls"][name]; } @@ -225,10 +229,11 @@ namespace tut { mediadataclient() { gPostRecords = &mLLSD; + gMinimumInterestLevel = (F64)0.0; - LLError::setDefaultLevel(LLError::LEVEL_DEBUG); - LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); - LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG); +// LLError::setDefaultLevel(LLError::LEVEL_DEBUG); +// LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); +// LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG); } LLSD mLLSD; }; @@ -630,52 +635,52 @@ namespace tut mdc->fetchMedia(o3); mdc->fetchMedia(o4); - int test_num = 0; + int tick_num = 0; - ensure(STR(test_num) + ". is in queue 1", mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 0); + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); ::pump_timers(); - ++test_num; + ++tick_num; // The first tick should remove the first one - ensure(STR(test_num) + ". is not in queue 1", !mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 1); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); // Now, pretend that object 4 moved relative to the avatar such // that it is now closest object4->setMediaInterest(50.0); ::pump_timers(); - ++test_num; + ++tick_num; // The second tick should still pick off item 2, but then re-sort // have picked off object 4 - ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is not in queue 4", !mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 2); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); ::pump_timers(); - ++test_num; + ++tick_num; // The third tick should pick off object 2 - ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 3); + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); // The fourth tick should pick off object 3 ::pump_timers(); - ++test_num; + ++tick_num; - ensure(STR(test_num) + ". is not in queue 3", !mdc->isInQueue(o3)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 4); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); ensure("queue empty", mdc->isEmpty()); } @@ -710,71 +715,71 @@ namespace tut mdc->fetchMedia(o3); mdc->fetchMedia(o4); - int test_num = 0; + int tick_num = 0; // 0 - ensure(STR(test_num) + ". is in queue 1", mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 0); + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); ::pump_timers(); - ++test_num; + ++tick_num; // 1 The first tick should remove object 2 - ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 1", mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 1); - ensure(STR(test_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2)); + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2)); ::pump_timers(); - ++test_num; + ++tick_num; // 2 The second tick should send object 4, but it will still be // "in the queue" - ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is in queue 1", mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 2); - ensure(STR(test_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); ::pump_timers(); - ++test_num; + ++tick_num; // 3 The third tick should remove object 1 - ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is not in queue 1", !mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 3); - ensure(STR(test_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); ::pump_timers(); - ++test_num; + ++tick_num; // 4 The fourth tick should send object 3, but it will still be // "in the queue" - ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is not in queue 1", !mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 4); - ensure(STR(test_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); ::pump_timers(); - ++test_num; + ++tick_num; // 5 The fifth tick should now identify objects 3 and 4 as no longer // needing "updating", and remove them from the queue - ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2)); - ensure(STR(test_num) + ". is not in queue 1", !mdc->isInQueue(o1)); - ensure(STR(test_num) + ". is not in queue 3", !mdc->isInQueue(o3)); - ensure(STR(test_num) + ". is not in queue 4", !mdc->isInQueue(o4)); - ensure(STR(test_num) + ". post records", gPostRecords->size(), 4); + ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4); ::pump_timers(); @@ -786,4 +791,148 @@ namespace tut ensure("refcount of o3", o3->getNumRefs(), 1); ensure("refcount of o4", o4->getNumRefs(), 1); } + + + template<> template<> + void mediadataclient_object_t::test<11>() + { + // + // Test LLMediaDataClient's destructor + // + LOG_TEST(11); + + LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); + int num_refs_start = o->getNumRefs(); + { + LLPointer mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + mdc->fetchMedia(o); + // must tick enough times to clear refcount of mdc + ::pump_timers(); + } + // Make sure everyone's destroyed properly + ensure("REF COUNT", o->getNumRefs(), num_refs_start); + } + + template<> template<> + void mediadataclient_object_t::test<12>() + { + // + // Test the "not interesting enough" call + // + LOG_TEST(12); + + LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true")); + LLMediaDataClientObject::ptr_t o1 = object1; + LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true")); + LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true")); + LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true")); + { + LLPointer mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + + // queue up all 4 objects. The first two are "interesting enough". + // Firing the timer 4 times should therefore leave them. + // Note that they should be sorted 4,3,2,1 + // Then, we'll make one "interesting enough", fire the timer a few + // times, and make sure only it gets pulled off the queue + gMinimumInterestLevel = 2.5; + mdc->fetchMedia(o1); + mdc->fetchMedia(o2); + mdc->fetchMedia(o3); + mdc->fetchMedia(o4); + + int tick_num = 0; + + // 0 + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0); + + ::pump_timers(); + ++tick_num; + + // 1 The first tick should remove object 4 + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4)); + + ::pump_timers(); + ++tick_num; + + // 2 The second tick should send object 3 + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3)); + + ::pump_timers(); + ++tick_num; + + // 3 The third tick should not pull off anything + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + + ::pump_timers(); + ++tick_num; + + // 4 The fourth tick (for good measure) should not pull off anything + ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2); + + // Okay, now futz with object 1's interest, such that it is now + // "interesting enough" + object1->setMediaInterest((F64)5.0); + + // This should sort so that the queue is now [1 2] + ::pump_timers(); + ++tick_num; + + // 5 The fifth tick should now identify objects 3 and 4 as no longer + // needing "updating", and remove them from the queue + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); + ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1)); + + ::pump_timers(); + ++tick_num; + + // 6 The sixth tick should not pull off anything + ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1)); + ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2)); + ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3)); + ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4)); + ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3); + + ::pump_timers(); + ++tick_num; + + // Whew....better NOT be empty ... o2 should still be there + ensure("queue not empty", !mdc->isEmpty()); + + // But, we need to clear the queue, or else we won't destroy MDC... + // this is a strange interplay between the queue timer and the MDC + ensure("o2 couldn't be removed from queue", mdc->removeFromQueue(o2)); + // tick + ::pump_timers(); + } + ensure("refcount of o1", o1->getNumRefs(), 1); + ensure("refcount of o2", o2->getNumRefs(), 1); + ensure("refcount of o3", o3->getNumRefs(), 1); + ensure("refcount of o4", o4->getNumRefs(), 1); + } } -- cgit v1.2.3