Made LLMediaDataClient not send requests on behalf of objects that are marked as dead.

When LLMediaDataClient::QueueTimer::tick() encounters an object at the head of the queue that's dead, it will now remove that object and loop, instead of sending a request and waiting for the tick timer to fire again.

Added an isDead() function to LLMediaDataClientObject, and an additional unit test that verifies the handling of dead objects.
meow-7.2.2
Monroe Linden 2009-11-19 16:35:11 -08:00
parent 320dfa1d72
commit ba3f7965e3
4 changed files with 139 additions and 50 deletions

View File

@ -371,67 +371,87 @@ BOOL LLMediaDataClient::QueueTimer::tick()
}
LLMediaDataClient::PriorityQueue &queue = *(mMDC->pRequestQueue);
if (queue.empty())
if(!queue.empty())
{
LL_DEBUGS("LLMediaDataClient") << "queue empty: " << queue << LL_ENDL;
return TRUE;
LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL;
}
LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL;
// Peel one off of the items from the queue, and execute request
request_ptr_t request = queue.top();
llassert(!request.isNull());
const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
bool performed_request = false;
bool error = false;
llassert(NULL != object);
if (NULL != object && object->hasMedia())
// quick retry loop for cases where we shouldn't wait for the next timer tick
while(true)
{
std::string url = request->getCapability();
if (!url.empty())
if (queue.empty())
{
const LLSD &sd_payload = request->getPayload();
LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL;
LL_DEBUGS("LLMediaDataClient") << "queue empty: " << queue << LL_ENDL;
return TRUE;
}
// Peel one off of the items from the queue, and execute request
request_ptr_t request = queue.top();
llassert(!request.isNull());
const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
bool performed_request = false;
bool error = false;
llassert(NULL != object);
// Call the subclass for creating the responder
LLHTTPClient::post(url, sd_payload, mMDC->createResponder(request));
performed_request = true;
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.pop();
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, mMDC->createResponder(request));
performed_request = true;
}
else {
LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL;
}
}
else {
LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL;
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;
}
}
else {
if (request.isNull())
bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries;
if (performed_request || exceeded_retries || error) // Try N times before giving up
{
LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL;
if (exceeded_retries)
{
LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for "
<< mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;
// XXX Should we bring up a warning dialog??
}
queue.pop();
}
else if (NULL == object)
{
LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL;
else {
request->incRetryCount();
}
else if (!object->hasMedia())
{
LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
}
error = true;
}
bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries;
if (performed_request || exceeded_retries || error) // Try N times before giving up
{
if (exceeded_retries)
{
LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for "
<< mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;
// XXX Should we bring up a warning dialog??
}
queue.pop();
}
else {
request->incRetryCount();
}
// end of quick retry loop -- any cases where we want to loop will use 'continue' to jump back to the start.
break;
}
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue is now: " << (*(mMDC->pRequestQueue)) << LL_ENDL;
return queue.empty();

View File

@ -62,6 +62,8 @@ public:
virtual F64 getTotalMediaInterest() 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;
// smart pointer
typedef LLPointer<LLMediaDataClientObject> ptr_t;

View File

@ -140,6 +140,9 @@ public:
virtual std::string getCapabilityUrl(const std::string &name) const
{ return mObject->getRegion()->getCapability(name); }
virtual bool isDead() const
{ return mObject->isDead(); }
private:
LLPointer<LLVOVolume> mObject;
};

View File

@ -152,12 +152,13 @@ public:
std::istringstream d(data);
LLSDSerialize::fromXML(mRep, d);
mNumBounceBacks = 0;
mDead = false;
// std::cout << ll_pretty_print_sd(mRep) << std::endl;
// std::cout << "ID: " << getID() << std::endl;
}
LLMediaDataClientObjectTest(const LLSD &rep)
: mRep(rep), mNumBounceBacks(0) {}
: mRep(rep), mNumBounceBacks(0), mDead(false) {}
~LLMediaDataClientObjectTest()
{ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; }
@ -187,12 +188,18 @@ public:
virtual std::string getCapabilityUrl(const std::string &name) const
{ return mRep["cap_urls"][name]; }
virtual bool isDead() const
{ return mDead; }
int getNumBounceBacks() const
{ return mNumBounceBacks; }
void markDead()
{ mDead = true; }
private:
LLSD mRep;
int mNumBounceBacks;
bool mDead;
};
// This special timer delay should ensure that the timer will fire on the very
@ -531,4 +538,61 @@ namespace tut
ensure("REF COUNT", o1->getNumRefs(), num_refs_start);
}
template<> template<>
void mediadataclient_object_t::test<8>()
{
// Test queue handling of objects that are marked dead.
LOG_TEST(8);
LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","1.0"));
LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","1.0"));
LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","1.0"));
LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","1.0"));
{
LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
// queue up all 4 objects
mdc->fetchMedia(o1);
mdc->fetchMedia(o2);
mdc->fetchMedia(o3);
mdc->fetchMedia(o4);
// and mark the second and fourth ones dead.
dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o2))->markDead();
dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o4))->markDead();
ensure("is in queue 1", mdc->isInQueue(o1));
ensure("is in queue 2", mdc->isInQueue(o2));
ensure("is in queue 3", mdc->isInQueue(o3));
ensure("is in queue 4", mdc->isInQueue(o4));
ensure("post records", gPostRecords->size(), 0);
::pump_timers();
// The first tick should remove the first one
ensure("is not in queue 1", !mdc->isInQueue(o1));
ensure("is in queue 2", mdc->isInQueue(o2));
ensure("is in queue 3", mdc->isInQueue(o3));
ensure("is in queue 4", mdc->isInQueue(o4));
ensure("post records", gPostRecords->size(), 1);
::pump_timers();
// The second tick should skip the second and remove the third
ensure("is not in queue 2", !mdc->isInQueue(o2));
ensure("is not in queue 3", !mdc->isInQueue(o3));
ensure("is in queue 4", mdc->isInQueue(o4));
ensure("post records", gPostRecords->size(), 2);
::pump_timers();
// The third tick should skip the fourth one and empty the queue.
ensure("is not in queue 4", !mdc->isInQueue(o4));
ensure("post records", gPostRecords->size(), 2);
ensure("queue empty", mdc->isEmpty());
}
}
}