summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
authorJosh Bell <josh@lindenlab.com>2008-02-13 01:02:09 +0000
committerJosh Bell <josh@lindenlab.com>2008-02-13 01:02:09 +0000
commit54e428d2094267d993fd51dc1d879106083d3db5 (patch)
treee9586f1c2fffbdaba897fa43f6d5ead18ae6f0df /indra/llmessage
parenteb55ba3c7f51fa47336bead33077c298cec33b65 (diff)
svn merge -r 79828:79862 svn+ssh://svn.lindenlab.com/svn/linden/qa/combo-merge-2008-02-12 --> release
QAR-280 - combo merge of: * QAR-249 Allow specifying max http protocol version in eventlet.httpd, and change backbone.py to specify HTTP/1.0 explicitly * QAR-272 Switch logout/disconnect messages to syslog/streambase * QAR-253 Test for the group names fix * QAR-260 metrics-3 for release merge
Diffstat (limited to 'indra/llmessage')
-rw-r--r--indra/llmessage/llassetstorage.cpp59
-rw-r--r--indra/llmessage/llassetstorage.h26
-rw-r--r--indra/llmessage/llcachename.cpp129
-rw-r--r--indra/llmessage/llcachename.h8
-rw-r--r--indra/llmessage/llhttpassetstorage.cpp67
5 files changed, 246 insertions, 43 deletions
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index d5e04456c4..e2043144b8 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -53,7 +53,10 @@
#include "lltransfersourceasset.h"
#include "lltransfertargetvfile.h" // For debugging
+#include "llmetrics.h"
+
LLAssetStorage *gAssetStorage = NULL;
+LLMetrics *LLAssetStorage::metric_recipient = NULL;
const LLUUID CATEGORIZE_LOST_AND_FOUND_ID("00000000-0000-0000-0000-000000000010");
@@ -1279,6 +1282,8 @@ void LLAssetStorage::storeAssetData(
F64 timeout)
{
llwarns << "storeAssetData: wrong version called" << llendl;
+ // LLAssetStorage metric: Virtual base call
+ reportMetric( LLUUID::null, asset_type, NULL, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 1" );
}
// virtual
@@ -1296,6 +1301,8 @@ void LLAssetStorage::storeAssetData(
F64 timeout)
{
llwarns << "storeAssetData: wrong version called" << llendl;
+ // LLAssetStorage metric: Virtual base call
+ reportMetric( asset_id, asset_type, NULL, requesting_agent_id, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 2" );
}
// virtual
@@ -1312,6 +1319,8 @@ void LLAssetStorage::storeAssetData(
F64 timeout)
{
llwarns << "storeAssetData: wrong version called" << llendl;
+ // LLAssetStorage metric: Virtual base call
+ reportMetric( asset_id, asset_type, NULL, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 3" );
}
// virtual
@@ -1328,6 +1337,8 @@ void LLAssetStorage::storeAssetData(
F64 timeout)
{
llwarns << "storeAssetData: wrong version called" << llendl;
+ // LLAssetStorage metric: Virtual base call
+ reportMetric( LLUUID::null, asset_type, NULL, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 4" );
}
// static
@@ -1372,3 +1383,51 @@ void LLAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const
// virtual
void LLAssetStorage::clearTempAssetData()
{ }
+
+// static
+void LLAssetStorage::reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const char *filename,
+ const LLUUID& agent_id, S32 asset_size, EMetricResult result,
+ const char *file, const S32 line, const char *message )
+{
+ if( !metric_recipient )
+ {
+ llinfos << "Couldn't store LLAssetStoreage::reportMetric - no metrics_recipient" << llendl;
+ return;
+ }
+
+ filename = filename ? filename : "";
+ file = file ? file : "";
+
+ // Create revised message - message = "message :: file:line"
+ std::string new_message; //( message );
+ new_message = message; // << " " << file << " " << line;
+ new_message += " :: ";
+ new_message += filename;
+ char line_string[16];
+ sprintf( line_string, ":%d", line );
+ new_message += line_string;
+ message = new_message.c_str();
+
+ // Change always_report to true if debugging... do not check it in this way
+ static bool always_report = false;
+ const char *metric_name = "LLAssetStorage::Metrics";
+
+ bool success = result == MR_OKAY;
+
+ if( (!success) || always_report )
+ {
+ LLSD stats;
+ stats["asset_id"] = asset_id;
+ stats["asset_type"] = asset_type;
+ stats["filename"] = filename? filename : "";
+ stats["agent_id"] = agent_id;
+ stats["asset_size"] = (S32)asset_size;
+ stats["result"] = (S32)result;
+
+ metric_recipient->recordEventDetails( metric_name, message, success, stats);
+ }
+ else
+ {
+ metric_recipient->recordEvent(metric_name, message, success);
+ }
+}
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index e2ccf2ca91..8da3926c63 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -420,6 +420,32 @@ private:
LLXferManager *xfer,
LLVFS *vfs,
const LLHost &upstream_host);
+
+protected:
+ enum EMetricResult
+ {
+ // Static valued enums for #dw readability - please copy this
+ // declaration to them on updates -- source in llassetstorage.h
+ MR_INVALID = -1, // Makes no sense
+ MR_OKAY = 0, // Success - no metric normally
+ MR_ZERO_SIZE = 1, // Zero size asset
+ MR_BAD_FUNCTION = 2, // Tried to use a virtual base (PROGRAMMER ERROR)
+ MR_FILE_NONEXIST = 3, // Old format store call - source file does not exist
+ MR_NO_FILENAME = 4, // Old format store call - source filename is NULL/0-length
+ MR_NO_UPSTREAM = 5, // Upstream provider is missing
+ MR_VFS_CORRUPTION = 6 // VFS is corrupt - too-large or mismatched stated/returned sizes
+ };
+
+ static class LLMetrics *metric_recipient;
+
+ static void reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const char *filename,
+ const LLUUID& agent_id, S32 asset_size, EMetricResult result,
+ const char *file, const S32 line, const char *message );
+public:
+ static void setMetricRecipient( LLMetrics *recip )
+ {
+ metric_recipient = recip;
+ }
};
////////////////////////////////////////////////////////////////////////
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index f731c95a14..3472c3eb5d 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -34,12 +34,13 @@
#include "llcachename.h"
// linden library includes
-#include "message.h"
-#include "llrand.h"
#include "lldbstrings.h"
#include "llframetimer.h"
#include "llhost.h"
+#include "llrand.h"
+#include "llsdserialize.h"
#include "lluuid.h"
+#include "message.h"
// Constants
const char* CN_WAITING = "(waiting)";
@@ -48,6 +49,14 @@ const char* CN_NONE = "(none)";
const char* CN_HIPPOS = "(hippos)";
const F32 HIPPO_PROBABILITY = 0.01f;
+// llsd serialization constants
+static const std::string AGENTS("agents");
+static const std::string GROUPS("groups");
+static const std::string CTIME("ctime");
+static const std::string FIRST("first");
+static const std::string LAST("last");
+static const std::string NAME("name");
+
// We track name requests in flight for up to this long.
// We won't re-request a name during this time
const U32 PENDING_TIMEOUT_SECS = 5 * 60;
@@ -392,41 +401,100 @@ void LLCacheName::importFile(FILE* fp)
llinfos << "LLCacheName loaded " << count << " names" << llendl;
}
-
-void LLCacheName::exportFile(FILE* fp)
+bool LLCacheName::importFile(std::istream& istr)
{
- fprintf(fp, "version\t%d\n", CN_FILE_VERSION);
+ LLSD data;
+ if(LLSDSerialize::fromXML(data, istr) < 1)
+ return false;
- for (Cache::iterator iter = impl.mCache.begin(),
- end = impl.mCache.end();
- iter != end; iter++)
+ // We'll expire entries more than a week old
+ U32 now = (U32)time(NULL);
+ const U32 SECS_PER_DAY = 60 * 60 * 24;
+ U32 delete_before_time = now - (7 * SECS_PER_DAY);
+
+ // iterate over the agents
+ S32 count = 0;
+ LLSD agents = data[AGENTS];
+ LLSD::map_iterator iter = agents.beginMap();
+ LLSD::map_iterator end = agents.endMap();
+ for( ; iter != end; ++iter)
{
- LLCacheNameEntry* entry = iter->second;
- // Only write entries for which we have valid data.
- // HACK: Only write agent names. This makes the reader easier.
- if ( entry->mFirstName[0]
- && entry->mLastName[0])
- {
- LLUUID id = iter->first;
+ LLUUID id((*iter).first);
+ LLSD agent = (*iter).second;
+ U32 ctime = (U32)agent[CTIME].asInteger();
+ if(ctime < delete_before_time) continue;
- // Trivial XOR encoding
- S32 i;
- for (i = 0; i < UUID_BYTES; i++)
- {
- id.mData[i] ^= 0x33;
- }
+ LLCacheNameEntry* entry = new LLCacheNameEntry();
+ entry->mIsGroup = false;
+ entry->mCreateTime = ctime;
+ std::string first = agent[FIRST].asString();
+ first.copy(entry->mFirstName, DB_FIRST_NAME_BUF_SIZE, 0);
+ entry->mFirstName[llmin(first.size(),(std::string::size_type)DB_FIRST_NAME_BUF_SIZE-1)] = '\0';
+ std::string last = agent[LAST].asString();
+ last.copy(entry->mLastName, DB_LAST_NAME_BUF_SIZE, 0);
+ entry->mLastName[llmin(last.size(),(std::string::size_type)DB_LAST_NAME_BUF_SIZE-1)] = '\0';
+ impl.mCache[id] = entry;
+ ++count;
+ }
+ llinfos << "LLCacheName loaded " << count << " agent names" << llendl;
+
+ count = 0;
+ LLSD groups = data[GROUPS];
+ iter = groups.beginMap();
+ end = groups.endMap();
+ for( ; iter != end; ++iter)
+ {
+ LLUUID id((*iter).first);
+ LLSD group = (*iter).second;
+ U32 ctime = (U32)group[CTIME].asInteger();
+ if(ctime < delete_before_time) continue;
- char id_string[UUID_STR_SIZE]; /*Flawfinder:ignore*/
- id.toString(id_string);
+ LLCacheNameEntry* entry = new LLCacheNameEntry();
+ entry->mIsGroup = true;
+ entry->mCreateTime = ctime;
+ std::string name = group[NAME].asString();
+ name.copy(entry->mGroupName, DB_GROUP_NAME_BUF_SIZE, 0);
+ entry->mGroupName[llmin(name.size(), (std::string::size_type)DB_GROUP_NAME_BUF_SIZE-1)] = '\0';
+ impl.mCache[id] = entry;
+ ++count;
+ }
+ llinfos << "LLCacheName loaded " << count << " group names" << llendl;
+ return true;
+}
- // ...not a group name
- fprintf(fp, "%s\t%u\t%s\t%s\n",
- id_string,
- entry->mCreateTime,
- entry->mFirstName,
- entry->mLastName);
+void LLCacheName::exportFile(std::ostream& ostr)
+{
+ LLSD data;
+ Cache::iterator iter = impl.mCache.begin();
+ Cache::iterator end = impl.mCache.end();
+ for( ; iter != end; ++iter)
+ {
+ // Only write entries for which we have valid data.
+ LLCacheNameEntry* entry = iter->second;
+ if(!entry
+ || (NULL != strchr(entry->mFirstName, '?'))
+ || (NULL != strchr(entry->mGroupName, '?')))
+ {
+ continue;
+ }
+
+ // store it
+ LLUUID id = iter->first;
+ std::string id_str = id.asString();
+ if(entry->mFirstName[0] && entry->mLastName[0])
+ {
+ data[AGENTS][id_str][FIRST] = entry->mFirstName;
+ data[AGENTS][id_str][LAST] = entry->mLastName;
+ data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime;
+ }
+ else if(entry->mIsGroup && entry->mGroupName[0])
+ {
+ data[GROUPS][id_str][NAME] = entry->mGroupName;
+ data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
}
}
+
+ LLSDSerialize::toPrettyXML(data, ostr);
}
@@ -884,6 +952,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
}
-
-
-
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index ab6282966d..4eae6365bc 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -63,9 +63,12 @@ public:
void cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL);
- // storing cache on disk; for viewer, in name.cache
+ // janky old format. Remove after a while. Phoenix. 2008-01-30
void importFile(FILE* fp);
- void exportFile(FILE* fp);
+
+ // storing cache on disk; for viewer, in name.cache
+ bool importFile(std::istream& istr);
+ void exportFile(std::ostream& ostr);
// If available, copies the first and last name into the strings provided.
// first must be at least DB_FIRST_NAME_BUF_SIZE characters.
@@ -104,6 +107,7 @@ public:
static LLString getDefaultName();
private:
+
class Impl;
Impl& impl;
};
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index c5b897b87b..cf9bde6fec 100644
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -451,7 +451,7 @@ void LLHTTPAssetStorage::storeAssetData(
bool user_waiting,
F64 timeout)
{
- if (mVFS->getExists(uuid, type))
+ if (mVFS->getExists(uuid, type)) // VFS treats nonexistant and zero-length identically
{
LLAssetRequest *req = new LLAssetRequest(uuid, type);
req->mUpCallback = callback;
@@ -460,6 +460,19 @@ void LLHTTPAssetStorage::storeAssetData(
req->mIsUserWaiting = user_waiting;
req->mTimeout = timeout;
+ // LLAssetStorage metric: Successful Request
+ S32 size = mVFS->getSize(uuid, type);
+ const char *message;
+ if( store_local )
+ {
+ message = "Added to local upload queue";
+ }
+ else
+ {
+ message = "Added to upload queue";
+ }
+ reportMetric( uuid, type, NULL, requesting_agent_id, size, MR_OKAY, __FILE__, __LINE__, message );
+
// this will get picked up and transmitted in checkForTimeouts
if(store_local)
{
@@ -479,6 +492,8 @@ void LLHTTPAssetStorage::storeAssetData(
llwarns << "AssetStorage: attempt to upload non-existent vfile " << uuid << ":" << LLAssetType::lookup(type) << llendl;
if (callback)
{
+ // LLAssetStorage metric: Zero size VFS
+ reportMetric( uuid, type, NULL, requesting_agent_id, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
callback(uuid, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE);
}
}
@@ -504,13 +519,17 @@ void LLHTTPAssetStorage::storeAssetData(
legacy->mUserData = user_data;
FILE *fp = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
+ S32 size = 0;
if (fp)
{
- LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
-
fseek(fp, 0, SEEK_END);
- S32 size = ftell(fp);
+ size = ftell(fp);
fseek(fp, 0, SEEK_SET);
+ }
+
+ if( size )
+ {
+ LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
file.setMaxSize(size);
@@ -528,6 +547,7 @@ void LLHTTPAssetStorage::storeAssetData(
LLFile::remove(filename);
}
+ // LLAssetStorage metric: Success not needed; handled in the overloaded method here:
storeAssetData(
asset_id,
asset_type,
@@ -540,8 +560,19 @@ void LLHTTPAssetStorage::storeAssetData(
user_waiting,
timeout);
}
- else
+ else // !size
{
+ if( fp )
+ {
+ // LLAssetStorage metric: Zero size
+ reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" );
+ fclose( fp );
+ }
+ else
+ {
+ // LLAssetStorage metric: Missing File
+ reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" );
+ }
if (callback)
{
callback(LLUUID::null, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE);
@@ -827,7 +858,16 @@ void LLHTTPAssetStorage::checkForTimeouts()
}
else
{
- llinfos << "Requesting PUT " << new_req->mURLBuffer << llendl;
+ // Get the uncompressed file size.
+ LLVFile file(mVFS,new_req->getUUID(),new_req->getType());
+ S32 size = file.getSize();
+ llinfos << "Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << llendl;
+ if (size == 0)
+ {
+ llwarns << "Rejecting zero size PUT request!" << llendl;
+ new_req->cleanupCurlHandle();
+ deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID());
+ }
}
// Pending upload will have been flagged by the request
}
@@ -867,8 +907,19 @@ void LLHTTPAssetStorage::checkForTimeouts()
}
else
{
+ // Get the uncompressed file size.
+ S32 size = file.getSize();
+
llinfos << "TAT: LLHTTPAssetStorage::checkForTimeouts() : pending local!"
- << " Requesting PUT " << new_req->mURLBuffer << llendl;
+ << " Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << llendl;
+ if (size == 0)
+ {
+
+ llwarns << "Rejecting zero size PUT request!" << llendl;
+ new_req->cleanupCurlHandle();
+ deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID());
+ }
+
}
// Pending upload will have been flagged by the request
}
@@ -1403,5 +1454,3 @@ void LLHTTPAssetStorage::clearTempAssetData()
llinfos << "TAT: Clearing temp asset data map" << llendl;
mTempAssets.clear();
}
-
-