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
master
Rick Pasetto 2009-12-10 17:03:40 -08:00
parent 248427b8f9
commit 2d01d763d5
5 changed files with 299 additions and 143 deletions

View File

@ -5514,7 +5514,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>120</integer>
<integer>100000</integer>
</map>
<key>PrimMediaMaxRoundRobinQueueSize</key>
<map>
@ -5525,7 +5525,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>15</integer>
<integer>100000</integer>
</map>
<key>ProbeHardwareOnStartup</key>
<map>

View File

@ -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;
queue_p->pop_front();
continue; // jump back to the start of the quick retry loop
}
if(object->isDead())
{
// 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
}
if (NULL != object && object->hasMedia())
{
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;
}
}
else {
if (request.isNull())
{
LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL;
LL_INFOS("LLMediaDataClient") << "Skipping NULL request" << LL_ENDL;
}
else if (NULL == object)
{
LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << 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;
}
else if (!object->hasMedia())
{
LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
}
error = true;
queue_p->pop_front();
continue; // jump back to the start of the quick retry loop
}
bool exceeded_retries = request->getRetryCount() > mMaxNumRetries;
if (performed_request || exceeded_retries || error) // Try N times before giving up
// 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())
{
LL_DEBUGS("LLMediaDataClient") << "Not fetching " << *request << ": not interesting enough" << LL_ENDL;
break;
}
// Finally, try to send the HTTP message to the cap url
std::string url = request->getCapability();
bool maybe_retry = false;
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));
}
else {
LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL;
maybe_retry = true;
}
bool exceeded_retries = request->getRetryCount() > mMaxNumRetries;
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)
{

View File

@ -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);

View File

@ -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); }

View File

@ -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<LLObjectMediaDataClient> 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<LLObjectMediaDataClient> 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);
}
}