Age | Commit message (Collapse) | Author |
|
|
|
The big idea is to reduce the number of per-tick callbacks asking, "Is it time
yet? Is it time yet?" We do that for LLEventTimer and LLEventTimeout.
LLLater presents doAtTime(LLDate), with doAfterInterval() and doPeriodically()
methods implemented using doAtTime(). All return handles. The free functions
doAfterInterval() and doPeriodically() now forward to the corresponding
LLLater methods.
LLLater also presents isRunning(handle) and cancel(handle).
LLLater borrows the tactic of LLEventTimer: while there's at least one running
timer, it registers an LLCallbackList tick() callback to service ready timers.
But instead of looping over all of them asking, "Are you ready?" it keeps them
in a priority queue ordered by desired timestamp, and only touches those whose
timestamp has been reached. Also, it honors a maximum time slice: once the
ready timers have run for longer than the limit, it defers processing other
ready timers to the next tick() call. The intent is to consume fewer cycles
per tick() call, both by the management machinery and the timers themselves.
Revamp LLCallbackList to accept C++ callables in addition to (classic C
function pointer, void*) pairs. Make addFunction() return a handle (different
than LLLater handles) that can be passed to a new deleteFunction() overload,
since std::function instances can't be compared for equality.
In fact, implement LLCallbackList using boost::signals2::signal, which provides
almost exactly what we want.
LLCallbackList continues to accept (function pointer, void*) pairs, but now
we store a lambda that calls the function pointer with that void*. It takes
less horsing around to create a C++ callable from a (function pointer, void*)
pair than the other way around. For containsFunction() and deleteFunction(),
such pairs are the keys for a lookup table whose values are handles.
Instead of having a static global LLCallbackList gIdleCallbacks, make
LLCallbackList an LLSingleton to guarantee initialization. For backwards
compatibility, gIdleCallbacks is now a macro for LLCallbackList::instance().
Move doOnIdleOneTime() and doOnIdleRepeating() functions to LLCallbackList
methods, but for backwards compatibility continue providing free functions.
Reimplement LLEventTimer using LLLater::doPeriodically(). One implication is
that LLEventTimer need no longer be derived from LLInstanceTracker, which we
used to iterate over all instances every tick. Give it start() and stop()
methods, since some subclasses (e.g. LLFlashTimer) used to call its member
LLTimer's start() and stop(). Remove updateClass():
LLCallbackList::callFunctions() now takes care of that.
Remove LLToastLifeTimer::start() and stop(), since LLEventTimer now provides
those. Remove getRemainingTimeF32(), since LLLater does not (yet) provide that
feature.
While at it, make LLEventTimer::tick() return bool instead of BOOL, and change
existing overrides.
Make LLApp::stepFrame() call LLCallbackList::callFunctions() instead of
LLEventTimer::updateClass().
We could have refactored LLEventTimer to use the mechanism now built into
LLLater, but frankly the LLEventTimer API is rather clumsy. You MUST derive a
subclass and override tick(), and you must instantiate your subclass on the
heap because, when your tick() override returns false, LLEventTimer deletes
its subclass instance. The LLLater API is simpler to use, and LLEventTimer is
much simplified by using it.
Merge lleventfilter.h's LLEventTimeoutBase into LLEventTimeout, and likewise
merge LLEventThrottleBase into LLEventThrottle. The separation was for
testability, but now that they're no longer based on LLTimer, it becomes
harder to use dummy time for testing. Temporarily skip tests based on
LLEventTimeoutBase and LLEventThrottleBase.
Instead of listening for LLEventPump("mainloop") ticks and using LLTimer,
LLEventTimeout now uses LLLater::doAfterInterval(). Instead of LLTimer and
LLEventTimeout, LLEventThrottle likewise now uses LLLater::doAfterInterval().
Recast a couple local LLEventTimeout pre-lambda callable classes with lambdas.
Dignify F64 with a new typedef LLDate::timestamp. LLDate heavily depends on
that as its base time representation, but there are those who question use of
floating-point for time. This is a step towards insulating us from any future
change.
|
|
|
|
|
|
|
|
cancel calls.
Refactor any remaining LLCore::HTTPHandlers to use boost::shared_ptr
Started minor refactor in the materials manager into coroutines (unfinished)
|
|
|
|
replace = NULL with .reset() on smart pointers.
|
|
|
|
Temp disable llmediaclient's unit tests for link issues.
|
|
|
|
|
|
|
|
|
|
changes to common libraries from the server codebase:
* Additional error checking in http handlers.
* Uniform log spam for http errors.
* Switch to using constants for http heads and status codes.
* Fixed bugs in incorrectly checking if parsing LLSD xml resulted in an error.
* Reduced spam regarding LLSD parsing errors in the default completedRaw http handler. It should not longer be necessary to short-circuit completedRaw to avoid spam.
* Ported over a few bug fixes from the server code.
* Switch mode http status codes to use S32 instead of U32.
* Ported LLSD::asStringRef from server code; avoids copying strings all over the place.
* Ported server change to LLSD::asBinary; this always returns a reference now instead of copying the entire binary blob.
* Ported server pretty notation format (and pretty binary format) to llsd serialization.
* The new LLCurl::Responder API no longer has two error handlers to choose from. Overriding the following methods have been deprecated:
** error - use httpFailure
** errorWithContent - use httpFailure
** result - use httpSuccess
** completed - use httpCompleted
** completedHeader - no longer necessary; call getResponseHeaders() from a completion method to obtain these headers.
* In order to 'catch' a completed http request, override one of these methods:
** httpSuccess - Called for any 2xx status code.
** httpFailure - Called for any non-2xx status code.
** httpComplete - Called for all status codes. Default implementation is to call either httpSuccess or httpFailure.
* It is recommended to keep these methods protected/private in order to avoid triggering of these methods without using a 'push' method (see below).
* Uniform error handling should followed whenever possible by calling a variant of this during httpFailure:
** llwarns << dumpResponse() << llendl;
* Be sure to include LOG_CLASS(your_class_name) in your class in order for the log entry to give more context.
* In order to 'push' a result into the responder, you should no longer call error, errorWithContent, result, or completed.
* Nor should you directly call httpSuccess/Failure/Completed (unless passing a message up to a parent class).
* Instead, you can set the internal content of a responder and trigger a corresponding method using the following methods:
** successResult - Sets results and calls httpSuccess
** failureResult - Sets results and calls httpFailure
** completedResult - Sets results and calls httpCompleted
* To obtain information about a the response from a reponder method, use the following getters:
** getStatus - HTTP status code
** getReason - Reason string
** getContent - Content (Parsed body LLSD)
** getResponseHeaders - Response Headers (LLSD map)
** getHTTPMethod - HTTP method of the request
** getURL - URL of the request
* It is still possible to override completeRaw if you want to manipulate data directly out of LLPumpIO.
* See indra/llmessage/llcurl.h for more information.
|
|
http error handlers to understand LLSD error responses. Fleshing out most http error handler message spam.
|
|
back-out the back-out for this branch. yay.
|
|
Backing out this merge that I pushed (prematurely) to the wrong place.
|
|
|
|
|
|
|
|
|
|
In LLVOVolume, added a count of LLMediaDataClientObjectImpl objects referencing each LLVOVolume object. This allows LLVOVolume::markDead() to skip the relatively expensive calls to removeFromQueue() when the LLVOVolume is known to have no active references.
Refactored LLMediaDataClient and its two child classes so that only LLObjectMediaDataClient has the round-robin queue (LLObjectMediaNavigateClient doesn't need it), and cleaned up some of the virtual function hierarchy around queue processing.
In LLMediaDataClient, added tracking for requests that aren't currently in a queue (i.e. requests that are in flight or waiting for retries) so they can be found when their objects are marked dead.
LLMediaDataClient::Request now directly keeps track of the object ID and face associated with the request.
Removed the "markedSent" concept from requests. Requests that have been sent are no longer kept in a queue.
The Retry timer now references the Request object instead of the Responder.
Replaced LLMediaDataClient::findOrRemove() with separate template functions for find and remove.
|
|
LLMediaDataClient::Request no longer stores the LLSD payload -- it now uses the link to the LLVOVolume (which it was already keeping around) to generate the LLSD for the request at the time it's sent.
LLMediaDataClient::Request no longer stores a capability name. Instead it uses the reference to its parent LLMediaDataClient subclass to refer to it as needed.
LLMediaDataClient::Request is now a base class, with subclasses for each specific request type -- GET, UPDATE, and NAVIGATE.
Responders are now created by a virtual method in the LLMediaDataClient::Request subclass instead of being created by the MDC. This allows different request types to use different responder classes.
Fixed an issue with LLMediaDataClient::QueueTimer and LLMediaDataClient::RetryTimer that caused the unit test to fail (they now do all the work in their tick() functions instead of using the destructor).
|
|
Added tags to some media-related logging in LLVOVolume.
Made LLMediaDataClient::Responder do most of its work in tick() instead of its destructor.
Added a comment to llmediadataclient.cpp that explains the idea behind the two-queue system.
Made LLMediaDataClient::sortQueue() remove requests from the queue that hold references to dead items. This should make teleporting away solve many of the pathological queueing cases.
Updated llmediadataclient test cases to reflect the change in behavior in sortQueue().
Removed some unnecessary const-ness in LLMediaDataClient::enqueue, which caused it to have to use const_cast.
|
|
|
|
This change bumps the queue sizes way up, because we
think that the "isInterestingEnough()" call will prevent
loading more media data than we think is necessary.
Still need to implement it in LLVOVolume, though
|
|
This is a fairly major change that addresses the issue of an object
with constantly-updating media. Before, that object would be put
into our single queue and sorted to a particular spot, and since it
continuously updates, it would "always be there". That means that
nothing "behind" it would ever get serviced.
This change introduces two queues for each MDC: one is the same
"sorted" queue as before, and the other is unsorted, and
"round-robins". New objects go into the sorted queue, objects
whose media we already know about get put into the unsorted queue.
The two queues are interleaved when serviced (one then the other is
serviced -- if one is empty we try the other -- until they are both
drained).
The round-robin queue works a little differently: after an item is
fetched from that queue (remember this would be an item we already
know about), that request is marked and put back at the end of the
queue. If that object gets a UDP update while in the queue, that mark
is "cleared". When it gets to the front of the queue again, if it
still marked, it is thrown away. If it is not marked, it is fetched,
and again marked and put at the end. This makes the queue
self-limiting in how big it can get.
I have also made some other changes:
- The sorting comparator now just delegates to the object for its
"interest" calculation. A higher value = more interesting.
LLVOVolume now uses its PixelArea for its "interest" calculation,
which seems apparently better (the prior distance calculation was
wrong anyway).
- The score is cached before the sort operation is performed, so that
it won't be expensive to sort
- Now, the media version that is fetched is saved in the LLVOVolume,
and we do not update if it is not newer (this is not very
useful...yet.)
- I've introduced hard limits (settable by debug settings) on the size
of the queues. The sorted queue will be culled (after sort) to that
count. NOTE: this will probably get removed in a later checkin, as
I've already gotten feedback that this is not desirable
- I've reorganized LLMediaDataClient so it makes more sense.
- I've made the request object a little smaller, so the queue won't take up so
much memory (more work could be done here)
- Added a unit test for the two-queue case (though more tests are needed!)
|
|
time an item is pulled off the queue
Review #43
This change refactors mediadataclient to no longer use a PriorityQueue (which sorts only on insertion), but rather just use a std::list which is re-sorted on insert, and also when "popped" (at the time the queue timer goes off).
Also implemented a unit test to make sure re-sorting occurs on timer tick.
|
|
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.
|
|
in flight
Review #33
This change marks the current selection "not editable" if
any objects in the selection are currently "in flight" (i.e.
their media data has not been fetched yet, or is in the
process of being fetched). This involved adding API to
LLMediaDataClient to query whether an object is in the
process of being fetched (i.e. in the queue). I've added
a unit test for this new API.
|
|
|
|
This required a bit of refactoring of LLMediaDataClient:
- Created LLMediaDataClientObject ABC, which now has a
concrete impl in LLVOVolume
- Created unit test with 6 tests (for now), testing
- LLObjectMediaDataClient::fetchMedia()
- LLObjectMediaDataClient::updateMedia()
- LLObjectMediaNavigateClient::navigate()
- queue ordering
- retries
- nav bounce back
- Also ensures that ref counting works properly (this is important, because
ownership is tricky with smart pointers put into queues, peeled off
into timers that fire and auto destruct, and HTTP responders that also
auto-destruct)
- Had to fix LLCurl::Responder's stub, which was not initializing
the ref count to 0, causing the ref counting tests to fail
(boy, that was hard to find!).
Reviewed by Callum
|
|
is "") if the server denies navigation
This refactors some of the bounceBack code into LLVOVolume.
It also changes an important rule: the edit panel now *will* send the
current URL to the server when you hit "OK". This change was done so
that if autoplay is on, we make sure the server gets the right data.
|
|
|
|
single reusable class
CC Review #7 (monroe)
LLMediaDataResponder and LLMediaDataFetcher were helpful classes that interacted with each other, but they were not general enough to cleanly be used for all media service interaction. This change refactors these classes into one (in fact, it is closer to a complete rewrite): LLMediaDataClient. This class has the following design points:
- You subclass from it when you want to specialize the responder, and then subclass from LLMediaDataClient::Responder if desired
- It has a few inner classes:
- LLMediaDataClient::Request, which now holds all of the data pertaining to a request, including retry counts
- LLMediaDataClient::Responder, which is now the LLHTTPClient::Responder
- LLMediaDataClient::PriorityQueue, which is now a STL priority_queue of Request objects.
- LLMediaDataClient::QueueTimer, which is the timer that fires to peel off queue items
- LLMediaDataClient::Responder::RetryTimer, which is the timer that is used when 503 errors are received.
The encapsulation of these inner classes is a lot cleaner and better reflects the scope of their responsibilities.
By and large, the logic hasn't really changed much. However, now there are two subclasses of LLMediaDataClient: one for the ObjectMedia cap and the other for the ObjectMediaNavigate cap. (I decided it was overkill to make three subclasses, one each for GET, UPDATE, and NAVIGATE, but we could still do that). LLVOVolume now instantiates both of these classes as statics (and destroys them on shutdown). They now have very simple API:
- LLObjectMediaDataClient::fetchMedia(LLVOVolume*) fetches the media for the given object
- LLObjectMediaDataClient::updateMedia(LLVOVolume*) sends an UPDATE of the media from the given object
- LLObjectMediaNavigateClient::navigate(LLVOVolume*, U8 texture_index, const std::string &url) navigates the given face (texture_index) on the given object to the given url.
|