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
parent
320dfa1d72
commit
ba3f7965e3
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue