summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llinstancetracker.h10
-rw-r--r--indra/llcommon/lltracerecording.cpp136
-rw-r--r--indra/llcommon/lltracerecording.h28
3 files changed, 170 insertions, 4 deletions
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 596bea548d..a79ddd088d 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -67,6 +67,7 @@ protected:
/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
/// If KEY is not provided, then instances are stored in a simple set
/// @NOTE: see explicit specialization below for default KEY==void case
+/// @NOTE: this class is not thread-safe unless used as read-only
template<typename T, typename KEY = void>
class LLInstanceTracker : public LLInstanceTrackerBase
{
@@ -120,13 +121,13 @@ public:
typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t;
key_iter(typename InstanceMap::iterator it)
- : mIterator(it)
+ : mIterator(it)
{
getStatic().incrementDepth();
}
key_iter(const key_iter& other)
- : mIterator(other.mIterator)
+ : mIterator(other.mIterator)
{
getStatic().incrementDepth();
}
@@ -171,7 +172,10 @@ public:
return instance_iter(getMap_().end());
}
- static S32 instanceCount() { return getMap_().size(); }
+ static S32 instanceCount()
+ {
+ return getMap_().size();
+ }
static key_iter beginKeys()
{
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 21156b4d61..2917c217d7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -396,6 +396,76 @@ void PeriodicRecording::nextPeriod()
}
}
+
+void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
+{
+ if (other.mRecordingPeriods.size() < 2) return;
+
+ EPlayState play_state = getPlayState();
+ pause();
+
+ EPlayState other_play_state = other.getPlayState();
+ other.pause();
+
+ if (mAutoResize)
+ {
+ // copy everything after current period of other recording to end of buffer
+ // this will only apply if other recording is using a fixed circular buffer
+ if (other.mCurPeriod < other.mRecordingPeriods.size() - 1)
+ {
+ std::copy( other.mRecordingPeriods.begin() + other.mCurPeriod + 1,
+ other.mRecordingPeriods.end(),
+ std::back_inserter(mRecordingPeriods));
+ }
+
+ // copy everything from beginning of other recording's buffer up to, but not including
+ // current period
+ std::copy( other.mRecordingPeriods.begin(),
+ other.mRecordingPeriods.begin() + other.mCurPeriod,
+ std::back_inserter(mRecordingPeriods));
+
+ mCurPeriod = mRecordingPeriods.size() - 1;
+ }
+ else
+ {
+ size_t num_to_copy = llmin( mRecordingPeriods.size(), other.mRecordingPeriods.size() );
+ std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin()
+ + ( (other.mCurPeriod + 1) // cur period
+ + (other.mRecordingPeriods.size() - num_to_copy) // minus room for copy
+ % other.mRecordingPeriods.size());
+ std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + ((mCurPeriod + 1) % mRecordingPeriods.size());
+
+ for(S32 i = 0; i < num_to_copy; i++)
+ {
+ *dest_it = *src_it;
+
+ if (++src_it == other.mRecordingPeriods.end())
+ {
+ src_it = other.mRecordingPeriods.begin();
+ }
+
+ if (++dest_it == mRecordingPeriods.end())
+ {
+ dest_it = mRecordingPeriods.begin();
+ }
+ }
+
+ mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size();
+ }
+
+ // if copying from periodic recording that wasn't active advance our period to the next available one
+ // otherwise continue recording on top of the last period of data received from the other recording
+ if (other_play_state != STARTED)
+ {
+ nextPeriod();
+ }
+
+ setPlayState(play_state);
+ other.setPlayState(other_play_state);
+}
+
+
+
void PeriodicRecording::start()
{
getCurRecording().start();
@@ -503,6 +573,72 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other)
mPotentialRecording.splitFrom(other.mPotentialRecording);
}
+///////////////////////////////////////////////////////////////////////
+// ExtendablePeriodicRecording
+///////////////////////////////////////////////////////////////////////
+
+void ExtendablePeriodicRecording::extend()
+{
+ // stop recording to get latest data
+ mPotentialRecording.stop();
+ // push the data back to accepted recording
+ mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
+ // flush data, so we can start from scratch
+ mPotentialRecording.reset();
+ // go back to play state we were in initially
+ mPotentialRecording.setPlayState(getPlayState());
+}
+
+void ExtendablePeriodicRecording::start()
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::start();
+ mPotentialRecording.start();
+}
+
+void ExtendablePeriodicRecording::stop()
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::stop();
+ mPotentialRecording.stop();
+}
+
+void ExtendablePeriodicRecording::pause()
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::pause();
+ mPotentialRecording.pause();
+}
+
+void ExtendablePeriodicRecording::resume()
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::resume();
+ mPotentialRecording.resume();
+}
+
+void ExtendablePeriodicRecording::restart()
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::restart();
+ mAcceptedRecording.reset();
+ mPotentialRecording.restart();
+}
+
+void ExtendablePeriodicRecording::reset()
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::reset();
+ mAcceptedRecording.reset();
+ mPotentialRecording.reset();
+}
+
+void ExtendablePeriodicRecording::splitTo(ExtendablePeriodicRecording& other)
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitTo(other);
+ mPotentialRecording.splitTo(other.mPotentialRecording);
+}
+
+void ExtendablePeriodicRecording::splitFrom(ExtendablePeriodicRecording& other)
+{
+ LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitFrom(other);
+ mPotentialRecording.splitFrom(other.mPotentialRecording);
+}
+
PeriodicRecording& get_frame_recording()
{
static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED));
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 7c4113dbf0..23b031b49b 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -254,6 +254,8 @@ namespace LLTrace
void nextPeriod();
U32 getNumPeriods() { return mRecordingPeriods.size(); }
+ void appendPeriodicRecording(PeriodicRecording& other);
+
Recording& getLastRecording()
{
U32 num_periods = mRecordingPeriods.size();
@@ -424,6 +426,7 @@ namespace LLTrace
void extend();
Recording& getAcceptedRecording() { return mAcceptedRecording; }
+ const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
// implementation for LLStopWatchControlsMixin
/*virtual*/ void start();
@@ -435,11 +438,34 @@ namespace LLTrace
/*virtual*/ void splitTo(ExtendableRecording& other);
/*virtual*/ void splitFrom(ExtendableRecording& other);
- const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
private:
Recording mAcceptedRecording;
Recording mPotentialRecording;
};
+
+ class ExtendablePeriodicRecording
+ : public LLStopWatchControlsMixin<ExtendablePeriodicRecording>
+ {
+ public:
+ void extend();
+
+ PeriodicRecording& getAcceptedRecording() { return mAcceptedRecording; }
+ const PeriodicRecording& getAcceptedRecording() const {return mAcceptedRecording;}
+
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void start();
+ /*virtual*/ void stop();
+ /*virtual*/ void pause();
+ /*virtual*/ void resume();
+ /*virtual*/ void restart();
+ /*virtual*/ void reset();
+ /*virtual*/ void splitTo(ExtendablePeriodicRecording& other);
+ /*virtual*/ void splitFrom(ExtendablePeriodicRecording& other);
+
+ private:
+ PeriodicRecording mAcceptedRecording;
+ PeriodicRecording mPotentialRecording;
+ };
}
#endif // LL_LLTRACERECORDING_H