2003-09-30 02:43:21 +00:00
/* -*- mode: C; c-file-style: "gnu" -*- */
2004-11-27 02:18:36 +00:00
/* test-profile.c Program that does basic message-response for timing; doesn't really use glib bindings
2003-09-30 02:43:21 +00:00
*
2004-11-26 06:22:53 +00:00
* Copyright ( C ) 2003 , 2004 Red Hat Inc .
2003-09-30 02:43:21 +00:00
*
2004-08-10 03:07:01 +00:00
* Licensed under the Academic Free License version 2.1
2003-09-30 02:43:21 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <config.h>
# include <glib.h>
2004-06-20 15:28:15 +00:00
# include <dbus/dbus-glib-lowlevel.h>
2003-09-30 02:43:21 +00:00
# include <stdlib.h>
2004-11-23 06:21:12 +00:00
# include <unistd.h>
2003-09-30 02:43:21 +00:00
2004-11-23 06:21:12 +00:00
# include <errno.h>
# include <fcntl.h>
# include <sys/socket.h>
# include <sys/un.h>
# include <netinet/in.h>
# include <string.h>
# include <sys/time.h>
# include <sys/stat.h>
# ifndef HAVE_SOCKLEN_T
# define socklen_t int
# endif
# define _DBUS_ZERO(object) (memset (&(object), '\0', sizeof ((object))))
# define _DBUS_MAX_SUN_PATH_LENGTH 99
/* Note that if you set threads > 1 you get a bogus profile since the
* clients start blocking on the server , so the client write ( ) will go
* higher in the profile the larger the number of threads .
*/
# define N_CLIENT_THREADS 1
2004-11-27 02:18:36 +00:00
/* It seems like at least 750000 or so iterations reduces the variability to sane levels */
2005-01-16 02:23:56 +00:00
# define N_ITERATIONS 750000
2004-11-26 06:22:53 +00:00
# define N_PROGRESS_UPDATES 20
2004-11-26 07:42:24 +00:00
/* Don't make PAYLOAD_SIZE too huge because it gets used as a static buffer size */
# define PAYLOAD_SIZE 0
2004-11-27 02:18:36 +00:00
# define ECHO_SERVICE "org.freedesktop.EchoTestServer"
2003-09-30 02:43:21 +00:00
# define ECHO_PATH " / org / freedesktop / EchoTest"
# define ECHO_INTERFACE "org.freedesktop.EchoTest"
2004-11-27 02:18:36 +00:00
# define ECHO_PING_METHOD "Ping"
2003-09-30 02:43:21 +00:00
2004-11-26 07:42:24 +00:00
static const char * messages_address ;
2004-11-23 06:21:12 +00:00
static const char * plain_sockets_address ;
2003-09-30 02:43:21 +00:00
static unsigned char * payload ;
2004-11-23 06:21:12 +00:00
static int echo_call_size ;
static int echo_return_size ;
2003-09-30 02:43:21 +00:00
2004-11-27 00:19:49 +00:00
typedef struct ProfileRunVTable ProfileRunVTable ;
2004-11-13 07:07:47 +00:00
typedef struct
{
2004-11-27 00:19:49 +00:00
const ProfileRunVTable * vtable ;
2004-11-13 07:07:47 +00:00
int iterations ;
GMainLoop * loop ;
} ClientData ;
typedef struct
{
2004-11-27 00:19:49 +00:00
const ProfileRunVTable * vtable ;
2004-11-13 07:07:47 +00:00
int handled ;
GMainLoop * loop ;
int n_clients ;
} ServerData ;
2004-11-27 00:19:49 +00:00
struct ProfileRunVTable
2004-11-23 06:21:12 +00:00
{
const char * name ;
2004-11-27 00:19:49 +00:00
gboolean fake_malloc_overhead ;
2004-11-23 06:21:12 +00:00
void * ( * init_server ) ( ServerData * sd ) ;
void ( * stop_server ) ( ServerData * sd ,
void * server ) ;
2004-11-27 00:19:49 +00:00
void * ( * client_thread_func ) ( void * data ) ; /* Data has to be the vtable */
2004-11-23 06:21:12 +00:00
/* this is so different runs show up in the profiler with
* different backtrace
*/
void ( * main_loop_run_func ) ( GMainLoop * loop ) ;
2004-11-27 00:19:49 +00:00
} ;
2004-11-23 06:21:12 +00:00
2004-11-27 02:18:36 +00:00
/* Note, this is all crack-a-rific; it isn't using DBusGProxy and thus is
* a major pain
*/
2003-09-30 02:43:21 +00:00
static void
2004-11-13 07:07:47 +00:00
send_echo_method_call ( DBusConnection * connection )
2003-09-30 02:43:21 +00:00
{
DBusMessage * message ;
2005-01-15 Havoc Pennington <hp@redhat.com>
* Land the new message args API and type system.
This patch is huge, but the public API change is not
really large. The set of D-BUS types has changed somewhat,
and the arg "getters" are more geared toward language bindings;
they don't make a copy, etc.
There are also some known issues. See these emails for details
on this huge patch:
http://lists.freedesktop.org/archives/dbus/2004-December/001836.html
http://lists.freedesktop.org/archives/dbus/2005-January/001922.html
* dbus/dbus-marshal-*: all the new stuff
* dbus/dbus-message.c: basically rewritten
* dbus/dbus-memory.c (check_guards): with "guards" enabled, init
freed blocks to be all non-nul bytes so using freed memory is less
likely to work right
* dbus/dbus-internals.c (_dbus_test_oom_handling): add
DBUS_FAIL_MALLOC=N environment variable, so you can do
DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or
DBUS_FAIL_MALLOC=10 to make it really, really, really slow and
thorough.
* qt/message.cpp: port to the new message args API
(operator<<): use str.utf8() rather than str.unicode()
(pretty sure this is right from the Qt docs?)
* glib/dbus-gvalue.c: port to the new message args API
* bus/dispatch.c, bus/driver.c: port to the new message args API
* dbus/dbus-string.c (_dbus_string_init_const_len): initialize the
"locked" flag to TRUE and align_offset to 0; I guess we never
looked at these anyhow, but seems cleaner.
* dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING):
move allocation padding macro to this header; use it to implement
(_DBUS_STRING_STATIC): ability to declare a static string.
* dbus/dbus-message.c (_dbus_message_has_type_interface_member):
change to return TRUE if the interface is not set.
* dbus/dbus-string.[hc]: move the D-BUS specific validation stuff
to dbus-marshal-validate.[hc]
* dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from
dbus-internals.c
* dbus/Makefile.am: cut over from dbus-marshal.[hc]
to dbus-marshal-*.[hc]
* dbus/dbus-object-tree.c (_dbus_decompose_path): move this
function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
const char * hello = " Hello World! " ;
dbus_int32_t i32 = 123456 ;
2003-09-30 02:43:21 +00:00
2004-11-27 02:18:36 +00:00
message = dbus_message_new_method_call ( ECHO_SERVICE ,
ECHO_PATH ,
ECHO_INTERFACE ,
ECHO_PING_METHOD ) ;
2003-09-30 02:43:21 +00:00
dbus_message_append_args ( message ,
2005-01-15 Havoc Pennington <hp@redhat.com>
* Land the new message args API and type system.
This patch is huge, but the public API change is not
really large. The set of D-BUS types has changed somewhat,
and the arg "getters" are more geared toward language bindings;
they don't make a copy, etc.
There are also some known issues. See these emails for details
on this huge patch:
http://lists.freedesktop.org/archives/dbus/2004-December/001836.html
http://lists.freedesktop.org/archives/dbus/2005-January/001922.html
* dbus/dbus-marshal-*: all the new stuff
* dbus/dbus-message.c: basically rewritten
* dbus/dbus-memory.c (check_guards): with "guards" enabled, init
freed blocks to be all non-nul bytes so using freed memory is less
likely to work right
* dbus/dbus-internals.c (_dbus_test_oom_handling): add
DBUS_FAIL_MALLOC=N environment variable, so you can do
DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or
DBUS_FAIL_MALLOC=10 to make it really, really, really slow and
thorough.
* qt/message.cpp: port to the new message args API
(operator<<): use str.utf8() rather than str.unicode()
(pretty sure this is right from the Qt docs?)
* glib/dbus-gvalue.c: port to the new message args API
* bus/dispatch.c, bus/driver.c: port to the new message args API
* dbus/dbus-string.c (_dbus_string_init_const_len): initialize the
"locked" flag to TRUE and align_offset to 0; I guess we never
looked at these anyhow, but seems cleaner.
* dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING):
move allocation padding macro to this header; use it to implement
(_DBUS_STRING_STATIC): ability to declare a static string.
* dbus/dbus-message.c (_dbus_message_has_type_interface_member):
change to return TRUE if the interface is not set.
* dbus/dbus-string.[hc]: move the D-BUS specific validation stuff
to dbus-marshal-validate.[hc]
* dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from
dbus-internals.c
* dbus/Makefile.am: cut over from dbus-marshal.[hc]
to dbus-marshal-*.[hc]
* dbus/dbus-object-tree.c (_dbus_decompose_path): move this
function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
DBUS_TYPE_STRING , & hello ,
DBUS_TYPE_INT32 , & i32 ,
2004-11-26 07:42:24 +00:00
# if PAYLOAD_SIZE > 0
2003-09-30 02:43:21 +00:00
DBUS_TYPE_ARRAY , DBUS_TYPE_BYTE ,
2005-01-15 Havoc Pennington <hp@redhat.com>
* Land the new message args API and type system.
This patch is huge, but the public API change is not
really large. The set of D-BUS types has changed somewhat,
and the arg "getters" are more geared toward language bindings;
they don't make a copy, etc.
There are also some known issues. See these emails for details
on this huge patch:
http://lists.freedesktop.org/archives/dbus/2004-December/001836.html
http://lists.freedesktop.org/archives/dbus/2005-January/001922.html
* dbus/dbus-marshal-*: all the new stuff
* dbus/dbus-message.c: basically rewritten
* dbus/dbus-memory.c (check_guards): with "guards" enabled, init
freed blocks to be all non-nul bytes so using freed memory is less
likely to work right
* dbus/dbus-internals.c (_dbus_test_oom_handling): add
DBUS_FAIL_MALLOC=N environment variable, so you can do
DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or
DBUS_FAIL_MALLOC=10 to make it really, really, really slow and
thorough.
* qt/message.cpp: port to the new message args API
(operator<<): use str.utf8() rather than str.unicode()
(pretty sure this is right from the Qt docs?)
* glib/dbus-gvalue.c: port to the new message args API
* bus/dispatch.c, bus/driver.c: port to the new message args API
* dbus/dbus-string.c (_dbus_string_init_const_len): initialize the
"locked" flag to TRUE and align_offset to 0; I guess we never
looked at these anyhow, but seems cleaner.
* dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING):
move allocation padding macro to this header; use it to implement
(_DBUS_STRING_STATIC): ability to declare a static string.
* dbus/dbus-message.c (_dbus_message_has_type_interface_member):
change to return TRUE if the interface is not set.
* dbus/dbus-string.[hc]: move the D-BUS specific validation stuff
to dbus-marshal-validate.[hc]
* dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from
dbus-internals.c
* dbus/Makefile.am: cut over from dbus-marshal.[hc]
to dbus-marshal-*.[hc]
* dbus/dbus-object-tree.c (_dbus_decompose_path): move this
function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
& payload , PAYLOAD_SIZE ,
2003-09-30 02:43:21 +00:00
# endif
DBUS_TYPE_INVALID ) ;
dbus_connection_send ( connection , message , NULL ) ;
dbus_message_unref ( message ) ;
dbus_connection_flush ( connection ) ;
}
2004-11-13 07:07:47 +00:00
static void
send_echo_method_return ( DBusConnection * connection ,
DBusMessage * call_message )
{
DBusMessage * message ;
message = dbus_message_new_method_return ( call_message ) ;
dbus_connection_send ( connection , message , NULL ) ;
dbus_message_unref ( message ) ;
dbus_connection_flush ( connection ) ;
}
2003-09-30 02:43:21 +00:00
static DBusHandlerResult
2004-11-27 02:18:36 +00:00
with_or_without_bus_client_filter ( DBusConnection * connection ,
DBusMessage * message ,
ClientData * cd )
2003-09-30 02:43:21 +00:00
{
if ( dbus_message_is_signal ( message ,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL ,
" Disconnected " ) )
{
g_printerr ( " Client thread disconnected \n " ) ;
exit ( 1 ) ;
}
2004-11-13 07:07:47 +00:00
else if ( dbus_message_get_type ( message ) = = DBUS_MESSAGE_TYPE_METHOD_RETURN )
2003-09-30 02:43:21 +00:00
{
2004-11-13 07:07:47 +00:00
cd - > iterations + = 1 ;
if ( cd - > iterations > = N_ITERATIONS )
2003-09-30 02:43:21 +00:00
{
2004-11-26 06:22:53 +00:00
g_printerr ( " \n Completed %d iterations \n " , N_ITERATIONS ) ;
2004-11-13 07:07:47 +00:00
g_main_loop_quit ( cd - > loop ) ;
2003-09-30 02:43:21 +00:00
}
2004-11-26 06:22:53 +00:00
else if ( cd - > iterations % ( N_ITERATIONS / N_PROGRESS_UPDATES ) = = 0 )
{
g_printerr ( " %d%% " , ( int ) ( cd - > iterations / ( double ) N_ITERATIONS * 100.0 ) ) ;
}
2004-11-13 07:07:47 +00:00
send_echo_method_call ( connection ) ;
2003-09-30 02:43:21 +00:00
return DBUS_HANDLER_RESULT_HANDLED ;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED ;
}
2004-11-27 02:18:36 +00:00
static DBusHandlerResult
no_bus_client_filter ( DBusConnection * connection ,
DBusMessage * message ,
void * user_data )
{
ClientData * cd = user_data ;
return with_or_without_bus_client_filter ( connection , message , cd ) ;
}
2003-09-30 02:43:21 +00:00
static void *
2004-11-27 02:18:36 +00:00
no_bus_thread_func ( void * data )
2003-09-30 02:43:21 +00:00
{
DBusError error ;
GMainContext * context ;
DBusConnection * connection ;
2004-11-13 07:07:47 +00:00
ClientData cd ;
2003-09-30 02:43:21 +00:00
2004-11-23 06:21:12 +00:00
g_printerr ( " Starting client thread %p \n " , g_thread_self ( ) ) ;
2003-09-30 02:43:21 +00:00
dbus_error_init ( & error ) ;
2004-11-26 07:42:24 +00:00
connection = dbus_connection_open ( messages_address , & error ) ;
2003-09-30 02:43:21 +00:00
if ( connection = = NULL )
{
g_printerr ( " could not open connection: %s \n " , error . message ) ;
dbus_error_free ( & error ) ;
exit ( 1 ) ;
}
2004-11-13 07:07:47 +00:00
context = g_main_context_new ( ) ;
cd . iterations = 1 ;
cd . loop = g_main_loop_new ( context , FALSE ) ;
2003-09-30 02:43:21 +00:00
if ( ! dbus_connection_add_filter ( connection ,
2004-11-27 02:18:36 +00:00
no_bus_client_filter , & cd , NULL ) )
2003-09-30 02:43:21 +00:00
g_error ( " no memory " ) ;
dbus_connection_setup_with_g_main ( connection , context ) ;
g_printerr ( " Client thread sending message to prime pingpong \n " ) ;
2004-11-13 07:07:47 +00:00
send_echo_method_call ( connection ) ;
2003-09-30 02:43:21 +00:00
g_printerr ( " Client thread sent message \n " ) ;
g_printerr ( " Client thread entering main loop \n " ) ;
2004-11-13 07:07:47 +00:00
g_main_loop_run ( cd . loop ) ;
2004-11-23 06:21:12 +00:00
g_printerr ( " Client thread %p exiting main loop \n " ,
g_thread_self ( ) ) ;
2004-11-13 07:07:47 +00:00
dbus_connection_disconnect ( connection ) ;
2003-09-30 02:43:21 +00:00
2004-11-13 07:07:47 +00:00
g_main_loop_unref ( cd . loop ) ;
2003-09-30 02:43:21 +00:00
g_main_context_unref ( context ) ;
2004-11-13 07:07:47 +00:00
2003-09-30 02:43:21 +00:00
return NULL ;
}
static DBusHandlerResult
2004-11-27 02:18:36 +00:00
no_bus_server_filter ( DBusConnection * connection ,
DBusMessage * message ,
void * user_data )
2003-09-30 02:43:21 +00:00
{
2004-11-13 07:07:47 +00:00
ServerData * sd = user_data ;
2003-09-30 02:43:21 +00:00
if ( dbus_message_is_signal ( message ,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL ,
" Disconnected " ) )
{
2004-11-13 07:07:47 +00:00
g_printerr ( " Client disconnected from server \n " ) ;
sd - > n_clients - = 1 ;
if ( sd - > n_clients = = 0 )
g_main_loop_quit ( sd - > loop ) ;
2003-09-30 02:43:21 +00:00
}
else if ( dbus_message_is_method_call ( message ,
ECHO_INTERFACE ,
2004-11-27 02:18:36 +00:00
ECHO_PING_METHOD ) )
2003-09-30 02:43:21 +00:00
{
2004-11-13 07:07:47 +00:00
sd - > handled + = 1 ;
send_echo_method_return ( connection , message ) ;
2003-09-30 02:43:21 +00:00
return DBUS_HANDLER_RESULT_HANDLED ;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED ;
}
static void
2004-11-27 02:18:36 +00:00
no_bus_new_connection_callback ( DBusServer * server ,
DBusConnection * new_connection ,
void * user_data )
2004-11-13 07:07:47 +00:00
{
ServerData * sd = user_data ;
2003-09-30 02:43:21 +00:00
dbus_connection_ref ( new_connection ) ;
dbus_connection_setup_with_g_main ( new_connection , NULL ) ;
if ( ! dbus_connection_add_filter ( new_connection ,
2004-11-27 02:18:36 +00:00
no_bus_server_filter , sd , NULL ) )
2003-09-30 02:43:21 +00:00
g_error ( " no memory " ) ;
2004-11-13 07:07:47 +00:00
sd - > n_clients + = 1 ;
2003-09-30 02:43:21 +00:00
/* FIXME we leak the handler */
}
2004-11-23 06:21:12 +00:00
static void *
2004-11-27 02:18:36 +00:00
no_bus_init_server ( ServerData * sd )
2003-09-30 02:43:21 +00:00
{
DBusServer * server ;
2004-11-23 06:21:12 +00:00
DBusError error ;
2003-09-30 02:43:21 +00:00
dbus_error_init ( & error ) ;
server = dbus_server_listen ( " unix:tmpdir= " DBUS_TEST_SOCKET_DIR ,
& error ) ;
if ( server = = NULL )
{
g_printerr ( " Could not start server: %s \n " ,
error . message ) ;
2004-11-23 06:21:12 +00:00
exit ( 1 ) ;
2003-09-30 02:43:21 +00:00
}
2004-11-26 07:42:24 +00:00
messages_address = dbus_server_get_address ( server ) ;
2003-09-30 02:43:21 +00:00
dbus_server_set_new_connection_function ( server ,
2004-11-27 02:18:36 +00:00
no_bus_new_connection_callback ,
2004-11-23 06:21:12 +00:00
sd , NULL ) ;
dbus_server_setup_with_g_main ( server , NULL ) ;
return server ;
}
static void
2004-11-27 02:18:36 +00:00
no_bus_stop_server ( ServerData * sd ,
2004-11-23 06:21:12 +00:00
void * server )
{
g_printerr ( " The following g_warning is because we try to call g_source_remove_poll() after g_source_destroy() in dbus-gmain.c, I think we need to add a source free func that clears out the watch/timeout funcs \n " ) ;
dbus_server_unref ( server ) ;
}
static void
2004-11-27 02:18:36 +00:00
no_bus_main_loop_run ( GMainLoop * loop )
{
g_main_loop_run ( loop ) ;
}
static const ProfileRunVTable no_bus_vtable = {
" dbus direct without bus " ,
FALSE ,
no_bus_init_server ,
no_bus_stop_server ,
no_bus_thread_func ,
no_bus_main_loop_run
} ;
typedef struct
{
const ProfileRunVTable * vtable ;
ServerData * sd ;
GHashTable * client_names ;
DBusConnection * connection ;
} WithBusServer ;
static DBusHandlerResult
with_bus_client_filter ( DBusConnection * connection ,
DBusMessage * message ,
void * user_data )
{
ClientData * cd = user_data ;
return with_or_without_bus_client_filter ( connection , message , cd ) ;
}
static void *
with_bus_thread_func ( void * data )
{
DBusError error ;
DBusConnection * connection ;
ClientData cd ;
const char * address ;
GMainContext * context ;
g_printerr ( " Starting client thread %p \n " , g_thread_self ( ) ) ;
address = g_getenv ( " DBUS_SESSION_BUS_ADDRESS " ) ;
if ( address = = NULL )
{
g_printerr ( " DBUS_SESSION_BUS_ADDRESS not set \n " ) ;
exit ( 1 ) ;
}
dbus_error_init ( & error ) ;
connection = dbus_connection_open ( address , & error ) ;
if ( connection = = NULL )
{
g_printerr ( " could not open connection to bus: %s \n " , error . message ) ;
dbus_error_free ( & error ) ;
exit ( 1 ) ;
}
if ( ! dbus_bus_register ( connection , & error ) )
{
g_printerr ( " could not register with bus: %s \n " , error . message ) ;
dbus_error_free ( & error ) ;
exit ( 1 ) ;
}
context = g_main_context_new ( ) ;
cd . iterations = 1 ;
cd . loop = g_main_loop_new ( context , FALSE ) ;
if ( ! dbus_connection_add_filter ( connection ,
with_bus_client_filter , & cd , NULL ) )
g_error ( " no memory " ) ;
dbus_connection_setup_with_g_main ( connection , context ) ;
g_printerr ( " Client thread sending message to prime pingpong \n " ) ;
send_echo_method_call ( connection ) ;
g_printerr ( " Client thread sent message \n " ) ;
g_printerr ( " Client thread entering main loop \n " ) ;
g_main_loop_run ( cd . loop ) ;
g_printerr ( " Client thread %p exiting main loop \n " ,
g_thread_self ( ) ) ;
dbus_connection_disconnect ( connection ) ;
g_main_loop_unref ( cd . loop ) ;
g_main_context_unref ( context ) ;
return NULL ;
}
static DBusHandlerResult
with_bus_server_filter ( DBusConnection * connection ,
DBusMessage * message ,
void * user_data )
{
WithBusServer * server = user_data ;
if ( dbus_message_is_signal ( message ,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL ,
" Disconnected " ) )
{
g_printerr ( " Server disconnected from message bus \n " ) ;
exit ( 1 ) ;
}
else if ( dbus_message_has_sender ( message ,
DBUS_SERVICE_ORG_FREEDESKTOP_DBUS ) & &
dbus_message_is_signal ( message ,
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS ,
" ServiceOwnerChanged " ) )
{
2005-01-16 02:23:56 +00:00
const char * service_name , * old_owner , * new_owner ;
2004-11-27 02:18:36 +00:00
DBusError error ;
service_name = NULL ;
old_owner = NULL ;
new_owner = NULL ;
dbus_error_init ( & error ) ;
if ( ! dbus_message_get_args ( message ,
& error ,
DBUS_TYPE_STRING , & service_name ,
DBUS_TYPE_STRING , & old_owner ,
DBUS_TYPE_STRING , & new_owner ,
DBUS_TYPE_INVALID ) )
{
g_printerr ( " dbus_message_get_args(): %s \n " , error . message ) ;
exit ( 1 ) ;
}
if ( g_hash_table_lookup ( server - > client_names ,
service_name ) & &
* old_owner ! = ' \0 ' & &
* new_owner = = ' \0 ' )
{
g_hash_table_remove ( server - > client_names ,
service_name ) ;
server - > sd - > n_clients - = 1 ;
if ( server - > sd - > n_clients = = 0 )
g_main_loop_quit ( server - > sd - > loop ) ;
}
}
else if ( dbus_message_is_method_call ( message ,
ECHO_INTERFACE ,
ECHO_PING_METHOD ) )
{
const char * sender ;
sender = dbus_message_get_sender ( message ) ;
if ( ! g_hash_table_lookup ( server - > client_names ,
sender ) )
{
g_printerr ( " First message from new client %s on bus \n " , sender ) ;
g_hash_table_replace ( server - > client_names ,
g_strdup ( sender ) ,
GINT_TO_POINTER ( 1 ) ) ;
server - > sd - > n_clients + = 1 ;
}
server - > sd - > handled + = 1 ;
send_echo_method_return ( connection , message ) ;
return DBUS_HANDLER_RESULT_HANDLED ;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED ;
}
static void *
with_bus_init_server ( ServerData * sd )
{
DBusGConnection * gconnection ;
DBusConnection * connection ;
GError * gerror ;
const char * s ;
WithBusServer * server ;
char * rule ;
server = g_new0 ( WithBusServer , 1 ) ;
server - > vtable = sd - > vtable ;
server - > sd = sd ;
s = g_getenv ( " DBUS_TEST_GLIB_RUN_TEST_SCRIPT " ) ;
if ( s = = NULL | |
* s ! = ' 1 ' )
{
g_printerr ( " You have to run with_bus mode with the run-test.sh script \n " ) ;
exit ( 1 ) ;
}
/* Note that we use the standard global bus connection for the
* server , and the clients open their own connections so they can
* have their own main loops and because I ' m not sure " talking to
* yourself " really works yet
*/
gerror = NULL ;
gconnection = dbus_g_bus_get ( DBUS_BUS_SESSION , & gerror ) ;
if ( gconnection = = NULL )
{
g_printerr ( " could not open connection to bus: %s \n " , gerror - > message ) ;
g_error_free ( gerror ) ;
exit ( 1 ) ;
}
server - > client_names = g_hash_table_new_full ( g_str_hash , g_str_equal ,
g_free , NULL ) ;
connection = dbus_g_connection_get_connection ( gconnection ) ;
dbus_bus_acquire_service ( connection ,
ECHO_SERVICE ,
0 , NULL ) ; /* ignore errors because we suck */
rule = g_strdup_printf ( " type='signal',sender='%s',member='%s' " ,
DBUS_SERVICE_ORG_FREEDESKTOP_DBUS ,
" ServiceOwnerChanged " ) ;
/* ignore errors because we suck */
dbus_bus_add_match ( connection , rule , NULL ) ;
g_free ( rule ) ;
if ( ! dbus_connection_add_filter ( connection ,
with_bus_server_filter , server , NULL ) )
g_error ( " no memory " ) ;
server - > connection = connection ;
server - > client_names = g_hash_table_new_full ( g_str_hash , g_str_equal ,
g_free , NULL ) ;
return server ;
}
static void
with_bus_stop_server ( ServerData * sd ,
void * serverv )
{
WithBusServer * server = serverv ;
dbus_connection_remove_filter ( server - > connection ,
with_bus_server_filter , server ) ;
g_hash_table_destroy ( server - > client_names ) ;
dbus_connection_unref ( server - > connection ) ;
g_free ( server ) ;
}
static void
with_bus_main_loop_run ( GMainLoop * loop )
2004-11-23 06:21:12 +00:00
{
g_main_loop_run ( loop ) ;
}
2004-11-27 02:18:36 +00:00
static const ProfileRunVTable with_bus_vtable = {
" routing via a bus " ,
2004-11-27 00:19:49 +00:00
FALSE ,
2004-11-27 02:18:36 +00:00
with_bus_init_server ,
with_bus_stop_server ,
with_bus_thread_func ,
with_bus_main_loop_run
2004-11-23 06:21:12 +00:00
} ;
2004-11-27 02:18:36 +00:00
2004-11-23 06:21:12 +00:00
typedef struct
{
2004-11-27 00:19:49 +00:00
const ProfileRunVTable * vtable ;
2004-11-23 06:21:12 +00:00
int listen_fd ;
ServerData * sd ;
unsigned int source_id ;
} PlainSocketServer ;
static void
read_and_drop_on_floor ( int fd ,
2004-11-27 00:19:49 +00:00
int count ,
gboolean fake_malloc_overhead )
2004-11-23 06:21:12 +00:00
{
int bytes_read ;
int val ;
2004-11-26 07:42:24 +00:00
char * buf ;
char * allocated ;
char not_allocated [ 512 + PAYLOAD_SIZE ] ;
2004-11-23 06:21:12 +00:00
2004-11-26 07:42:24 +00:00
g_assert ( count < ( int ) sizeof ( not_allocated ) ) ;
if ( fake_malloc_overhead )
{
allocated = g_malloc ( count ) ;
buf = allocated ;
}
else
{
allocated = NULL ;
buf = not_allocated ;
}
2004-11-23 06:21:12 +00:00
bytes_read = 0 ;
while ( bytes_read < count )
{
again :
2004-11-26 07:42:24 +00:00
val = read ( fd , buf + bytes_read , count - bytes_read ) ;
2004-11-23 06:21:12 +00:00
if ( val < 0 )
{
if ( errno = = EINTR )
goto again ;
else
{
g_printerr ( " read() failed thread %p: %s \n " ,
g_thread_self ( ) , strerror ( errno ) ) ;
exit ( 1 ) ;
}
}
else
{
bytes_read + = val ;
}
}
2004-11-26 07:42:24 +00:00
if ( fake_malloc_overhead )
g_free ( allocated ) ;
2004-11-23 06:21:12 +00:00
#if 0
2004-11-26 06:22:53 +00:00
g_printerr ( " %p read %d bytes from fd %d \n " ,
2004-11-23 06:21:12 +00:00
g_thread_self ( ) , bytes_read , fd ) ;
# endif
}
static void
write_junk ( int fd ,
2004-11-27 00:19:49 +00:00
int count ,
gboolean fake_malloc_overhead )
2004-11-23 06:21:12 +00:00
{
int bytes_written ;
int val ;
2004-11-26 07:42:24 +00:00
char * buf ;
char * allocated ;
char not_allocated [ 512 + PAYLOAD_SIZE ] ;
2004-11-23 06:21:12 +00:00
2004-11-26 07:42:24 +00:00
g_assert ( count < ( int ) sizeof ( not_allocated ) ) ;
if ( fake_malloc_overhead )
{
int i ;
allocated = g_malloc ( count ) ;
buf = allocated ;
/* Write some stuff into the allocated buffer to simulate
* creating some sort of data
*/
i = 0 ;
while ( i < count )
{
allocated [ i ] = ( char ) i ;
+ + i ;
}
}
else
{
allocated = NULL ;
buf = not_allocated ;
}
2004-11-23 06:21:12 +00:00
bytes_written = 0 ;
while ( bytes_written < count )
{
again :
2004-11-26 07:42:24 +00:00
val = write ( fd , buf + bytes_written , count - bytes_written ) ;
2004-11-23 06:21:12 +00:00
if ( val < 0 )
{
if ( errno = = EINTR )
goto again ;
else
{
g_printerr ( " write() failed thread %p: %s \n " ,
g_thread_self ( ) , strerror ( errno ) ) ;
exit ( 1 ) ;
}
}
else
{
bytes_written + = val ;
}
}
2004-11-26 07:42:24 +00:00
if ( fake_malloc_overhead )
g_free ( allocated ) ;
2004-11-23 06:21:12 +00:00
#if 0
2004-11-26 06:22:53 +00:00
g_printerr ( " %p wrote %d bytes to fd %d \n " ,
2004-11-23 06:21:12 +00:00
g_thread_self ( ) , bytes_written , fd ) ;
# endif
}
static gboolean
plain_sockets_talk_to_client_watch ( GIOChannel * source ,
GIOCondition condition ,
gpointer data )
{
PlainSocketServer * server = data ;
int client_fd = g_io_channel_unix_get_fd ( source ) ;
if ( condition & G_IO_HUP )
{
g_printerr ( " Client disconnected from server \n " ) ;
server - > sd - > n_clients - = 1 ;
if ( server - > sd - > n_clients = = 0 )
g_main_loop_quit ( server - > sd - > loop ) ;
return FALSE ; /* remove watch */
}
else if ( condition & G_IO_IN )
{
server - > sd - > handled + = 1 ;
2004-11-27 00:19:49 +00:00
read_and_drop_on_floor ( client_fd , echo_call_size , server - > vtable - > fake_malloc_overhead ) ;
write_junk ( client_fd , echo_return_size , server - > vtable - > fake_malloc_overhead ) ;
2004-11-23 06:21:12 +00:00
}
else
{
g_printerr ( " Unexpected IO condition in server thread \n " ) ;
exit ( 1 ) ;
}
return TRUE ;
}
static gboolean
plain_sockets_new_client_watch ( GIOChannel * source ,
GIOCondition condition ,
gpointer data )
{
int client_fd ;
struct sockaddr addr ;
socklen_t addrlen ;
GIOChannel * channel ;
PlainSocketServer * server = data ;
if ( ! ( condition & G_IO_IN ) )
{
g_printerr ( " Unexpected IO condition on server socket \n " ) ;
exit ( 1 ) ;
}
addrlen = sizeof ( addr ) ;
retry :
client_fd = accept ( server - > listen_fd , & addr , & addrlen ) ;
if ( client_fd < 0 )
{
if ( errno = = EINTR )
goto retry ;
else
{
g_printerr ( " Failed to accept() connection from client: %s \n " ,
strerror ( errno ) ) ;
exit ( 1 ) ;
}
}
channel = g_io_channel_unix_new ( client_fd ) ;
g_io_add_watch ( channel ,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_PRI ,
plain_sockets_talk_to_client_watch ,
server ) ;
g_io_channel_unref ( channel ) ;
server - > sd - > n_clients + = 1 ;
return TRUE ;
}
static void *
plain_sockets_init_server ( ServerData * sd )
{
PlainSocketServer * server ;
struct sockaddr_un addr ;
static char path [ ] = " /tmp/dbus-test-profile-XXXXXX " ;
char * p ;
GIOChannel * channel ;
server = g_new0 ( PlainSocketServer , 1 ) ;
server - > sd = sd ;
2004-11-27 00:19:49 +00:00
server - > vtable = sd - > vtable ; /* for convenience */
2004-11-23 06:21:12 +00:00
p = path ;
while ( * p )
{
if ( * p = = ' X ' )
* p = ' a ' + ( int ) ( 26.0 * rand ( ) / ( RAND_MAX + 1.0 ) ) ;
+ + p ;
}
2004-11-26 06:22:53 +00:00
g_printerr ( " Socket is %s \n " , path ) ;
2004-11-23 06:21:12 +00:00
server - > listen_fd = socket ( PF_UNIX , SOCK_STREAM , 0 ) ;
if ( server - > listen_fd < 0 )
{
g_printerr ( " Failed to create socket: %s " ,
strerror ( errno ) ) ;
exit ( 1 ) ;
}
_DBUS_ZERO ( addr ) ;
addr . sun_family = AF_UNIX ;
# ifdef HAVE_ABSTRACT_SOCKETS
/* remember that abstract names aren't nul-terminated so we rely
* on sun_path being filled in with zeroes above .
*/
addr . sun_path [ 0 ] = ' \0 ' ; /* this is what says "use abstract" */
strncpy ( & addr . sun_path [ 1 ] , path , _DBUS_MAX_SUN_PATH_LENGTH - 2 ) ;
/* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
# else /* HAVE_ABSTRACT_SOCKETS */
{
struct stat sb ;
if ( stat ( path , & sb ) = = 0 & &
S_ISSOCK ( sb . st_mode ) )
unlink ( path ) ;
}
strncpy ( addr . sun_path , path , _DBUS_MAX_SUN_PATH_LENGTH - 1 ) ;
# endif /* ! HAVE_ABSTRACT_SOCKETS */
if ( bind ( server - > listen_fd , ( struct sockaddr * ) & addr , sizeof ( addr ) ) < 0 )
{
g_printerr ( " Failed to bind socket \" %s \" : %s " ,
path , strerror ( errno ) ) ;
exit ( 1 ) ;
}
if ( listen ( server - > listen_fd , 30 /* backlog */ ) < 0 )
{
g_printerr ( " Failed to listen on socket \" %s \" : %s " ,
path , strerror ( errno ) ) ;
exit ( 1 ) ;
}
plain_sockets_address = path ;
channel = g_io_channel_unix_new ( server - > listen_fd ) ;
server - > source_id =
g_io_add_watch ( channel ,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_PRI ,
plain_sockets_new_client_watch ,
server ) ;
g_io_channel_unref ( channel ) ;
return server ;
}
static void
plain_sockets_stop_server ( ServerData * sd ,
void * server_v )
{
PlainSocketServer * server = server_v ;
g_source_remove ( server - > source_id ) ;
close ( server - > listen_fd ) ;
g_free ( server ) ;
{
struct stat sb ;
if ( stat ( plain_sockets_address , & sb ) = = 0 & &
S_ISSOCK ( sb . st_mode ) )
unlink ( plain_sockets_address ) ;
}
}
static gboolean
plain_sockets_client_side_watch ( GIOChannel * source ,
GIOCondition condition ,
gpointer data )
{
ClientData * cd = data ;
int fd = g_io_channel_unix_get_fd ( source ) ;
if ( condition & G_IO_IN )
{
2004-11-27 00:19:49 +00:00
read_and_drop_on_floor ( fd , echo_return_size , cd - > vtable - > fake_malloc_overhead ) ;
2004-11-23 06:21:12 +00:00
}
else if ( condition & G_IO_OUT )
{
cd - > iterations + = 1 ;
if ( cd - > iterations > = N_ITERATIONS )
{
2004-11-26 06:22:53 +00:00
g_printerr ( " \n Completed %d iterations \n " , N_ITERATIONS ) ;
2004-11-23 06:21:12 +00:00
g_main_loop_quit ( cd - > loop ) ;
}
2004-11-26 06:22:53 +00:00
else if ( cd - > iterations % ( N_ITERATIONS / N_PROGRESS_UPDATES ) = = 0 )
{
g_printerr ( " %d%% " , ( int ) ( cd - > iterations / ( double ) N_ITERATIONS * 100.0 ) ) ;
}
2004-11-23 06:21:12 +00:00
2004-11-27 00:19:49 +00:00
write_junk ( fd , echo_call_size , cd - > vtable - > fake_malloc_overhead ) ;
2004-11-23 06:21:12 +00:00
}
else
{
g_printerr ( " Unexpected IO condition in client thread \n " ) ;
exit ( 1 ) ;
}
return TRUE ;
}
static void *
plain_sockets_thread_func ( void * data )
{
GMainContext * context ;
ClientData cd ;
int fd ;
struct sockaddr_un addr ;
GIOChannel * channel ;
GSource * gsource ;
g_printerr ( " Starting client thread %p \n " ,
g_thread_self ( ) ) ;
fd = socket ( PF_UNIX , SOCK_STREAM , 0 ) ;
if ( fd < 0 )
{
g_printerr ( " Failed to create socket: %s " ,
strerror ( errno ) ) ;
exit ( 1 ) ;
}
_DBUS_ZERO ( addr ) ;
addr . sun_family = AF_UNIX ;
# ifdef HAVE_ABSTRACT_SOCKETS
/* remember that abstract names aren't nul-terminated so we rely
* on sun_path being filled in with zeroes above .
*/
addr . sun_path [ 0 ] = ' \0 ' ; /* this is what says "use abstract" */
strncpy ( & addr . sun_path [ 1 ] , plain_sockets_address , _DBUS_MAX_SUN_PATH_LENGTH - 2 ) ;
/* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
# else /* HAVE_ABSTRACT_SOCKETS */
strncpy ( addr . sun_path , plain_sockets_address , _DBUS_MAX_SUN_PATH_LENGTH - 1 ) ;
# endif /* ! HAVE_ABSTRACT_SOCKETS */
if ( connect ( fd , ( struct sockaddr * ) & addr , sizeof ( addr ) ) < 0 )
{
g_printerr ( " Failed to connect to socket %s: %s " ,
plain_sockets_address , strerror ( errno ) ) ;
exit ( 1 ) ;
}
context = g_main_context_new ( ) ;
cd . iterations = 1 ;
cd . loop = g_main_loop_new ( context , FALSE ) ;
channel = g_io_channel_unix_new ( fd ) ;
gsource = g_io_create_watch ( channel ,
G_IO_IN | G_IO_OUT |
G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_PRI ) ;
g_source_set_callback ( gsource ,
( GSourceFunc ) plain_sockets_client_side_watch ,
& cd , NULL ) ;
g_source_attach ( gsource , context ) ;
g_io_channel_unref ( channel ) ;
g_printerr ( " Client thread writing to prime pingpong \n " ) ;
2004-11-27 00:19:49 +00:00
write_junk ( fd , echo_call_size , cd . vtable - > fake_malloc_overhead ) ;
2004-11-23 06:21:12 +00:00
g_printerr ( " Client thread done writing primer \n " ) ;
g_printerr ( " Client thread entering main loop \n " ) ;
g_main_loop_run ( cd . loop ) ;
g_printerr ( " Client thread %p exiting main loop \n " ,
g_thread_self ( ) ) ;
g_source_destroy ( gsource ) ;
close ( fd ) ;
g_main_loop_unref ( cd . loop ) ;
g_main_context_unref ( context ) ;
return NULL ;
}
static void
plain_sockets_main_loop_run ( GMainLoop * loop )
{
g_main_loop_run ( loop ) ;
}
static const ProfileRunVTable plain_sockets_vtable = {
" plain sockets " ,
2004-11-27 00:19:49 +00:00
FALSE ,
2004-11-23 06:21:12 +00:00
plain_sockets_init_server ,
plain_sockets_stop_server ,
plain_sockets_thread_func ,
plain_sockets_main_loop_run
} ;
2004-11-26 07:42:24 +00:00
static const ProfileRunVTable plain_sockets_with_malloc_vtable = {
" plain sockets with malloc overhead " ,
2004-11-27 00:19:49 +00:00
TRUE ,
2004-11-26 07:42:24 +00:00
plain_sockets_init_server ,
plain_sockets_stop_server ,
plain_sockets_thread_func ,
plain_sockets_main_loop_run
} ;
2004-11-25 Havoc Pennington <hp@redhat.com>
The primary change here is to always write() once before adding
the write watch, which gives us about a 10% performance increase.
* dbus/dbus-transport-unix.c: a number of modifications to cope
with removing messages_pending
(check_write_watch): properly handle
DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of
messages_pending stuff
(check_read_watch): properly handle WAITING_FOR_MEMORY and
AUTHENTICATED cases
(unix_handle_watch): after writing, see if the write watch can be
removed
(unix_do_iteration): assert that write_watch/read_watch are
non-NULL rather than testing that they aren't, since they
aren't allowed to be NULL. check_write_watch() at the end so
we add the watch if we did not finish writing (e.g. got EAGAIN)
* dbus/dbus-transport-protected.h: remove messages_pending call,
since it resulted in too much inefficient watch adding/removing;
instead we now require that the transport user does an iteration
after queueing outgoing messages, and after trying the first
write() we add a write watch if we got EAGAIN or exceeded our
max bytes to write per iteration setting
* dbus/dbus-string.c (_dbus_string_validate_signature): add this
function
* dbus/dbus-server-unix.c (unix_finalize): the socket name was
freed and then accessed, valgrind flagged this bug, fix it
* dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken
as the last valid field plus 1, where really it is equal to the
last valid field. Corrects some message corruption issues.
* dbus/dbus-mainloop.c: verbosity changes
* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM
instead of aborting in one of the test codepaths
* dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that
caused not printing the pid ever again if a verbose was missing
the newline at the end
(_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE
* dbus/dbus-connection.c: verbosity changes;
(dbus_connection_has_messages_to_send): new function
(_dbus_connection_message_sent): no longer call transport->messages_pending
(_dbus_connection_send_preallocated_unlocked): do one iteration to
try to write() immediately, so we can avoid the write watch. This
is the core purpose of this patchset
(_dbus_connection_get_dispatch_status_unlocked): if disconnected,
dump the outgoing message queue, so nobody will get confused
trying to send them or thinking stuff is pending to be sent
* bus/test.c: verbosity changes
* bus/driver.c: verbosity/assertion changes
* bus/dispatch.c: a bunch of little tweaks to get it working again
because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
static double
2004-11-23 06:21:12 +00:00
do_profile_run ( const ProfileRunVTable * vtable )
{
GTimer * timer ;
int i ;
double secs ;
ServerData sd ;
void * server ;
2004-11-13 07:07:47 +00:00
2004-11-26 07:42:24 +00:00
g_printerr ( " Profiling %s \n " , vtable - > name ) ;
2004-11-13 07:07:47 +00:00
sd . handled = 0 ;
sd . n_clients = 0 ;
sd . loop = g_main_loop_new ( NULL , FALSE ) ;
2004-11-27 00:19:49 +00:00
sd . vtable = vtable ;
2003-09-30 02:43:21 +00:00
2004-11-23 06:21:12 +00:00
server = ( * vtable - > init_server ) ( & sd ) ;
2003-09-30 02:43:21 +00:00
for ( i = 0 ; i < N_CLIENT_THREADS ; i + + )
{
2004-11-27 00:19:49 +00:00
g_thread_create ( vtable - > client_thread_func , ( void * ) vtable , FALSE , NULL ) ;
2003-09-30 02:43:21 +00:00
}
2004-11-13 07:07:47 +00:00
timer = g_timer_new ( ) ;
2004-11-23 06:21:12 +00:00
g_printerr ( " Server thread %p entering main loop \n " ,
g_thread_self ( ) ) ;
( * vtable - > main_loop_run_func ) ( sd . loop ) ;
g_printerr ( " Server thread %p exiting main loop \n " ,
g_thread_self ( ) ) ;
2003-09-30 02:43:21 +00:00
2004-11-13 07:07:47 +00:00
secs = g_timer_elapsed ( timer , NULL ) ;
g_timer_destroy ( timer ) ;
2004-11-23 06:21:12 +00:00
g_printerr ( " %s: %g seconds, %d round trips, %f seconds per pingpong \n " ,
vtable - > name , secs , sd . handled , secs / sd . handled ) ;
2004-11-13 07:07:47 +00:00
2004-11-23 06:21:12 +00:00
( * vtable - > stop_server ) ( & sd , server ) ;
2003-09-30 02:43:21 +00:00
2004-11-13 07:07:47 +00:00
g_main_loop_unref ( sd . loop ) ;
2004-11-25 Havoc Pennington <hp@redhat.com>
The primary change here is to always write() once before adding
the write watch, which gives us about a 10% performance increase.
* dbus/dbus-transport-unix.c: a number of modifications to cope
with removing messages_pending
(check_write_watch): properly handle
DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of
messages_pending stuff
(check_read_watch): properly handle WAITING_FOR_MEMORY and
AUTHENTICATED cases
(unix_handle_watch): after writing, see if the write watch can be
removed
(unix_do_iteration): assert that write_watch/read_watch are
non-NULL rather than testing that they aren't, since they
aren't allowed to be NULL. check_write_watch() at the end so
we add the watch if we did not finish writing (e.g. got EAGAIN)
* dbus/dbus-transport-protected.h: remove messages_pending call,
since it resulted in too much inefficient watch adding/removing;
instead we now require that the transport user does an iteration
after queueing outgoing messages, and after trying the first
write() we add a write watch if we got EAGAIN or exceeded our
max bytes to write per iteration setting
* dbus/dbus-string.c (_dbus_string_validate_signature): add this
function
* dbus/dbus-server-unix.c (unix_finalize): the socket name was
freed and then accessed, valgrind flagged this bug, fix it
* dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken
as the last valid field plus 1, where really it is equal to the
last valid field. Corrects some message corruption issues.
* dbus/dbus-mainloop.c: verbosity changes
* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM
instead of aborting in one of the test codepaths
* dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that
caused not printing the pid ever again if a verbose was missing
the newline at the end
(_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE
* dbus/dbus-connection.c: verbosity changes;
(dbus_connection_has_messages_to_send): new function
(_dbus_connection_message_sent): no longer call transport->messages_pending
(_dbus_connection_send_preallocated_unlocked): do one iteration to
try to write() immediately, so we can avoid the write watch. This
is the core purpose of this patchset
(_dbus_connection_get_dispatch_status_unlocked): if disconnected,
dump the outgoing message queue, so nobody will get confused
trying to send them or thinking stuff is pending to be sent
* bus/test.c: verbosity changes
* bus/driver.c: verbosity/assertion changes
* bus/dispatch.c: a bunch of little tweaks to get it working again
because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
return secs ;
2004-11-23 06:21:12 +00:00
}
2004-11-27 02:18:36 +00:00
static void
print_result ( const ProfileRunVTable * vtable ,
double seconds ,
double baseline )
{
g_printerr ( " %g times slower for %s (%g seconds, %f per iteration) \n " ,
seconds / baseline , vtable - > name ,
seconds , seconds / N_ITERATIONS ) ;
}
2004-11-23 06:21:12 +00:00
int
main ( int argc , char * argv [ ] )
{
g_thread_init ( NULL ) ;
dbus_g_thread_init ( ) ;
2005-01-15 Havoc Pennington <hp@redhat.com>
* Land the new message args API and type system.
This patch is huge, but the public API change is not
really large. The set of D-BUS types has changed somewhat,
and the arg "getters" are more geared toward language bindings;
they don't make a copy, etc.
There are also some known issues. See these emails for details
on this huge patch:
http://lists.freedesktop.org/archives/dbus/2004-December/001836.html
http://lists.freedesktop.org/archives/dbus/2005-January/001922.html
* dbus/dbus-marshal-*: all the new stuff
* dbus/dbus-message.c: basically rewritten
* dbus/dbus-memory.c (check_guards): with "guards" enabled, init
freed blocks to be all non-nul bytes so using freed memory is less
likely to work right
* dbus/dbus-internals.c (_dbus_test_oom_handling): add
DBUS_FAIL_MALLOC=N environment variable, so you can do
DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or
DBUS_FAIL_MALLOC=10 to make it really, really, really slow and
thorough.
* qt/message.cpp: port to the new message args API
(operator<<): use str.utf8() rather than str.unicode()
(pretty sure this is right from the Qt docs?)
* glib/dbus-gvalue.c: port to the new message args API
* bus/dispatch.c, bus/driver.c: port to the new message args API
* dbus/dbus-string.c (_dbus_string_init_const_len): initialize the
"locked" flag to TRUE and align_offset to 0; I guess we never
looked at these anyhow, but seems cleaner.
* dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING):
move allocation padding macro to this header; use it to implement
(_DBUS_STRING_STATIC): ability to declare a static string.
* dbus/dbus-message.c (_dbus_message_has_type_interface_member):
change to return TRUE if the interface is not set.
* dbus/dbus-string.[hc]: move the D-BUS specific validation stuff
to dbus-marshal-validate.[hc]
* dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from
dbus-internals.c
* dbus/Makefile.am: cut over from dbus-marshal.[hc]
to dbus-marshal-*.[hc]
* dbus/dbus-object-tree.c (_dbus_decompose_path): move this
function here from dbus-marshal.c
2005-01-15 07:15:38 +00:00
# ifndef DBUS_DISABLE_ASSERT
g_printerr ( " You should probably --disable-asserts before you profile as they have noticeable overhead \n " ) ;
# endif
# if DBUS_ENABLE_VERBOSE_MODE
g_printerr ( " You should probably --disable-verbose-mode before you profile as verbose has noticeable overhead \n " ) ;
# endif
2004-11-23 06:21:12 +00:00
payload = g_malloc ( PAYLOAD_SIZE ) ;
/* The actual size of the DBusMessage on the wire, as of Nov 23 2004,
* without the payload
*/
2004-11-26 07:42:24 +00:00
echo_call_size = 140 + PAYLOAD_SIZE ;
2004-11-23 06:21:12 +00:00
echo_return_size = 32 ;
if ( argc > 1 & & strcmp ( argv [ 1 ] , " plain_sockets " ) = = 0 )
do_profile_run ( & plain_sockets_vtable ) ;
2004-11-26 07:42:24 +00:00
else if ( argc > 1 & & strcmp ( argv [ 1 ] , " plain_sockets_with_malloc " ) = = 0 )
2004-11-27 02:18:36 +00:00
do_profile_run ( & plain_sockets_with_malloc_vtable ) ;
else if ( argc > 1 & & strcmp ( argv [ 1 ] , " no_bus " ) = = 0 )
do_profile_run ( & no_bus_vtable ) ;
else if ( argc > 1 & & strcmp ( argv [ 1 ] , " with_bus " ) = = 0 )
do_profile_run ( & with_bus_vtable ) ;
2004-11-26 07:42:24 +00:00
else if ( argc > 1 & & strcmp ( argv [ 1 ] , " all " ) = = 0 )
{
2004-11-27 02:18:36 +00:00
double e1 , e2 , e3 , e4 ;
2004-11-25 Havoc Pennington <hp@redhat.com>
The primary change here is to always write() once before adding
the write watch, which gives us about a 10% performance increase.
* dbus/dbus-transport-unix.c: a number of modifications to cope
with removing messages_pending
(check_write_watch): properly handle
DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of
messages_pending stuff
(check_read_watch): properly handle WAITING_FOR_MEMORY and
AUTHENTICATED cases
(unix_handle_watch): after writing, see if the write watch can be
removed
(unix_do_iteration): assert that write_watch/read_watch are
non-NULL rather than testing that they aren't, since they
aren't allowed to be NULL. check_write_watch() at the end so
we add the watch if we did not finish writing (e.g. got EAGAIN)
* dbus/dbus-transport-protected.h: remove messages_pending call,
since it resulted in too much inefficient watch adding/removing;
instead we now require that the transport user does an iteration
after queueing outgoing messages, and after trying the first
write() we add a write watch if we got EAGAIN or exceeded our
max bytes to write per iteration setting
* dbus/dbus-string.c (_dbus_string_validate_signature): add this
function
* dbus/dbus-server-unix.c (unix_finalize): the socket name was
freed and then accessed, valgrind flagged this bug, fix it
* dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken
as the last valid field plus 1, where really it is equal to the
last valid field. Corrects some message corruption issues.
* dbus/dbus-mainloop.c: verbosity changes
* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM
instead of aborting in one of the test codepaths
* dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that
caused not printing the pid ever again if a verbose was missing
the newline at the end
(_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE
* dbus/dbus-connection.c: verbosity changes;
(dbus_connection_has_messages_to_send): new function
(_dbus_connection_message_sent): no longer call transport->messages_pending
(_dbus_connection_send_preallocated_unlocked): do one iteration to
try to write() immediately, so we can avoid the write watch. This
is the core purpose of this patchset
(_dbus_connection_get_dispatch_status_unlocked): if disconnected,
dump the outgoing message queue, so nobody will get confused
trying to send them or thinking stuff is pending to be sent
* bus/test.c: verbosity changes
* bus/driver.c: verbosity/assertion changes
* bus/dispatch.c: a bunch of little tweaks to get it working again
because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
2004-11-26 07:42:24 +00:00
e1 = do_profile_run ( & plain_sockets_vtable ) ;
e2 = do_profile_run ( & plain_sockets_with_malloc_vtable ) ;
2004-11-27 02:18:36 +00:00
e3 = do_profile_run ( & no_bus_vtable ) ;
e4 = do_profile_run ( & with_bus_vtable ) ;
g_printerr ( " Baseline plain sockets time %g seconds for %d iterations \n " ,
e1 , N_ITERATIONS ) ;
print_result ( & plain_sockets_vtable , e1 , e1 ) ;
print_result ( & plain_sockets_with_malloc_vtable , e2 , e1 ) ;
print_result ( & no_bus_vtable , e3 , e1 ) ;
print_result ( & with_bus_vtable , e4 , e1 ) ;
2004-11-25 Havoc Pennington <hp@redhat.com>
The primary change here is to always write() once before adding
the write watch, which gives us about a 10% performance increase.
* dbus/dbus-transport-unix.c: a number of modifications to cope
with removing messages_pending
(check_write_watch): properly handle
DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of
messages_pending stuff
(check_read_watch): properly handle WAITING_FOR_MEMORY and
AUTHENTICATED cases
(unix_handle_watch): after writing, see if the write watch can be
removed
(unix_do_iteration): assert that write_watch/read_watch are
non-NULL rather than testing that they aren't, since they
aren't allowed to be NULL. check_write_watch() at the end so
we add the watch if we did not finish writing (e.g. got EAGAIN)
* dbus/dbus-transport-protected.h: remove messages_pending call,
since it resulted in too much inefficient watch adding/removing;
instead we now require that the transport user does an iteration
after queueing outgoing messages, and after trying the first
write() we add a write watch if we got EAGAIN or exceeded our
max bytes to write per iteration setting
* dbus/dbus-string.c (_dbus_string_validate_signature): add this
function
* dbus/dbus-server-unix.c (unix_finalize): the socket name was
freed and then accessed, valgrind flagged this bug, fix it
* dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken
as the last valid field plus 1, where really it is equal to the
last valid field. Corrects some message corruption issues.
* dbus/dbus-mainloop.c: verbosity changes
* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM
instead of aborting in one of the test codepaths
* dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that
caused not printing the pid ever again if a verbose was missing
the newline at the end
(_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE
* dbus/dbus-connection.c: verbosity changes;
(dbus_connection_has_messages_to_send): new function
(_dbus_connection_message_sent): no longer call transport->messages_pending
(_dbus_connection_send_preallocated_unlocked): do one iteration to
try to write() immediately, so we can avoid the write watch. This
is the core purpose of this patchset
(_dbus_connection_get_dispatch_status_unlocked): if disconnected,
dump the outgoing message queue, so nobody will get confused
trying to send them or thinking stuff is pending to be sent
* bus/test.c: verbosity changes
* bus/driver.c: verbosity/assertion changes
* bus/dispatch.c: a bunch of little tweaks to get it working again
because this patchset changes when/where you need to block.
2004-11-26 01:53:13 +00:00
}
2004-11-23 06:21:12 +00:00
else
2004-11-27 02:18:36 +00:00
{
g_printerr ( " Specify profile type plain_sockets, plain_sockets_with_malloc, no_bus, with_bus, all \n " ) ;
exit ( 1 ) ;
}
2004-11-27 07:30:22 +00:00
/* Make valgrind happy */
dbus_shutdown ( ) ;
2003-09-30 02:43:21 +00:00
return 0 ;
}