Automated merge with ssh://rick@hg.lindenlab.com/skolb/media
commit
0a8d9fa5b5
|
|
@ -5504,6 +5504,28 @@
|
|||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>5.0</real>
|
||||
</map>
|
||||
<key>PrimMediaMaxSortedQueueSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum number of objects the viewer will load media for initially</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>100000</integer>
|
||||
</map>
|
||||
<key>PrimMediaMaxRoundRobinQueueSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum number of objects the viewer will continuously update media for</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>100000</integer>
|
||||
</map>
|
||||
<key>ProbeHardwareOnStartup</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,408 @@
|
|||
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 = 10000;
|
||||
const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
|
||||
F32 retry_timer_delay,
|
||||
U32 max_retries,
|
||||
U32 max_sorted_queue_size,
|
||||
U32 max_round_robin_queue_size)
|
||||
: mQueueTimerDelay(queue_timer_delay),
|
||||
mRetryTimerDelay(retry_timer_delay),
|
||||
mMaxNumRetries(max_retries),
|
||||
mMaxSortedQueueSize(max_sorted_queue_size),
|
||||
mMaxRoundRobinQueueSize(max_round_robin_queue_size),
|
||||
mQueueTimerIsRunning(false),
|
||||
mCurrentQueueIsTheSortedQueue(true)
|
||||
{
|
||||
}
|
||||
|
||||
LLMediaDataClient::~LLMediaDataClient()
|
||||
{
|
||||
stopQueueTimer();
|
||||
|
||||
// This should clear the queue, and hopefully call all the destructors.
|
||||
LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " <<
|
||||
(isEmpty() ? "<empty> " : "<not empty> ") << LL_ENDL;
|
||||
|
||||
mSortedQueue.clear();
|
||||
mRoundRobinQueue.clear();
|
||||
}
|
||||
|
||||
bool LLMediaDataClient::isEmpty() const
|
||||
{
|
||||
return mSortedQueue.empty() && mRoundRobinQueue.empty();
|
||||
}
|
||||
|
||||
bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object)
|
||||
{
|
||||
return (LLMediaDataClient::findOrRemove(mSortedQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull()
|
||||
|| (LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull()));
|
||||
}
|
||||
|
||||
bool LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object)
|
||||
{
|
||||
bool removedFromSortedQueue = LLMediaDataClient::findOrRemove(mSortedQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull();
|
||||
bool removedFromRoundRobinQueue = LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull();
|
||||
return removedFromSortedQueue || removedFromRoundRobinQueue;
|
||||
}
|
||||
|
||||
//static
|
||||
LLMediaDataClient::request_ptr_t LLMediaDataClient::findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, LLMediaDataClient::Request::Type type)
|
||||
{
|
||||
request_ptr_t result;
|
||||
request_queue_t::iterator iter = queue.begin();
|
||||
request_queue_t::iterator end = queue.end();
|
||||
while (iter != end)
|
||||
{
|
||||
if (obj->getID() == (*iter)->getObject()->getID() && (type == LLMediaDataClient::Request::ANY || type == (*iter)->getType()))
|
||||
{
|
||||
result = *iter;
|
||||
if (remove) queue.erase(iter);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
|
||||
{
|
||||
if (object.isNull() || ! object->hasMedia()) return;
|
||||
|
||||
// Push the object on the queue
|
||||
enqueue(new Request(getCapabilityName(), payload, object, this));
|
||||
}
|
||||
|
||||
void LLMediaDataClient::enqueue(const Request *request)
|
||||
{
|
||||
if (request->isNew())
|
||||
{
|
||||
// Add to sorted queue
|
||||
if (LLMediaDataClient::findOrRemove(mSortedQueue, request->getObject(), true/*remove*/, request->getType()).notNull())
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "REMOVING OLD request for " << *request << " ALREADY THERE!" << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("LLMediaDataClient") << "Queuing SORTED request for " << *request << LL_ENDL;
|
||||
|
||||
// Sadly, we have to const-cast because items put into the queue are not const
|
||||
mSortedQueue.push_back(const_cast<LLMediaDataClient::Request*>(request));
|
||||
|
||||
LL_DEBUGS("LLMediaDataClient") << "SORTED queue:" << mSortedQueue << LL_ENDL;
|
||||
}
|
||||
else {
|
||||
if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize)
|
||||
{
|
||||
LL_INFOS_ONCE("LLMediaDataClient") << "RR QUEUE MAXED OUT!!!" << LL_ENDL;
|
||||
LL_DEBUGS("LLMediaDataClient") << "Not queuing " << *request << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// ROUND ROBIN: if it is there, and it is a GET request, leave it. If not, put at front!
|
||||
request_ptr_t existing_request;
|
||||
if (request->getType() == Request::GET)
|
||||
{
|
||||
existing_request = LLMediaDataClient::findOrRemove(mRoundRobinQueue, request->getObject(), false/*remove*/, request->getType());
|
||||
}
|
||||
if (existing_request.isNull())
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "Queuing RR request for " << *request << LL_ENDL;
|
||||
// Push the request on the pending queue
|
||||
// Sadly, we have to const-cast because items put into the queue are not const
|
||||
mRoundRobinQueue.push_front(const_cast<LLMediaDataClient::Request*>(request));
|
||||
|
||||
LL_DEBUGS("LLMediaDataClient") << "RR queue:" << mRoundRobinQueue << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "ALREADY THERE: NOT Queuing request for " << *request << LL_ENDL;
|
||||
|
||||
existing_request->markSent(false);
|
||||
}
|
||||
}
|
||||
// Start the timer if not already running
|
||||
startQueueTimer();
|
||||
}
|
||||
|
||||
void LLMediaDataClient::startQueueTimer()
|
||||
{
|
||||
if (! mQueueTimerIsRunning)
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
|
||||
// LLEventTimer automagically takes care of the lifetime of this object
|
||||
new QueueTimer(mQueueTimerDelay, this);
|
||||
}
|
||||
else {
|
||||
LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLMediaDataClient::stopQueueTimer()
|
||||
{
|
||||
mQueueTimerIsRunning = false;
|
||||
}
|
||||
|
||||
bool LLMediaDataClient::processQueueTimer()
|
||||
{
|
||||
sortQueue();
|
||||
|
||||
if(!isEmpty())
|
||||
{
|
||||
LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue size is: " << mSortedQueue.size()
|
||||
<< ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL;
|
||||
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue is: " << mSortedQueue << LL_ENDL;
|
||||
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, RR queue is: " << mRoundRobinQueue << LL_ENDL;
|
||||
}
|
||||
|
||||
serviceQueue();
|
||||
|
||||
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue size is: " << mSortedQueue.size()
|
||||
<< ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL;
|
||||
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue is: " << mSortedQueue << LL_ENDL;
|
||||
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, RR queue is: " << mRoundRobinQueue << LL_ENDL;
|
||||
|
||||
return isEmpty();
|
||||
}
|
||||
|
||||
void LLMediaDataClient::sortQueue()
|
||||
{
|
||||
if(!mSortedQueue.empty())
|
||||
{
|
||||
// Score all items first
|
||||
request_queue_t::iterator iter = mSortedQueue.begin();
|
||||
request_queue_t::iterator end = mSortedQueue.end();
|
||||
while (iter != end)
|
||||
{
|
||||
(*iter)->updateScore();
|
||||
iter++;
|
||||
}
|
||||
|
||||
// Re-sort the list...
|
||||
// NOTE: should this be a stable_sort? If so we need to change to using a vector.
|
||||
mSortedQueue.sort(LLMediaDataClient::compareRequests);
|
||||
|
||||
// ...then cull items over the max
|
||||
U32 size = mSortedQueue.size();
|
||||
if (size > mMaxSortedQueueSize)
|
||||
{
|
||||
U32 num_to_cull = (size - mMaxSortedQueueSize);
|
||||
LL_INFOS("LLMediaDataClient") << "sorted queue MAXED OUT! Culling "
|
||||
<< num_to_cull << " items" << LL_ENDL;
|
||||
while (num_to_cull-- > 0)
|
||||
{
|
||||
mSortedQueue.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2)
|
||||
{
|
||||
if (o2.isNull()) return true;
|
||||
if (o1.isNull()) return false;
|
||||
return ( o1->getScore() > o2->getScore() );
|
||||
}
|
||||
|
||||
void LLMediaDataClient::serviceQueue()
|
||||
{
|
||||
request_queue_t *queue_p = getCurrentQueue();
|
||||
|
||||
// quick retry loop for cases where we shouldn't wait for the next timer tick
|
||||
while(true)
|
||||
{
|
||||
if (queue_p->empty())
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "queue empty: " << (*queue_p) << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Peel one off of the items from the queue, and execute request
|
||||
request_ptr_t request = queue_p->front();
|
||||
llassert(!request.isNull());
|
||||
const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
|
||||
llassert(NULL != object);
|
||||
|
||||
// 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())
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
// 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 "
|
||||
<< mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;
|
||||
// XXX Should we bring up a warning dialog??
|
||||
}
|
||||
|
||||
queue_p->pop_front();
|
||||
|
||||
if (! mCurrentQueueIsTheSortedQueue) {
|
||||
// Round robin
|
||||
request->markSent(true);
|
||||
mRoundRobinQueue.push_back(request);
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
int i = 0;
|
||||
LLMediaDataClient::request_queue_t::const_iterator iter = q.begin();
|
||||
LLMediaDataClient::request_queue_t::const_iterator end = q.end();
|
||||
while (iter != end)
|
||||
{
|
||||
s << "\t" << i << "]: " << (*iter)->getObject()->getID().asString();
|
||||
iter++;
|
||||
i++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient::QueueTimer
|
||||
// Queue of LLMediaDataClientObject smart pointers to request media for.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
|
||||
: LLEventTimer(time), mMDC(mdc)
|
||||
{
|
||||
mMDC->setIsRunning(true);
|
||||
}
|
||||
|
||||
LLMediaDataClient::QueueTimer::~QueueTimer()
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "~QueueTimer" << LL_ENDL;
|
||||
mMDC->setIsRunning(false);
|
||||
mMDC = NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLMediaDataClient::QueueTimer::tick()
|
||||
{
|
||||
if (mMDC.isNull()) return TRUE;
|
||||
return mMDC->processQueueTimer();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient::Responder::RetryTimer
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr)
|
||||
: LLEventTimer(time), mResponder(mdr)
|
||||
{
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLMediaDataClient::Responder::RetryTimer::~RetryTimer()
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL;
|
||||
|
||||
// XXX This is weird: Instead of doing the work in tick() (which re-schedules
|
||||
// a timer, which might be risky), do it here, in the destructor. Yes, it is very odd.
|
||||
// Instead of retrying, we just put the request back onto the queue
|
||||
LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << " retrying" << LL_ENDL;
|
||||
mResponder->getRequest()->reEnqueue();
|
||||
|
||||
// Release the ref to the responder.
|
||||
mResponder = NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLMediaDataClient::Responder::RetryTimer::tick()
|
||||
{
|
||||
// Don't fire again
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
@ -69,16 +471,18 @@ const U32 LLMediaDataClient::MAX_RETRIES = 4;
|
|||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
/*static*/U32 LLMediaDataClient::Request::sNum = 0;
|
||||
|
||||
LLMediaDataClient::Request::Request(const std::string &cap_name,
|
||||
LLMediaDataClient::Request::Request(const char *cap_name,
|
||||
const LLSD& sd_payload,
|
||||
LLMediaDataClientObject *obj,
|
||||
LLMediaDataClient *mdc)
|
||||
: mCapName(cap_name),
|
||||
mPayload(sd_payload),
|
||||
mObject(obj),
|
||||
mNum(++sNum),
|
||||
mRetryCount(0),
|
||||
mMDC(mdc)
|
||||
: mCapName(cap_name),
|
||||
mPayload(sd_payload),
|
||||
mObject(obj),
|
||||
mNum(++sNum),
|
||||
mRetryCount(0),
|
||||
mMDC(mdc),
|
||||
mMarkedSent(false),
|
||||
mScore((F64)0.0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +493,7 @@ LLMediaDataClient::Request::~Request()
|
|||
mObject = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string LLMediaDataClient::Request::getCapability() const
|
||||
{
|
||||
return getObject()->getCapabilityUrl(getCapName());
|
||||
|
|
@ -99,11 +503,11 @@ std::string LLMediaDataClient::Request::getCapability() const
|
|||
// discover it.
|
||||
LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const
|
||||
{
|
||||
if (mCapName == "ObjectMediaNavigate")
|
||||
if (0 == strcmp(mCapName, "ObjectMediaNavigate"))
|
||||
{
|
||||
return NAVIGATE;
|
||||
}
|
||||
else if (mCapName == "ObjectMedia")
|
||||
else if (0 == strcmp(mCapName, "ObjectMedia"))
|
||||
{
|
||||
const std::string &verb = mPayload["verb"];
|
||||
if (verb == "GET")
|
||||
|
|
@ -133,10 +537,13 @@ const char *LLMediaDataClient::Request::getTypeAsString() const
|
|||
case NAVIGATE:
|
||||
return "NAVIGATE";
|
||||
break;
|
||||
case ANY:
|
||||
return "ANY";
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLMediaDataClient::Request::reEnqueue() const
|
||||
{
|
||||
|
|
@ -147,7 +554,7 @@ void LLMediaDataClient::Request::reEnqueue() const
|
|||
F32 LLMediaDataClient::Request::getRetryTimerDelay() const
|
||||
{
|
||||
return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY :
|
||||
mMDC->mRetryTimerDelay;
|
||||
mMDC->mRetryTimerDelay;
|
||||
}
|
||||
|
||||
U32 LLMediaDataClient::Request::getMaxNumRetries() const
|
||||
|
|
@ -155,52 +562,38 @@ U32 LLMediaDataClient::Request::getMaxNumRetries() const
|
|||
return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries;
|
||||
}
|
||||
|
||||
void LLMediaDataClient::Request::markSent(bool flag)
|
||||
{
|
||||
if (mMarkedSent != flag)
|
||||
{
|
||||
mMarkedSent = flag;
|
||||
if (!mMarkedSent)
|
||||
{
|
||||
mNum = ++sNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLMediaDataClient::Request::updateScore()
|
||||
{
|
||||
F64 tmp = mObject->getMediaInterest();
|
||||
if (tmp != mScore)
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "Score for " << mObject->getID() << " changed from " << mScore << " to " << tmp << LL_ENDL;
|
||||
mScore = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
|
||||
{
|
||||
s << "<request>"
|
||||
<< "<num>" << r.getNum() << "</num>"
|
||||
<< "<type>" << r.getTypeAsString() << "</type>"
|
||||
<< "<object_id>" << r.getObject()->getID() << "</object_id>"
|
||||
<< "<num_retries>" << r.getRetryCount() << "</num_retries>"
|
||||
<< "</request> ";
|
||||
s << "request: num=" << r.getNum()
|
||||
<< " type=" << r.getTypeAsString()
|
||||
<< " ID=" << r.getObject()->getID()
|
||||
<< " #retries=" << r.getRetryCount();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient::Responder::RetryTimer
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr)
|
||||
: LLEventTimer(time), mResponder(mdr)
|
||||
{
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLMediaDataClient::Responder::RetryTimer::~RetryTimer()
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL;
|
||||
|
||||
// XXX This is weird: Instead of doing the work in tick() (which re-schedules
|
||||
// a timer, which might be risky), do it here, in the destructor. Yes, it is very odd.
|
||||
// Instead of retrying, we just put the request back onto the queue
|
||||
LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL;
|
||||
mResponder->getRequest()->reEnqueue();
|
||||
|
||||
// Release the ref to the responder.
|
||||
mResponder = NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLMediaDataClient::Responder::RetryTimer::tick()
|
||||
{
|
||||
// Don't fire again
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient::Responder
|
||||
|
|
@ -208,7 +601,7 @@ BOOL LLMediaDataClient::Responder::RetryTimer::tick()
|
|||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
|
||||
: mRequest(request)
|
||||
: mRequest(request)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -224,20 +617,20 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
|
|||
if (status == HTTP_SERVICE_UNAVAILABLE)
|
||||
{
|
||||
F32 retry_timeout = mRequest->getRetryTimerDelay();
|
||||
|
||||
|
||||
mRequest->incRetryCount();
|
||||
|
||||
if (mRequest->getRetryCount() < mRequest->getMaxNumRetries())
|
||||
{
|
||||
LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
|
||||
|
||||
LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
|
||||
|
||||
// Start timer (instances are automagically tracked by
|
||||
// InstanceTracker<> and LLEventTimer)
|
||||
new RetryTimer(F32(retry_timeout/*secs*/), this);
|
||||
}
|
||||
else {
|
||||
LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retry count " <<
|
||||
mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
|
||||
LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " <<
|
||||
mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -246,288 +639,10 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*virtual*/
|
||||
void LLMediaDataClient::Responder::result(const LLSD& content)
|
||||
{
|
||||
LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_print_sd(content) << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient::Comparator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// static
|
||||
bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2)
|
||||
{
|
||||
if (o2.isNull()) return true;
|
||||
if (o1.isNull()) return false;
|
||||
|
||||
// The score is intended to be a measure of how close an object is or
|
||||
// how much screen real estate (interest) it takes up
|
||||
// Further away = lower score.
|
||||
// Lesser interest = lower score
|
||||
// For instance, here are some cases:
|
||||
// 1: Two items with no impl, closest one wins
|
||||
// 2: Two items with an impl: interest should rule, but distance is
|
||||
// still taken into account (i.e. something really close might take
|
||||
// precedence over a large item far away)
|
||||
// 3: One item with an impl, another without: item with impl wins
|
||||
// (XXX is that what we want?)
|
||||
// Calculate the scores for each.
|
||||
F64 o1_score = getObjectScore(o1->getObject());
|
||||
F64 o2_score = getObjectScore(o2->getObject());
|
||||
return ( o1_score > o2_score );
|
||||
}
|
||||
|
||||
// static
|
||||
F64 LLMediaDataClient::getObjectScore(const LLMediaDataClientObject::ptr_t &obj)
|
||||
{
|
||||
// *TODO: make this less expensive?
|
||||
F64 dist = obj->getDistanceFromAvatar() + 0.1; // avoids div by 0
|
||||
// square the distance so that they are in the same "unit magnitude" as
|
||||
// the interest (which is an area)
|
||||
dist *= dist;
|
||||
F64 interest = obj->getTotalMediaInterest() + 1.0;
|
||||
|
||||
return interest/dist;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient::PriorityQueue
|
||||
// Queue of LLMediaDataClientObject smart pointers to request media for.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// dump the queue
|
||||
std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q)
|
||||
{
|
||||
int i = 0;
|
||||
LLMediaDataClient::request_queue_t::const_iterator iter = q.begin();
|
||||
LLMediaDataClient::request_queue_t::const_iterator end = q.end();
|
||||
while (iter != end)
|
||||
{
|
||||
s << "\t" << i << "]: " << (*iter)->getObject()->getID().asString();
|
||||
iter++;
|
||||
i++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// find the given object in the queue.
|
||||
bool LLMediaDataClient::find(const LLMediaDataClientObject::ptr_t &obj) const
|
||||
{
|
||||
request_queue_t::const_iterator iter = pRequestQueue->begin();
|
||||
request_queue_t::const_iterator end = pRequestQueue->end();
|
||||
while (iter != end)
|
||||
{
|
||||
if (obj->getID() == (*iter)->getObject()->getID())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient::QueueTimer
|
||||
// Queue of LLMediaDataClientObject smart pointers to request media for.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
|
||||
: LLEventTimer(time), mMDC(mdc)
|
||||
{
|
||||
mMDC->setIsRunning(true);
|
||||
}
|
||||
|
||||
LLMediaDataClient::QueueTimer::~QueueTimer()
|
||||
{
|
||||
LL_DEBUGS("LLMediaDataClient") << "~QueueTimer" << LL_ENDL;
|
||||
mMDC->setIsRunning(false);
|
||||
mMDC = NULL;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLMediaDataClient::QueueTimer::tick()
|
||||
{
|
||||
if (NULL == mMDC->pRequestQueue)
|
||||
{
|
||||
// Shutting down? stop.
|
||||
LL_DEBUGS("LLMediaDataClient") << "queue gone" << LL_ENDL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
request_queue_t &queue = *(mMDC->pRequestQueue);
|
||||
|
||||
if(!queue.empty())
|
||||
{
|
||||
LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL;
|
||||
|
||||
// Re-sort the list every time...
|
||||
// XXX Is this really what we want?
|
||||
queue.sort(LLMediaDataClient::compareRequests);
|
||||
}
|
||||
|
||||
// quick retry loop for cases where we shouldn't wait for the next timer tick
|
||||
while(true)
|
||||
{
|
||||
if (queue.empty())
|
||||
{
|
||||
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.front();
|
||||
llassert(!request.isNull());
|
||||
const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
|
||||
bool performed_request = false;
|
||||
bool error = false;
|
||||
llassert(NULL != object);
|
||||
|
||||
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_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, mMDC->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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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_front();
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
void LLMediaDataClient::startQueueTimer()
|
||||
{
|
||||
if (! mQueueTimerIsRunning)
|
||||
{
|
||||
LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
|
||||
// LLEventTimer automagically takes care of the lifetime of this object
|
||||
new QueueTimer(mQueueTimerDelay, this);
|
||||
}
|
||||
else {
|
||||
LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLMediaDataClient::stopQueueTimer()
|
||||
{
|
||||
mQueueTimerIsRunning = false;
|
||||
}
|
||||
|
||||
void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
|
||||
{
|
||||
if (object.isNull() || ! object->hasMedia()) return;
|
||||
|
||||
// Push the object on the priority queue
|
||||
enqueue(new Request(getCapabilityName(), payload, object, this));
|
||||
}
|
||||
|
||||
void LLMediaDataClient::enqueue(const Request *request)
|
||||
{
|
||||
LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL;
|
||||
// Push the request on the priority queue
|
||||
// Sadly, we have to const-cast because items put into the queue are not const
|
||||
pRequestQueue->push_back(const_cast<LLMediaDataClient::Request*>(request));
|
||||
LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL;
|
||||
// Start the timer if not already running
|
||||
startQueueTimer();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LLMediaDataClient
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
|
||||
F32 retry_timer_delay,
|
||||
U32 max_retries)
|
||||
: mQueueTimerDelay(queue_timer_delay),
|
||||
mRetryTimerDelay(retry_timer_delay),
|
||||
mMaxNumRetries(max_retries),
|
||||
mQueueTimerIsRunning(false)
|
||||
{
|
||||
pRequestQueue = new request_queue_t();
|
||||
}
|
||||
|
||||
LLMediaDataClient::~LLMediaDataClient()
|
||||
{
|
||||
stopQueueTimer();
|
||||
|
||||
// This should clear the queue, and hopefully call all the destructors.
|
||||
LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " <<
|
||||
(pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL;
|
||||
delete pRequestQueue;
|
||||
pRequestQueue = NULL;
|
||||
}
|
||||
|
||||
bool LLMediaDataClient::isEmpty() const
|
||||
{
|
||||
return (NULL == pRequestQueue) ? true : pRequestQueue->empty();
|
||||
}
|
||||
|
||||
bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object) const
|
||||
{
|
||||
return (NULL == pRequestQueue) ? false : find(object);
|
||||
LL_DEBUGS("LLMediaDataClient") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -569,7 +684,7 @@ void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)
|
|||
}
|
||||
sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
|
||||
|
||||
LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL;
|
||||
LL_DEBUGS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL;
|
||||
|
||||
request(object, sd_payload);
|
||||
}
|
||||
|
|
@ -581,7 +696,7 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
|
|||
llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
|
||||
if (type == LLMediaDataClient::Request::GET)
|
||||
{
|
||||
LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_print_sd(content) << LL_ENDL;
|
||||
LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;
|
||||
|
||||
// Look for an error
|
||||
if (content.has("error"))
|
||||
|
|
@ -598,12 +713,13 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
|
|||
if (object_id != getRequest()->getObject()->getID())
|
||||
{
|
||||
// NOT good, wrong object id!!
|
||||
LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
|
||||
LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, update with object media data
|
||||
getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]);
|
||||
getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
|
||||
content[LLTextureEntry::MEDIA_VERSION_KEY]);
|
||||
}
|
||||
}
|
||||
else if (type == LLMediaDataClient::Request::UPDATE)
|
||||
|
|
|
|||
|
|
@ -55,15 +55,19 @@ public:
|
|||
// Does this object have media?
|
||||
virtual bool hasMedia() const = 0;
|
||||
// Update the object's media data to the given array
|
||||
virtual void updateObjectMediaData(LLSD const &media_data_array) = 0;
|
||||
// Return the distance from the object to the avatar
|
||||
virtual F64 getDistanceFromAvatar() const = 0;
|
||||
virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0;
|
||||
// Return the total "interest" of the media (on-screen area)
|
||||
virtual F64 getTotalMediaInterest() const = 0;
|
||||
virtual F64 getMediaInterest() 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;
|
||||
// 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;
|
||||
|
||||
// smart pointer
|
||||
typedef LLPointer<LLMediaDataClientObject> ptr_t;
|
||||
|
|
@ -79,11 +83,15 @@ 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;// = 10000;
|
||||
const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000;
|
||||
|
||||
// Constructor
|
||||
LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
|
||||
F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
|
||||
U32 max_retries = MAX_RETRIES);
|
||||
U32 max_retries = MAX_RETRIES,
|
||||
U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
|
||||
U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE);
|
||||
|
||||
// Make the request
|
||||
void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload);
|
||||
|
|
@ -94,7 +102,13 @@ public:
|
|||
bool isEmpty() const;
|
||||
|
||||
// Returns true iff the given object is in the queue
|
||||
bool isInQueue(const LLMediaDataClientObject::ptr_t &object) const;
|
||||
bool isInQueue(const LLMediaDataClientObject::ptr_t &object);
|
||||
|
||||
// Remove the given object from the queue. Returns true iff the given object is removed.
|
||||
bool removeFromQueue(const LLMediaDataClientObject::ptr_t &object);
|
||||
|
||||
// Called only by the Queue timer and tests (potentially)
|
||||
bool processQueueTimer();
|
||||
|
||||
protected:
|
||||
// Destructor
|
||||
|
|
@ -107,11 +121,12 @@ protected:
|
|||
enum Type {
|
||||
GET,
|
||||
UPDATE,
|
||||
NAVIGATE
|
||||
NAVIGATE,
|
||||
ANY
|
||||
};
|
||||
|
||||
Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
|
||||
const std::string &getCapName() const { return mCapName; }
|
||||
Request(const char *cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
|
||||
const char *getCapName() const { return mCapName; }
|
||||
const LLSD &getPayload() const { return mPayload; }
|
||||
LLMediaDataClientObject *getObject() const { return mObject; }
|
||||
|
||||
|
|
@ -132,6 +147,12 @@ protected:
|
|||
F32 getRetryTimerDelay() const;
|
||||
U32 getMaxNumRetries() const;
|
||||
|
||||
bool isNew() const { return mObject.notNull() ? mObject->isNew() : false; }
|
||||
void markSent(bool flag);
|
||||
bool isMarkedSent() const { return mMarkedSent; }
|
||||
void updateScore();
|
||||
F64 getScore() const { return mScore; }
|
||||
|
||||
public:
|
||||
friend std::ostream& operator<<(std::ostream &s, const Request &q);
|
||||
|
||||
|
|
@ -139,14 +160,16 @@ protected:
|
|||
virtual ~Request(); // use unref();
|
||||
|
||||
private:
|
||||
std::string mCapName;
|
||||
const char *mCapName;
|
||||
LLSD mPayload;
|
||||
LLMediaDataClientObject::ptr_t mObject;
|
||||
// Simple tracking
|
||||
const U32 mNum;
|
||||
U32 mNum;
|
||||
static U32 sNum;
|
||||
U32 mRetryCount;
|
||||
|
||||
F64 mScore;
|
||||
bool mMarkedSent;
|
||||
|
||||
// Back pointer to the MDC...not a ref!
|
||||
LLMediaDataClient *mMDC;
|
||||
};
|
||||
|
|
@ -184,18 +207,23 @@ protected:
|
|||
};
|
||||
|
||||
protected:
|
||||
|
||||
void enqueue(const Request*);
|
||||
|
||||
|
||||
// Subclasses must override this factory method to return a new responder
|
||||
virtual Responder *createResponder(const request_ptr_t &request) const = 0;
|
||||
|
||||
// Subclasses must override to return a cap name
|
||||
virtual const char *getCapabilityName() const = 0;
|
||||
|
||||
private:
|
||||
virtual void sortQueue();
|
||||
virtual void serviceQueue();
|
||||
|
||||
private:
|
||||
typedef std::list<request_ptr_t> request_queue_t;
|
||||
|
||||
void enqueue(const Request*);
|
||||
|
||||
// Return whether the given object is/was in the queue
|
||||
static LLMediaDataClient::request_ptr_t findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, Request::Type type);
|
||||
|
||||
// Comparator for sorting
|
||||
static bool compareRequests(const request_ptr_t &o1, const request_ptr_t &o2);
|
||||
|
|
@ -215,34 +243,40 @@ private:
|
|||
// back-pointer
|
||||
LLPointer<LLMediaDataClient> mMDC;
|
||||
};
|
||||
|
||||
// Return whether the given object is in the queue
|
||||
bool find(const LLMediaDataClientObject::ptr_t &obj) const;
|
||||
|
||||
void startQueueTimer();
|
||||
void stopQueueTimer();
|
||||
void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
|
||||
|
||||
|
||||
void swapCurrentQueue();
|
||||
request_queue_t *getCurrentQueue();
|
||||
|
||||
const F32 mQueueTimerDelay;
|
||||
const F32 mRetryTimerDelay;
|
||||
const U32 mMaxNumRetries;
|
||||
const U32 mMaxSortedQueueSize;
|
||||
const U32 mMaxRoundRobinQueueSize;
|
||||
|
||||
bool mQueueTimerIsRunning;
|
||||
|
||||
request_queue_t *pRequestQueue;
|
||||
request_queue_t mSortedQueue;
|
||||
request_queue_t mRoundRobinQueue;
|
||||
bool mCurrentQueueIsTheSortedQueue;
|
||||
};
|
||||
|
||||
|
||||
// MediaDataResponder specific for the ObjectMedia cap
|
||||
// MediaDataClient specific for the ObjectMedia cap
|
||||
class LLObjectMediaDataClient : public LLMediaDataClient
|
||||
{
|
||||
public:
|
||||
LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
|
||||
F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
|
||||
U32 max_retries = MAX_RETRIES)
|
||||
U32 max_retries = MAX_RETRIES,
|
||||
U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
|
||||
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);
|
||||
|
|
@ -264,7 +298,7 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
// MediaDataResponder specific for the ObjectMediaNavigate cap
|
||||
// MediaDataClient specific for the ObjectMediaNavigate cap
|
||||
class LLObjectMediaNavigateClient : public LLMediaDataClient
|
||||
{
|
||||
public:
|
||||
|
|
@ -273,10 +307,12 @@ public:
|
|||
|
||||
LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
|
||||
F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
|
||||
U32 max_retries = MAX_RETRIES)
|
||||
U32 max_retries = MAX_RETRIES,
|
||||
U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
|
|||
class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
|
||||
{
|
||||
public:
|
||||
LLMediaDataClientObjectImpl(LLVOVolume *obj) : mObject(obj) {}
|
||||
LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) {}
|
||||
LLMediaDataClientObjectImpl() { mObject = NULL; }
|
||||
|
||||
virtual U8 getMediaDataCount() const
|
||||
|
|
@ -128,14 +128,19 @@ public:
|
|||
virtual bool hasMedia() const
|
||||
{ return mObject->hasMedia(); }
|
||||
|
||||
virtual void updateObjectMediaData(LLSD const &data)
|
||||
{ mObject->updateObjectMediaData(data); }
|
||||
|
||||
virtual F64 getDistanceFromAvatar() const
|
||||
{ return mObject->getRenderPosition().length(); }
|
||||
virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string)
|
||||
{ mObject->updateObjectMediaData(data, version_string); }
|
||||
|
||||
virtual F64 getTotalMediaInterest() const
|
||||
{ return mObject->getTotalMediaInterest(); }
|
||||
virtual F64 getMediaInterest() const
|
||||
{
|
||||
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); }
|
||||
|
|
@ -143,8 +148,15 @@ public:
|
|||
virtual bool isDead() const
|
||||
{ return mObject->isDead(); }
|
||||
|
||||
virtual U32 getMediaVersion() const
|
||||
{ return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); }
|
||||
|
||||
virtual bool isNew() const
|
||||
{ return mNew; }
|
||||
|
||||
private:
|
||||
LLPointer<LLVOVolume> mObject;
|
||||
bool mNew;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -165,6 +177,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
|
|||
mSpotLightPriority = 0.f;
|
||||
|
||||
mMediaImplList.resize(getNumTEs());
|
||||
mLastFetchedMediaVersion = -1;
|
||||
}
|
||||
|
||||
LLVOVolume::~LLVOVolume()
|
||||
|
|
@ -190,7 +203,9 @@ void LLVOVolume::markDead()
|
|||
{
|
||||
if (!mDead)
|
||||
{
|
||||
// TODO: tell LLMediaDataClient to remove this object from its queue
|
||||
LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false);
|
||||
sObjectMediaClient->removeFromQueue(obj);
|
||||
sObjectMediaNavigateClient->removeFromQueue(obj);
|
||||
|
||||
// Detach all media impls from this object
|
||||
for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
|
||||
|
|
@ -210,8 +225,12 @@ void LLVOVolume::initClass()
|
|||
const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
|
||||
const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
|
||||
const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
|
||||
sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries);
|
||||
sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries);
|
||||
const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize");
|
||||
const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize");
|
||||
sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries,
|
||||
max_sorted_queue_size, max_round_robin_queue_size);
|
||||
sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay,
|
||||
max_retries, max_sorted_queue_size, max_round_robin_queue_size);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -406,7 +425,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
|
|||
// If the media changed at all, request new media data
|
||||
LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<
|
||||
((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
|
||||
requestMediaDataUpdate();
|
||||
requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED);
|
||||
}
|
||||
else {
|
||||
LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " <<
|
||||
|
|
@ -1698,16 +1717,16 @@ LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id)
|
|||
return result;
|
||||
}
|
||||
|
||||
void LLVOVolume::requestMediaDataUpdate()
|
||||
void LLVOVolume::requestMediaDataUpdate(bool isNew)
|
||||
{
|
||||
sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this));
|
||||
sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew));
|
||||
}
|
||||
|
||||
bool LLVOVolume::isMediaDataBeingFetched() const
|
||||
{
|
||||
// I know what I'm doing by const_casting this away: this is just
|
||||
// a wrapper class that is only going to do a lookup.
|
||||
return sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this)));
|
||||
return sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false));
|
||||
}
|
||||
|
||||
void LLVOVolume::cleanUpMediaImpls()
|
||||
|
|
@ -1725,18 +1744,25 @@ void LLVOVolume::cleanUpMediaImpls()
|
|||
}
|
||||
}
|
||||
|
||||
void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array)
|
||||
void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version)
|
||||
{
|
||||
// media_data_array is an array of media entry maps
|
||||
// media_version is the version string in the response.
|
||||
U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version);
|
||||
|
||||
//llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl;
|
||||
|
||||
LLSD::array_const_iterator iter = media_data_array.beginArray();
|
||||
LLSD::array_const_iterator end = media_data_array.endArray();
|
||||
U8 texture_index = 0;
|
||||
for (; iter != end; ++iter, ++texture_index)
|
||||
// Only update it if it is newer!
|
||||
if ( (S32)fetched_version > mLastFetchedMediaVersion)
|
||||
{
|
||||
syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/);
|
||||
mLastFetchedMediaVersion = fetched_version;
|
||||
//llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl;
|
||||
|
||||
LLSD::array_const_iterator iter = media_data_array.beginArray();
|
||||
LLSD::array_const_iterator end = media_data_array.endArray();
|
||||
U8 texture_index = 0;
|
||||
for (; iter != end; ++iter, ++texture_index)
|
||||
{
|
||||
syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1904,7 +1930,7 @@ void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plu
|
|||
|
||||
llinfos << "broadcasting navigate with URI " << new_location << llendl;
|
||||
|
||||
sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location);
|
||||
sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1968,7 +1994,7 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
|
|||
|
||||
void LLVOVolume::sendMediaDataUpdate()
|
||||
{
|
||||
sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this));
|
||||
sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false));
|
||||
}
|
||||
|
||||
void LLVOVolume::removeMediaImpl(S32 texture_index)
|
||||
|
|
@ -2063,7 +2089,7 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
|
|||
|
||||
F64 LLVOVolume::getTotalMediaInterest() const
|
||||
{
|
||||
F64 interest = (F64)0.0;
|
||||
F64 interest = (F64)-1.0; // means not interested;
|
||||
int i = 0;
|
||||
const int end = getNumTEs();
|
||||
for ( ; i < end; ++i)
|
||||
|
|
@ -2071,6 +2097,7 @@ F64 LLVOVolume::getTotalMediaInterest() const
|
|||
const viewer_media_t &impl = getMediaImpl(i);
|
||||
if (!impl.isNull())
|
||||
{
|
||||
if (interest == (F64)-1.0) interest = (F64)0.0;
|
||||
interest += impl->getInterest();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ public:
|
|||
|
||||
// Update this object's media data with the given media data array
|
||||
// (typically this is only called upon a response from a server request)
|
||||
void updateObjectMediaData(const LLSD &media_data_array);
|
||||
void updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version);
|
||||
|
||||
// Bounce back media at the given index to its current URL (or home URL, if current URL is empty)
|
||||
void mediaNavigateBounceBack(U8 texture_index);
|
||||
|
|
@ -270,13 +270,16 @@ public:
|
|||
// Returns 'true' iff the media data for this object is in flight
|
||||
bool isMediaDataBeingFetched() const;
|
||||
|
||||
// Returns the "last fetched" media version, or -1 if not fetched yet
|
||||
S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; }
|
||||
|
||||
protected:
|
||||
S32 computeLODDetail(F32 distance, F32 radius);
|
||||
BOOL calcLOD();
|
||||
LLFace* addFace(S32 face_index);
|
||||
void updateTEData();
|
||||
|
||||
void requestMediaDataUpdate();
|
||||
void requestMediaDataUpdate(bool isNew);
|
||||
void cleanUpMediaImpls();
|
||||
void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
|
||||
void removeMediaImpl(S32 texture_index) ;
|
||||
|
|
@ -300,6 +303,7 @@ private:
|
|||
LLPointer<LLViewerFetchedTexture> mSculptTexture;
|
||||
LLPointer<LLViewerFetchedTexture> mLightTexture;
|
||||
media_list_t mMediaImplList;
|
||||
S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1
|
||||
|
||||
// statics
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -75,15 +75,13 @@
|
|||
<string>baz</string> \
|
||||
</array>"
|
||||
|
||||
#define _DATA_URLS(ID,DIST,INT,URL1,URL2) " \
|
||||
#define _DATA_URLS(ID,INTEREST,NEW,URL1,URL2) " \
|
||||
<llsd> \
|
||||
<map> \
|
||||
<key>uuid</key> \
|
||||
<string>" ID "</string> \
|
||||
<key>distance</key> \
|
||||
<real>" DIST "</real> \
|
||||
<key>interest</key> \
|
||||
<real>" INT "</real> \
|
||||
<real>" INTEREST "</real> \
|
||||
<key>cap_urls</key> \
|
||||
<map> \
|
||||
<key>ObjectMedia</key> \
|
||||
|
|
@ -93,21 +91,26 @@
|
|||
</map> \
|
||||
<key>media_data</key> \
|
||||
" MEDIA_DATA " \
|
||||
<key>is_dead</key> \
|
||||
<boolean>false</boolean> \
|
||||
<key>is_new</key> \
|
||||
<boolean>" NEW "</boolean> \
|
||||
</map> \
|
||||
</llsd>"
|
||||
|
||||
#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
|
||||
#define _DATA(ID,INTEREST,NEW) _DATA_URLS(ID,INTEREST,NEW,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
|
||||
|
||||
const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0");
|
||||
const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true");
|
||||
|
||||
#define STR(I) boost::lexical_cast<std::string>(I)
|
||||
|
||||
#define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" << \
|
||||
"================================================================================\n" << \
|
||||
"===================================== TEST " #N " ===================================\n" << \
|
||||
"==================================== TEST " #N " ===================================\n" << \
|
||||
"================================================================================\n" << LL_ENDL;
|
||||
|
||||
LLSD *gPostRecords = NULL;
|
||||
F64 gMinimumInterestLevel = (F64)0.0;
|
||||
|
||||
// stubs:
|
||||
void LLHTTPClient::post(
|
||||
|
|
@ -125,21 +128,20 @@ void LLHTTPClient::post(
|
|||
gPostRecords->append(record);
|
||||
|
||||
// Magic URL that triggers a 503:
|
||||
LLSD result;
|
||||
result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY];
|
||||
if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )
|
||||
{
|
||||
responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason");
|
||||
return;
|
||||
}
|
||||
else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)
|
||||
{
|
||||
LLSD result;
|
||||
LLSD error;
|
||||
error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
|
||||
result["error"] = error;
|
||||
responder->result(result);
|
||||
}
|
||||
else {
|
||||
responder->result(LLSD());
|
||||
}
|
||||
}
|
||||
responder->result(result);
|
||||
}
|
||||
|
||||
const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
|
||||
|
|
@ -152,13 +154,12 @@ 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), mDead(false) {}
|
||||
: mRep(rep), mNumBounceBacks(0) {}
|
||||
~LLMediaDataClientObjectTest()
|
||||
{ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; }
|
||||
|
||||
|
|
@ -169,43 +170,47 @@ public:
|
|||
virtual LLUUID getID() const
|
||||
{ return mRep["uuid"]; }
|
||||
virtual void mediaNavigateBounceBack(U8 index)
|
||||
{
|
||||
mNumBounceBacks++;
|
||||
}
|
||||
{ mNumBounceBacks++; }
|
||||
|
||||
virtual bool hasMedia() const
|
||||
{ return mRep.has("media_data"); }
|
||||
|
||||
virtual void updateObjectMediaData(LLSD const &media_data_array)
|
||||
{ mRep["media_data"] = media_data_array; }
|
||||
|
||||
virtual F64 getDistanceFromAvatar() const
|
||||
{ return (LLSD::Real)mRep["distance"]; }
|
||||
|
||||
virtual F64 getTotalMediaInterest() const
|
||||
virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &media_version)
|
||||
{ mRep["media_data"] = media_data_array; mRep["media_version"] = media_version; }
|
||||
|
||||
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]; }
|
||||
|
||||
virtual bool isDead() const
|
||||
{ return mDead; }
|
||||
|
||||
void setDistanceFromAvatar(F64 val)
|
||||
{ mRep["distance"] = val; }
|
||||
{ return mRep["is_dead"]; }
|
||||
|
||||
void setTotalMediaInterest(F64 val)
|
||||
virtual U32 getMediaVersion() const
|
||||
{ return (LLSD::Integer)mRep["media_version"]; }
|
||||
|
||||
virtual bool isNew() const
|
||||
{ return mRep["is_new"]; }
|
||||
|
||||
void setMediaInterest(F64 val)
|
||||
{ mRep["interest"] = val; }
|
||||
|
||||
int getNumBounceBacks() const
|
||||
{ return mNumBounceBacks; }
|
||||
|
||||
void markDead()
|
||||
{ mDead = true; }
|
||||
{ mRep["is_dead"] = true; }
|
||||
|
||||
void markOld()
|
||||
{ mRep["is_new"] = false; }
|
||||
|
||||
private:
|
||||
LLSD mRep;
|
||||
int mNumBounceBacks;
|
||||
bool mDead;
|
||||
};
|
||||
|
||||
// This special timer delay should ensure that the timer will fire on the very
|
||||
|
|
@ -224,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;
|
||||
};
|
||||
|
|
@ -378,11 +384,11 @@ namespace tut
|
|||
LOG_TEST(4);
|
||||
|
||||
LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
|
||||
_DATA(VALID_OBJECT_ID_1,"3.0","1.0"));
|
||||
_DATA(VALID_OBJECT_ID_1,"1.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
|
||||
_DATA(VALID_OBJECT_ID_2,"1.0","1.0"));
|
||||
_DATA(VALID_OBJECT_ID_2,"3.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
|
||||
_DATA(VALID_OBJECT_ID_3,"2.0","1.0"));
|
||||
_DATA(VALID_OBJECT_ID_3,"2.0","true"));
|
||||
{
|
||||
LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
|
||||
const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 };
|
||||
|
|
@ -428,8 +434,7 @@ namespace tut
|
|||
|
||||
LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
|
||||
_DATA_URLS(VALID_OBJECT_ID,
|
||||
"1.0",
|
||||
"1.0",
|
||||
"1.0","true",
|
||||
FAKE_OBJECT_MEDIA_CAP_URL_503,
|
||||
FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));
|
||||
int num_refs_start = o->getNumRefs();
|
||||
|
|
@ -484,8 +489,7 @@ namespace tut
|
|||
|
||||
LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
|
||||
_DATA_URLS(VALID_OBJECT_ID,
|
||||
"1.0",
|
||||
"1.0",
|
||||
"1.0","true",
|
||||
FAKE_OBJECT_MEDIA_CAP_URL,
|
||||
FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));
|
||||
{
|
||||
|
|
@ -517,9 +521,9 @@ namespace tut
|
|||
LOG_TEST(7);
|
||||
|
||||
LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
|
||||
_DATA(VALID_OBJECT_ID_1,"3.0","1.0"));
|
||||
_DATA(VALID_OBJECT_ID_1,"3.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
|
||||
_DATA(VALID_OBJECT_ID_2,"1.0","1.0"));
|
||||
_DATA(VALID_OBJECT_ID_2,"1.0","true"));
|
||||
int num_refs_start = o1->getNumRefs();
|
||||
{
|
||||
LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
|
||||
|
|
@ -551,10 +555,10 @@ namespace tut
|
|||
// 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"));
|
||||
LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true"));
|
||||
{
|
||||
LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
|
||||
|
||||
|
|
@ -616,10 +620,11 @@ namespace tut
|
|||
//
|
||||
LOG_TEST(9);
|
||||
|
||||
LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"10.0","1.0"));
|
||||
LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"20.0","1.0"));
|
||||
LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"30.0","1.0"));
|
||||
LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"40.0","1.0"));
|
||||
LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true"));
|
||||
LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true"));
|
||||
LLMediaDataClientObject::ptr_t o4 = object4;
|
||||
{
|
||||
LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
|
||||
|
||||
|
|
@ -630,53 +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
|
||||
static_cast<LLMediaDataClientObjectTest*>(
|
||||
static_cast<LLMediaDataClientObject*>(o4))->setDistanceFromAvatar(5.0);
|
||||
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());
|
||||
}
|
||||
|
|
@ -686,4 +690,249 @@ namespace tut
|
|||
ensure("refcount of o4", o4->getNumRefs(), 1);
|
||||
}
|
||||
|
||||
|
||||
template<> template<>
|
||||
void mediadataclient_object_t::test<10>()
|
||||
{
|
||||
//
|
||||
// Test using the "round-robin" queue
|
||||
//
|
||||
LOG_TEST(10);
|
||||
|
||||
LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
|
||||
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","false"));
|
||||
LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false"));
|
||||
{
|
||||
LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
|
||||
|
||||
// queue up all 4 objects. The first two should be in the sorted
|
||||
// queue [2 1], the second in the round-robin queue. The queues
|
||||
// are serviced interleaved, so we should expect:
|
||||
// 2, 4, 1, 3
|
||||
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 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();
|
||||
++tick_num;
|
||||
|
||||
// 2 The second tick should send object 4, but it will still be
|
||||
// "in the queue"
|
||||
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();
|
||||
++tick_num;
|
||||
|
||||
// 3 The third tick should remove object 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();
|
||||
++tick_num;
|
||||
|
||||
// 4 The fourth tick should send object 3, but it will still be
|
||||
// "in the queue"
|
||||
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();
|
||||
++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 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();
|
||||
|
||||
// Whew....better be empty
|
||||
ensure("queue empty", mdc->isEmpty());
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue