diff options
| author | Ryan Lortie <desrt@desrt.ca> | 2007-09-20 00:13:35 -0400 | 
|---|---|---|
| committer | Ryan Lortie <desrt@desrt.ca> | 2007-09-20 00:13:35 -0400 | 
| commit | 8c6b0ab3f7e437362112eeaf83a566475b85d27c (patch) | |
| tree | a8e56fe093b9597bf69c1b4c9144ba8490a1c3da | |
| parent | 44ed90c10d435f1a12c2b4b1a601040fa585ce38 (diff) | |
Add support for compacting DBusStrings to release wasted memory.
2007-09-19  Ryan Lortie  <desrt@desrt.ca>
        * dbus/dbus-string.[ch] (compact, _dbus_string_compact,
        _dbus_string_lock): new compact function to free up allocated memory
        that is no longer used.
        * dbus/dbus-message.c (load_message): call _dbus_string_compact on the
        message loader buffer.
        * dbus/dbus-transport-socket.c (do_reading, do_writing): call
        _dbus_string_compact on the incoming/outgoing "encoded" buffers.
        * dbus/dbus-string-util.c (_dbus_string_test): add a few tests for
        string compacting.
| -rw-r--r-- | ChangeLog | 23 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 3 | ||||
| -rw-r--r-- | dbus/dbus-string-util.c | 56 | ||||
| -rw-r--r-- | dbus/dbus-string.c | 63 | ||||
| -rw-r--r-- | dbus/dbus-string.h | 2 | ||||
| -rw-r--r-- | dbus/dbus-transport-socket.c | 2 | 
6 files changed, 130 insertions, 19 deletions
| @@ -1,3 +1,20 @@ +2007-09-19  Ryan Lortie  <desrt@desrt.ca> + +	Add support for compacting DBusStrings to release wasted memory. + +	* dbus/dbus-string.[ch] (compact, _dbus_string_compact, +	_dbus_string_lock): new compact function to free up allocated memory +	that is no longer used. + +	* dbus/dbus-message.c (load_message): call _dbus_string_compact on the +	message loader buffer. + +	* dbus/dbus-transport-socket.c (do_reading, do_writing): call +	_dbus_string_compact on the incoming/outgoing "encoded" buffers. + +	* dbus/dbus-string-util.c (_dbus_string_test): add a few tests for +	string compacting. +  2007-09-13  Ryan Lortie  <desrt@desrt.ca>  	* HACKING: add more explicit git branch/tag instructions @@ -625,7 +642,7 @@  2007-06-14  Havoc Pennington  <hp@redhat.com>  	* bus/dispatch.c (check_get_connection_unix_process_id): mop up -	getpid() (noticed by Peter KKümmel) and adapt the test to  +	getpid() (noticed by Peter Kümmel) and adapt the test to   	expect a "pid unknown" error when running on Windows.  2007-06-14  Havoc Pennington  <hp@redhat.com> @@ -688,7 +705,7 @@  2007-06-14  Simon McVittie  <simon.mcvittie@collabora.co.uk>  	* doc/dbus-specification.xml: say the protocol version is 1 instead of -	0 (patch from Kristoffer Lundén, fd.o#10033) and remove the FIXME +	0 (patch from Kristoffer Lundén, fd.o#10033) and remove the FIXME  	about removing protocol version from messages (as per Havoc's comment  	on that bug) @@ -1413,7 +1430,7 @@  2006-12-12  John (J5) Palmieri  <johnp@redhat.com>  	* bus/signal.c: Fix match_rule_equal errata -	(CVE-2006-6107 - Patch from Kimmo Hämäläinen  +	(CVE-2006-6107 - Patch from Kimmo Hämäläinen   	<kimmo.hamalainen@nokia.com>)  2006-11-19  Thiago Macieira  <thiago@kde.org> diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 91f6ebec..cd447985 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -3545,6 +3545,9 @@ load_message (DBusMessageLoader *loader,    _dbus_string_delete (&loader->data, 0, header_len + body_len); +  /* don't waste more than 2k of memory */ +  _dbus_string_compact (&loader->data, 2048); +    _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);    _dbus_assert (_dbus_string_get_length (&message->body) == body_len); diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c index cee02c4c..492c5289 100644 --- a/dbus/dbus-string-util.c +++ b/dbus/dbus-string-util.c @@ -790,6 +790,62 @@ _dbus_string_test (void)      _dbus_string_free (&str);      _dbus_string_free (&line);    } + +  { +    if (!_dbus_string_init (&str)) +      _dbus_assert_not_reached ("no memory"); + +    for (i = 0; i < 10000; i++) +      if (!_dbus_string_append (&str, "abcdefghijklmnopqrstuvwxyz")) +        _dbus_assert_not_reached ("no memory"); + +    if (!_dbus_string_set_length (&str, 10)) +      _dbus_assert_not_reached ("failed to set length"); + +    /* actually compact */ +    if (!_dbus_string_compact (&str, 2048)) +      _dbus_assert_not_reached ("failed to compact after set_length"); + +    /* peek inside to make sure it worked */ +    if (((DBusRealString *)&str)->allocated > 30) +      _dbus_assert_not_reached ("compacting string didn't do anything"); + +    if (!_dbus_string_equal_c_str (&str, "abcdefghij")) +      _dbus_assert_not_reached ("unexpected content after compact"); + +    /* compact nothing */ +    if (!_dbus_string_compact (&str, 2048)) +      _dbus_assert_not_reached ("failed to compact 2nd time"); + +    if (!_dbus_string_equal_c_str (&str, "abcdefghij")) +      _dbus_assert_not_reached ("unexpected content after 2nd compact"); + +    /* and make sure it still works...*/ +    if (!_dbus_string_append (&str, "123456")) +      _dbus_assert_not_reached ("failed to append after compact"); + +    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456")) +      _dbus_assert_not_reached ("unexpected content after append"); + +    /* after growing automatically, this should do nothing */ +    if (!_dbus_string_compact (&str, 20000)) +      _dbus_assert_not_reached ("failed to compact after grow"); + +    /* but this one will do something */ +    if (!_dbus_string_compact (&str, 0)) +      _dbus_assert_not_reached ("failed to compact after grow"); + +    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456")) +      _dbus_assert_not_reached ("unexpected content"); + +    if (!_dbus_string_append (&str, "!@#$%")) +      _dbus_assert_not_reached ("failed to append after compact"); + +    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456!@#$%")) +      _dbus_assert_not_reached ("unexpected content"); + +    _dbus_string_free (&str); +  }    return TRUE;  } diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index 62ac8c31..000b4f64 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -271,6 +271,32 @@ _dbus_string_free (DBusString *str)    real->invalid = TRUE;  } +static dbus_bool_t +compact (DBusRealString *real, +         int             max_waste) +{ +  unsigned char *new_str; +  int new_allocated; +  int waste; + +  waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING); + +  if (waste <= max_waste) +    return TRUE; + +  new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; + +  new_str = dbus_realloc (real->str - real->align_offset, new_allocated); +  if (_DBUS_UNLIKELY (new_str == NULL)) +    return FALSE; + +  real->str = new_str + real->align_offset; +  real->allocated = new_allocated; +  fixup_alignment (real); + +  return TRUE; +} +  #ifdef DBUS_BUILD_TESTS  /* Not using this feature at the moment,   * so marked DBUS_BUILD_TESTS-only @@ -295,22 +321,7 @@ _dbus_string_lock (DBusString *str)     * we know we won't change the string further     */  #define MAX_WASTE 48 -  if (real->allocated - MAX_WASTE > real->len) -    { -      unsigned char *new_str; -      int new_allocated; - -      new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; - -      new_str = dbus_realloc (real->str - real->align_offset, -                              new_allocated); -      if (new_str != NULL) -        { -          real->str = new_str + real->align_offset; -          real->allocated = new_allocated; -          fixup_alignment (real); -        } -    } +  compact (real, MAX_WASTE);  }  #endif /* DBUS_BUILD_TESTS */ @@ -361,6 +372,26 @@ reallocate_for_length (DBusRealString *real,    return TRUE;  } +/** + * Compacts the string to avoid wasted memory.  Wasted memory is + * memory that is allocated but not actually required to store the + * current length of the string.  The compact is only done if more + * than the given amount of memory is being wasted (otherwise the + * waste is ignored and the call does nothing). + * + * @param str the string + * @param max_waste the maximum amount of waste to ignore + * @returns #FALSE if the compact failed due to realloc failure + */ +dbus_bool_t +_dbus_string_compact (DBusString *str, +                      int         max_waste) +{ +  DBUS_STRING_PREAMBLE (str); + +  return compact (real, max_waste); +} +  static dbus_bool_t  set_length (DBusRealString *real,              int             new_length) diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h index 076fed63..b0100f3a 100644 --- a/dbus/dbus-string.h +++ b/dbus/dbus-string.h @@ -73,6 +73,8 @@ dbus_bool_t   _dbus_string_init_preallocated     (DBusString        *str,                                                    int                allocate_size);  void          _dbus_string_free                  (DBusString        *str);  void          _dbus_string_lock                  (DBusString        *str); +dbus_bool_t   _dbus_string_compact               (DBusString        *str, +                                                  int                max_waste);  #ifndef _dbus_string_get_data  char*         _dbus_string_get_data              (DBusString        *str);  #endif /* _dbus_string_get_data */ diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index a31c1597..f6d0e9c2 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -642,6 +642,7 @@ do_writing (DBusTransport *transport)              {                socket_transport->message_bytes_written = 0;                _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); +              _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);                _dbus_connection_message_sent (transport->connection,                                               message); @@ -733,6 +734,7 @@ do_reading (DBusTransport *transport)                                                _dbus_string_get_length (buffer) - orig_len);            _dbus_string_set_length (&socket_transport->encoded_incoming, 0); +          _dbus_string_compact (&socket_transport->encoded_incoming, 2048);          }      }    else | 
