summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcorehttp/bufferstream.h59
-rw-r--r--indra/llcorehttp/tests/test_bufferstream.hpp54
-rw-r--r--indra/newview/lltexturefetch.cpp27
-rw-r--r--indra/newview/lltexturefetch.h8
4 files changed, 133 insertions, 15 deletions
diff --git a/indra/llcorehttp/bufferstream.h b/indra/llcorehttp/bufferstream.h
index 60bda9ff9a..9327a798aa 100644
--- a/indra/llcorehttp/bufferstream.h
+++ b/indra/llcorehttp/bufferstream.h
@@ -34,13 +34,59 @@
#include "bufferarray.h"
+/// @file bufferstream.h
+///
+/// std::streambuf and std::iostream adapters for BufferArray
+/// objects.
+///
+/// BufferArrayStreamBuf inherits std::streambuf and implements
+/// an unbuffered interface for streambuf. This may or may not
+/// be the most time efficient implementation and it is a little
+/// challenging.
+///
+/// BufferArrayStream inherits std::iostream and will be the
+/// adapter object most callers will be interested in (though
+/// it uses BufferArrayStreamBuf internally). Instances allow
+/// for the usual streaming operators ('<<', '>>') and serialization
+/// methods.
+///
+/// Example of LLSD serialization to a BufferArray:
+///
+/// BufferArray * ba = new BufferArray;
+/// BufferArrayStream bas(ba);
+/// LLSDSerialize::toXML(llsd, bas);
+/// operationOnBufferArray(ba);
+/// ba->release();
+/// ba = NULL;
+/// // operationOnBufferArray and bas are each holding
+/// // references to the ba instance at this point.
+///
+
namespace LLCore
{
+// =====================================================
+// BufferArrayStreamBuf
+// =====================================================
+
+/// Adapter class to put a std::streambuf interface on a BufferArray
+///
+/// Application developers will rarely be interested in anything
+/// other than the constructor and even that will rarely be used
+/// except indirectly via the @BufferArrayStream class. The
+/// choice of interfaces implemented yields a bufferless adapter
+/// that doesn't used either the input or output pointer triplets
+/// of the more common buffered implementations. This may or may
+/// not be faster and that question could stand to be looked at
+/// sometime.
+///
+
class BufferArrayStreamBuf : public std::streambuf
{
public:
+ /// Constructor increments the reference count on the
+ /// BufferArray argument and calls release() on destruction.
BufferArrayStreamBuf(BufferArray * array);
virtual ~BufferArrayStreamBuf();
@@ -74,9 +120,22 @@ protected:
}; // end class BufferArrayStreamBuf
+// =====================================================
+// BufferArrayStream
+// =====================================================
+
+/// Adapter class that supplies streaming operators to BufferArray
+///
+/// Provides a streaming adapter to an existing BufferArray
+/// instance so that the convenient '<<' and '>>' conversions
+/// can be applied to a BufferArray. Very convenient for LLSD
+/// serialization and parsing as well.
+
class BufferArrayStream : public std::iostream
{
public:
+ /// Constructor increments the reference count on the
+ /// BufferArray argument and calls release() on destruction.
BufferArrayStream(BufferArray * ba);
~BufferArrayStream();
diff --git a/indra/llcorehttp/tests/test_bufferstream.hpp b/indra/llcorehttp/tests/test_bufferstream.hpp
index 45ddb7fd80..831c901b9d 100644
--- a/indra/llcorehttp/tests/test_bufferstream.hpp
+++ b/indra/llcorehttp/tests/test_bufferstream.hpp
@@ -31,6 +31,8 @@
#include <iostream>
#include "test_allocator.h"
+#include "llsd.h"
+#include "llsdserialize.h"
using namespace LLCore;
@@ -173,6 +175,8 @@ void BufferStreamTestObjectType::test<5>()
const char * content("This is a string. A fragment.");
const size_t c_len(strlen(content));
ba->append(content, c_len);
+
+ // Creat an adapter for the BufferArray
BufferArrayStreamBuf * bsb = new BufferArrayStreamBuf(ba);
ensure("Memory being used", mMemTotal < GetMemTotal());
@@ -223,7 +227,7 @@ void BufferStreamTestObjectType::test<6>()
//ba->append(content, strlen(content));
{
- // create a new ref counted object with an implicit reference
+ // Creat an adapter for the BufferArray
BufferArrayStream bas(ba);
ensure("Memory being used", mMemTotal < GetMemTotal());
@@ -246,6 +250,54 @@ void BufferStreamTestObjectType::test<6>()
}
+template <> template <>
+void BufferStreamTestObjectType::test<7>()
+{
+ set_test_name("BufferArrayStream with LLSD serialization");
+
+ // record the total amount of dynamically allocated memory
+ mMemTotal = GetMemTotal();
+
+ // create a new ref counted BufferArray with implicit reference
+ BufferArray * ba = new BufferArray;
+
+ {
+ // Creat an adapter for the BufferArray
+ BufferArrayStream bas(ba);
+ ensure("Memory being used", mMemTotal < GetMemTotal());
+
+ // LLSD
+ LLSD llsd = LLSD::emptyMap();
+
+ llsd["int"] = LLSD::Integer(3);
+ llsd["float"] = LLSD::Real(923289.28992);
+ llsd["string"] = LLSD::String("aksjdl;ajsdgfjgfal;sdgjakl;sdfjkl;ajsdfkl;ajsdfkl;jaskl;dfj");
+
+ LLSD llsd_map = LLSD::emptyMap();
+ llsd_map["int"] = LLSD::Integer(-2889);
+ llsd_map["float"] = LLSD::Real(2.37829e32);
+ llsd_map["string"] = LLSD::String("OHIGODHSPDGHOSDHGOPSHDGP");
+
+ llsd["map"] = llsd_map;
+
+ // Serialize it
+ LLSDSerialize::toXML(llsd, bas);
+
+ std::string str;
+ bas >> str;
+ // std::cout << "SERIALIZED LLSD: " << str << std::endl;
+ ensure("Extracted string has reasonable length", str.size() > 60);
+ }
+
+ // release the implicit reference, causing the object to be released
+ ba->release();
+ ba = NULL;
+
+ // make sure we didn't leak any memory
+ // ensure("Allocated memory returned", mMemTotal == GetMemTotal());
+}
+
+
} // end namespace tut
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 4995d9f5ea..6b186811f1 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -58,6 +58,7 @@
#include "httphandler.h"
#include "httpresponse.h"
#include "bufferarray.h"
+#include "bufferstream.h"
//////////////////////////////////////////////////////////////////////////////
@@ -2182,6 +2183,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHttpRequest(NULL),
mHttpOptions(NULL),
mHttpHeaders(NULL),
+ mHttpMetricsHeaders(NULL),
mHttpSemaphore(HTTP_REQUESTS_IN_QUEUE_HIGH_WATER),
mTotalCacheReadCount(0U),
mTotalCacheWriteCount(0U),
@@ -2194,6 +2196,8 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHttpOptions = new LLCore::HttpOptions;
mHttpHeaders = new LLCore::HttpHeaders;
mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c");
+ mHttpMetricsHeaders = new LLCore::HttpHeaders;
+ mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml");
}
LLTextureFetch::~LLTextureFetch()
@@ -2219,6 +2223,12 @@ LLTextureFetch::~LLTextureFetch()
mHttpHeaders = NULL;
}
+ if (mHttpMetricsHeaders)
+ {
+ mHttpMetricsHeaders->release();
+ mHttpMetricsHeaders = NULL;
+ }
+
mHttpWaitResource.clear();
delete mHttpRequest;
@@ -3501,29 +3511,18 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
if (! mCapsURL.empty())
{
- // *FIXME: This mess to get an llsd into a string though
- // it's actually no worse than what we currently do...
- std::stringstream body;
- LLSDSerialize::toXML(merged_llsd, body);
- std::string body_str(body.str());
- body.clear();
-
- LLCore::HttpHeaders * headers = new LLCore::HttpHeaders;
- headers->mHeaders.push_back("Content-Type: application/llsd+xml");
-
LLCore::BufferArray * ba = new LLCore::BufferArray;
- ba->append(body_str.c_str(), body_str.length());
- body_str.clear();
+ LLCore::BufferArrayStream bas(ba);
+ LLSDSerialize::toXML(merged_llsd, bas);
fetcher->getHttpRequest().requestPost(report_policy_class,
report_priority,
mCapsURL,
ba,
NULL,
- headers,
+ fetcher->getMetricsHeaders(),
handler);
ba->release();
- headers->release();
LLTextureFetch::svMetricsDataBreak = false;
}
else
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index e17c71113a..4d762a0e05 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -157,6 +157,13 @@ public:
// Threads: T*
LLCore::HttpRequest & getHttpRequest() { return *mHttpRequest; }
+ // Return a pointer to the shared metrics headers definition.
+ // Does not increment the reference count, caller is required
+ // to do that to hold a reference for any length of time.
+ //
+ // Threads: T*
+ LLCore::HttpHeaders * getMetricsHeaders() const { return mHttpMetricsHeaders; }
+
bool isQAMode() const { return mQAMode; }
// ----------------------------------
@@ -322,6 +329,7 @@ private:
LLCore::HttpRequest * mHttpRequest; // Ttf
LLCore::HttpOptions * mHttpOptions; // Ttf
LLCore::HttpHeaders * mHttpHeaders; // Ttf
+ LLCore::HttpHeaders * mHttpMetricsHeaders; // Ttf
// We use a resource semaphore to keep HTTP requests in
// WAIT_HTTP_RESOURCE2 if there aren't sufficient slots in the