Commit 8c6b0ab3 authored by Allison Lortie's avatar Allison Lortie
Browse files

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.
parent 44ed90c1
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 Lundn, 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>
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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)
......
......@@ -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 */
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment