summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2007-09-20 00:13:35 -0400
committerRyan Lortie <desrt@desrt.ca>2007-09-20 00:13:35 -0400
commit8c6b0ab3f7e437362112eeaf83a566475b85d27c (patch)
treea8e56fe093b9597bf69c1b4c9144ba8490a1c3da
parent44ed90c10d435f1a12c2b4b1a601040fa585ce38 (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--ChangeLog23
-rw-r--r--dbus/dbus-message.c3
-rw-r--r--dbus/dbus-string-util.c56
-rw-r--r--dbus/dbus-string.c63
-rw-r--r--dbus/dbus-string.h2
-rw-r--r--dbus/dbus-transport-socket.c2
6 files changed, 130 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 1c9168fa..32c6436e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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