diff options
Diffstat (limited to 'linden')
29 files changed, 1075 insertions, 212 deletions
diff --git a/linden/etc/message.xml b/linden/etc/message.xml index 0695d05..d833074 100644 --- a/linden/etc/message.xml +++ b/linden/etc/message.xml | |||
@@ -441,6 +441,30 @@ | |||
441 | <boolean>true</boolean> | 441 | <boolean>true</boolean> |
442 | </map> | 442 | </map> |
443 | 443 | ||
444 | <key>EnableSimulator</key> | ||
445 | <map> | ||
446 | <key>flavor</key> | ||
447 | <string>llsd</string> | ||
448 | <key>trusted-sender</key> | ||
449 | <boolean>true</boolean> | ||
450 | </map> | ||
451 | |||
452 | <key>TeleportFinish</key> | ||
453 | <map> | ||
454 | <key>flavor</key> | ||
455 | <string>llsd</string> | ||
456 | <key>trusted-sender</key> | ||
457 | <boolean>true</boolean> | ||
458 | </map> | ||
459 | |||
460 | <key>CrossedRegion</key> | ||
461 | <map> | ||
462 | <key>flavor</key> | ||
463 | <string>llsd</string> | ||
464 | <key>trusted-sender</key> | ||
465 | <boolean>true</boolean> | ||
466 | </map> | ||
467 | |||
444 | <!-- UDPDeprecated Messages --> | 468 | <!-- UDPDeprecated Messages --> |
445 | <key>ScriptRunningReply</key> | 469 | <key>ScriptRunningReply</key> |
446 | <map> | 470 | <map> |
diff --git a/linden/indra/lib/python/indra/ipc/llsdhttp.py b/linden/indra/lib/python/indra/ipc/llsdhttp.py index 1cf1146..ed64899 100644 --- a/linden/indra/lib/python/indra/ipc/llsdhttp.py +++ b/linden/indra/lib/python/indra/ipc/llsdhttp.py | |||
@@ -51,6 +51,8 @@ request_ = suite.request_ | |||
51 | # import every httpc error exception into our namespace for convenience | 51 | # import every httpc error exception into our namespace for convenience |
52 | for x in httpc.status_to_error_map.itervalues(): | 52 | for x in httpc.status_to_error_map.itervalues(): |
53 | globals()[x.__name__] = x | 53 | globals()[x.__name__] = x |
54 | ConnectionError = httpc.ConnectionError | ||
55 | Retriable = httpc.Retriable | ||
54 | 56 | ||
55 | for x in (httpc.ConnectionError,): | 57 | for x in (httpc.ConnectionError,): |
56 | globals()[x.__name__] = x | 58 | globals()[x.__name__] = x |
diff --git a/linden/indra/lib/python/indra/ipc/mysql_pool.py b/linden/indra/lib/python/indra/ipc/mysql_pool.py index 507b185..25a66cf 100644 --- a/linden/indra/lib/python/indra/ipc/mysql_pool.py +++ b/linden/indra/lib/python/indra/ipc/mysql_pool.py | |||
@@ -30,8 +30,10 @@ import MySQLdb | |||
30 | from eventlet import db_pool | 30 | from eventlet import db_pool |
31 | 31 | ||
32 | class DatabaseConnector(db_pool.DatabaseConnector): | 32 | class DatabaseConnector(db_pool.DatabaseConnector): |
33 | def __init__(self, credentials, min_size = 0, max_size = 4, *args, **kwargs): | 33 | def __init__(self, credentials, *args, **kwargs): |
34 | super(DatabaseConnector, self).__init__(MySQLdb, credentials, min_size, max_size, conn_pool=db_pool.ConnectionPool, *args, **kwargs) | 34 | super(DatabaseConnector, self).__init__(MySQLdb, credentials, |
35 | conn_pool=db_pool.ConnectionPool, | ||
36 | *args, **kwargs) | ||
35 | 37 | ||
36 | # get is extended relative to eventlet.db_pool to accept a port argument | 38 | # get is extended relative to eventlet.db_pool to accept a port argument |
37 | def get(self, host, dbname, port=3306): | 39 | def get(self, host, dbname, port=3306): |
@@ -42,7 +44,7 @@ class DatabaseConnector(db_pool.DatabaseConnector): | |||
42 | new_kwargs['host'] = host | 44 | new_kwargs['host'] = host |
43 | new_kwargs['port'] = port | 45 | new_kwargs['port'] = port |
44 | new_kwargs.update(self.credentials_for(host)) | 46 | new_kwargs.update(self.credentials_for(host)) |
45 | dbpool = ConnectionPool(self._min_size, self._max_size, *self._args, **new_kwargs) | 47 | dbpool = ConnectionPool(*self._args, **new_kwargs) |
46 | self._databases[key] = dbpool | 48 | self._databases[key] = dbpool |
47 | 49 | ||
48 | return self._databases[key] | 50 | return self._databases[key] |
@@ -51,8 +53,8 @@ class ConnectionPool(db_pool.TpooledConnectionPool): | |||
51 | """A pool which gives out saranwrapped MySQLdb connections from a pool | 53 | """A pool which gives out saranwrapped MySQLdb connections from a pool |
52 | """ | 54 | """ |
53 | 55 | ||
54 | def __init__(self, min_size = 0, max_size = 4, *args, **kwargs): | 56 | def __init__(self, *args, **kwargs): |
55 | super(ConnectionPool, self).__init__(MySQLdb, min_size, max_size, *args, **kwargs) | 57 | super(ConnectionPool, self).__init__(MySQLdb, *args, **kwargs) |
56 | 58 | ||
57 | def get(self): | 59 | def get(self): |
58 | conn = super(ConnectionPool, self).get() | 60 | conn = super(ConnectionPool, self).get() |
@@ -77,14 +79,3 @@ class ConnectionPool(db_pool.TpooledConnectionPool): | |||
77 | conn.connection_parameters = converted_kwargs | 79 | conn.connection_parameters = converted_kwargs |
78 | return conn | 80 | return conn |
79 | 81 | ||
80 | def clear(self): | ||
81 | """ Close all connections that this pool still holds a reference to, leaving it empty.""" | ||
82 | for conn in self.free_items: | ||
83 | try: | ||
84 | conn.close() | ||
85 | except: | ||
86 | pass # even if stuff happens here, we still want to at least try to close all the other connections | ||
87 | self.free_items.clear() | ||
88 | |||
89 | def __del__(self): | ||
90 | self.clear() | ||
diff --git a/linden/indra/lib/python/indra/ipc/servicebuilder.py b/linden/indra/lib/python/indra/ipc/servicebuilder.py index 89cdfad..01f2c6f 100644 --- a/linden/indra/lib/python/indra/ipc/servicebuilder.py +++ b/linden/indra/lib/python/indra/ipc/servicebuilder.py | |||
@@ -51,12 +51,10 @@ def build(name, context={}, **kwargs): | |||
51 | > servicebuilder.build('version-manager-version', context, version='1.18.1.2') | 51 | > servicebuilder.build('version-manager-version', context, version='1.18.1.2') |
52 | 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2' | 52 | 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2' |
53 | """ | 53 | """ |
54 | context = context.copy() # shouldn't modify the caller's dictionary | ||
55 | context.update(kwargs) | ||
56 | global _g_builder | 54 | global _g_builder |
57 | if _g_builder is None: | 55 | if _g_builder is None: |
58 | _g_builder = ServiceBuilder() | 56 | _g_builder = ServiceBuilder() |
59 | return _g_builder.buildServiceURL(name, context) | 57 | return _g_builder.buildServiceURL(name, context, **kwargs) |
60 | 58 | ||
61 | class ServiceBuilder(object): | 59 | class ServiceBuilder(object): |
62 | def __init__(self, services_definition = services_config): | 60 | def __init__(self, services_definition = services_config): |
@@ -81,13 +79,36 @@ class ServiceBuilder(object): | |||
81 | else: | 79 | else: |
82 | self.builders[service['name']] = service_builder | 80 | self.builders[service['name']] = service_builder |
83 | 81 | ||
84 | def buildServiceURL(self, name, context): | 82 | def buildServiceURL(self, name, context={}, **kwargs): |
85 | """\ | 83 | """\ |
86 | @brief given the environment on construction, return a service URL. | 84 | @brief given the environment on construction, return a service URL. |
87 | @param name The name of the service. | 85 | @param name The name of the service. |
88 | @param context A dict of name value lookups for the service. | 86 | @param context A dict of name value lookups for the service. |
87 | @param kwargs Any keyword arguments are treated as members of the | ||
88 | context, this allows you to be all 31337 by writing shit like: | ||
89 | servicebuilder.build('name', param=value) | ||
89 | @returns Returns the | 90 | @returns Returns the |
90 | """ | 91 | """ |
92 | context = context.copy() # shouldn't modify the caller's dictionary | ||
93 | context.update(kwargs) | ||
91 | base_url = config.get('services-base-url') | 94 | base_url = config.get('services-base-url') |
92 | svc_path = russ.format(self.builders[name], context) | 95 | svc_path = russ.format(self.builders[name], context) |
93 | return base_url + svc_path | 96 | return base_url + svc_path |
97 | |||
98 | |||
99 | def on_in(query_name, host_key, schema_key): | ||
100 | """\ | ||
101 | @brief Constructs an on/in snippet (for running named queries) | ||
102 | from a schema name and two keys referencing values stored in | ||
103 | indra.xml. | ||
104 | |||
105 | @param query_name Name of the query. | ||
106 | @param host_key Logical name of destination host. Will be | ||
107 | looked up in indra.xml. | ||
108 | @param schema_key Logical name of destination schema. Will | ||
109 | be looked up in indra.xml. | ||
110 | """ | ||
111 | host_name = config.get(host_key) | ||
112 | schema_name = config.get(schema_key) | ||
113 | return '/'.join( ('on', host_name, 'in', schema_name, query_name.lstrip('/')) ) | ||
114 | |||
diff --git a/linden/indra/lib/python/indra/ipc/siesta.py b/linden/indra/lib/python/indra/ipc/siesta.py index 5fbea29..b206f18 100644 --- a/linden/indra/lib/python/indra/ipc/siesta.py +++ b/linden/indra/lib/python/indra/ipc/siesta.py | |||
@@ -24,9 +24,9 @@ except ImportError: | |||
24 | 24 | ||
25 | llsd_parsers = { | 25 | llsd_parsers = { |
26 | 'application/json': json_decode, | 26 | 'application/json': json_decode, |
27 | 'application/llsd+binary': llsd.parse_binary, | 27 | llsd.BINARY_MIME_TYPE: llsd.parse_binary, |
28 | 'application/llsd+notation': llsd.parse_notation, | 28 | 'application/llsd+notation': llsd.parse_notation, |
29 | 'application/llsd+xml': llsd.parse_xml, | 29 | llsd.XML_MIME_TYPE: llsd.parse_xml, |
30 | 'application/xml': llsd.parse_xml, | 30 | 'application/xml': llsd.parse_xml, |
31 | } | 31 | } |
32 | 32 | ||
diff --git a/linden/indra/lib/python/indra/util/llmanifest.py b/linden/indra/lib/python/indra/util/llmanifest.py index 4675177..a00d242 100644 --- a/linden/indra/lib/python/indra/util/llmanifest.py +++ b/linden/indra/lib/python/indra/util/llmanifest.py | |||
@@ -584,7 +584,7 @@ class LLManifest(object): | |||
584 | 584 | ||
585 | def wildcard_regex(self, src_glob, dst_glob): | 585 | def wildcard_regex(self, src_glob, dst_glob): |
586 | src_re = re.escape(src_glob) | 586 | src_re = re.escape(src_glob) |
587 | src_re = src_re.replace('\*', '([-a-zA-Z0-9._ ]+)') | 587 | src_re = src_re.replace('\*', '([-a-zA-Z0-9._ ]*)') |
588 | dst_temp = dst_glob | 588 | dst_temp = dst_glob |
589 | i = 1 | 589 | i = 1 |
590 | while dst_temp.count("*") > 0: | 590 | while dst_temp.count("*") > 0: |
@@ -621,6 +621,7 @@ class LLManifest(object): | |||
621 | count = 0 | 621 | count = 0 |
622 | if self.wildcard_pattern.search(src): | 622 | if self.wildcard_pattern.search(src): |
623 | for s,d in self.expand_globs(src, dst): | 623 | for s,d in self.expand_globs(src, dst): |
624 | assert(s != d) | ||
624 | count += self.process_file(s, d) | 625 | count += self.process_file(s, d) |
625 | else: | 626 | else: |
626 | # if we're specifying a single path (not a glob), | 627 | # if we're specifying a single path (not a glob), |
diff --git a/linden/indra/lib/python/indra/util/llversion.py b/linden/indra/lib/python/indra/util/llversion.py index 666cce4..fe9448f 100644 --- a/linden/indra/lib/python/indra/util/llversion.py +++ b/linden/indra/lib/python/indra/util/llversion.py | |||
@@ -50,7 +50,10 @@ def get_version(version_type): | |||
50 | m = re.search('const S32 IMP_VERSION_MINOR = (\d+);', file_str) | 50 | m = re.search('const S32 IMP_VERSION_MINOR = (\d+);', file_str) |
51 | VER_MINOR = m.group(1) | 51 | VER_MINOR = m.group(1) |
52 | m = re.search('const S32 IMP_VERSION_PATCH = (\d+);', file_str) | 52 | m = re.search('const S32 IMP_VERSION_PATCH = (\d+);', file_str) |
53 | version = "%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s" % locals() | 53 | VER_PATCH = m.group(1) |
54 | m = re.search('const S32 IMP_VERSION_TEST = (\d+);', file_str) | ||
55 | VER_BUILD = m.group(1) | ||
56 | version = "%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_TEST)s" % locals() | ||
54 | return version | 57 | return version |
55 | 58 | ||
56 | def get_channel(version_type): | 59 | def get_channel(version_type): |
diff --git a/linden/indra/lib/python/indra/util/named_query.py b/linden/indra/lib/python/indra/util/named_query.py index 20f2ec7..788fb0e 100644 --- a/linden/indra/lib/python/indra/util/named_query.py +++ b/linden/indra/lib/python/indra/util/named_query.py | |||
@@ -47,6 +47,8 @@ except NameError: | |||
47 | from indra.base import llsd | 47 | from indra.base import llsd |
48 | from indra.base import config | 48 | from indra.base import config |
49 | 49 | ||
50 | DEBUG = False | ||
51 | |||
50 | NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') | 52 | NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq') |
51 | NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) | 53 | NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX) |
52 | 54 | ||
@@ -63,7 +65,9 @@ def _init_g_named_manager(sql_dir = None): | |||
63 | 65 | ||
64 | # extra fallback directory in case config doesn't return what we want | 66 | # extra fallback directory in case config doesn't return what we want |
65 | if sql_dir is None: | 67 | if sql_dir is None: |
66 | sql_dir = os.path.dirname(__file__) + "../../../../web/dataservice/sql" | 68 | sql_dir = os.path.abspath( |
69 | os.path.join( | ||
70 | os.path.realpath(os.path.dirname(__file__)), "..", "..", "..", "..", "web", "dataservice", "sql")) | ||
67 | 71 | ||
68 | global _g_named_manager | 72 | global _g_named_manager |
69 | _g_named_manager = NamedQueryManager( | 73 | _g_named_manager = NamedQueryManager( |
@@ -103,11 +107,12 @@ class NamedQuery(object): | |||
103 | def __init__(self, name, filename): | 107 | def __init__(self, name, filename): |
104 | """ Construct a NamedQuery object. The name argument is an | 108 | """ Construct a NamedQuery object. The name argument is an |
105 | arbitrary name as a handle for the query, and the filename is | 109 | arbitrary name as a handle for the query, and the filename is |
106 | a path to a file containing an llsd named query document.""" | 110 | a path to a file or a file-like object containing an llsd named |
111 | query document.""" | ||
107 | self._stat_interval_seconds = 5 # 5 seconds | 112 | self._stat_interval_seconds = 5 # 5 seconds |
108 | self._name = name | 113 | self._name = name |
109 | if (filename is not None) \ | 114 | if (filename is not None and isinstance(filename, (str, unicode)) |
110 | and (NQ_FILE_SUFFIX != filename[-NQ_FILE_SUFFIX_LEN:]): | 115 | and NQ_FILE_SUFFIX != filename[-NQ_FILE_SUFFIX_LEN:]): |
111 | filename = filename + NQ_FILE_SUFFIX | 116 | filename = filename + NQ_FILE_SUFFIX |
112 | self._location = filename | 117 | self._location = filename |
113 | self._alternative = dict() | 118 | self._alternative = dict() |
@@ -122,8 +127,8 @@ class NamedQuery(object): | |||
122 | 127 | ||
123 | def get_modtime(self): | 128 | def get_modtime(self): |
124 | """ Returns the mtime (last modified time) of the named query | 129 | """ Returns the mtime (last modified time) of the named query |
125 | file, if such exists.""" | 130 | filename. For file-like objects, expect a modtime of 0""" |
126 | if self._location: | 131 | if self._location and isinstance(self._location, (str, unicode)): |
127 | return os.path.getmtime(self._location) | 132 | return os.path.getmtime(self._location) |
128 | return 0 | 133 | return 0 |
129 | 134 | ||
@@ -131,7 +136,12 @@ class NamedQuery(object): | |||
131 | """ Loads and parses the named query file into self. Does | 136 | """ Loads and parses the named query file into self. Does |
132 | nothing if self.location is nonexistant.""" | 137 | nothing if self.location is nonexistant.""" |
133 | if self._location: | 138 | if self._location: |
134 | self._reference_contents(llsd.parse(open(self._location).read())) | 139 | if isinstance(self._location, (str, unicode)): |
140 | contents = llsd.parse(open(self._location).read()) | ||
141 | else: | ||
142 | # we probably have a file-like object. Godspeed! | ||
143 | contents = llsd.parse(self._location.read()) | ||
144 | self._reference_contents(contents) | ||
135 | # Check for alternative implementations | 145 | # Check for alternative implementations |
136 | try: | 146 | try: |
137 | for name, alt in self._contents['alternative'].items(): | 147 | for name, alt in self._contents['alternative'].items(): |
@@ -182,6 +192,16 @@ class NamedQuery(object): | |||
182 | ready them for use in LIKE statements""" | 192 | ready them for use in LIKE statements""" |
183 | if sql: | 193 | if sql: |
184 | #print >>sys.stderr, "sql:",sql | 194 | #print >>sys.stderr, "sql:",sql |
195 | |||
196 | # This first sub is to properly escape any % signs that | ||
197 | # are meant to be literally passed through to mysql in the | ||
198 | # query. It leaves any %'s that are used for | ||
199 | # like-expressions. | ||
200 | expr = re.compile("(?<=[^a-zA-Z0-9_-])%(?=[^:])") | ||
201 | sql = expr.sub('%%', sql) | ||
202 | |||
203 | # This should tackle the rest of the %'s in the query, by | ||
204 | # converting them to LIKE clauses. | ||
185 | expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%") | 205 | expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%") |
186 | sql = expr.sub(self._prepare_like, sql) | 206 | sql = expr.sub(self._prepare_like, sql) |
187 | expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)") | 207 | expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)") |
@@ -333,7 +353,8 @@ class NamedQuery(object): | |||
333 | cursor = connection.cursor() | 353 | cursor = connection.cursor() |
334 | 354 | ||
335 | statement = self.sql(connection, params) | 355 | statement = self.sql(connection, params) |
336 | #print "SQL:", statement | 356 | if DEBUG: |
357 | print "SQL:", statement | ||
337 | rows = cursor.execute(statement) | 358 | rows = cursor.execute(statement) |
338 | 359 | ||
339 | # *NOTE: the expect_rows argument is a very cheesy way to get some | 360 | # *NOTE: the expect_rows argument is a very cheesy way to get some |
diff --git a/linden/indra/llcommon/llstat.cpp b/linden/indra/llcommon/llstat.cpp index 4b79fcb..706acdb 100644 --- a/linden/indra/llcommon/llstat.cpp +++ b/linden/indra/llcommon/llstat.cpp | |||
@@ -31,55 +31,288 @@ | |||
31 | #include "linden_common.h" | 31 | #include "linden_common.h" |
32 | 32 | ||
33 | #include "llstat.h" | 33 | #include "llstat.h" |
34 | #include "lllivefile.h" | ||
35 | #include "llerrorcontrol.h" | ||
34 | #include "llframetimer.h" | 36 | #include "llframetimer.h" |
35 | #include "timing.h" | 37 | #include "timing.h" |
38 | #include "llsd.h" | ||
39 | #include "llsdserialize.h" | ||
40 | #include "llstl.h" | ||
41 | #include "u64.h" | ||
36 | 42 | ||
37 | class LLStatAccum::impl | 43 | |
44 | // statics | ||
45 | BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information | ||
46 | LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects | ||
47 | std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step" | ||
48 | |||
49 | //------------------------------------------------------------------------ | ||
50 | // Live config file to trigger stats logging | ||
51 | static const char STATS_CONFIG_FILE_NAME[] = "/dev/shm/simperf/simperf_proc_config.llsd"; | ||
52 | static const F32 STATS_CONFIG_REFRESH_RATE = 5.0; // seconds | ||
53 | |||
54 | class LLStatsConfigFile : public LLLiveFile | ||
38 | { | 55 | { |
39 | public: | 56 | public: |
40 | static const TimeScale IMPL_NUM_SCALES = (TimeScale)(SCALE_TWO_MINUTE + 1); | 57 | LLStatsConfigFile() |
41 | static U64 sScaleTimes[IMPL_NUM_SCALES]; | 58 | : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE), |
59 | mChanged(false), mStatsp(NULL) { } | ||
42 | 60 | ||
43 | BOOL mUseFrameTimer; | 61 | static std::string filename(); |
62 | |||
63 | protected: | ||
64 | /* virtual */ void loadFile(); | ||
44 | 65 | ||
45 | BOOL mRunning; | 66 | public: |
46 | U64 mLastTime; | 67 | void init(LLPerfStats* statsp); |
47 | 68 | static LLStatsConfigFile& instance(); | |
48 | struct Bucket | 69 | // return the singleton stats config file |
49 | { | ||
50 | F64 accum; | ||
51 | U64 endTime; | ||
52 | 70 | ||
53 | BOOL lastValid; | 71 | bool mChanged; |
54 | F64 lastAccum; | ||
55 | }; | ||
56 | 72 | ||
57 | Bucket mBuckets[IMPL_NUM_SCALES]; | 73 | protected: |
74 | LLPerfStats* mStatsp; | ||
75 | }; | ||
58 | 76 | ||
59 | BOOL mLastSampleValid; | 77 | std::string LLStatsConfigFile::filename() |
60 | F64 mLastSampleValue; | 78 | { |
79 | return STATS_CONFIG_FILE_NAME; | ||
80 | } | ||
61 | 81 | ||
82 | void LLStatsConfigFile::init(LLPerfStats* statsp) | ||
83 | { | ||
84 | mStatsp = statsp; | ||
85 | } | ||
62 | 86 | ||
63 | impl(bool useFrameTimer); | 87 | LLStatsConfigFile& LLStatsConfigFile::instance() |
88 | { | ||
89 | static LLStatsConfigFile the_file; | ||
90 | return the_file; | ||
91 | } | ||
64 | 92 | ||
65 | void reset(U64 when); | ||
66 | 93 | ||
67 | void sum(F64 value); | 94 | /* virtual */ |
68 | void sum(F64 value, U64 when); | 95 | // Load and parse the stats configuration file |
96 | void LLStatsConfigFile::loadFile() | ||
97 | { | ||
98 | if (!mStatsp) | ||
99 | { | ||
100 | llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl; | ||
101 | return; | ||
102 | } | ||
103 | mChanged = true; | ||
104 | |||
105 | LLSD stats_config; | ||
106 | { | ||
107 | llifstream file(filename().c_str()); | ||
108 | if (file.is_open()) | ||
109 | { | ||
110 | LLSDSerialize::fromXML(stats_config, file); | ||
111 | if (stats_config.isUndefined()) | ||
112 | { | ||
113 | llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl; | ||
114 | mStatsp->setReportPerformanceDuration( 0.f ); | ||
115 | return; | ||
116 | } | ||
117 | } | ||
118 | else | ||
119 | { // File went away, turn off stats if it was on | ||
120 | if ( mStatsp->frameStatsIsRunning() ) | ||
121 | { | ||
122 | llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl; | ||
123 | mStatsp->setReportPerformanceDuration( 0.f ); | ||
124 | } | ||
125 | return; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | F32 duration = 0.f; | ||
130 | F32 interval = 0.f; | ||
131 | |||
132 | const char * w = "duration"; | ||
133 | if (stats_config.has(w)) | ||
134 | { | ||
135 | duration = (F32)stats_config[w].asReal(); | ||
136 | } | ||
137 | w = "interval"; | ||
138 | if (stats_config.has(w)) | ||
139 | { | ||
140 | interval = (F32)stats_config[w].asReal(); | ||
141 | } | ||
142 | |||
143 | mStatsp->setReportPerformanceDuration( duration ); | ||
144 | mStatsp->setReportPerformanceInterval( interval ); | ||
145 | |||
146 | if ( duration > 0 ) | ||
147 | { | ||
148 | if ( interval == 0.f ) | ||
149 | { | ||
150 | llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl; | ||
151 | } | ||
152 | else | ||
153 | { | ||
154 | llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl; | ||
155 | } | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | llinfos << "Performance stats recording turned off" << llendl; | ||
160 | } | ||
161 | } | ||
69 | 162 | ||
70 | F32 meanValue(TimeScale scale) const; | ||
71 | 163 | ||
72 | U64 getCurrentUsecs() const; | 164 | //------------------------------------------------------------------------ |
73 | // Get current microseconds based on timer type | ||
74 | }; | ||
75 | 165 | ||
166 | LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) : | ||
167 | mFrameStatsFileFailure(FALSE), | ||
168 | mSkipFirstFrameStats(FALSE), | ||
169 | mProcessName(process_name), | ||
170 | mProcessPID(process_pid), | ||
171 | mReportPerformanceStatInterval(1.f), | ||
172 | mReportPerformanceStatEnd(0.0) | ||
173 | { } | ||
76 | 174 | ||
77 | U64 LLStatAccum::impl::sScaleTimes[IMPL_NUM_SCALES] = | 175 | LLPerfStats::~LLPerfStats() |
176 | { | ||
177 | LLPerfBlock::clearDynamicStats(); | ||
178 | mFrameStatsFile.close(); | ||
179 | } | ||
180 | |||
181 | void LLPerfStats::init() | ||
182 | { | ||
183 | // Initialize the stats config file instance. | ||
184 | (void) LLStatsConfigFile::instance().init(this); | ||
185 | (void) LLStatsConfigFile::instance().checkAndReload(); | ||
186 | } | ||
187 | |||
188 | // Open file for statistics | ||
189 | void LLPerfStats::openPerfStatsFile() | ||
190 | { | ||
191 | if ( !mFrameStatsFile | ||
192 | && !mFrameStatsFileFailure ) | ||
193 | { | ||
194 | std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID); | ||
195 | mFrameStatsFile.close(); | ||
196 | mFrameStatsFile.clear(); | ||
197 | mFrameStatsFile.open(stats_file, llofstream::out); | ||
198 | if ( mFrameStatsFile.fail() ) | ||
199 | { | ||
200 | llinfos << "Error opening statistics log file " << stats_file << llendl; | ||
201 | mFrameStatsFileFailure = TRUE; | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | LLSD process_info = LLSD::emptyMap(); | ||
206 | process_info["name"] = mProcessName; | ||
207 | process_info["pid"] = (LLSD::Integer) mProcessPID; | ||
208 | process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval; | ||
209 | // Add process-specific info. | ||
210 | addProcessHeaderInfo(process_info); | ||
211 | |||
212 | mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | // Dump out performance metrics over some time interval | ||
218 | void LLPerfStats::dumpIntervalPerformanceStats() | ||
219 | { | ||
220 | // Ensure output file is OK | ||
221 | openPerfStatsFile(); | ||
222 | |||
223 | if ( mFrameStatsFile ) | ||
224 | { | ||
225 | LLSD stats = LLSD::emptyMap(); | ||
226 | |||
227 | LLStatAccum::TimeScale scale; | ||
228 | if ( getReportPerformanceInterval() == 0.f ) | ||
229 | { | ||
230 | scale = LLStatAccum::SCALE_PER_FRAME; | ||
231 | } | ||
232 | else if ( getReportPerformanceInterval() < 0.5f ) | ||
233 | { | ||
234 | scale = LLStatAccum::SCALE_100MS; | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | scale = LLStatAccum::SCALE_SECOND; | ||
239 | } | ||
240 | |||
241 | // Write LLSD into log | ||
242 | stats["utc_time"] = (LLSD::String) LLError::utcTime(); | ||
243 | stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000)); // milliseconds since epoch | ||
244 | stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount(); | ||
245 | |||
246 | // Add process-specific frame info. | ||
247 | addProcessFrameInfo(stats, scale); | ||
248 | LLPerfBlock::addStatsToLLSDandReset( stats, scale ); | ||
249 | |||
250 | mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | // Set length of performance stat recording | ||
255 | void LLPerfStats::setReportPerformanceDuration( F32 seconds ) | ||
256 | { | ||
257 | if ( seconds <= 0.f ) | ||
258 | { | ||
259 | mReportPerformanceStatEnd = 0.0; | ||
260 | LLPerfBlock::setStatsEnabled( FALSE ); | ||
261 | mFrameStatsFile.close(); | ||
262 | LLPerfBlock::clearDynamicStats(); | ||
263 | } | ||
264 | else | ||
265 | { | ||
266 | mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds); | ||
267 | // Clear failure flag to try and create the log file once | ||
268 | mFrameStatsFileFailure = FALSE; | ||
269 | LLPerfBlock::setStatsEnabled( TRUE ); | ||
270 | mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame) | ||
271 | } | ||
272 | } | ||
273 | |||
274 | void LLPerfStats::updatePerFrameStats() | ||
275 | { | ||
276 | (void) LLStatsConfigFile::instance().checkAndReload(); | ||
277 | static LLFrameTimer performance_stats_timer; | ||
278 | if ( frameStatsIsRunning() ) | ||
279 | { | ||
280 | if ( mReportPerformanceStatInterval == 0 ) | ||
281 | { // Record info every frame | ||
282 | if ( mSkipFirstFrameStats ) | ||
283 | { // Skip the first time - was started this frame | ||
284 | mSkipFirstFrameStats = FALSE; | ||
285 | } | ||
286 | else | ||
287 | { | ||
288 | dumpIntervalPerformanceStats(); | ||
289 | } | ||
290 | } | ||
291 | else | ||
292 | { | ||
293 | performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() ); | ||
294 | if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval )) | ||
295 | { | ||
296 | dumpIntervalPerformanceStats(); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd ) | ||
301 | { // Reached end of time, clear it to stop reporting | ||
302 | setReportPerformanceDuration(0.f); // Don't set mReportPerformanceStatEnd directly | ||
303 | llinfos << "Recording performance stats completed" << llendl; | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | |||
308 | |||
309 | //------------------------------------------------------------------------ | ||
310 | |||
311 | U64 LLStatAccum::sScaleTimes[NUM_SCALES] = | ||
78 | { | 312 | { |
79 | USEC_PER_SEC / 10, // 100 millisec | 313 | USEC_PER_SEC / 10, // 100 millisec |
80 | USEC_PER_SEC * 1, // seconds | 314 | USEC_PER_SEC * 1, // seconds |
81 | USEC_PER_SEC * 60, // minutes | 315 | USEC_PER_SEC * 60, // minutes |
82 | USEC_PER_SEC * 60 * 2 // two minutes | ||
83 | #if ENABLE_LONG_TIME_STATS | 316 | #if ENABLE_LONG_TIME_STATS |
84 | // enable these when more time scales are desired | 317 | // enable these when more time scales are desired |
85 | USEC_PER_SEC * 60*60, // hours | 318 | USEC_PER_SEC * 60*60, // hours |
@@ -89,19 +322,27 @@ U64 LLStatAccum::impl::sScaleTimes[IMPL_NUM_SCALES] = | |||
89 | }; | 322 | }; |
90 | 323 | ||
91 | 324 | ||
92 | LLStatAccum::impl::impl(bool useFrameTimer) | 325 | |
326 | LLStatAccum::LLStatAccum(bool useFrameTimer) | ||
327 | : mUseFrameTimer(useFrameTimer), | ||
328 | mRunning(FALSE), | ||
329 | mLastSampleValue(0.0), | ||
330 | mLastSampleValid(FALSE) | ||
331 | { | ||
332 | } | ||
333 | |||
334 | LLStatAccum::~LLStatAccum() | ||
93 | { | 335 | { |
94 | mUseFrameTimer = useFrameTimer; | ||
95 | mRunning = FALSE; | ||
96 | mLastSampleValid = FALSE; | ||
97 | } | 336 | } |
98 | 337 | ||
99 | void LLStatAccum::impl::reset(U64 when) | 338 | |
339 | |||
340 | void LLStatAccum::reset(U64 when) | ||
100 | { | 341 | { |
101 | mRunning = TRUE; | 342 | mRunning = TRUE; |
102 | mLastTime = when; | 343 | mLastTime = when; |
103 | 344 | ||
104 | for (int i = 0; i < IMPL_NUM_SCALES; ++i) | 345 | for (int i = 0; i < NUM_SCALES; ++i) |
105 | { | 346 | { |
106 | mBuckets[i].accum = 0.0; | 347 | mBuckets[i].accum = 0.0; |
107 | mBuckets[i].endTime = when + sScaleTimes[i]; | 348 | mBuckets[i].endTime = when + sScaleTimes[i]; |
@@ -109,12 +350,12 @@ void LLStatAccum::impl::reset(U64 when) | |||
109 | } | 350 | } |
110 | } | 351 | } |
111 | 352 | ||
112 | void LLStatAccum::impl::sum(F64 value) | 353 | void LLStatAccum::sum(F64 value) |
113 | { | 354 | { |
114 | sum(value, getCurrentUsecs()); | 355 | sum(value, getCurrentUsecs()); |
115 | } | 356 | } |
116 | 357 | ||
117 | void LLStatAccum::impl::sum(F64 value, U64 when) | 358 | void LLStatAccum::sum(F64 value, U64 when) |
118 | { | 359 | { |
119 | if (!mRunning) | 360 | if (!mRunning) |
120 | { | 361 | { |
@@ -131,7 +372,10 @@ void LLStatAccum::impl::sum(F64 value, U64 when) | |||
131 | return; | 372 | return; |
132 | } | 373 | } |
133 | 374 | ||
134 | for (int i = 0; i < IMPL_NUM_SCALES; ++i) | 375 | // how long is this value for |
376 | U64 timeSpan = when - mLastTime; | ||
377 | |||
378 | for (int i = 0; i < NUM_SCALES; ++i) | ||
135 | { | 379 | { |
136 | Bucket& bucket = mBuckets[i]; | 380 | Bucket& bucket = mBuckets[i]; |
137 | 381 | ||
@@ -143,8 +387,6 @@ void LLStatAccum::impl::sum(F64 value, U64 when) | |||
143 | { | 387 | { |
144 | U64 timeScale = sScaleTimes[i]; | 388 | U64 timeScale = sScaleTimes[i]; |
145 | 389 | ||
146 | U64 timeSpan = when - mLastTime; | ||
147 | // how long is this value for | ||
148 | U64 timeLeft = when - bucket.endTime; | 390 | U64 timeLeft = when - bucket.endTime; |
149 | // how much time is left after filling this bucket | 391 | // how much time is left after filling this bucket |
150 | 392 | ||
@@ -173,13 +415,18 @@ void LLStatAccum::impl::sum(F64 value, U64 when) | |||
173 | } | 415 | } |
174 | 416 | ||
175 | 417 | ||
176 | F32 LLStatAccum::impl::meanValue(TimeScale scale) const | 418 | F32 LLStatAccum::meanValue(TimeScale scale) const |
177 | { | 419 | { |
178 | if (!mRunning) | 420 | if (!mRunning) |
179 | { | 421 | { |
180 | return 0.0; | 422 | return 0.0; |
181 | } | 423 | } |
182 | if (scale < 0 || scale >= IMPL_NUM_SCALES) | 424 | if ( scale == SCALE_PER_FRAME ) |
425 | { // Per-frame not supported here | ||
426 | scale = SCALE_100MS; | ||
427 | } | ||
428 | |||
429 | if (scale < 0 || scale >= NUM_SCALES) | ||
183 | { | 430 | { |
184 | llwarns << "llStatAccum::meanValue called for unsupported scale: " | 431 | llwarns << "llStatAccum::meanValue called for unsupported scale: " |
185 | << scale << llendl; | 432 | << scale << llendl; |
@@ -209,7 +456,7 @@ F32 LLStatAccum::impl::meanValue(TimeScale scale) const | |||
209 | } | 456 | } |
210 | 457 | ||
211 | 458 | ||
212 | U64 LLStatAccum::impl::getCurrentUsecs() const | 459 | U64 LLStatAccum::getCurrentUsecs() const |
213 | { | 460 | { |
214 | if (mUseFrameTimer) | 461 | if (mUseFrameTimer) |
215 | { | 462 | { |
@@ -222,25 +469,44 @@ U64 LLStatAccum::impl::getCurrentUsecs() const | |||
222 | } | 469 | } |
223 | 470 | ||
224 | 471 | ||
472 | // ------------------------------------------------------------------------ | ||
225 | 473 | ||
226 | 474 | LLStatRate::LLStatRate(bool use_frame_timer) | |
227 | 475 | : LLStatAccum(use_frame_timer) | |
228 | LLStatAccum::LLStatAccum(bool useFrameTimer) | ||
229 | : m(* new impl(useFrameTimer)) | ||
230 | { | 476 | { |
231 | } | 477 | } |
232 | 478 | ||
233 | LLStatAccum::~LLStatAccum() | 479 | void LLStatRate::count(U32 value) |
234 | { | 480 | { |
235 | delete &m; | 481 | sum((F64)value * sScaleTimes[SCALE_SECOND]); |
236 | } | 482 | } |
237 | 483 | ||
238 | F32 LLStatAccum::meanValue(TimeScale scale) const | 484 | |
239 | { | 485 | void LLStatRate::mark() |
240 | return m.meanValue(scale); | 486 | { |
241 | } | 487 | // Effectively the same as count(1), but sets mLastSampleValue |
488 | U64 when = getCurrentUsecs(); | ||
489 | |||
490 | if ( mRunning | ||
491 | && (when > mLastTime) ) | ||
492 | { // Set mLastSampleValue to the time from the last mark() | ||
493 | F64 duration = ((F64)(when - mLastTime)) / sScaleTimes[SCALE_SECOND]; | ||
494 | if ( duration > 0.0 ) | ||
495 | { | ||
496 | mLastSampleValue = 1.0 / duration; | ||
497 | } | ||
498 | else | ||
499 | { | ||
500 | mLastSampleValue = 0.0; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | sum( (F64) sScaleTimes[SCALE_SECOND], when); | ||
505 | } | ||
242 | 506 | ||
243 | 507 | ||
508 | // ------------------------------------------------------------------------ | ||
509 | |||
244 | 510 | ||
245 | LLStatMeasure::LLStatMeasure(bool use_frame_timer) | 511 | LLStatMeasure::LLStatMeasure(bool use_frame_timer) |
246 | : LLStatAccum(use_frame_timer) | 512 | : LLStatAccum(use_frame_timer) |
@@ -249,53 +515,209 @@ LLStatMeasure::LLStatMeasure(bool use_frame_timer) | |||
249 | 515 | ||
250 | void LLStatMeasure::sample(F64 value) | 516 | void LLStatMeasure::sample(F64 value) |
251 | { | 517 | { |
252 | U64 when = m.getCurrentUsecs(); | 518 | U64 when = getCurrentUsecs(); |
253 | 519 | ||
254 | if (m.mLastSampleValid) | 520 | if (mLastSampleValid) |
255 | { | 521 | { |
256 | F64 avgValue = (value + m.mLastSampleValue) / 2.0; | 522 | F64 avgValue = (value + mLastSampleValue) / 2.0; |
257 | F64 interval = (F64)(when - m.mLastTime); | 523 | F64 interval = (F64)(when - mLastTime); |
258 | 524 | ||
259 | m.sum(avgValue * interval, when); | 525 | sum(avgValue * interval, when); |
260 | } | 526 | } |
261 | else | 527 | else |
262 | { | 528 | { |
263 | m.reset(when); | 529 | reset(when); |
264 | } | 530 | } |
265 | 531 | ||
266 | m.mLastSampleValid = TRUE; | 532 | mLastSampleValid = TRUE; |
267 | m.mLastSampleValue = value; | 533 | mLastSampleValue = value; |
268 | } | 534 | } |
269 | 535 | ||
270 | 536 | ||
271 | LLStatRate::LLStatRate(bool use_frame_timer) | 537 | // ------------------------------------------------------------------------ |
272 | : LLStatAccum(use_frame_timer) | 538 | |
539 | LLStatTime::LLStatTime(const std::string & key) | ||
540 | : LLStatAccum(false), | ||
541 | mFrameNumber(LLFrameTimer::getFrameCount()), | ||
542 | mTotalTimeInFrame(0), | ||
543 | mKey(key) | ||
544 | #if LL_DEBUG | ||
545 | , mRunning(FALSE) | ||
546 | #endif | ||
273 | { | 547 | { |
274 | } | 548 | } |
275 | 549 | ||
276 | void LLStatRate::count(U32 value) | 550 | void LLStatTime::start() |
551 | { | ||
552 | // Reset frame accumluation if the frame number has changed | ||
553 | U32 frame_number = LLFrameTimer::getFrameCount(); | ||
554 | if ( frame_number != mFrameNumber ) | ||
555 | { | ||
556 | mFrameNumber = frame_number; | ||
557 | mTotalTimeInFrame = 0; | ||
558 | } | ||
559 | |||
560 | sum(0.0); | ||
561 | |||
562 | #if LL_DEBUG | ||
563 | // Shouldn't be running already | ||
564 | llassert( !mRunning ); | ||
565 | mRunning = TRUE; | ||
566 | #endif | ||
567 | } | ||
568 | |||
569 | void LLStatTime::stop() | ||
570 | { | ||
571 | U64 end_time = getCurrentUsecs(); | ||
572 | U64 duration = end_time - mLastTime; | ||
573 | sum(F64(duration), end_time); | ||
574 | //llinfos << "mTotalTimeInFrame incremented from " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl; | ||
575 | mTotalTimeInFrame += duration; | ||
576 | |||
577 | #if LL_DEBUG | ||
578 | mRunning = FALSE; | ||
579 | #endif | ||
580 | } | ||
581 | |||
582 | /* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const | ||
277 | { | 583 | { |
278 | m.sum((F64)value * impl::sScaleTimes[SCALE_SECOND]); | 584 | if ( LLStatAccum::SCALE_PER_FRAME == scale ) |
585 | { | ||
586 | return mTotalTimeInFrame; | ||
587 | } | ||
588 | else | ||
589 | { | ||
590 | return LLStatAccum::meanValue(scale); | ||
591 | } | ||
279 | } | 592 | } |
280 | 593 | ||
281 | 594 | ||
282 | LLStatTime::LLStatTime(bool use_frame_timer) | 595 | // ------------------------------------------------------------------------ |
283 | : LLStatAccum(use_frame_timer) | 596 | |
597 | |||
598 | // Use this constructor for pre-defined LLStatTime objects | ||
599 | LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL) | ||
284 | { | 600 | { |
601 | if (mPredefinedStat) | ||
602 | { | ||
603 | // If dynamic stats are turned on, this will create a separate entry in the stat map. | ||
604 | initDynamicStat(mPredefinedStat->mKey); | ||
605 | |||
606 | // Start predefined stats. These stats are not part of the stat map. | ||
607 | mPredefinedStat->start(); | ||
608 | } | ||
285 | } | 609 | } |
286 | 610 | ||
287 | void LLStatTime::start() | 611 | // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key. |
612 | // These are also turned on or off via the switch passed in | ||
613 | LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL) | ||
288 | { | 614 | { |
289 | m.sum(0.0); | 615 | if (!sStatsEnabled) return; |
616 | |||
617 | if (NULL == key2 || strlen(key2) == 0) | ||
618 | { | ||
619 | initDynamicStat(key1); | ||
620 | } | ||
621 | else | ||
622 | { | ||
623 | std::ostringstream key; | ||
624 | key << key1 << "_" << key2; | ||
625 | initDynamicStat(key.str()); | ||
626 | } | ||
290 | } | 627 | } |
291 | 628 | ||
292 | void LLStatTime::stop() | 629 | void LLPerfBlock::initDynamicStat(const std::string& key) |
630 | { | ||
631 | // Early exit if dynamic stats aren't enabled. | ||
632 | if (!sStatsEnabled) return; | ||
633 | |||
634 | mLastPath = sCurrentStatPath; // Save and restore current path | ||
635 | sCurrentStatPath += "/" + key; // Add key to current path | ||
636 | |||
637 | // See if the LLStatTime object already exists | ||
638 | stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath); | ||
639 | if ( iter == sStatMap.end() ) | ||
640 | { | ||
641 | // StatEntry object doesn't exist, so create it | ||
642 | mDynamicStat = new StatEntry( key ); | ||
643 | sStatMap[ sCurrentStatPath ] = mDynamicStat; // Set the entry for this path | ||
644 | } | ||
645 | else | ||
646 | { | ||
647 | // Found this path in the map, use the object there | ||
648 | mDynamicStat = (*iter).second; // Get StatEntry for the current path | ||
649 | } | ||
650 | |||
651 | if (mDynamicStat) | ||
652 | { | ||
653 | mDynamicStat->mStat.start(); | ||
654 | mDynamicStat->mCount++; | ||
655 | } | ||
656 | else | ||
657 | { | ||
658 | llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl; | ||
659 | sCurrentStatPath = mLastPath; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | |||
664 | // Destructor does the time accounting | ||
665 | LLPerfBlock::~LLPerfBlock() | ||
666 | { | ||
667 | if (mPredefinedStat) mPredefinedStat->stop(); | ||
668 | if (mDynamicStat) | ||
669 | { | ||
670 | mDynamicStat->mStat.stop(); | ||
671 | sCurrentStatPath = mLastPath; // Restore the path in case sStatsEnabled changed during this block | ||
672 | } | ||
673 | } | ||
674 | |||
675 | |||
676 | // Clear the map of any dynamic stats. Static routine | ||
677 | void LLPerfBlock::clearDynamicStats() | ||
678 | { | ||
679 | std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer()); | ||
680 | sStatMap.clear(); | ||
681 | } | ||
682 | |||
683 | // static - Extract the stat info into LLSD | ||
684 | void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, | ||
685 | LLStatAccum::TimeScale scale ) | ||
293 | { | 686 | { |
294 | U64 endTime = m.getCurrentUsecs(); | 687 | // If we aren't in per-frame scale, we need to go from second to microsecond. |
295 | m.sum((F64)(endTime - m.mLastTime), endTime); | 688 | U32 scale_adjustment = 1; |
689 | if (LLStatAccum::SCALE_PER_FRAME != scale) | ||
690 | { | ||
691 | scale_adjustment = USEC_PER_SEC; | ||
692 | } | ||
693 | stat_map_t::iterator iter = sStatMap.begin(); | ||
694 | for ( ; iter != sStatMap.end(); ++iter ) | ||
695 | { // Put the entry into LLSD "/full/path/to/stat/" = microsecond total time | ||
696 | const std::string & stats_full_path = (*iter).first; | ||
697 | |||
698 | StatEntry * stat = (*iter).second; | ||
699 | if (stat) | ||
700 | { | ||
701 | if (stat->mCount > 0) | ||
702 | { | ||
703 | stats[stats_full_path] = LLSD::emptyMap(); | ||
704 | stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale)); | ||
705 | if (stat->mCount > 1) | ||
706 | { | ||
707 | stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount; | ||
708 | } | ||
709 | stat->mCount = 0; | ||
710 | } | ||
711 | } | ||
712 | else | ||
713 | { // WTF? Shouldn't have a NULL pointer in the map. | ||
714 | llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl; | ||
715 | } | ||
716 | } | ||
296 | } | 717 | } |
297 | 718 | ||
298 | 719 | ||
720 | // ------------------------------------------------------------------------ | ||
299 | 721 | ||
300 | LLTimer LLStat::sTimer; | 722 | LLTimer LLStat::sTimer; |
301 | LLFrameTimer LLStat::sFrameTimer; | 723 | LLFrameTimer LLStat::sFrameTimer; |
diff --git a/linden/indra/llcommon/llstat.h b/linden/indra/llcommon/llstat.h index 0a7e014..63813e2 100644 --- a/linden/indra/llcommon/llstat.h +++ b/linden/indra/llcommon/llstat.h | |||
@@ -33,9 +33,13 @@ | |||
33 | #define LL_LLSTAT_H | 33 | #define LL_LLSTAT_H |
34 | 34 | ||
35 | #include <deque> | 35 | #include <deque> |
36 | #include <map> | ||
36 | 37 | ||
37 | #include "lltimer.h" | 38 | #include "lltimer.h" |
38 | #include "llframetimer.h" | 39 | #include "llframetimer.h" |
40 | #include "llfile.h" | ||
41 | |||
42 | class LLSD; | ||
39 | 43 | ||
40 | // Set this if longer stats are needed | 44 | // Set this if longer stats are needed |
41 | #define ENABLE_LONG_TIME_STATS 0 | 45 | #define ENABLE_LONG_TIME_STATS 0 |
@@ -58,25 +62,50 @@ public: | |||
58 | SCALE_100MS, | 62 | SCALE_100MS, |
59 | SCALE_SECOND, | 63 | SCALE_SECOND, |
60 | SCALE_MINUTE, | 64 | SCALE_MINUTE, |
61 | SCALE_TWO_MINUTE, | ||
62 | #if ENABLE_LONG_TIME_STATS | 65 | #if ENABLE_LONG_TIME_STATS |
63 | SCALE_HOUR, | 66 | SCALE_HOUR, |
64 | SCALE_DAY, | 67 | SCALE_DAY, |
65 | SCALE_WEEK, | 68 | SCALE_WEEK, |
66 | #endif | 69 | #endif |
67 | NUM_SCALES | 70 | NUM_SCALES, // Use to size storage arrays |
71 | SCALE_PER_FRAME // For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets | ||
68 | }; | 72 | }; |
69 | 73 | ||
70 | F32 meanValue(TimeScale scale) const; | 74 | static U64 sScaleTimes[NUM_SCALES]; |
75 | |||
76 | virtual F32 meanValue(TimeScale scale) const; | ||
71 | // see the subclasses for the specific meaning of value | 77 | // see the subclasses for the specific meaning of value |
72 | 78 | ||
73 | F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); } | 79 | F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); } |
74 | F32 meanValueOverLastSecond() const { return meanValue(SCALE_SECOND); } | 80 | F32 meanValueOverLastSecond() const { return meanValue(SCALE_SECOND); } |
75 | F32 meanValueOverLastMinute() const { return meanValue(SCALE_MINUTE); } | 81 | F32 meanValueOverLastMinute() const { return meanValue(SCALE_MINUTE); } |
76 | 82 | ||
77 | protected: | 83 | void reset(U64 when); |
78 | class impl; | 84 | |
79 | impl& m; | 85 | void sum(F64 value); |
86 | void sum(F64 value, U64 when); | ||
87 | |||
88 | U64 getCurrentUsecs() const; | ||
89 | // Get current microseconds based on timer type | ||
90 | |||
91 | BOOL mUseFrameTimer; | ||
92 | BOOL mRunning; | ||
93 | |||
94 | U64 mLastTime; | ||
95 | |||
96 | struct Bucket | ||
97 | { | ||
98 | F64 accum; | ||
99 | U64 endTime; | ||
100 | |||
101 | BOOL lastValid; | ||
102 | F64 lastAccum; | ||
103 | }; | ||
104 | |||
105 | Bucket mBuckets[NUM_SCALES]; | ||
106 | |||
107 | BOOL mLastSampleValid; | ||
108 | F64 mLastSampleValue; | ||
80 | }; | 109 | }; |
81 | 110 | ||
82 | class LLStatMeasure : public LLStatAccum | 111 | class LLStatMeasure : public LLStatAccum |
@@ -105,39 +134,120 @@ public: | |||
105 | void count(U32); | 134 | void count(U32); |
106 | // used to note that n items have occured | 135 | // used to note that n items have occured |
107 | 136 | ||
108 | void mark() { count(1); } | 137 | void mark(); |
109 | // used for counting the rate thorugh a point in the code | 138 | // used for counting the rate thorugh a point in the code |
110 | }; | 139 | }; |
111 | 140 | ||
112 | 141 | ||
113 | class LLTimeBlock; | ||
114 | |||
115 | class LLStatTime : public LLStatAccum | 142 | class LLStatTime : public LLStatAccum |
116 | // gathers statistics about time spent in a block of code | 143 | // gathers statistics about time spent in a block of code |
117 | // measure average duration per second in the block | 144 | // measure average duration per second in the block |
118 | { | 145 | { |
119 | public: | 146 | public: |
120 | LLStatTime(bool use_frame_timer = false); | 147 | LLStatTime( const std::string & key = "undefined" ); |
148 | |||
149 | U32 mFrameNumber; // Current frame number | ||
150 | U64 mTotalTimeInFrame; // Total time (microseconds) accumulated during the last frame | ||
151 | |||
152 | void setKey( const std::string & key ) { mKey = key; }; | ||
153 | |||
154 | virtual F32 meanValue(TimeScale scale) const; | ||
121 | 155 | ||
122 | private: | 156 | private: |
123 | void start(); | 157 | void start(); // Start and stop measuring time block |
124 | void stop(); | 158 | void stop(); |
125 | friend class LLTimeBlock; | 159 | |
160 | std::string mKey; // Tag representing this time block | ||
161 | |||
162 | #if LL_DEBUG | ||
163 | BOOL mRunning; // TRUE if start() has been called | ||
164 | #endif | ||
165 | |||
166 | friend class LLPerfBlock; | ||
126 | }; | 167 | }; |
127 | 168 | ||
128 | class LLTimeBlock | 169 | // ---------------------------------------------------------------------------- |
170 | |||
171 | |||
172 | // Use this class on the stack to record statistics about an area of code | ||
173 | class LLPerfBlock | ||
129 | { | 174 | { |
130 | public: | 175 | public: |
131 | LLTimeBlock(LLStatTime& stat) : mStat(stat) { mStat.start(); } | 176 | struct StatEntry |
132 | ~LLTimeBlock() { mStat.stop(); } | 177 | { |
178 | StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {} | ||
179 | LLStatTime mStat; | ||
180 | U32 mCount; | ||
181 | }; | ||
182 | typedef std::map<std::string, StatEntry*> stat_map_t; | ||
183 | |||
184 | // Use this constructor for pre-defined LLStatTime objects | ||
185 | LLPerfBlock(LLStatTime* stat); | ||
186 | |||
187 | // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key | ||
188 | LLPerfBlock( const char* key1, const char* key2 = NULL); | ||
189 | |||
190 | |||
191 | ~LLPerfBlock(); | ||
192 | |||
193 | static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; }; | ||
194 | static S32 getStatsEnabled() { return sStatsEnabled; }; | ||
195 | |||
196 | static void clearDynamicStats(); // Reset maps to clear out dynamic objects | ||
197 | static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin | ||
198 | LLStatAccum::TimeScale scale ); | ||
199 | |||
133 | private: | 200 | private: |
134 | LLStatTime& mStat; | 201 | // Initialize dynamically created LLStatTime objects |
202 | void initDynamicStat(const std::string& key); | ||
203 | |||
204 | std::string mLastPath; // Save sCurrentStatPath when this is called | ||
205 | LLStatTime * mPredefinedStat; // LLStatTime object to get data | ||
206 | StatEntry * mDynamicStat; // StatEntryobject to get data | ||
207 | |||
208 | static BOOL sStatsEnabled; // Normally FALSE | ||
209 | static stat_map_t sStatMap; // Map full path string to LLStatTime objects | ||
210 | static std::string sCurrentStatPath; // Something like "frame/physics/physics step" | ||
135 | }; | 211 | }; |
136 | 212 | ||
213 | // ---------------------------------------------------------------------------- | ||
137 | 214 | ||
215 | class LLPerfStats | ||
216 | { | ||
217 | public: | ||
218 | LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0); | ||
219 | virtual ~LLPerfStats(); | ||
220 | |||
221 | virtual void init(); // Reset and start all stat timers | ||
222 | virtual void updatePerFrameStats(); | ||
223 | // Override these function to add process-specific information to the performance log header and per-frame logging. | ||
224 | virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ } | ||
225 | virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ } | ||
226 | |||
227 | // High-resolution frame stats | ||
228 | BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); }; | ||
229 | F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; }; | ||
230 | void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; }; | ||
231 | void setReportPerformanceDuration( F32 seconds ); | ||
232 | void setProcessName(const std::string& process_name) { mProcessName = process_name; } | ||
233 | void setProcessPID(S32 process_pid) { mProcessPID = process_pid; } | ||
138 | 234 | ||
235 | protected: | ||
236 | void openPerfStatsFile(); // Open file for high resolution metrics logging | ||
237 | void dumpIntervalPerformanceStats(); | ||
238 | |||
239 | llofstream mFrameStatsFile; // File for per-frame stats | ||
240 | BOOL mFrameStatsFileFailure; // Flag to prevent repeat opening attempts | ||
241 | BOOL mSkipFirstFrameStats; // Flag to skip one (partial) frame report | ||
242 | std::string mProcessName; | ||
243 | S32 mProcessPID; | ||
139 | 244 | ||
245 | private: | ||
246 | F32 mReportPerformanceStatInterval; // Seconds between performance stats | ||
247 | F64 mReportPerformanceStatEnd; // End time (seconds) for performance stats | ||
248 | }; | ||
140 | 249 | ||
250 | // ---------------------------------------------------------------------------- | ||
141 | class LLStat | 251 | class LLStat |
142 | { | 252 | { |
143 | public: | 253 | public: |
diff --git a/linden/indra/llmath/llmodularmath.h b/linden/indra/llmath/llmodularmath.h new file mode 100644 index 0000000..67083ea --- /dev/null +++ b/linden/indra/llmath/llmodularmath.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /** | ||
2 | * @file llmodularmath.h | ||
3 | * @brief Useful modular math functions. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | #ifndef LLMODULARMATH_H | ||
33 | #define LLMODULARMATH_H | ||
34 | |||
35 | namespace LLModularMath | ||
36 | { | ||
37 | // Return difference between lhs and rhs | ||
38 | // treating the U32 operands and result | ||
39 | // as unsigned values of given width. | ||
40 | template<int width> | ||
41 | inline U32 subtract(U32 lhs, U32 rhs) | ||
42 | { | ||
43 | // Generate a bit mask which will truncate | ||
44 | // unsigned values to given width at compile time. | ||
45 | const U32 mask = (1 << width) - 1; | ||
46 | |||
47 | // Operands are unsigned, so modular | ||
48 | // arithmetic applies. If lhs < rhs, | ||
49 | // difference will wrap in to lower | ||
50 | // bits of result, which is then masked | ||
51 | // to give a value that can be represented | ||
52 | // by an unsigned value of width bits. | ||
53 | return mask & (lhs - rhs); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | #endif | ||
diff --git a/linden/indra/llmessage/llcircuit.cpp b/linden/indra/llmessage/llcircuit.cpp index 12a1520..7b2f241 100644 --- a/linden/indra/llmessage/llcircuit.cpp +++ b/linden/indra/llmessage/llcircuit.cpp | |||
@@ -60,6 +60,7 @@ | |||
60 | #include "llrand.h" | 60 | #include "llrand.h" |
61 | #include "llstl.h" | 61 | #include "llstl.h" |
62 | #include "lltransfermanager.h" | 62 | #include "lltransfermanager.h" |
63 | #include "llmodularmath.h" | ||
63 | 64 | ||
64 | const F32 PING_INTERVAL = 5.f; // seconds | 65 | const F32 PING_INTERVAL = 5.f; // seconds |
65 | const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked. | 66 | const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked. |
@@ -676,6 +677,8 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) | |||
676 | mPacketsIn++; | 677 | mPacketsIn++; |
677 | setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID); | 678 | setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID); |
678 | 679 | ||
680 | mLastPacketGap = 0; | ||
681 | mOutOfOrderRate.count(0); | ||
679 | return; | 682 | return; |
680 | } | 683 | } |
681 | 684 | ||
@@ -683,6 +686,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) | |||
683 | 686 | ||
684 | 687 | ||
685 | // now, check to see if we've got a gap | 688 | // now, check to see if we've got a gap |
689 | U32 gap = 0; | ||
686 | if ((mPacketsInID == id)) | 690 | if ((mPacketsInID == id)) |
687 | { | 691 | { |
688 | // nope! bump and wrap the counter, then return | 692 | // nope! bump and wrap the counter, then return |
@@ -704,6 +708,11 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) | |||
704 | // otherwise, walk from mCurrentCircuit->mPacketsInID to id with wrapping, adding the values to the map | 708 | // otherwise, walk from mCurrentCircuit->mPacketsInID to id with wrapping, adding the values to the map |
705 | // and setting mPacketsInID to id + 1 % LL_MAX_OUT_PACKET_ID | 709 | // and setting mPacketsInID to id + 1 % LL_MAX_OUT_PACKET_ID |
706 | 710 | ||
711 | // babbage: all operands in expression are unsigned, so modular | ||
712 | // arithmetic will always find correct gap, regardless of wrap arounds. | ||
713 | const U8 width = 24; | ||
714 | gap = LLModularMath::subtract<width>(mPacketsInID, id); | ||
715 | |||
707 | if (mPotentialLostPackets.find(id) != mPotentialLostPackets.end()) | 716 | if (mPotentialLostPackets.find(id) != mPotentialLostPackets.end()) |
708 | { | 717 | { |
709 | if(gMessageSystem->mVerboseLog) | 718 | if(gMessageSystem->mVerboseLog) |
@@ -765,6 +774,8 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) | |||
765 | 774 | ||
766 | } | 775 | } |
767 | } | 776 | } |
777 | mOutOfOrderRate.count(gap); | ||
778 | mLastPacketGap = gap; | ||
768 | } | 779 | } |
769 | 780 | ||
770 | 781 | ||
diff --git a/linden/indra/llmessage/llcircuit.h b/linden/indra/llmessage/llcircuit.h index 552b50f..b53c955 100644 --- a/linden/indra/llmessage/llcircuit.h +++ b/linden/indra/llmessage/llcircuit.h | |||
@@ -45,6 +45,7 @@ | |||
45 | #include "llpacketack.h" | 45 | #include "llpacketack.h" |
46 | #include "lluuid.h" | 46 | #include "lluuid.h" |
47 | #include "llthrottle.h" | 47 | #include "llthrottle.h" |
48 | #include "llstat.h" | ||
48 | 49 | ||
49 | // | 50 | // |
50 | // Constants | 51 | // Constants |
@@ -133,6 +134,10 @@ public: | |||
133 | S32 getUnackedPacketCount() const { return mUnackedPacketCount; } | 134 | S32 getUnackedPacketCount() const { return mUnackedPacketCount; } |
134 | S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; } | 135 | S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; } |
135 | F64 getNextPingSendTime() const { return mNextPingSendTime; } | 136 | F64 getNextPingSendTime() const { return mNextPingSendTime; } |
137 | F32 getOutOfOrderRate(LLStatAccum::TimeScale scale = LLStatAccum::SCALE_MINUTE) | ||
138 | { return mOutOfOrderRate.meanValue(scale); } | ||
139 | U32 getLastPacketGap() const { return mLastPacketGap; } | ||
140 | LLHost getHost() const { return mHost; } | ||
136 | 141 | ||
137 | LLThrottleGroup &getThrottleGroup() { return mThrottles; } | 142 | LLThrottleGroup &getThrottleGroup() { return mThrottles; } |
138 | 143 | ||
@@ -276,6 +281,9 @@ protected: | |||
276 | LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers | 281 | LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers |
277 | 282 | ||
278 | S32 mCurrentResendCount; // Number of resent packets since last spam | 283 | S32 mCurrentResendCount; // Number of resent packets since last spam |
284 | LLStatRate mOutOfOrderRate; // Rate of out of order packets coming in. | ||
285 | U32 mLastPacketGap; // Gap in sequence number of last packet. | ||
286 | |||
279 | }; | 287 | }; |
280 | 288 | ||
281 | 289 | ||
diff --git a/linden/indra/llmessage/llcurl.cpp b/linden/indra/llmessage/llcurl.cpp index 834ec4b..167e237 100644 --- a/linden/indra/llmessage/llcurl.cpp +++ b/linden/indra/llmessage/llcurl.cpp | |||
@@ -265,6 +265,10 @@ LLCurl::Easy* LLCurl::Easy::getEasy() | |||
265 | delete easy; | 265 | delete easy; |
266 | return NULL; | 266 | return NULL; |
267 | } | 267 | } |
268 | |||
269 | // set no DMS caching as default for all easy handles. This prevents them adopting a | ||
270 | // multi handles cache if they are added to one. | ||
271 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); | ||
268 | ++gCurlEasyCount; | 272 | ++gCurlEasyCount; |
269 | return easy; | 273 | return easy; |
270 | } | 274 | } |
@@ -747,7 +751,7 @@ bool LLCurlRequest::post(const std::string& url, const LLSD& data, LLCurl::Respo | |||
747 | easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL); | 751 | easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL); |
748 | easy->setopt(CURLOPT_POSTFIELDSIZE, bytes); | 752 | easy->setopt(CURLOPT_POSTFIELDSIZE, bytes); |
749 | 753 | ||
750 | easy->slist_append("Content-Type: application/xml"); | 754 | easy->slist_append("Content-Type: application/llsd+xml"); |
751 | easy->setHeaders(); | 755 | easy->setHeaders(); |
752 | 756 | ||
753 | lldebugs << "POSTING: " << bytes << " bytes." << llendl; | 757 | lldebugs << "POSTING: " << bytes << " bytes." << llendl; |
diff --git a/linden/indra/llmessage/llhttpassetstorage.cpp b/linden/indra/llmessage/llhttpassetstorage.cpp index fdd521f..6d5a716 100644 --- a/linden/indra/llmessage/llhttpassetstorage.cpp +++ b/linden/indra/llmessage/llhttpassetstorage.cpp | |||
@@ -256,6 +256,10 @@ void LLHTTPAssetRequest::setupCurlHandle() | |||
256 | // disable use of proxy, which can't handle chunked transfers | 256 | // disable use of proxy, which can't handle chunked transfers |
257 | } | 257 | } |
258 | mHTTPHeaders = curl_slist_append(mHTTPHeaders, "Pragma:"); | 258 | mHTTPHeaders = curl_slist_append(mHTTPHeaders, "Pragma:"); |
259 | |||
260 | // bug in curl causes DNS to be cached for too long a time, 0 sets it to never cache DNS results internally (to curl) | ||
261 | curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); | ||
262 | |||
259 | // resist the temptation to explicitly add the Transfer-Encoding: chunked | 263 | // resist the temptation to explicitly add the Transfer-Encoding: chunked |
260 | // header here - invokes a libCURL bug | 264 | // header here - invokes a libCURL bug |
261 | curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mHTTPHeaders); | 265 | curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mHTTPHeaders); |
diff --git a/linden/indra/llmessage/llhttpclient.cpp b/linden/indra/llmessage/llhttpclient.cpp index ef163fa..a07f379 100644 --- a/linden/indra/llmessage/llhttpclient.cpp +++ b/linden/indra/llmessage/llhttpclient.cpp | |||
@@ -106,7 +106,7 @@ namespace | |||
106 | LLSDInjector(const LLSD& sd) : mSD(sd) {} | 106 | LLSDInjector(const LLSD& sd) : mSD(sd) {} |
107 | virtual ~LLSDInjector() {} | 107 | virtual ~LLSDInjector() {} |
108 | 108 | ||
109 | const char* contentType() { return "application/xml"; } | 109 | const char* contentType() { return "application/llsd+xml"; } |
110 | 110 | ||
111 | virtual EStatus process_impl(const LLChannelDescriptors& channels, | 111 | virtual EStatus process_impl(const LLChannelDescriptors& channels, |
112 | buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) | 112 | buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) |
@@ -160,9 +160,10 @@ namespace | |||
160 | fstream.seekg(0, std::ios::end); | 160 | fstream.seekg(0, std::ios::end); |
161 | U32 fileSize = fstream.tellg(); | 161 | U32 fileSize = fstream.tellg(); |
162 | fstream.seekg(0, std::ios::beg); | 162 | fstream.seekg(0, std::ios::beg); |
163 | std::vector<char> fileBuffer(fileSize); | 163 | char* fileBuffer; |
164 | fstream.read(&fileBuffer[0], fileSize); | 164 | fileBuffer = new char [fileSize]; |
165 | ostream.write(&fileBuffer[0], fileSize); | 165 | fstream.read(fileBuffer, fileSize); |
166 | ostream.write(fileBuffer, fileSize); | ||
166 | fstream.close(); | 167 | fstream.close(); |
167 | eos = true; | 168 | eos = true; |
168 | return STATUS_DONE; | 169 | return STATUS_DONE; |
@@ -189,9 +190,10 @@ namespace | |||
189 | 190 | ||
190 | LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ); | 191 | LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ); |
191 | S32 fileSize = vfile.getSize(); | 192 | S32 fileSize = vfile.getSize(); |
192 | std::vector<U8> fileBuffer(fileSize); | 193 | U8* fileBuffer; |
193 | vfile.read(&fileBuffer[0], fileSize); | 194 | fileBuffer = new U8 [fileSize]; |
194 | ostream.write((char*)&fileBuffer[0], fileSize); | 195 | vfile.read(fileBuffer, fileSize); |
196 | ostream.write((char*)fileBuffer, fileSize); | ||
195 | eos = true; | 197 | eos = true; |
196 | return STATUS_DONE; | 198 | return STATUS_DONE; |
197 | } | 199 | } |
@@ -236,7 +238,8 @@ static void request( | |||
236 | //the Pragma header it so gratuitously inserts | 238 | //the Pragma header it so gratuitously inserts |
237 | //Before inserting the header, force libcurl | 239 | //Before inserting the header, force libcurl |
238 | //to not use the proxy (read: llurlrequest.cpp) | 240 | //to not use the proxy (read: llurlrequest.cpp) |
239 | if ((iter->first == "Pragma") && (iter->second.asString() == "")) | 241 | static const std::string PRAGMA("Pragma"); |
242 | if ((iter->first == PRAGMA) && (iter->second.asString().empty())) | ||
240 | { | 243 | { |
241 | req->useProxy(false); | 244 | req->useProxy(false); |
242 | } | 245 | } |
@@ -245,6 +248,19 @@ static void request( | |||
245 | req->addHeader(header.str().c_str()); | 248 | req->addHeader(header.str().c_str()); |
246 | } | 249 | } |
247 | } | 250 | } |
251 | |||
252 | // Check to see if we have already set Accept or not. If no one | ||
253 | // set it, set it to application/llsd+xml since that's what we | ||
254 | // almost always want. | ||
255 | if( method != LLURLRequest::HTTP_PUT && method != LLURLRequest::HTTP_POST ) | ||
256 | { | ||
257 | static const std::string ACCEPT("Accept"); | ||
258 | if(!headers.has(ACCEPT)) | ||
259 | { | ||
260 | req->addHeader("Accept: application/llsd+xml"); | ||
261 | } | ||
262 | } | ||
263 | |||
248 | req->setCallback(new LLHTTPClientURLAdaptor(responder)); | 264 | req->setCallback(new LLHTTPClientURLAdaptor(responder)); |
249 | 265 | ||
250 | if (method == LLURLRequest::HTTP_POST && gMessageSystem) | 266 | if (method == LLURLRequest::HTTP_POST && gMessageSystem) |
@@ -252,12 +268,22 @@ static void request( | |||
252 | req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d", | 268 | req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d", |
253 | gMessageSystem->mPort).c_str()); | 269 | gMessageSystem->mPort).c_str()); |
254 | } | 270 | } |
255 | 271 | ||
256 | if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST) | 272 | if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST) |
257 | { | 273 | { |
258 | req->addHeader(llformat("Content-Type: %s", | 274 | static const std::string CONTENT_TYPE("Content-Type"); |
259 | body_injector->contentType()).c_str()); | 275 | if(!headers.has(CONTENT_TYPE)) |
260 | 276 | { | |
277 | // If the Content-Type header was passed in, it has | ||
278 | // already been added as a header through req->addHeader | ||
279 | // in the loop above. We defer to the caller's wisdom, but | ||
280 | // if they did not specify a Content-Type, then ask the | ||
281 | // injector. | ||
282 | req->addHeader( | ||
283 | llformat( | ||
284 | "Content-Type: %s", | ||
285 | body_injector->contentType()).c_str()); | ||
286 | } | ||
261 | chain.push_back(LLIOPipe::ptr_t(body_injector)); | 287 | chain.push_back(LLIOPipe::ptr_t(body_injector)); |
262 | } | 288 | } |
263 | 289 | ||
@@ -284,9 +310,13 @@ void LLHTTPClient::getByteRange( | |||
284 | request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers); | 310 | request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers); |
285 | } | 311 | } |
286 | 312 | ||
287 | void LLHTTPClient::head(const std::string& url, ResponderPtr responder, const F32 timeout) | 313 | void LLHTTPClient::head( |
314 | const std::string& url, | ||
315 | ResponderPtr responder, | ||
316 | const LLSD& headers, | ||
317 | const F32 timeout) | ||
288 | { | 318 | { |
289 | request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout); | 319 | request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers); |
290 | } | 320 | } |
291 | 321 | ||
292 | void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout) | 322 | void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout) |
@@ -397,39 +427,66 @@ LLSD LLHTTPClient::blockingGet(const std::string& url) | |||
397 | return response; | 427 | return response; |
398 | } | 428 | } |
399 | 429 | ||
400 | void LLHTTPClient::put(const std::string& url, const LLSD& body, ResponderPtr responder, const F32 timeout) | 430 | void LLHTTPClient::put( |
431 | const std::string& url, | ||
432 | const LLSD& body, | ||
433 | ResponderPtr responder, | ||
434 | const LLSD& headers, | ||
435 | const F32 timeout) | ||
401 | { | 436 | { |
402 | request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, timeout); | 437 | request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, timeout, headers); |
403 | } | 438 | } |
404 | 439 | ||
405 | void LLHTTPClient::post(const std::string& url, const LLSD& body, ResponderPtr responder, const F32 timeout) | 440 | void LLHTTPClient::post( |
441 | const std::string& url, | ||
442 | const LLSD& body, | ||
443 | ResponderPtr responder, | ||
444 | const LLSD& headers, | ||
445 | const F32 timeout) | ||
406 | { | 446 | { |
407 | request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout); | 447 | request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout, headers); |
408 | } | 448 | } |
409 | 449 | ||
410 | void LLHTTPClient::postRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder, const F32 timeout) | 450 | void LLHTTPClient::postRaw( |
451 | const std::string& url, | ||
452 | const U8* data, | ||
453 | S32 size, | ||
454 | ResponderPtr responder, | ||
455 | const LLSD& headers, | ||
456 | const F32 timeout) | ||
411 | { | 457 | { |
412 | request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout); | 458 | request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout, headers); |
413 | } | 459 | } |
414 | 460 | ||
415 | void LLHTTPClient::postFile(const std::string& url, const std::string& filename, ResponderPtr responder, const F32 timeout) | 461 | void LLHTTPClient::postFile( |
462 | const std::string& url, | ||
463 | const std::string& filename, | ||
464 | ResponderPtr responder, | ||
465 | const LLSD& headers, | ||
466 | const F32 timeout) | ||
416 | { | 467 | { |
417 | request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, timeout); | 468 | request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, timeout, headers); |
418 | } | 469 | } |
419 | 470 | ||
420 | void LLHTTPClient::postFile(const std::string& url, const LLUUID& uuid, | 471 | void LLHTTPClient::postFile( |
421 | LLAssetType::EType asset_type, ResponderPtr responder, const F32 timeout) | 472 | const std::string& url, |
473 | const LLUUID& uuid, | ||
474 | LLAssetType::EType asset_type, | ||
475 | ResponderPtr responder, | ||
476 | const LLSD& headers, | ||
477 | const F32 timeout) | ||
422 | { | 478 | { |
423 | request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout); | 479 | request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers); |
424 | } | 480 | } |
425 | 481 | ||
426 | // static | 482 | // static |
427 | void LLHTTPClient::del( | 483 | void LLHTTPClient::del( |
428 | const std::string& url, | 484 | const std::string& url, |
429 | ResponderPtr responder, | 485 | ResponderPtr responder, |
486 | const LLSD& headers, | ||
430 | const F32 timeout) | 487 | const F32 timeout) |
431 | { | 488 | { |
432 | request(url, LLURLRequest::HTTP_DELETE, NULL, responder, timeout); | 489 | request(url, LLURLRequest::HTTP_DELETE, NULL, responder, timeout, headers); |
433 | } | 490 | } |
434 | 491 | ||
435 | // static | 492 | // static |
@@ -437,9 +494,10 @@ void LLHTTPClient::move( | |||
437 | const std::string& url, | 494 | const std::string& url, |
438 | const std::string& destination, | 495 | const std::string& destination, |
439 | ResponderPtr responder, | 496 | ResponderPtr responder, |
497 | const LLSD& hdrs, | ||
440 | const F32 timeout) | 498 | const F32 timeout) |
441 | { | 499 | { |
442 | LLSD headers; | 500 | LLSD headers = hdrs; |
443 | headers["Destination"] = destination; | 501 | headers["Destination"] = destination; |
444 | request(url, LLURLRequest::HTTP_MOVE, NULL, responder, timeout, headers); | 502 | request(url, LLURLRequest::HTTP_MOVE, NULL, responder, timeout, headers); |
445 | } | 503 | } |
diff --git a/linden/indra/llmessage/llhttpclient.h b/linden/indra/llmessage/llhttpclient.h index 50c6f7a..367098f 100644 --- a/linden/indra/llmessage/llhttpclient.h +++ b/linden/indra/llmessage/llhttpclient.h | |||
@@ -62,28 +62,56 @@ public: | |||
62 | 62 | ||
63 | /** @name non-blocking API */ | 63 | /** @name non-blocking API */ |
64 | //@{ | 64 | //@{ |
65 | static void head(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 65 | static void head( |
66 | const std::string& url, | ||
67 | ResponderPtr, | ||
68 | const LLSD& headers = LLSD(), | ||
69 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | ||
66 | static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr, const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 70 | static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr, const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); |
67 | static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 71 | static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); |
68 | static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 72 | static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); |
69 | 73 | ||
70 | static void put(const std::string& url, const LLSD& body, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 74 | static void put( |
75 | const std::string& url, | ||
76 | const LLSD& body, | ||
77 | ResponderPtr, | ||
78 | const LLSD& headers = LLSD(), | ||
79 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | ||
71 | static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 80 | static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); |
72 | static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 81 | static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); |
73 | 82 | ||
74 | static void post(const std::string& url, const LLSD& body, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 83 | static void post( |
75 | 84 | const std::string& url, | |
85 | const LLSD& body, | ||
86 | ResponderPtr, | ||
87 | const LLSD& headers = LLSD(), | ||
88 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | ||
76 | /** Takes ownership of data and deletes it when sent */ | 89 | /** Takes ownership of data and deletes it when sent */ |
77 | static void postRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 90 | static void postRaw( |
78 | 91 | const std::string& url, | |
79 | static void postFile(const std::string& url, const std::string& filename, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 92 | const U8* data, |
80 | # | 93 | S32 size, |
81 | static void postFile(const std::string& url, const LLUUID& uuid, | 94 | ResponderPtr responder, |
82 | LLAssetType::EType asset_type, ResponderPtr responder, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 95 | const LLSD& headers = LLSD(), |
96 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | ||
97 | static void postFile( | ||
98 | const std::string& url, | ||
99 | const std::string& filename, | ||
100 | ResponderPtr, | ||
101 | const LLSD& headers = LLSD(), | ||
102 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | ||
103 | static void postFile( | ||
104 | const std::string& url, | ||
105 | const LLUUID& uuid, | ||
106 | LLAssetType::EType asset_type, | ||
107 | ResponderPtr responder, | ||
108 | const LLSD& headers = LLSD(), | ||
109 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | ||
83 | 110 | ||
84 | static void del( | 111 | static void del( |
85 | const std::string& url, | 112 | const std::string& url, |
86 | ResponderPtr responder, | 113 | ResponderPtr responder, |
114 | const LLSD& headers = LLSD(), | ||
87 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 115 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); |
88 | ///< sends a DELETE method, but we can't call it delete in c++ | 116 | ///< sends a DELETE method, but we can't call it delete in c++ |
89 | 117 | ||
@@ -93,12 +121,14 @@ public: | |||
93 | * @param url The complete serialized (and escaped) url to get. | 121 | * @param url The complete serialized (and escaped) url to get. |
94 | * @param destination The complete serialized destination url. | 122 | * @param destination The complete serialized destination url. |
95 | * @param responder The responder that will handle the result. | 123 | * @param responder The responder that will handle the result. |
124 | * @param headers A map of key:value headers to pass to the request | ||
96 | * @param timeout The number of seconds to give the server to respond. | 125 | * @param timeout The number of seconds to give the server to respond. |
97 | */ | 126 | */ |
98 | static void move( | 127 | static void move( |
99 | const std::string& url, | 128 | const std::string& url, |
100 | const std::string& destination, | 129 | const std::string& destination, |
101 | ResponderPtr responder, | 130 | ResponderPtr responder, |
131 | const LLSD& headers = LLSD(), | ||
102 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); | 132 | const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); |
103 | 133 | ||
104 | //@} | 134 | //@} |
diff --git a/linden/indra/llmessage/lliohttpserver.cpp b/linden/indra/llmessage/lliohttpserver.cpp index d4155f6..64222ff 100644 --- a/linden/indra/llmessage/lliohttpserver.cpp +++ b/linden/indra/llmessage/lliohttpserver.cpp | |||
@@ -47,6 +47,7 @@ | |||
47 | #include "llpumpio.h" | 47 | #include "llpumpio.h" |
48 | #include "llsd.h" | 48 | #include "llsd.h" |
49 | #include "llsdserialize_xml.h" | 49 | #include "llsdserialize_xml.h" |
50 | #include "llstat.h" | ||
50 | #include "llstl.h" | 51 | #include "llstl.h" |
51 | #include "lltimer.h" | 52 | #include "lltimer.h" |
52 | 53 | ||
@@ -171,22 +172,26 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( | |||
171 | std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB]; | 172 | std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB]; |
172 | if(verb == HTTP_VERB_GET) | 173 | if(verb == HTTP_VERB_GET) |
173 | { | 174 | { |
175 | LLPerfBlock getblock("http_get"); | ||
174 | mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); | 176 | mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); |
175 | } | 177 | } |
176 | else if(verb == HTTP_VERB_PUT) | 178 | else if(verb == HTTP_VERB_PUT) |
177 | { | 179 | { |
180 | LLPerfBlock putblock("http_put"); | ||
178 | LLSD input; | 181 | LLSD input; |
179 | LLSDSerialize::fromXML(input, istr); | 182 | LLSDSerialize::fromXML(input, istr); |
180 | mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input); | 183 | mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input); |
181 | } | 184 | } |
182 | else if(verb == HTTP_VERB_POST) | 185 | else if(verb == HTTP_VERB_POST) |
183 | { | 186 | { |
187 | LLPerfBlock postblock("http_post"); | ||
184 | LLSD input; | 188 | LLSD input; |
185 | LLSDSerialize::fromXML(input, istr); | 189 | LLSDSerialize::fromXML(input, istr); |
186 | mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input); | 190 | mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input); |
187 | } | 191 | } |
188 | else if(verb == HTTP_VERB_DELETE) | 192 | else if(verb == HTTP_VERB_DELETE) |
189 | { | 193 | { |
194 | LLPerfBlock delblock("http_delete"); | ||
190 | mNode.del(LLHTTPNode::ResponsePtr(mResponse), context); | 195 | mNode.del(LLHTTPNode::ResponsePtr(mResponse), context); |
191 | } | 196 | } |
192 | else if(verb == HTTP_VERB_OPTIONS) | 197 | else if(verb == HTTP_VERB_OPTIONS) |
@@ -240,7 +245,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( | |||
240 | case STATE_GOOD_RESULT: | 245 | case STATE_GOOD_RESULT: |
241 | { | 246 | { |
242 | LLSD headers = mHeaders; | 247 | LLSD headers = mHeaders; |
243 | headers["Content-Type"] = "application/xml"; | 248 | headers["Content-Type"] = "application/llsd+xml"; |
244 | context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers; | 249 | context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers; |
245 | LLBufferStream ostr(channels, buffer.get()); | 250 | LLBufferStream ostr(channels, buffer.get()); |
246 | LLSDSerialize::toXML(mGoodResult, ostr); | 251 | LLSDSerialize::toXML(mGoodResult, ostr); |
diff --git a/linden/indra/llmessage/llmail.cpp b/linden/indra/llmessage/llmail.cpp index 8ae7206..0504080 100644 --- a/linden/indra/llmessage/llmail.cpp +++ b/linden/indra/llmessage/llmail.cpp | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "llblowfishcipher.h" | 51 | #include "llblowfishcipher.h" |
52 | #include "llerror.h" | 52 | #include "llerror.h" |
53 | #include "llhost.h" | 53 | #include "llhost.h" |
54 | #include "llsd.h" | ||
54 | #include "llstring.h" | 55 | #include "llstring.h" |
55 | #include "lluuid.h" | 56 | #include "lluuid.h" |
56 | #include "net.h" | 57 | #include "net.h" |
@@ -111,16 +112,22 @@ void disconnect_smtp() | |||
111 | // Returns TRUE on success. | 112 | // Returns TRUE on success. |
112 | // message should NOT be SMTP escaped. | 113 | // message should NOT be SMTP escaped. |
113 | // static | 114 | // static |
114 | BOOL LLMail::send(const char* from_name, const char* from_address, | 115 | BOOL LLMail::send( |
115 | const char* to_name, const char* to_address, | 116 | const char* from_name, |
116 | const char* subject, const char* message) | 117 | const char* from_address, |
118 | const char* to_name, | ||
119 | const char* to_address, | ||
120 | const char* subject, | ||
121 | const char* message, | ||
122 | const LLSD& headers) | ||
117 | { | 123 | { |
118 | std::string header = buildSMTPTransaction( | 124 | std::string header = buildSMTPTransaction( |
119 | from_name, | 125 | from_name, |
120 | from_address, | 126 | from_address, |
121 | to_name, | 127 | to_name, |
122 | to_address, | 128 | to_address, |
123 | subject); | 129 | subject, |
130 | headers); | ||
124 | if(header.empty()) | 131 | if(header.empty()) |
125 | { | 132 | { |
126 | return FALSE; | 133 | return FALSE; |
@@ -192,7 +199,8 @@ std::string LLMail::buildSMTPTransaction( | |||
192 | const char* from_address, | 199 | const char* from_address, |
193 | const char* to_name, | 200 | const char* to_name, |
194 | const char* to_address, | 201 | const char* to_address, |
195 | const char* subject) | 202 | const char* subject, |
203 | const LLSD& headers) | ||
196 | { | 204 | { |
197 | if(!from_address || !to_address) | 205 | if(!from_address || !to_address) |
198 | { | 206 | { |
@@ -236,8 +244,20 @@ std::string LLMail::buildSMTPTransaction( | |||
236 | << "DATA\r\n" | 244 | << "DATA\r\n" |
237 | << "From: " << from_fmt.str() << "\r\n" | 245 | << "From: " << from_fmt.str() << "\r\n" |
238 | << "To: " << to_fmt.str() << "\r\n" | 246 | << "To: " << to_fmt.str() << "\r\n" |
239 | << "Subject: " << subject << "\r\n" | 247 | << "Subject: " << subject << "\r\n"; |
240 | << "\r\n"; | 248 | |
249 | if(headers.isMap()) | ||
250 | { | ||
251 | LLSD::map_const_iterator iter = headers.beginMap(); | ||
252 | LLSD::map_const_iterator end = headers.endMap(); | ||
253 | for(; iter != end; ++iter) | ||
254 | { | ||
255 | header << (*iter).first << ": " << ((*iter).second).asString() | ||
256 | << "\r\n"; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | header << "\r\n"; | ||
241 | return header.str(); | 261 | return header.str(); |
242 | } | 262 | } |
243 | 263 | ||
diff --git a/linden/indra/llmessage/llmail.h b/linden/indra/llmessage/llmail.h index 86b7793..018e180 100644 --- a/linden/indra/llmessage/llmail.h +++ b/linden/indra/llmessage/llmail.h | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | typedef struct apr_pool_t apr_pool_t; | 35 | typedef struct apr_pool_t apr_pool_t; |
36 | 36 | ||
37 | class LLUUID; | 37 | #include "llsd.h" |
38 | 38 | ||
39 | class LLMail | 39 | class LLMail |
40 | { | 40 | { |
@@ -45,34 +45,51 @@ public: | |||
45 | // Allow all email transmission to be disabled/enabled. | 45 | // Allow all email transmission to be disabled/enabled. |
46 | static void enable(bool mail_enabled); | 46 | static void enable(bool mail_enabled); |
47 | 47 | ||
48 | // returns TRUE if the call succeeds, FALSE otherwise. | 48 | /** |
49 | // | 49 | * @brief send an email |
50 | // Results in: | 50 | * @param from_name The name of the email sender |
51 | // From: "from_name" <from_address> | 51 | * @param from_address The email address for the sender |
52 | // To: "to_name" <to_address> | 52 | * @param to_name The name of the email recipient |
53 | // Subject: subject | 53 | * @param to_address The email recipient address |
54 | // message | 54 | * @param subject The subject of the email |
55 | static BOOL send(const char* from_name, const char* from_address, | 55 | * @param headers optional X-Foo headers in an llsd map. |
56 | const char* to_name, const char* to_address, | 56 | * @return Returns TRUE if the call succeeds, FALSE otherwise. |
57 | const char* subject, const char* message); | 57 | * |
58 | * Results in: | ||
59 | * From: "from_name" <from_address> | ||
60 | * To: "to_name" <to_address> | ||
61 | * Subject: subject | ||
62 | * | ||
63 | * message | ||
64 | */ | ||
65 | static BOOL send( | ||
66 | const char* from_name, | ||
67 | const char* from_address, | ||
68 | const char* to_name, | ||
69 | const char* to_address, | ||
70 | const char* subject, | ||
71 | const char* message, | ||
72 | const LLSD& headers = LLSD()); | ||
58 | 73 | ||
59 | /** | 74 | /** |
60 | * @brief build the complete smtp transaction & header for use in an | 75 | * @brief build the complete smtp transaction & header for use in an |
61 | * mail. | 76 | * mail. |
62 | * | 77 | * |
63 | * @param from_name The name of the email sender | 78 | * @param from_name The name of the email sender |
64 | * @param from_address The email address for the sender | 79 | * @param from_address The email address for the sender |
65 | * @param to_name The name of the email recipient | 80 | * @param to_name The name of the email recipient |
66 | * @param to_name The email recipient address | 81 | * @param to_address The email recipient address |
67 | * @param subject The subject of the email | 82 | * @param subject The subject of the email |
68 | * @return Returns the complete SMTP transaction mail header. | 83 | * @param headers optional X-Foo headers in an llsd map. |
69 | */ | 84 | * @return Returns the complete SMTP transaction mail header. |
85 | */ | ||
70 | static std::string buildSMTPTransaction( | 86 | static std::string buildSMTPTransaction( |
71 | const char* from_name, | 87 | const char* from_name, |
72 | const char* from_address, | 88 | const char* from_address, |
73 | const char* to_name, | 89 | const char* to_name, |
74 | const char* to_address, | 90 | const char* to_address, |
75 | const char* subject); | 91 | const char* subject, |
92 | const LLSD& headers = LLSD()); | ||
76 | 93 | ||
77 | /** | 94 | /** |
78 | * @brief send an email with header and body. | 95 | * @brief send an email with header and body. |
diff --git a/linden/indra/llmessage/llmessagetemplate.cpp b/linden/indra/llmessage/llmessagetemplate.cpp index 4a560ca..ff44d45 100644 --- a/linden/indra/llmessage/llmessagetemplate.cpp +++ b/linden/indra/llmessage/llmessagetemplate.cpp | |||
@@ -50,7 +50,7 @@ void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S3 | |||
50 | } | 50 | } |
51 | if(size) | 51 | if(size) |
52 | { | 52 | { |
53 | delete mData; // Delete it if it already exists | 53 | delete[] mData; // Delete it if it already exists |
54 | mData = new U8[size]; | 54 | mData = new U8[size]; |
55 | htonmemcpy(mData, data, mType, size); | 55 | htonmemcpy(mData, data, mType, size); |
56 | } | 56 | } |
@@ -175,3 +175,23 @@ std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg) | |||
175 | 175 | ||
176 | return s; | 176 | return s; |
177 | } | 177 | } |
178 | |||
179 | void LLMessageTemplate::banUdp() | ||
180 | { | ||
181 | static const char* deprecation[] = { | ||
182 | "NotDeprecated", | ||
183 | "Deprecated", | ||
184 | "UDPDeprecated", | ||
185 | "UDPBlackListed" | ||
186 | }; | ||
187 | if (mDeprecation != MD_DEPRECATED) | ||
188 | { | ||
189 | llinfos << "Setting " << mName << " to UDPBlackListed was " << deprecation[mDeprecation] << llendl; | ||
190 | mDeprecation = MD_UDPBLACKLISTED; | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | llinfos << mName << " is already more deprecated than UDPBlackListed" << llendl; | ||
195 | } | ||
196 | } | ||
197 | |||
diff --git a/linden/indra/llmessage/llmessagetemplate.h b/linden/indra/llmessage/llmessagetemplate.h index 716c618..445d1a8 100644 --- a/linden/indra/llmessage/llmessagetemplate.h +++ b/linden/indra/llmessage/llmessagetemplate.h | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include "lldarray.h" | 35 | #include "lldarray.h" |
36 | #include "message.h" // TODO: babbage: Remove... | 36 | #include "message.h" // TODO: babbage: Remove... |
37 | #include "llstat.h" | ||
37 | #include "llstl.h" | 38 | #include "llstl.h" |
38 | 39 | ||
39 | class LLMsgVarData | 40 | class LLMsgVarData |
@@ -370,20 +371,23 @@ public: | |||
370 | { | 371 | { |
371 | if (mHandlerFunc) | 372 | if (mHandlerFunc) |
372 | { | 373 | { |
374 | LLPerfBlock msg_cb_time("msg_cb", mName); | ||
373 | mHandlerFunc(msgsystem, mUserData); | 375 | mHandlerFunc(msgsystem, mUserData); |
374 | return TRUE; | 376 | return TRUE; |
375 | } | 377 | } |
376 | return FALSE; | 378 | return FALSE; |
377 | } | 379 | } |
378 | 380 | ||
379 | bool isBanned(bool trustedSource) const | 381 | bool isUdpBanned() const |
380 | { | 382 | { |
381 | return trustedSource ? mBanFromTrusted : mBanFromUntrusted; | 383 | return mDeprecation == MD_UDPBLACKLISTED; |
382 | } | 384 | } |
383 | 385 | ||
384 | bool isUdpBanned() const | 386 | void banUdp(); |
387 | |||
388 | bool isBanned(bool trustedSource) const | ||
385 | { | 389 | { |
386 | return mDeprecation == MD_UDPBLACKLISTED; | 390 | return trustedSource ? mBanFromTrusted : mBanFromUntrusted; |
387 | } | 391 | } |
388 | 392 | ||
389 | friend std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg); | 393 | friend std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg); |
diff --git a/linden/indra/llmessage/llmessagethrottle.cpp b/linden/indra/llmessage/llmessagethrottle.cpp index ad9df26..47e1bd6 100644 --- a/linden/indra/llmessage/llmessagethrottle.cpp +++ b/linden/indra/llmessage/llmessagethrottle.cpp | |||
@@ -119,7 +119,7 @@ BOOL LLMessageThrottle::addViewerAlert(const LLUUID& to, const std::string& mesg | |||
119 | full_mesg << to << mesg; | 119 | full_mesg << to << mesg; |
120 | 120 | ||
121 | // Create an entry for this message. | 121 | // Create an entry for this message. |
122 | size_t hash = llhash<const char*> (full_mesg.str().c_str()); | 122 | size_t hash = llhash(full_mesg.str().c_str()); |
123 | LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime()); | 123 | LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime()); |
124 | 124 | ||
125 | // Check if this message is already in the list. | 125 | // Check if this message is already in the list. |
@@ -153,7 +153,7 @@ BOOL LLMessageThrottle::addAgentAlert(const LLUUID& agent, const LLUUID& task, c | |||
153 | full_mesg << agent << task << mesg; | 153 | full_mesg << agent << task << mesg; |
154 | 154 | ||
155 | // Create an entry for this message. | 155 | // Create an entry for this message. |
156 | size_t hash = llhash<const char*> (full_mesg.str().c_str()); | 156 | size_t hash = llhash(full_mesg.str().c_str()); |
157 | LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime()); | 157 | LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime()); |
158 | 158 | ||
159 | // Check if this message is already in the list. | 159 | // Check if this message is already in the list. |
diff --git a/linden/indra/llmessage/llnamevalue.cpp b/linden/indra/llmessage/llnamevalue.cpp index c44f6ce..f661261 100644 --- a/linden/indra/llmessage/llnamevalue.cpp +++ b/linden/indra/llmessage/llnamevalue.cpp | |||
@@ -896,7 +896,7 @@ void LLNameValue::setVec3(const LLVector3 &a) | |||
896 | } | 896 | } |
897 | 897 | ||
898 | 898 | ||
899 | std::string LLNameValue::printNameValue() | 899 | std::string LLNameValue::printNameValue() const |
900 | { | 900 | { |
901 | std::string buffer; | 901 | std::string buffer; |
902 | buffer = llformat("%s %s %s %s ", mName, mStringType, mStringClass, mStringSendto); | 902 | buffer = llformat("%s %s %s %s ", mName, mStringType, mStringClass, mStringSendto); |
@@ -905,7 +905,7 @@ std::string LLNameValue::printNameValue() | |||
905 | return buffer; | 905 | return buffer; |
906 | } | 906 | } |
907 | 907 | ||
908 | std::string LLNameValue::printData() | 908 | std::string LLNameValue::printData() const |
909 | { | 909 | { |
910 | std::string buffer; | 910 | std::string buffer; |
911 | switch(mType) | 911 | switch(mType) |
diff --git a/linden/indra/llmessage/llnamevalue.h b/linden/indra/llmessage/llnamevalue.h index 52beb07..f6c5040 100644 --- a/linden/indra/llmessage/llnamevalue.h +++ b/linden/indra/llmessage/llnamevalue.h | |||
@@ -148,8 +148,8 @@ public: | |||
148 | BOOL sendToViewer() const; | 148 | BOOL sendToViewer() const; |
149 | 149 | ||
150 | void callCallback(); | 150 | void callCallback(); |
151 | std::string printNameValue(); | 151 | std::string printNameValue() const; |
152 | std::string printData(); | 152 | std::string printData() const; |
153 | 153 | ||
154 | ENameValueType getTypeEnum() const { return mType; } | 154 | ENameValueType getTypeEnum() const { return mType; } |
155 | ENameValueClass getClassEnum() const { return mClass; } | 155 | ENameValueClass getClassEnum() const { return mClass; } |
diff --git a/linden/indra/llmessage/llpumpio.cpp b/linden/indra/llmessage/llpumpio.cpp index 6adf9c2..9ce0bab 100644 --- a/linden/indra/llmessage/llpumpio.cpp +++ b/linden/indra/llmessage/llpumpio.cpp | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "llapr.h" | 41 | #include "llapr.h" |
42 | #include "llmemtype.h" | 42 | #include "llmemtype.h" |
43 | #include "llstl.h" | 43 | #include "llstl.h" |
44 | #include "llstat.h" | ||
44 | 45 | ||
45 | // These should not be enabled in production, but they can be | 46 | // These should not be enabled in production, but they can be |
46 | // intensely useful during development for finding certain kinds of | 47 | // intensely useful during development for finding certain kinds of |
@@ -521,7 +522,10 @@ void LLPumpIO::pump(const S32& poll_timeout) | |||
521 | //llinfos << "polling" << llendl; | 522 | //llinfos << "polling" << llendl; |
522 | S32 count = 0; | 523 | S32 count = 0; |
523 | S32 client_id = 0; | 524 | S32 client_id = 0; |
524 | apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd); | 525 | { |
526 | LLPerfBlock polltime("pump_poll"); | ||
527 | apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd); | ||
528 | } | ||
525 | PUMP_DEBUG; | 529 | PUMP_DEBUG; |
526 | for(S32 ii = 0; ii < count; ++ii) | 530 | for(S32 ii = 0; ii < count; ++ii) |
527 | { | 531 | { |
diff --git a/linden/indra/llmessage/llregionflags.h b/linden/indra/llmessage/llregionflags.h index af010ae..46624c1 100644 --- a/linden/indra/llmessage/llregionflags.h +++ b/linden/indra/llmessage/llregionflags.h | |||
@@ -60,8 +60,10 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7); | |||
60 | // All content wiped once per night | 60 | // All content wiped once per night |
61 | const U32 REGION_FLAGS_SANDBOX = (1 << 8); | 61 | const U32 REGION_FLAGS_SANDBOX = (1 << 8); |
62 | const U32 REGION_FLAGS_NULL_LAYER = (1 << 9); | 62 | const U32 REGION_FLAGS_NULL_LAYER = (1 << 9); |
63 | const U32 REGION_FLAGS_SKIP_AGENT_ACTION = (1 << 10); | 63 | // const U32 REGION_FLAGS_SKIP_AGENT_ACTION = (1 << 10); |
64 | const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11); | 64 | const U32 REGION_FLAGS_HARD_ALLOW_LAND_TRANSFER = (1 << 10); // Region allows land reselling |
65 | // const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11); | ||
66 | const U32 REGION_FLAGS_HARD_ALLOW_POST_CLASSIFIED = (1 << 11); // Region allows posting of classified ads | ||
65 | const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies | 67 | const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies |
66 | const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13); | 68 | const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13); |
67 | const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics | 69 | const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics |
diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp index b20731a..3ee3c03 100644 --- a/linden/indra/llmessage/message.cpp +++ b/linden/indra/llmessage/message.cpp | |||
@@ -3956,22 +3956,27 @@ void LLMessageSystem::getString(const char *block, const char *var, | |||
3956 | blocknum); | 3956 | blocknum); |
3957 | } | 3957 | } |
3958 | 3958 | ||
3959 | S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) | 3959 | BOOL LLMessageSystem::has(const char *blockname) const |
3960 | { | ||
3961 | return getNumberOfBlocks(blockname) > 0; | ||
3962 | } | ||
3963 | |||
3964 | S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const | ||
3960 | { | 3965 | { |
3961 | return mMessageReader->getNumberOfBlocks(blockname); | 3966 | return mMessageReader->getNumberOfBlocks(blockname); |
3962 | } | 3967 | } |
3963 | 3968 | ||
3964 | S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) | 3969 | S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const |
3965 | { | 3970 | { |
3966 | return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname)); | 3971 | return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname)); |
3967 | } | 3972 | } |
3968 | 3973 | ||
3969 | S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) | 3974 | S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const |
3970 | { | 3975 | { |
3971 | return mMessageReader->getSize(blockname, varname); | 3976 | return mMessageReader->getSize(blockname, varname); |
3972 | } | 3977 | } |
3973 | 3978 | ||
3974 | S32 LLMessageSystem::getSize(const char *blockname, const char *varname) | 3979 | S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const |
3975 | { | 3980 | { |
3976 | return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), | 3981 | return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), |
3977 | LLMessageStringTable::getInstance()->getString(varname)); | 3982 | LLMessageStringTable::getInstance()->getString(varname)); |
@@ -3979,13 +3984,13 @@ S32 LLMessageSystem::getSize(const char *blockname, const char *varname) | |||
3979 | 3984 | ||
3980 | // size in bytes of variable length data | 3985 | // size in bytes of variable length data |
3981 | S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum, | 3986 | S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum, |
3982 | const char *varname) | 3987 | const char *varname) const |
3983 | { | 3988 | { |
3984 | return mMessageReader->getSize(blockname, blocknum, varname); | 3989 | return mMessageReader->getSize(blockname, blocknum, varname); |
3985 | } | 3990 | } |
3986 | 3991 | ||
3987 | S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum, | 3992 | S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum, |
3988 | const char *varname) | 3993 | const char *varname) const |
3989 | { | 3994 | { |
3990 | return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum, | 3995 | return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum, |
3991 | LLMessageStringTable::getInstance()->getString(varname)); | 3996 | LLMessageStringTable::getInstance()->getString(varname)); |
@@ -4021,3 +4026,18 @@ bool LLMessageSystem::checkAllMessages(S64 frame_count, LLPumpIO* http_pump) | |||
4021 | http_pump->callback(); | 4026 | http_pump->callback(); |
4022 | return (mPacketsIn - packetsIn) > 0; | 4027 | return (mPacketsIn - packetsIn) > 0; |
4023 | } | 4028 | } |
4029 | |||
4030 | void LLMessageSystem::banUdpMessage(const std::string& name) | ||
4031 | { | ||
4032 | message_template_name_map_t::iterator itt = mMessageTemplates.find( | ||
4033 | LLMessageStringTable::getInstance()->getString(name.c_str()) | ||
4034 | ); | ||
4035 | if(itt != mMessageTemplates.end()) | ||
4036 | { | ||
4037 | itt->second->banUdp(); | ||
4038 | } | ||
4039 | else | ||
4040 | { | ||
4041 | llwarns << "Attempted to ban an unknown message: " << name << "." << llendl; | ||
4042 | } | ||
4043 | } | ||
diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h index 8807521..b72aa9a 100644 --- a/linden/indra/llmessage/message.h +++ b/linden/indra/llmessage/message.h | |||
@@ -562,6 +562,9 @@ public: | |||
562 | /** Return false true if name is unknown or trusted */ | 562 | /** Return false true if name is unknown or trusted */ |
563 | bool isUntrustedMessage(const std::string& name) const; | 563 | bool isUntrustedMessage(const std::string& name) const; |
564 | 564 | ||
565 | // Change this message to be UDP black listed. | ||
566 | void banUdpMessage(const std::string& name); | ||
567 | |||
565 | private: | 568 | private: |
566 | // A list of the circuits that need to be sent DenyTrustedCircuit messages. | 569 | // A list of the circuits that need to be sent DenyTrustedCircuit messages. |
567 | typedef std::set<LLHost> host_set_t; | 570 | typedef std::set<LLHost> host_set_t; |
@@ -591,13 +594,14 @@ public: | |||
591 | LLHost findHost(const U32 circuit_code); | 594 | LLHost findHost(const U32 circuit_code); |
592 | void sanityCheck(); | 595 | void sanityCheck(); |
593 | 596 | ||
594 | S32 getNumberOfBlocksFast(const char *blockname); | 597 | BOOL has(const char *blockname) const; |
595 | S32 getNumberOfBlocks(const char *blockname); | 598 | S32 getNumberOfBlocksFast(const char *blockname) const; |
596 | S32 getSizeFast(const char *blockname, const char *varname); | 599 | S32 getNumberOfBlocks(const char *blockname) const; |
597 | S32 getSize(const char *blockname, const char *varname); | 600 | S32 getSizeFast(const char *blockname, const char *varname) const; |
601 | S32 getSize(const char *blockname, const char *varname) const; | ||
598 | S32 getSizeFast(const char *blockname, S32 blocknum, | 602 | S32 getSizeFast(const char *blockname, S32 blocknum, |
599 | const char *varname); // size in bytes of data | 603 | const char *varname) const; // size in bytes of data |
600 | S32 getSize(const char *blockname, S32 blocknum, const char *varname); | 604 | S32 getSize(const char *blockname, S32 blocknum, const char *varname) const; |
601 | 605 | ||
602 | void resetReceiveCounts(); // resets receive counts for all message types to 0 | 606 | void resetReceiveCounts(); // resets receive counts for all message types to 0 |
603 | void dumpReceiveCounts(); // dumps receive count for each message type to llinfos | 607 | void dumpReceiveCounts(); // dumps receive count for each message type to llinfos |