You can subscribe to this list here.
2005 |
Jan
|
Feb
|
Mar
(56) |
Apr
(109) |
May
(15) |
Jun
(3) |
Jul
(37) |
Aug
(96) |
Sep
(40) |
Oct
(4) |
Nov
(54) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2006 |
Jan
(47) |
Feb
(30) |
Mar
(102) |
Apr
(120) |
May
(68) |
Jun
(54) |
Jul
(53) |
Aug
(122) |
Sep
(190) |
Oct
(71) |
Nov
(85) |
Dec
(108) |
2007 |
Jan
(72) |
Feb
(190) |
Mar
(53) |
Apr
(101) |
May
(145) |
Jun
(148) |
Jul
(167) |
Aug
(143) |
Sep
(23) |
Oct
(198) |
Nov
(223) |
Dec
(195) |
2008 |
Jan
(100) |
Feb
(129) |
Mar
(79) |
Apr
(77) |
May
(34) |
Jun
(95) |
Jul
(112) |
Aug
(160) |
Sep
(82) |
Oct
(124) |
Nov
(199) |
Dec
(355) |
2009 |
Jan
(436) |
Feb
(89) |
Mar
(298) |
Apr
(189) |
May
(33) |
Jun
(88) |
Jul
(105) |
Aug
(44) |
Sep
(181) |
Oct
(87) |
Nov
(75) |
Dec
(1) |
2010 |
Jan
(63) |
Feb
(21) |
Mar
(3) |
Apr
(1) |
May
(1) |
Jun
(3) |
Jul
(26) |
Aug
(37) |
Sep
(26) |
Oct
(15) |
Nov
(13) |
Dec
|
From: <dg...@su...> - 2009-02-05 13:09:19
|
Author: bellmich Date: Thu Feb 5 14:07:25 2009 New Revision: 921 URL: http://libsyncml.opensync.org/changeset/921 Log: tolerate HTTP only builds (without OBEX support) Modified: trunk/tests/check_data_sync_api.c Modified: trunk/tests/check_data_sync_api.c ============================================================================== --- trunk/tests/check_data_sync_api.c Thu Feb 5 14:06:37 2009 (r920) +++ trunk/tests/check_data_sync_api.c Thu Feb 5 14:07:25 2009 (r921) @@ -408,8 +408,14 @@ SmlError *error = NULL; init_testbed("OBEX", "17002"); + /* register datastore + * the source must be identical if this is http + */ client_source = "dcim"; - server_source = "photos"; + if (!strcmp(transport, "OBEX")) + server_source = "photos"; + else + server_source = "dcim"; if (!smlDataSyncAddDatastore( client, "image/jpeg", |
From: <dg...@su...> - 2009-02-05 13:08:32
|
Author: bellmich Date: Thu Feb 5 14:06:37 2009 New Revision: 920 URL: http://libsyncml.opensync.org/changeset/920 Log: added dependencies of the DS API test Modified: trunk/tests/CMakeLists.txt Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Thu Feb 5 12:30:29 2009 (r919) +++ trunk/tests/CMakeLists.txt Thu Feb 5 14:06:37 2009 (r920) @@ -29,7 +29,6 @@ ADD_CHECK_TEST( san check_san.c ${TEST_TARGET_LIBRARIES} ) ADD_CHECK_TEST( devinf check_devinf.c ${TEST_TARGET_LIBRARIES} ) ADD_CHECK_TEST( sync check_sync.c ${TEST_TARGET_LIBRARIES} ) - ADD_CHECK_TEST( ds_api check_data_sync_api.c ${TEST_TARGET_LIBRARIES} ) # dependent tests @@ -58,6 +57,10 @@ ADD_MOBILE_TEST( nokia_9500_vcard_vcal ${TEST_TARGET_LIBRARIES} ) ENDIF ( ENABLE_OBEX AND ENABLE_OPENOBEX_TCP AND ENABLE_WBXML AND ENABLE_GLIB2_GREGEX ) + IF ( ENABLE_OPENOBEX_TCP OR ENABLE_HTTP ) + ADD_CHECK_TEST( ds_api check_data_sync_api.c ${TEST_TARGET_LIBRARIES} ) + ENDIF ( ENABLE_OPENOBEX_TCP OR ENABLE_HTTP ) + # tests of deprecated stuff # such tests produce compiler warnings |
From: <dg...@su...> - 2009-02-05 12:32:55
|
Author: bellmich Date: Thu Feb 5 12:30:29 2009 New Revision: 919 URL: http://libsyncml.opensync.org/changeset/919 Log: fixed wrong order of #ifdef and #endif Modified: trunk/tests/check_data_sync_api.c Modified: trunk/tests/check_data_sync_api.c ============================================================================== --- trunk/tests/check_data_sync_api.c Thu Feb 5 12:27:06 2009 (r918) +++ trunk/tests/check_data_sync_api.c Thu Feb 5 12:30:29 2009 (r919) @@ -242,8 +242,8 @@ if (!strcasecmp(transport_type, "OBEX")) { transport = "OBEX"; } -#ifdef ENABLE_HTTP #endif +#ifdef ENABLE_HTTP if (!strcasecmp(transport_type, "HTTP")) { transport = "HTTP"; } |
From: <dg...@su...> - 2009-02-05 11:28:57
|
Author: bellmich Date: Thu Feb 5 12:27:06 2009 New Revision: 918 URL: http://libsyncml.opensync.org/changeset/918 Log: try to fix compiler error from Solaris CC Modified: trunk/libsyncml/data_sync_api/data_sync_callbacks.c Modified: trunk/libsyncml/data_sync_api/data_sync_callbacks.c ============================================================================== --- trunk/libsyncml/data_sync_api/data_sync_callbacks.c Thu Feb 5 10:29:17 2009 (r917) +++ trunk/libsyncml/data_sync_api/data_sync_callbacks.c Thu Feb 5 12:27:06 2009 (r918) @@ -553,7 +553,8 @@ type = SML_CHANGE_ADD; /* decode base64 data if necessary */ - size_t appClassLength = index(datastore->contentType, '/') - datastore->contentType; + size_t appClassLength = ((size_t) index(datastore->contentType, '/')) - + ((size_t) datastore->contentType); if ( ( strstr(datastore->contentType, SML_CONTENT_TYPE_APPLICATION) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_APPLICATION) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_AUDIO) == datastore->contentType && |
From: <dg...@su...> - 2009-02-05 10:17:25
|
Author: bellmich Date: Thu Feb 5 11:15:37 2009 New Revision: 184 URL: http://libwbxml.opensync.org/changeset/184 Log: fixed DDF tests Added: wbxmlTestSuite/trunk/ddf/ddf-001.ddf (props changed) - copied unchanged from r182, wbxmlTestSuite/trunk/ddf/ddf-001.xml Deleted: wbxmlTestSuite/trunk/ddf/ddf-001.xml Modified: wbxmlTestSuite/trunk/launchTests.sh Copied: wbxmlTestSuite/trunk/ddf/ddf-001.ddf (from r182, wbxmlTestSuite/trunk/ddf/ddf-001.xml) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ wbxmlTestSuite/trunk/ddf/ddf-001.ddf Thu Feb 5 11:15:37 2009 (r184, copy of r182, wbxmlTestSuite/trunk/ddf/ddf-001.xml) @@ -0,0 +1,55 @@ +<?xml version="1.0"?> +<!DOCTYPE MgmtTree PUBLIC "-//OMA//DTD-DM-DDF 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/dm_ddf-v1_2.dtd"> + <MgmtTree xmlns="syncml:dmddf1.2"> + <VerDTD>1.2</VerDTD> + <Node> + <NodeName>E-Mail</NodeName> + <RTProperties> + <Format> + <node/> + </Format> + <Type> + <DDFName>com.operatorX.dm/1.0/EMail</DDFName> + </Type> + </RTProperties> + <Node> + <NodeName>POP3</NodeName> + <Node> + <NodeName>POPServer</NodeName> + <RTProperties> + <Format> + <chr/> + </Format> + <Type> + <MIME>text/plain</MIME> + </Type> + </RTProperties> + <Value>mail.Operatorx.com</Value> + </Node> + <Node> + <NodeName>UserID</NodeName> + <RTProperties> + <Format> + <chr/> + </Format> + <Type> + <MIME>text/plain</MIME> + </Type> + </RTProperties> + <Value>UserName</Value> + </Node> + <Node> + <NodeName>PWD</NodeName> + <RTProperties> + <Format> + <chr/> + </Format> + <Type> + <MIME>text/plain</MIME> + </Type> + </RTProperties> + <Value>4571F7C34A9876B3</Value> + </Node> + </Node> + </Node> + </MgmtTree> Modified: wbxmlTestSuite/trunk/launchTests.sh ============================================================================== --- wbxmlTestSuite/trunk/launchTests.sh Fri Jan 23 15:50:38 2009 (r183) +++ wbxmlTestSuite/trunk/launchTests.sh Thu Feb 5 11:15:37 2009 (r184) @@ -146,8 +146,10 @@ else if [ "$TESTDIR" = "airsync" ]; then PARAMS="-l AIRSYNC" - else if [ "$TESTDIR" != `basename $i ddf` ]; + else if [ "$TESTDIR" = "ddf" -a `basename $j` != `basename $j ddf` ]; then + # only pure DDF documents need this option + # embedded DDF documents do not need this option PARAMS="-l DMDDF12" else PARAMS="" |
From: <dg...@su...> - 2009-02-05 09:31:03
|
Author: bellmich Date: Thu Feb 5 10:29:17 2009 New Revision: 917 URL: http://libsyncml.opensync.org/changeset/917 Log: added Samsung SGH-F480 to the list of the supported models This patch was provided by Frederic Brin (duckx). Modified: trunk/libsyncml/transports/obex_client_samsung.c Modified: trunk/libsyncml/transports/obex_client_samsung.c ============================================================================== --- trunk/libsyncml/transports/obex_client_samsung.c Thu Feb 5 10:25:18 2009 (r916) +++ trunk/libsyncml/transports/obex_client_samsung.c Thu Feb 5 10:29:17 2009 (r917) @@ -53,6 +53,7 @@ !g_strcasecmp("SGH-E770", env->model) || !g_strcasecmp("SGH-E860", env->model) || !g_strcasecmp("SGH-E900", env->model) || + !g_strcasecmp("SGH-F480", env->model) || !g_strcasecmp("SGH-S500i", env->model) || !g_strcasecmp("SGH-T609", env->model) || !g_strcasecmp("SGH-X800", env->model) || |
From: <dg...@su...> - 2009-02-05 09:27:03
|
Author: bellmich Date: Thu Feb 5 10:25:18 2009 New Revision: 916 URL: http://libsyncml.opensync.org/changeset/916 Log: fixed wrong return value for vendor detection via AT commands This patch was provided by FrédériBrin (duckx). Modified: trunk/libsyncml/transports/obex_client.c Modified: trunk/libsyncml/transports/obex_client.c ============================================================================== --- trunk/libsyncml/transports/obex_client.c Thu Feb 5 10:17:54 2009 (r915) +++ trunk/libsyncml/transports/obex_client.c Thu Feb 5 10:25:18 2009 (r916) @@ -231,7 +231,7 @@ smlSafeCFree(&big); smlTrace(TRACE_EXIT, "%s - %d", __func__, vendor); - return SML_OBEX_VENDOR_UNKNOWN; + return vendor; } static int smlTransportObexClientCableConnect(obex_t *handle, gpointer ud) |
From: <dg...@su...> - 2009-02-05 09:19:40
|
Author: bellmich Date: Thu Feb 5 10:17:54 2009 New Revision: 915 URL: http://libsyncml.opensync.org/changeset/915 Log: If somebody no longer references an error then the error should no longer be accessible for him. Modified: trunk/libsyncml/sml_error.c Modified: trunk/libsyncml/sml_error.c ============================================================================== --- trunk/libsyncml/sml_error.c Thu Feb 5 10:16:30 2009 (r914) +++ trunk/libsyncml/sml_error.c Thu Feb 5 10:17:54 2009 (r915) @@ -241,8 +241,10 @@ if (!smlErrorIsSet(error)) return; - if (!g_atomic_int_dec_and_test(&(*error)->refCount)) + if (!g_atomic_int_dec_and_test(&((*error)->refCount))) { + *error = NULL; return; + } if ((*error)->message) smlSafeCFree (&((*error)->message)); |
From: <dg...@su...> - 2009-02-05 09:18:18
|
Author: bellmich Date: Thu Feb 5 10:16:30 2009 New Revision: 914 URL: http://libsyncml.opensync.org/changeset/914 Log: If the transport is freed directly after the call to smlTransportNew then the finalize function of the transport implementation is called. Therefore the context is not always present. Modified: trunk/libsyncml/transports/obex_server.c Modified: trunk/libsyncml/transports/obex_server.c ============================================================================== --- trunk/libsyncml/transports/obex_server.c Thu Feb 5 10:14:29 2009 (r913) +++ trunk/libsyncml/transports/obex_server.c Thu Feb 5 10:16:30 2009 (r914) @@ -748,7 +748,8 @@ } /* free context */ - g_main_context_unref(env->tsp->context); + if (env->tsp->context) + g_main_context_unref(env->tsp->context); /* free functions */ if (env->functions) |
From: <dg...@su...> - 2009-02-05 09:16:18
|
Author: bellmich Date: Thu Feb 5 10:14:29 2009 New Revision: 913 URL: http://libsyncml.opensync.org/changeset/913 Log: make sure that a failure is failure even if CK_FORK=NO (Thanks goes to dgollub for the check support.) Modified: trunk/tests/support.h Modified: trunk/tests/support.h ============================================================================== --- trunk/tests/support.h Wed Feb 4 16:50:41 2009 (r912) +++ trunk/tests/support.h Thu Feb 5 10:14:29 2009 (r913) @@ -32,5 +32,6 @@ {\ int _result = expr;\ fail_unless(_result, ## __VA_ARGS__);\ + if (!_result) smlAssertMsg(0, g_strdup_printf(__VA_ARGS__));\ } |
From: <dg...@su...> - 2009-02-04 15:52:25
|
Author: bellmich Date: Wed Feb 4 16:50:41 2009 New Revision: 912 URL: http://libsyncml.opensync.org/changeset/912 Log: detect prior errors (FreeBSD) Modified: trunk/tests/check_sync.c Modified: trunk/tests/check_sync.c ============================================================================== --- trunk/tests/check_sync.c Wed Feb 4 16:36:57 2009 (r911) +++ trunk/tests/check_sync.c Wed Feb 4 16:50:41 2009 (r912) @@ -346,6 +346,7 @@ smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); + sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); @@ -529,6 +530,7 @@ smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); + sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); @@ -782,6 +784,7 @@ smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); + sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); @@ -1102,6 +1105,7 @@ smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); + sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); |
From: <dg...@su...> - 2009-02-04 15:39:48
|
Author: Graham Cobb Date: Wed Feb 4 16:37:58 2009 New Revision: 5261 URL: http://www.opensync.org/changeset/5261 Log: Fix double-deallocation crash during exit caused by bad refcounting in opensync_member.c. Modified: trunk/ChangeLog trunk/opensync/group/opensync_member.c trunk/opensync/ipc/opensync_queue.c Modified: trunk/ChangeLog ============================================================================== --- trunk/ChangeLog Wed Feb 4 15:32:36 2009 (r5260) +++ trunk/ChangeLog Wed Feb 4 16:37:58 2009 (r5261) @@ -1,3 +1,12 @@ +2009-02-04 Graham Cobb <g+...@co...> + + * opensync/group/opensync_member.c (osync_member_load): Use osync_member_add_objtype_sink + so references get added properly. + (osync_member_flush_objtypes): Use osync_member_remove_objtype_sink so references get + removed properly + + * opensync/ipc/opensync_queue.c (osync_queue_set_message_handler): Fix bad osync_trace format + 2009-02-03 Graham Cobb <g+...@co...> * tests/ipc-tests/check_ipc.c (ipc_loop_timeout_with_idle): Change test parameters Modified: trunk/opensync/group/opensync_member.c ============================================================================== --- trunk/opensync/group/opensync_member.c Wed Feb 4 15:32:36 2009 (r5260) +++ trunk/opensync/group/opensync_member.c Wed Feb 4 16:37:58 2009 (r5261) @@ -396,7 +396,7 @@ if (!sink) goto error_free_doc; - member->objtypes = g_list_append(member->objtypes, sink); + osync_member_add_objtype_sink(member, sink); } else if (!xmlStrcmp(cur->name, (const xmlChar *)"timeout")) { /* Sink Function Timeout settings for main sink */ if (!member->main_sink) @@ -832,8 +832,7 @@ while (member->objtypes) { OSyncObjTypeSink *sink = member->objtypes->data; - osync_objtype_sink_unref(sink); - member->objtypes = g_list_remove(member->objtypes, member->objtypes->data); + osync_member_remove_objtype_sink(member, sink); } if (member->main_sink) { Modified: trunk/opensync/ipc/opensync_queue.c ============================================================================== --- trunk/opensync/ipc/opensync_queue.c Wed Feb 4 15:32:36 2009 (r5260) +++ trunk/opensync/ipc/opensync_queue.c Wed Feb 4 16:37:58 2009 (r5261) @@ -1169,7 +1169,7 @@ void osync_queue_set_message_handler(OSyncQueue *queue, OSyncMessageHandler handler, gpointer user_data) { - osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, queue, handler, user_data); + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, queue, handler, user_data); queue->message_handler = handler; queue->user_data = user_data; |
From: <dg...@su...> - 2009-02-04 15:38:39
|
Author: bellmich Date: Wed Feb 4 16:36:57 2009 New Revision: 911 URL: http://libsyncml.opensync.org/changeset/911 Log: fixed Solaris CC warning (implicit function declaration) Modified: trunk/libsyncml/data_sync_api/data_sync.c Modified: trunk/libsyncml/data_sync_api/data_sync.c ============================================================================== --- trunk/libsyncml/data_sync_api/data_sync.c Wed Feb 4 16:34:36 2009 (r910) +++ trunk/libsyncml/data_sync_api/data_sync.c Wed Feb 4 16:36:57 2009 (r911) @@ -26,6 +26,9 @@ #include <libsyncml/data_sync_api/standard.h> #include <libsyncml/data_sync_api/callbacks.h> +/* required because of function index */ +#include <strings.h> + #include "data_sync.h" #include "data_sync_client.h" #include "data_sync_server.h" |
From: <dg...@su...> - 2009-02-04 15:36:21
|
Author: bellmich Date: Wed Feb 4 16:34:36 2009 New Revision: 910 URL: http://libsyncml.opensync.org/changeset/910 Log: try to fix compiler error from Solaris CC Modified: trunk/libsyncml/data_sync_api/data_sync.c Modified: trunk/libsyncml/data_sync_api/data_sync.c ============================================================================== --- trunk/libsyncml/data_sync_api/data_sync.c Fri Jan 30 16:11:35 2009 (r909) +++ trunk/libsyncml/data_sync_api/data_sync.c Wed Feb 4 16:34:36 2009 (r910) @@ -535,7 +535,10 @@ SmlDataSyncDatastore *datastore = change->datastore; /* copy data */ - size_t appClassLength = index(datastore->contentType, '/') - datastore->contentType; + smlAssert(datastore->contentType); + smlAssert(index(datastore->contentType, '/')); + size_t appClassLength = ((size_t) index(datastore->contentType, '/')) - + ((size_t) datastore->contentType); if ( ( strstr(datastore->contentType, SML_CONTENT_TYPE_APPLICATION) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_APPLICATION) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_AUDIO) == datastore->contentType && |
From: <dg...@su...> - 2009-02-04 14:34:25
|
Author: friedrich.beckmann Date: Wed Feb 4 15:32:36 2009 New Revision: 5260 URL: http://www.opensync.org/changeset/5260 Log: engine_error_single_init_error, ..double_init_error, ...no_objtype_error, ...no_config_error did not work. See ticket #1056 Added: trunk/tests/data/sync/configs/group/1/mock-sync.no-objtype-error.conf Modified: trunk/tests/engine-tests/check_engine_error.c Added: trunk/tests/data/sync/configs/group/1/mock-sync.no-objtype-error.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/sync/configs/group/1/mock-sync.no-objtype-error.conf Wed Feb 4 15:32:36 2009 (r5260) @@ -0,0 +1,3 @@ +<?xml version="1.0"?> +<config version="1.0"> +</config> Modified: trunk/tests/engine-tests/check_engine_error.c ============================================================================== --- trunk/tests/engine-tests/check_engine_error.c Wed Feb 4 01:57:21 2009 (r5259) +++ trunk/tests/engine-tests/check_engine_error.c Wed Feb 4 15:32:36 2009 (r5260) @@ -154,270 +154,6 @@ g_free(env); } -static OSyncDebugGroup *_create_group(char *testbed) -{ - OSyncDebugGroup *debug = g_malloc0(sizeof(OSyncDebugGroup)); - - OSyncError *error = NULL; - debug->group = osync_group_new(&error); - fail_unless(debug->group != NULL, NULL); - fail_unless(error == NULL, NULL); - char *path = g_strdup_printf("%s/configs/group", testbed); - osync_group_set_configdir(debug->group, path); - g_free(path); - - debug->member1 = osync_member_new(&error); - fail_unless(debug->member1 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member1); - osync_member_set_pluginname(debug->member1, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/1", testbed); - osync_member_set_configdir(debug->member1, path); - g_free(path); - _member_add_objtype(debug->member1, "mockobjtype1"); - OSyncPluginConfig *config1 = simple_plugin_config(NULL, "data1", "mockobjtype1", "mockformat1", NULL); - osync_member_set_config(debug->member1, config1); - osync_plugin_config_unref(config1); - - debug->member2 = osync_member_new(&error); - fail_unless(debug->member2 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member2); - osync_member_set_pluginname(debug->member2, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/2", testbed); - osync_member_set_configdir(debug->member2, path); - g_free(path); - - _member_add_objtype(debug->member2, "mockobjtype1"); - - OSyncPluginConfig *config2 = simple_plugin_config(NULL, "data2", "mockobjtype1", "mockformat1", NULL); - osync_member_set_config(debug->member2, config2); - osync_plugin_config_unref(config2); - - - - debug->plugin = osync_plugin_new(&error); - fail_unless(debug->plugin != NULL, NULL); - fail_unless(error == NULL, NULL); - - osync_plugin_set_name(debug->plugin, "mock-sync-foo"); - osync_plugin_set_longname(debug->plugin, "Mock Sync Plugin"); - osync_plugin_set_description(debug->plugin, "This is a pseudo plugin"); - osync_plugin_set_start_type(debug->plugin, OSYNC_START_TYPE_THREAD); - osync_plugin_set_config_type(debug->plugin, OSYNC_PLUGIN_NO_CONFIGURATION); - - osync_plugin_set_initialize(debug->plugin, initialize); - osync_plugin_set_finalize(debug->plugin, finalize); - - - debug->plugin2 = osync_plugin_new(&error); - fail_unless(debug->plugin2 != NULL, NULL); - fail_unless(error == NULL, NULL); - - osync_plugin_set_name(debug->plugin2, "mock-sync-foo"); - osync_plugin_set_longname(debug->plugin2, "Mock Sync Plugin"); - osync_plugin_set_description(debug->plugin2, "This is a pseudo plugin"); - osync_plugin_set_start_type(debug->plugin2, OSYNC_START_TYPE_THREAD); - - osync_plugin_set_initialize(debug->plugin2, initialize_error); - osync_plugin_set_finalize(debug->plugin2, finalize); - - return debug; -} - -static OSyncDebugGroup *_create_group2(char *testbed) -{ - OSyncDebugGroup *debug = g_malloc0(sizeof(OSyncDebugGroup)); - - OSyncError *error = NULL; - debug->group = osync_group_new(&error); - fail_unless(debug->group != NULL, NULL); - fail_unless(error == NULL, NULL); - char *path = g_strdup_printf("%s/configs/group", testbed); - osync_group_set_configdir(debug->group, path); - g_free(path); - - debug->member1 = osync_member_new(&error); - fail_unless(debug->member1 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member1); - osync_member_set_pluginname(debug->member1, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/1", testbed); - osync_member_set_configdir(debug->member1, path); - g_free(path); - - _member_add_objtype(debug->member1, "mockobjtype1"); - OSyncPluginConfig *config1 = simple_plugin_config(NULL, "data1", "mockobjtype1", "mockformat1", NULL); - osync_member_set_config(debug->member1, config1); - osync_plugin_config_unref(config1); - - - debug->member2 = osync_member_new(&error); - fail_unless(debug->member2 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member2); - osync_member_set_pluginname(debug->member2, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/2", testbed); - osync_member_set_configdir(debug->member2, path); - g_free(path); - - _member_add_objtype(debug->member2, "mockobjtype1"); - OSyncPluginConfig *config2 = simple_plugin_config(NULL, "data2", "mockobjtype1", "mockformat1", NULL); - osync_member_set_config(debug->member2, config2); - osync_plugin_config_unref(config2); - - - debug->plugin = osync_plugin_new(&error); - fail_unless(debug->plugin != NULL, NULL); - fail_unless(error == NULL, NULL); - - osync_plugin_set_name(debug->plugin, "mock-sync-foo"); - osync_plugin_set_longname(debug->plugin, "Mock Sync Plugin"); - osync_plugin_set_description(debug->plugin, "This is a pseudo plugin"); - osync_plugin_set_start_type(debug->plugin, OSYNC_START_TYPE_THREAD); - osync_plugin_set_config_type(debug->plugin, OSYNC_PLUGIN_NO_CONFIGURATION); - - osync_plugin_set_initialize(debug->plugin, initialize_error); - osync_plugin_set_finalize(debug->plugin, finalize); - - - debug->plugin2 = osync_plugin_new(&error); - fail_unless(debug->plugin2 != NULL, NULL); - fail_unless(error == NULL, NULL); - - osync_plugin_set_name(debug->plugin2, "mock-sync-foo"); - osync_plugin_set_longname(debug->plugin2, "Mock Sync Plugin"); - osync_plugin_set_description(debug->plugin2, "This is a pseudo plugin"); - osync_plugin_set_start_type(debug->plugin2, OSYNC_START_TYPE_THREAD); - - osync_plugin_set_initialize(debug->plugin2, initialize_error); - osync_plugin_set_finalize(debug->plugin2, finalize); - - return debug; -} - -static OSyncDebugGroup *_create_group3(char *testbed) -{ - OSyncDebugGroup *debug = g_malloc0(sizeof(OSyncDebugGroup)); - - OSyncError *error = NULL; - debug->group = osync_group_new(&error); - fail_unless(debug->group != NULL, NULL); - fail_unless(error == NULL, NULL); - char *path = g_strdup_printf("%s/configs/group", testbed); - osync_group_set_configdir(debug->group, path); - g_free(path); - - debug->member1 = osync_member_new(&error); - fail_unless(debug->member1 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member1); - osync_member_set_pluginname(debug->member1, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/1", testbed); - osync_member_set_configdir(debug->member1, path); - g_free(path); - - _member_add_objtype(debug->member1, "mockobjtype1"); - - debug->member2 = osync_member_new(&error); - fail_unless(debug->member2 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member2); - osync_member_set_pluginname(debug->member2, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/2", testbed); - osync_member_set_configdir(debug->member2, path); - g_free(path); - - _member_add_objtype(debug->member2, "mockobjtype1"); - - - - debug->plugin = osync_plugin_new(&error); - fail_unless(debug->plugin != NULL, NULL); - fail_unless(error == NULL, NULL); - - osync_plugin_set_name(debug->plugin, "mock-sync-foo"); - osync_plugin_set_longname(debug->plugin, "Mock Sync Plugin"); - osync_plugin_set_description(debug->plugin, "This is a pseudo plugin"); - osync_plugin_set_start_type(debug->plugin, OSYNC_START_TYPE_THREAD); - osync_plugin_set_config_type(debug->plugin, OSYNC_PLUGIN_NO_CONFIGURATION); - - osync_plugin_set_initialize(debug->plugin, initialize_error); - osync_plugin_set_finalize(debug->plugin, finalize); - - - debug->plugin2 = osync_plugin_new(&error); - fail_unless(debug->plugin2 != NULL, NULL); - fail_unless(error == NULL, NULL); - - osync_plugin_set_name(debug->plugin2, "mock-sync-foo"); - osync_plugin_set_longname(debug->plugin2, "Mock Sync Plugin"); - osync_plugin_set_description(debug->plugin2, "This is a pseudo plugin"); - osync_plugin_set_start_type(debug->plugin2, OSYNC_START_TYPE_THREAD); - - osync_plugin_set_initialize(debug->plugin2, initialize_error); - osync_plugin_set_finalize(debug->plugin2, finalize); - - return debug; -} - -static OSyncDebugGroup *_create_group4(char *testbed) -{ - OSyncDebugGroup *debug = g_malloc0(sizeof(OSyncDebugGroup)); - - OSyncError *error = NULL; - debug->group = osync_group_new(&error); - fail_unless(debug->group != NULL, NULL); - fail_unless(error == NULL, NULL); - char *path = g_strdup_printf("%s/configs/group", testbed); - osync_group_set_configdir(debug->group, path); - g_free(path); - - debug->member1 = osync_member_new(&error); - fail_unless(debug->member1 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member1); - osync_member_set_pluginname(debug->member1, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/1", testbed); - osync_member_set_configdir(debug->member1, path); - g_free(path); - - _member_add_objtype(debug->member1, "mockobjtype1"); - OSyncPluginConfig *config1 = simple_plugin_config(NULL, "data1", "mockobjtype1", "mockformat1", NULL); - osync_member_set_config(debug->member1, config1); - osync_plugin_config_unref(config1); - - - debug->member2 = osync_member_new(&error); - fail_unless(debug->member2 != NULL, NULL); - fail_unless(error == NULL, NULL); - osync_group_add_member(debug->group, debug->member2); - osync_member_set_pluginname(debug->member2, "mock-sync-foo"); - path = g_strdup_printf("%s/configs/group/2", testbed); - osync_member_set_configdir(debug->member2, path); - g_free(path); - - OSyncPluginConfig *config2 = simple_plugin_config(NULL, "data2", "mockobjtype1", "mockformat1", NULL); - osync_member_set_config(debug->member2, config2); - osync_plugin_config_unref(config2); - - - debug->plugin = osync_plugin_new(&error); - fail_unless(debug->plugin != NULL, NULL); - fail_unless(error == NULL, NULL); - - osync_plugin_set_name(debug->plugin, "mock-sync-foo"); - osync_plugin_set_longname(debug->plugin, "Mock Sync Plugin"); - osync_plugin_set_description(debug->plugin, "This is a pseudo plugin"); - osync_plugin_set_start_type(debug->plugin, OSYNC_START_TYPE_THREAD); - osync_plugin_set_config_type(debug->plugin, OSYNC_PLUGIN_NO_CONFIGURATION); - - osync_plugin_set_initialize(debug->plugin, initialize); - osync_plugin_set_finalize(debug->plugin, finalize); - - return debug; -} - static OSyncDebugGroup *_create_group5(char *testbed) { OSyncDebugGroup *debug = g_malloc0(sizeof(OSyncDebugGroup)); @@ -538,14 +274,17 @@ START_TEST (engine_error_single_init_error) { - char *testbed = setup_testbed("sync_setup"); + char *testbed = setup_testbed("sync"); char *formatdir = g_strdup_printf("%s/formats", testbed); char *plugindir = g_strdup_printf("%s/plugins", testbed); - + OSyncError *error = NULL; - OSyncDebugGroup *debug = _create_group(testbed); - - OSyncEngine *engine = osync_engine_new(debug->group, &error); + OSyncGroup *group = osync_group_new(&error); + osync_group_set_schemadir(group, testbed); + osync_group_load(group, "configs/group", &error); + fail_unless(error == NULL, NULL); + + OSyncEngine *engine = osync_engine_new(group, &error); fail_unless(engine != NULL, NULL); fail_unless(error == NULL, NULL); @@ -553,20 +292,21 @@ osync_engine_set_plugindir(engine, plugindir); osync_engine_set_formatdir(engine, formatdir); - _engine_instrument_pluginenv(engine, debug); + /* This will trigger an error in the mock-sync plugin of member 2 */ + /* in the initialize function */ + g_setenv("INIT_NULL", "2", TRUE); fail_unless(!osync_engine_initialize(engine, &error), NULL); fail_unless(error != NULL, NULL); + fail_unless(strcmp("Triggering INIT_NULL error", osync_error_print(&error)) == 0, NULL); osync_error_unref(&error); fail_unless(!synchronize_once(engine, &error), NULL); fail_unless(error != NULL, NULL); osync_error_unref(&error); - _free_group(debug); - osync_engine_unref(engine); - + osync_group_unref(group); g_free(formatdir); g_free(plugindir); @@ -576,35 +316,39 @@ START_TEST (engine_error_double_init_error) { - char *testbed = setup_testbed("sync_setup"); + char *testbed = setup_testbed("sync"); char *formatdir = g_strdup_printf("%s/formats", testbed); char *plugindir = g_strdup_printf("%s/plugins", testbed); - + OSyncError *error = NULL; - OSyncDebugGroup *debug = _create_group2(testbed); - - OSyncEngine *engine = osync_engine_new(debug->group, &error); + OSyncGroup *group = osync_group_new(&error); + osync_group_set_schemadir(group, testbed); + osync_group_load(group, "configs/group", &error); + fail_unless(error == NULL, NULL); + + OSyncEngine *engine = osync_engine_new(group, &error); fail_unless(engine != NULL, NULL); fail_unless(error == NULL, NULL); - + osync_engine_set_schemadir(engine, testbed); osync_engine_set_plugindir(engine, plugindir); osync_engine_set_formatdir(engine, formatdir); - - _engine_instrument_pluginenv(engine, debug); + /* This triggers an error in plugin 1 and 2 */ + g_setenv("INIT_NULL", "3", TRUE); + fail_unless(!osync_engine_initialize(engine, &error), NULL); fail_unless(error != NULL, NULL); + if (error) + fail_unless(strcmp("Triggering INIT_NULL error", osync_error_print(&error)) == 0, NULL); osync_error_unref(&error); fail_unless(!synchronize_once(engine, &error), NULL); fail_unless(error != NULL, NULL); osync_error_unref(&error); - _free_group(debug); - osync_engine_unref(engine); - + osync_group_unref(group); g_free(formatdir); g_free(plugindir); @@ -614,14 +358,19 @@ START_TEST (engine_error_no_config_error) { - char *testbed = setup_testbed("sync_setup"); + char *testbed = setup_testbed("sync"); char *formatdir = g_strdup_printf("%s/formats", testbed); char *plugindir = g_strdup_printf("%s/plugins", testbed); - + + fail_unless(g_unlink("configs/group/2/mock-sync.conf") == 0, NULL); + OSyncError *error = NULL; - OSyncDebugGroup *debug = _create_group3(testbed); - - OSyncEngine *engine = osync_engine_new(debug->group, &error); + OSyncGroup *group = osync_group_new(&error); + osync_group_set_schemadir(group, testbed); + osync_group_load(group, "configs/group", &error); + fail_unless(error == NULL, NULL); + + OSyncEngine *engine = osync_engine_new(group, &error); fail_unless(engine != NULL, NULL); fail_unless(error == NULL, NULL); @@ -629,20 +378,18 @@ osync_engine_set_plugindir(engine, plugindir); osync_engine_set_formatdir(engine, formatdir); - _engine_instrument_pluginenv(engine, debug); - fail_unless(!osync_engine_initialize(engine, &error), NULL); fail_unless(error != NULL, NULL); + if (error) + fail_unless(strcmp("Plugin is not configured", osync_error_print(&error)) == 0, NULL); osync_error_unref(&error); fail_unless(!synchronize_once(engine, &error), NULL); fail_unless(error != NULL, NULL); osync_error_unref(&error); - _free_group(debug); - osync_engine_unref(engine); - + osync_group_unref(group); g_free(formatdir); g_free(plugindir); @@ -650,37 +397,41 @@ } END_TEST + START_TEST (engine_error_no_objtype_error) { - char *testbed = setup_testbed("sync_setup"); + char *testbed = setup_testbed("sync"); char *formatdir = g_strdup_printf("%s/formats", testbed); char *plugindir = g_strdup_printf("%s/plugins", testbed); - + + fail_unless(g_unlink("configs/group/1/mock-sync.conf") == 0, NULL); + fail_unless(g_rename("configs/group/1/mock-sync.no-objtype-error.conf", + "configs/group/1/mock-sync.conf") == 0, NULL); + OSyncError *error = NULL; - OSyncDebugGroup *debug = _create_group4(testbed); - - OSyncEngine *engine = osync_engine_new(debug->group, &error); + OSyncGroup *group = osync_group_new(&error); + osync_group_set_schemadir(group, testbed); + osync_group_load(group, "configs/group", &error); + fail_unless(error == NULL, NULL); + + OSyncEngine *engine = osync_engine_new(group, &error); fail_unless(engine != NULL, NULL); fail_unless(error == NULL, NULL); osync_engine_set_schemadir(engine, testbed); osync_engine_set_plugindir(engine, plugindir); osync_engine_set_formatdir(engine, formatdir); - - _engine_instrument_pluginenv(engine, debug); - fail_unless(!osync_engine_initialize(engine, &error), NULL); - fail_unless(error != NULL, NULL); + fail_unless(osync_engine_initialize(engine, &error), NULL); + fail_unless(error == NULL, NULL); osync_error_unref(&error); fail_unless(!synchronize_once(engine, &error), NULL); fail_unless(error != NULL, NULL); osync_error_unref(&error); - _free_group(debug); - osync_engine_unref(engine); - + osync_group_unref(group); g_free(formatdir); g_free(plugindir); |
From: <dg...@su...> - 2009-02-04 00:59:14
|
Author: Graham Cobb Date: Wed Feb 4 01:57:21 2009 New Revision: 5259 URL: http://www.opensync.org/changeset/5259 Log: gpe-sync: fix valgrind problems Modified: plugins/gpe/ChangeLog plugins/gpe/src/utils.c Modified: plugins/gpe/ChangeLog ============================================================================== --- plugins/gpe/ChangeLog Tue Feb 3 20:54:04 2009 (r5258) +++ plugins/gpe/ChangeLog Wed Feb 4 01:57:21 2009 (r5259) @@ -1,3 +1,8 @@ +2009-02-04 Graham Cobb <g+...@co...> + + * src/utils.c (report_change): Include NUL terminator in change data + (report_change): Fix osync_trace format + 2009-01-17 Graham Cobb <g+...@co...> * src/utils.c (report_deleted): Fix end condition for uids loop Modified: plugins/gpe/src/utils.c ============================================================================== --- plugins/gpe/src/utils.c Tue Feb 3 20:54:04 2009 (r5258) +++ plugins/gpe/src/utils.c Wed Feb 4 01:57:21 2009 (r5259) @@ -78,12 +78,12 @@ */ osync_bool report_change (sink_environment *sinkenv, OSyncContext *ctx, gchar *type, gchar *uid, gchar *hash, char *string) { - osync_trace(TRACE_ENTRY, "GPE-SYNC %s(%p, %p, %p, %p, %p, %p, %p)", __func__, sinkenv, ctx, type, uid, hash, string); + osync_trace(TRACE_ENTRY, "GPE-SYNC %s(%p, %p, %p, %p, %p, %p)", __func__, sinkenv, ctx, type, uid, hash, string); osync_trace(TRACE_SENSITIVE, "GPE-SYNC %s: reporting item type = %s, uid = %s, hash = %s, string = %s", __func__, type, uid, hash, string); OSyncError *error = NULL; - OSyncData *data = osync_data_new(string, strlen(string), sinkenv->objformat, &error); + OSyncData *data = osync_data_new(string, strlen(string)+1, sinkenv->objformat, &error); if (!data) { osync_context_report_osyncwarning(ctx, error); osync_error_unref(&error); |
From: <dg...@su...> - 2009-02-03 19:55:48
|
Author: Graham Cobb Date: Tue Feb 3 20:54:04 2009 New Revision: 5258 URL: http://www.opensync.org/changeset/5258 Log: Timeout merge complete This commit is just to tidy up attributes Modified: trunk/ (props changed) trunk/tests/data/sync_mixed_objtype/ (props changed) |
From: <dg...@su...> - 2009-02-03 19:50:07
|
Author: Graham Cobb Date: Tue Feb 3 20:48:24 2009 New Revision: 5257 URL: http://www.opensync.org/changeset/5257 Log: Timeout merge #3: 6) Implement a mechanism to protect the queue itself: i.e. is the receiver still reading the queue? 4) Handle timeout before reply queue set up by generating an error message on the command queue Modified: trunk/ChangeLog trunk/opensync/ipc/opensync_queue.c trunk/opensync/ipc/opensync_queue_private.h trunk/tests/CMakeLists.txt trunk/tests/ipc-tests/check_ipc.c Modified: trunk/ChangeLog ============================================================================== --- trunk/ChangeLog Tue Feb 3 20:35:06 2009 (r5256) +++ trunk/ChangeLog Tue Feb 3 20:48:24 2009 (r5257) @@ -1,5 +1,59 @@ +2009-02-03 Graham Cobb <g+...@co...> + + * tests/ipc-tests/check_ipc.c (ipc_loop_timeout_with_idle): Change test parameters + so test completes within 30 second limit. + +2009-02-02 Graham Cobb <g+...@co...> + + * opensync/ipc/opensync_queue_private.h (OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT): Define + minimum pending queue timeout. + + * opensync/ipc/opensync_queue.c (_osync_queue_restart_pending_timeout): Apply + minimum value to pending queue timeout. + +2009-02-01 Graham Cobb <g+...@co...> + + * tests/ipc-tests/check_ipc.c: Add ipc_timeout_noreceiver test. + + * opensync/ipc/opensync_queue.c (osync_queue_send_message_with_timeout): Track maximum + timeout seen. Start pending queue timeout. + (_osync_queue_remove_pending_reply): restart pending queue timeout if necessary + (_osync_queue_restart_pending_timeout): Add function to start/restart pending queue timeout + (_timeout_check): Fix calculation of expiry of timeout. Add pending queue timeout. + (_timeout_dispatch): Fix calculation of expiry of timeout. Add pending queue timeout. + + * opensync/ipc/opensync_queue_private.h: Add max_timeout and pending_timeout fields (to queue). + (OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY): Add value to assume for IPC delay in pending queue timout. + +2009-01-25 Graham Cobb <g+...@co...> + + * opensync/engine/opensync_sink_engine.c (osync_sink_engine_new): Ref objengine [Bug #1052] + (osync_sink_engine_unref): Unref objengine [Bug #1052] + + * opensync/engine/opensync_obj_engine.c (_osync_obj_engine_*_callback): Unref sinkengine [Bug #1052] + (osync_obj_engine_command): Ref sinkengine every time it is used for a callback [Bug #1052] + + * opensync/ipc/opensync_queue.c (osync_queue_disconnect): Empty pending + queue before performing disconnect. Pending messages with callbacks + will get called with an error message. + (_incoming_check): Do not action incoming queue if a disconnect is in progress. + This avoids entries being added to pending queue while we are trying to empty it. + (osync_queue_send_message_with_timeout): Do not allow sending messages which require + adding entries to the reply queue pending list if the reply queue is being disconnected. + + * opensync/ipc/opensync_queue_private.h: Add disc_in_progress flag to queue. + 2009-01-24 Graham Cobb <g+...@co...> + * opensync/ipc/opensync_queue.c (_osync_queue_generate_error): Add + _osync_queue_generate_error + (_osync_send_timeout_response): If there is no reply queue, + call _osync_queue_generate_error + + * tests/CMakeLists.txt: Add ipc_timeout_noreplyq + + * tests/ipc-tests/check_ipc.c: Add ipc_timeout_noreplyq + * opensync/ipc/opensync_queue.c (osync_queue_remove_cross_link): Add osync_queue_remove_cross_link (osync_queue_disconnect): Call osync_queue_remove_cross_link Modified: trunk/opensync/ipc/opensync_queue.c ============================================================================== --- trunk/opensync/ipc/opensync_queue.c Tue Feb 3 20:35:06 2009 (r5256) +++ trunk/opensync/ipc/opensync_queue.c Tue Feb 3 20:48:24 2009 (r5257) @@ -29,6 +29,30 @@ #include "opensync_queue_internals.h" #include "opensync_queue_private.h" +static gboolean _osync_queue_generate_error(OSyncQueue *queue, OSyncMessageCommand errcode, OSyncError **error) +{ + OSyncMessage *message; + + queue->connected = FALSE; + + /* Now we can send the hup message, and wake up the consumer thread so + * it can pickup the messages in the incoming queue */ + message = osync_message_new(errcode, 0, error); + if (!message) { + return FALSE; + } + osync_trace(TRACE_INTERNAL, "Generating incoming error message %p(%s), id= %lli", message, osync_message_get_commandstr(message), osync_message_get_id(message)); + + osync_message_ref(message); + + g_async_queue_push(queue->incoming, message); + + if (queue->incomingContext) + g_main_context_wakeup(queue->incomingContext); + + return TRUE; +} + static gboolean _timeout_prepare(GSource *source, gint *timeout_) { /* TODO adapt *timeout_ value to shortest message timeout value... @@ -55,6 +79,16 @@ * list since another thread might be duing the updates */ g_mutex_lock(queue->pendingLock); + /* First check the overall queue timer */ + if (queue->pendingCount> 0 && queue->pending_timeout.tv_sec > 0) { + if (current_time.tv_sec > queue->pending_timeout.tv_sec + || (current_time.tv_sec == queue->pending_timeout.tv_sec + && current_time.tv_usec >= queue->pending_timeout.tv_usec) ) { + g_mutex_unlock(queue->pendingLock); + return TRUE; + } + } + for (p = queue->pendingReplies; p; p = p->next) { pending = p->data; @@ -63,7 +97,7 @@ toinfo = pending->timeout_info; - if (current_time.tv_sec >= toinfo->expiration.tv_sec + if (current_time.tv_sec > toinfo->expiration.tv_sec || (current_time.tv_sec == toinfo->expiration.tv_sec && current_time.tv_usec >= toinfo->expiration.tv_usec)) { /* Unlock the pending lock since the messages might be sent during the callback */ @@ -96,6 +130,18 @@ * list since another thread might be duing the updates */ g_mutex_lock(queue->pendingLock); + /* First check the overall queue timer */ + if (queue->pendingCount> 0 && queue->pending_timeout.tv_sec > 0) { + if (current_time.tv_sec > queue->pending_timeout.tv_sec + || (current_time.tv_sec == queue->pending_timeout.tv_sec + && current_time.tv_usec >= queue->pending_timeout.tv_usec) ) { + /* The queue has died. Generate an error */ + osync_trace(TRACE_INTERNAL, "%s: Pending queue timer expired: receiver must have died", __func__); + _osync_queue_generate_error(queue, OSYNC_MESSAGE_QUEUE_ERROR, NULL); + queue->pending_timeout.tv_sec = 0; // Stop timer + } + } + for (p = queue->pendingReplies; p; p = p->next) { pending = p->data; @@ -104,8 +150,8 @@ toinfo = pending->timeout_info; - if (current_time.tv_sec == toinfo->expiration.tv_sec || - (current_time.tv_sec >= toinfo->expiration.tv_sec + if (current_time.tv_sec > toinfo->expiration.tv_sec || + (current_time.tv_sec == toinfo->expiration.tv_sec && current_time.tv_usec >= toinfo->expiration.tv_usec)) { OSyncError *error = NULL; OSyncError *timeouterr = NULL; @@ -175,7 +221,8 @@ if (g_async_queue_length(queue->incoming) > 0 && (queue->pendingLimit == 0 - || queue->pendingCount < queue->pendingLimit) ) + || queue->pendingCount < queue->pendingLimit) + && !queue->disc_in_progress ) return TRUE; return FALSE; @@ -191,15 +238,45 @@ osync_queue_send_message_with_timeout(queue->reply_queue, NULL, errormsg, 0, NULL); } else { osync_message_unref(errormsg); - /* TODO: as we can't send the timeout response, disconnect the queue to signal to - the sender that they aren't going to get a response. Note: we can't just - call osync_queue_disconnect as that tries to kill the thread and hits a deadlock! */ + /* As we can't send the timeout response, create an error and drop it in the incoming queue + so the higher layer will disconnect. Note: we can't just call osync_queue_disconnect + as that tries to kill the thread and hits a deadlock! */ + if (!_osync_queue_generate_error(queue, OSYNC_MESSAGE_QUEUE_ERROR, NULL)) { + osync_trace(TRACE_EXIT_ERROR, "%s: cannot even generate error on incoming queue", __func__); + return; + } osync_trace(TRACE_EXIT_ERROR, "%s: cannot find reply queue to send timeout error", __func__); return; } osync_trace(TRACE_EXIT, "%s", __func__); } +/* Restart the pending queue timeout */ +static void _osync_queue_restart_pending_timeout(OSyncQueue *queue) +{ + /* Note that the pending queue timeout is just to make sure that progress is being made. + It does not time individual commands -- it just makes sure that responses are being + received for outstanding commands at some rate. Individual message timeouts are + handled at the receiver. The main purpose of this timer is to detect if the + receiver has stopped receiving for some reason. + + The timer is started when the first message is put on the pending queue and is reset + and restarted whenever a response is received. The timeout value is based on the + largest message timeout seen to date. */ + + /* Note: queue->pending_timout is protected by the pending lock, which should be held + by the caller before calling this function */ + + if (queue->max_timeout) { + unsigned int timeout; + timeout = queue->max_timeout + OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY; + if (timeout < OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT) + timeout = OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT; + g_source_get_current_time(queue->timeout_source, &queue->pending_timeout); + queue->pending_timeout.tv_sec += timeout; + } +} + /* Find and remove a pending message that this message is a reply to */ static void _osync_queue_remove_pending_reply(OSyncQueue *queue, OSyncMessage *reply, gboolean callback) { @@ -226,7 +303,8 @@ gets called twice! */ queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); - queue->pendingCount--; + if (--queue->pendingCount != 0) + _osync_queue_restart_pending_timeout(queue); /* Unlock the pending lock since the messages might be sent during the callback */ g_mutex_unlock(queue->pendingLock); @@ -271,7 +349,7 @@ osync_message_get_timeout(message), osync_message_get_id(message)); if (osync_message_get_cmd(message) == OSYNC_MESSAGE_REPLY || osync_message_get_cmd(message) == OSYNC_MESSAGE_ERRORREPLY) { - /* Remove pending reply and call callback */ + /* Remove pending reply and call callback*/ _osync_queue_remove_pending_reply(queue, message, TRUE); } else { unsigned int timeout = osync_message_get_timeout(message); @@ -570,18 +648,8 @@ return TRUE; case OSYNC_QUEUE_EVENT_HUP: case OSYNC_QUEUE_EVENT_ERROR: - queue->connected = FALSE; - - /* Now we can send the hup message, and wake up the consumer thread so - * it can pickup the messages in the incoming queue */ - message = osync_message_new(OSYNC_MESSAGE_QUEUE_HUP, 0, &error); - if (!message) + if (!_osync_queue_generate_error(queue, OSYNC_MESSAGE_QUEUE_HUP, &error)) goto error; - - g_async_queue_push(queue->incoming, message); - - if (queue->incomingContext) - g_main_context_wakeup(queue->incomingContext); return FALSE; } @@ -1000,6 +1068,52 @@ osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, queue, error); osync_assert(queue); + /* Before doing the real disconnect, we empty the pending queue by creating HUP + errors for anything on it. In order to make sure it empties, the disconnect + is marked as in progress so that no more entries get put on it (e.g. if a + callback tries to send another message). */ + + g_mutex_lock(queue->pendingLock); + + queue->disc_in_progress = TRUE; + + while (queue->pendingCount > 0) { + OSyncPendingMessage *pending = queue->pendingReplies->data; + OSyncError *error = NULL; + OSyncError *huperr = NULL; + OSyncMessage *errormsg = NULL; + + queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); + queue->pendingCount--; + + /* Call the callback of the pending message */ + if (pending->callback) { + osync_error_set(&huperr, OSYNC_ERROR_IO_ERROR, "Disconnect."); + errormsg = osync_message_new_errorreply(NULL, huperr, &error); + osync_error_unref(&huperr); + osync_message_set_id(errormsg, pending->id); + + /* Unlock the pending lock during the callback */ + g_mutex_unlock(queue->pendingLock); + + osync_trace(TRACE_INTERNAL, "%s: Reporting disconnect error for message %lli", __func__, pending->id); + + pending->callback(errormsg, pending->user_data); + if (errormsg != NULL) + osync_message_unref(errormsg); + + /* Lock again */ + g_mutex_lock(queue->pendingLock); + } + + // TODO: Refcounting for OSyncPendingMessage + if (pending->timeout_info) + g_free(pending->timeout_info); + + osync_free(pending); + } + g_mutex_unlock(queue->pendingLock); + osync_queue_remove_cross_link(queue); g_mutex_lock(queue->disconnectLock); @@ -1038,6 +1152,10 @@ queue->fd = -1; queue->connected = FALSE; g_mutex_unlock(queue->disconnectLock); + + g_mutex_lock(queue->pendingLock); + queue->disc_in_progress = FALSE; + g_mutex_unlock(queue->pendingLock); osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; @@ -1221,6 +1339,13 @@ GTimeVal current_time; long long int id = 0; osync_assert(replyqueue); + + g_mutex_lock(replyqueue->pendingLock); + if (replyqueue->disc_in_progress) { + osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Disconnect in progress."); + goto error; + } + pending = osync_try_malloc0(sizeof(OSyncPendingMessage), error); if (!pending) goto error; @@ -1236,6 +1361,9 @@ if (timeout) { /* Send timeout info to other end to handle */ osync_message_set_timeout(message, timeout); + /* Note largest timeout seen */ + if (timeout > replyqueue->max_timeout) + replyqueue->max_timeout = timeout; } else { osync_trace(TRACE_INTERNAL, "handler message got sent without timeout!: %s", osync_message_get_commandstr(message)); } @@ -1243,9 +1371,11 @@ pending->callback = osync_message_get_handler(message); pending->user_data = osync_message_get_handler_data(message); - g_mutex_lock(replyqueue->pendingLock); replyqueue->pendingReplies = osync_list_append(replyqueue->pendingReplies, pending); - replyqueue->pendingCount++; + if (replyqueue->pendingCount++ == 0) { + /* Start queue timeout */ + _osync_queue_restart_pending_timeout(replyqueue); + } g_mutex_unlock(replyqueue->pendingLock); } Modified: trunk/opensync/ipc/opensync_queue_private.h ============================================================================== --- trunk/opensync/ipc/opensync_queue_private.h Tue Feb 3 20:35:06 2009 (r5256) +++ trunk/opensync/ipc/opensync_queue_private.h Tue Feb 3 20:48:24 2009 (r5257) @@ -96,8 +96,24 @@ /* Queue for receiving commands we are replying to */ OSyncQueue *cmd_queue; + + /* Disconnect in progress */ + gboolean disc_in_progress; + + /* Largest timeout value seen so far */ + unsigned int max_timeout; + + /* Expiration time of pending queue timeout */ + GTimeVal pending_timeout; }; +/** @brief Pending queue timeout addition for ipc delay + */ +#define OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY 1 + +/** @brief Pending queue minimum timeout + */ +#define OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT 20 /** @brief Timeout object */ Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Tue Feb 3 20:35:06 2009 (r5256) +++ trunk/tests/CMakeLists.txt Tue Feb 3 20:48:24 2009 (r5257) @@ -249,6 +249,8 @@ OSYNC_TESTCASE(ipc ipc_loop_with_timeout) OSYNC_TESTCASE(ipc ipc_late_reply) OSYNC_TESTCASE(ipc ipc_loop_timeout_with_idle) +OSYNC_TESTCASE(ipc ipc_timeout_noreplyq) +OSYNC_TESTCASE(ipc ipc_timeout_noreceiver) ENDIF (NOT WIN32) BUILD_CHECK_TEST( mapping mapping-tests/check_mapping.c ${TEST_TARGET_LIBRARIES} ) Modified: trunk/tests/ipc-tests/check_ipc.c ============================================================================== --- trunk/tests/ipc-tests/check_ipc.c Tue Feb 3 20:35:06 2009 (r5256) +++ trunk/tests/ipc-tests/check_ipc.c Tue Feb 3 20:48:24 2009 (r5257) @@ -2089,10 +2089,13 @@ static void _message_handler(OSyncMessage *message, void *user_data) { + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); + osync_trace(TRACE_INTERNAL, "%s",osync_message_get_commandstr(message)); if (osync_message_is_error(message)) num_callback_timeout++; else num_callback++; + osync_trace(TRACE_EXIT, "%s", __func__); } char *data5 = "this is another test string"; @@ -2664,11 +2667,12 @@ /* Same as ipc_loop_with_timeout except that the client handler doesn't sleep, so the queue dispatchers can run while the operation is waiting. - Even though each action takes 1 second, none of these messages should time out - as they are being sent with a timeout of 3 seconds */ + Even though each action takes 1 second, and might be delayed by 3 seconds + due to the messages already processed on the pending queue, none of these + messages should time out as they are being sent with a timeout of 5 seconds */ num_msgs = 0; - req_msgs = 30; + req_msgs = 10; char *testbed = setup_testbed(NULL); osync_testing_file_remove("/tmp/testpipe-server"); @@ -2693,7 +2697,8 @@ OSyncThread *thread = osync_thread_new(context, &error); osync_queue_set_message_handler(client_queue, client_handler_first_part, GINT_TO_POINTER(1)); - osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); + // Set pending limit to 3 so response wil be delayed at most 3 seconds + osync_queue_set_pending_limit(client_queue, 3); osync_queue_setup_with_gmainloop(client_queue, context); @@ -2765,7 +2770,8 @@ osync_message_set_handler(message, callback_handler_check_reply, GINT_TO_POINTER(1)); - fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 10, &error), NULL); + // Timeout of 5 will do as pending limit is 3 + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 5, &error), NULL); fail_unless(!osync_error_is_set(&error), NULL); osync_message_unref(message); @@ -2803,6 +2809,321 @@ } END_TEST +void client_handler6(OSyncMessage *message, void *user_data) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); + OSyncError *error = NULL; + + osync_assert(GPOINTER_TO_INT(user_data) ==1); + + if (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_ERROR) { + osync_queue_disconnect(client_queue, NULL); + osync_trace(TRACE_EXIT, "%s: disconnect", __func__); + return; + } + + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_INITIALIZE); + + int int1; + long long int longint1; + char *string; + char databuf[strlen(data5) + 1]; + + osync_message_read_int(message, &int1); + osync_message_read_string(message, &string); + osync_message_read_long_long_int(message, &longint1); + osync_message_read_data(message, databuf, strlen(data5) + 1); + + osync_assert(int1 == 4000000); + osync_assert(!strcmp(string, "this is a test string")); + osync_assert(longint1 == 400000000); + osync_assert(!strcmp(databuf, data5)); + + /* TIMEOUT TIMEOUT TIMEOUT (no reply...) */ + + /* Proper code would reply to this message, but for testing + purposes we don't reply and simulate a "timeout" situation */ + + osync_trace(TRACE_EXIT, "%s", __func__); +} +START_TEST (ipc_timeout_noreplyq) +{ + /* This testcase is inteded to test timeout before the command and reply queues are cross-linked. + Client got forked and listens for messages from Server and replies. + + To simulate a "timeout" situation the Client doesn't reply to one of the Server messages. + + As there is no reply queue, an error will be sent to the **client**, who then disconnects + so an error (although not a timeout) ends up sent to the server. + */ + + char *testbed = setup_testbed(NULL); + osync_testing_file_remove("/tmp/testpipe-server"); + osync_testing_file_remove("/tmp/testpipe-client"); + + num_callback_timeout = 0; + num_callback = 0; + + OSyncError *error = NULL; + server_queue = osync_queue_new("/tmp/testpipe-server", &error); + client_queue = osync_queue_new("/tmp/testpipe-client", &error); + OSyncMessage *message = NULL; + + osync_queue_create(server_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_create(client_queue, &error); + fail_unless(error == NULL, NULL); + + pid_t cpid = fork(); + if (cpid == 0) { //Child + + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(client_queue, client_handler6, GINT_TO_POINTER(1)); + osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); + + osync_queue_setup_with_gmainloop(client_queue, context); + + osync_thread_start(thread); + + osync_assert(osync_queue_connect(client_queue, OSYNC_QUEUE_RECEIVER, &error)); + osync_assert(error == NULL); + + osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); + osync_assert(error == NULL); + + /* Do not cross-link */ + /*osync_queue_cross_link(client_queue, server_queue);*/ + + message = osync_queue_get_message(server_queue); + + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP); + + osync_message_unref(message); + + if (osync_queue_disconnect(server_queue, &error) != TRUE || error != NULL) + exit(1); + osync_queue_unref(server_queue); + + osync_assert(osync_queue_disconnect(client_queue, &error)); + osync_assert(error == NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + osync_queue_unref(client_queue); + + g_free(testbed); + + exit(0); + } else { + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(server_queue, server_handler4, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(server_queue, context); + + osync_thread_start(thread); + + fail_unless(osync_queue_connect(client_queue, OSYNC_QUEUE_SENDER, &error), NULL); + fail_unless(error == NULL, NULL); + + fail_unless(osync_queue_connect(server_queue, OSYNC_QUEUE_RECEIVER, &error), NULL); + fail_unless(error == NULL, NULL); + + message = osync_message_new(OSYNC_MESSAGE_INITIALIZE, 0, &error); + fail_unless(message != NULL, NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_set_handler(message, _message_handler, NULL); + + osync_message_write_int(message, 4000000); + osync_message_write_string(message, "this is a test string"); + osync_message_write_long_long_int(message, 400000000); + osync_message_write_data(message, data5, strlen(data5) + 1); + + // Send with timeout of one second + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 1, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_unref(message); + + while (!(message = osync_queue_get_message(client_queue))) { + g_usleep(10000); + } + + fail_unless(osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP); + osync_message_unref(message); + + osync_queue_disconnect(client_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_disconnect(server_queue, &error); + fail_unless(error == NULL, NULL); + + int status = 0; + wait(&status); + fail_unless(WEXITSTATUS(status) == 0, NULL); + } + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == TRUE, NULL); + + fail_unless(osync_queue_remove(client_queue, &error), NULL); + fail_unless(osync_queue_remove(server_queue, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + /* Check if the timeout handler replied with an error */ + fail_unless(num_callback_timeout == 1, NULL); + fail_unless(num_callback == 0, NULL); + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == FALSE, NULL); + + osync_queue_unref(client_queue); + osync_queue_unref(server_queue); + + destroy_testbed(testbed); +} +END_TEST + +START_TEST (ipc_timeout_noreceiver) +{ + /* This testcase is intended to test the case where the receiver is not even listening, + and so does not run the timeout. + */ + + char *testbed = setup_testbed(NULL); + osync_testing_file_remove("/tmp/testpipe-server"); + osync_testing_file_remove("/tmp/testpipe-client"); + + num_callback_timeout = 0; + num_callback = 0; + + OSyncError *error = NULL; + server_queue = osync_queue_new("/tmp/testpipe-server", &error); + client_queue = osync_queue_new("/tmp/testpipe-client", &error); + OSyncMessage *message = NULL; + + osync_queue_create(server_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_create(client_queue, &error); + fail_unless(error == NULL, NULL); + + pid_t cpid = fork(); + if (cpid == 0) { //Child + + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(client_queue, client_handler1, GINT_TO_POINTER(1)); + osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); + + /* Do not start receiver */ + /* osync_queue_setup_with_gmainloop(client_queue, context); */ + + osync_thread_start(thread); + + osync_assert(osync_queue_connect(client_queue, OSYNC_QUEUE_RECEIVER, &error)); + osync_assert(error == NULL); + + osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); + osync_assert(error == NULL); + + /* Do not cross-link */ + osync_queue_cross_link(client_queue, server_queue); + + message = osync_queue_get_message(server_queue); + + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP); + + osync_message_unref(message); + + if (osync_queue_disconnect(server_queue, &error) != TRUE || error != NULL) + exit(1); + osync_queue_unref(server_queue); + + osync_assert(osync_queue_disconnect(client_queue, &error)); + osync_assert(error == NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + osync_queue_unref(client_queue); + + g_free(testbed); + + exit(0); + } else { + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(server_queue, server_handler4, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(server_queue, context); + + osync_thread_start(thread); + + fail_unless(osync_queue_connect(client_queue, OSYNC_QUEUE_SENDER, &error), NULL); + fail_unless(error == NULL, NULL); + + fail_unless(osync_queue_connect(server_queue, OSYNC_QUEUE_RECEIVER, &error), NULL); + fail_unless(error == NULL, NULL); + + message = osync_message_new(OSYNC_MESSAGE_INITIALIZE, 0, &error); + fail_unless(message != NULL, NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_set_handler(message, _message_handler, NULL); + + osync_message_write_int(message, 4000000); + osync_message_write_string(message, "this is a test string"); + osync_message_write_long_long_int(message, 400000000); + osync_message_write_data(message, data5, strlen(data5) + 1); + + // Send with timeout of one second + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 1, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_unref(message); + + /* Note: OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT is 20 */ + g_usleep(25*G_USEC_PER_SEC); + + /* Check if the timeout handler replied with an error. + Note: it is important we check **before** we start disconnecting + otherwise we are not testing the right thing */ + fail_unless(num_callback_timeout == 1, NULL); + fail_unless(num_callback == 0, NULL); + + osync_queue_disconnect(client_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_disconnect(server_queue, &error); + fail_unless(error == NULL, NULL); + + int status = 0; + wait(&status); + fail_unless(WEXITSTATUS(status) == 0, NULL); + } + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == TRUE, NULL); + + fail_unless(osync_queue_remove(client_queue, &error), NULL); + fail_unless(osync_queue_remove(server_queue, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == FALSE, NULL); + + osync_queue_unref(client_queue); + osync_queue_unref(server_queue); + + destroy_testbed(testbed); +} +END_TEST + OSYNC_TESTCASE_START("ipc") OSYNC_TESTCASE_ADD(ipc_new) OSYNC_TESTCASE_ADD(ipc_ref) @@ -2832,5 +3153,7 @@ OSYNC_TESTCASE_ADD(ipc_late_reply) OSYNC_TESTCASE_ADD(ipc_loop_with_timeout) OSYNC_TESTCASE_ADD(ipc_loop_timeout_with_idle) +OSYNC_TESTCASE_ADD(ipc_timeout_noreplyq) +OSYNC_TESTCASE_ADD(ipc_timeout_noreceiver) OSYNC_TESTCASE_END |
From: <dg...@su...> - 2009-02-03 19:36:47
|
Author: Graham Cobb Date: Tue Feb 3 20:35:06 2009 New Revision: 5256 URL: http://www.opensync.org/changeset/5256 Log: Bug #1052: add refs in obj_engine and sink_engine Modified: trunk/opensync/engine/opensync_obj_engine.c trunk/opensync/engine/opensync_sink_engine.c Modified: trunk/opensync/engine/opensync_obj_engine.c ============================================================================== --- trunk/opensync/engine/opensync_obj_engine.c Tue Feb 3 20:26:06 2009 (r5255) +++ trunk/opensync/engine/opensync_obj_engine.c Tue Feb 3 20:35:06 2009 (r5256) @@ -118,6 +118,7 @@ } else osync_trace(TRACE_INTERNAL, "Not yet: %i", osync_bitcount(engine->sink_errors | engine->sink_connects)); + osync_sink_engine_unref(sinkengine); osync_trace(TRACE_EXIT, "%s", __func__); } @@ -148,6 +149,7 @@ } else osync_trace(TRACE_INTERNAL, "Not yet: %i", osync_bitcount(engine->sink_errors | engine->sink_connect_done)); + osync_sink_engine_unref(sinkengine); osync_trace(TRACE_EXIT, "%s", __func__); } @@ -191,6 +193,8 @@ _osync_obj_engine_generate_event_disconnected(engine, error); + osync_sink_engine_unref(sinkengine); + osync_trace(TRACE_EXIT, "%s", __func__); } @@ -322,9 +326,12 @@ static void _osync_obj_engine_read_ignored_callback(OSyncClientProxy *proxy, void *userdata, OSyncError *error) { + OSyncSinkEngine *sinkengine = userdata; + OSyncObjEngine *engine = sinkengine->engine; /* TODO: Share _generate_read_event fucntion with _osync_obj_engine_read_callback? To report errors .. and handle _timeout problems of _read_ignored call. */ + osync_sink_engine_unref(sinkengine); } @@ -356,6 +363,7 @@ } else osync_trace(TRACE_INTERNAL, "Not yet: %i", osync_bitcount(engine->sink_errors | engine->sink_get_changes)); + osync_sink_engine_unref(sinkengine); osync_trace(TRACE_EXIT, "%s", __func__); } @@ -582,6 +590,7 @@ } else osync_trace(TRACE_INTERNAL, "Not yet: %i", osync_bitcount(engine->sink_errors | engine->sink_sync_done)); + osync_sink_engine_unref(sinkengine); osync_trace(TRACE_EXIT, "%s", __func__); } @@ -920,6 +929,7 @@ if (!osync_client_proxy_connect(sinkengine->proxy, _osync_obj_engine_connect_callback, sinkengine, engine->objtype, engine->slowsync, error)) goto error; + osync_sink_engine_ref(sinkengine); // Note that connect callback has a reference } break; case OSYNC_ENGINE_COMMAND_CONNECT_DONE: @@ -928,6 +938,7 @@ if (!osync_client_proxy_connect_done(sinkengine->proxy, _osync_obj_engine_connect_done_callback, sinkengine, engine->objtype, error)) goto error; + osync_sink_engine_ref(sinkengine); // Note that connect_done callback has a reference } break; case OSYNC_ENGINE_COMMAND_READ: @@ -943,6 +954,7 @@ if (!osync_client_proxy_read(sinkengine->proxy, _osync_obj_engine_read_ignored_callback, sinkengine, change, error)) goto error; + osync_sink_engine_ref(sinkengine); // Note that read_ignored callback has a reference } } @@ -974,6 +986,7 @@ if (!osync_client_proxy_get_changes(sinkengine->proxy, _osync_obj_engine_read_callback, sinkengine, engine->objtype, engine->slowsync, error)) goto error; + osync_sink_engine_ref(sinkengine); // Note that read callback has a reference } break; @@ -1080,6 +1093,7 @@ if (!osync_client_proxy_sync_done(sinkengine->proxy, _osync_obj_engine_sync_done_callback, sinkengine, engine->objtype, error)) goto error; + osync_sink_engine_ref(sinkengine); // Note that sync_done callback has a reference } break; case OSYNC_ENGINE_COMMAND_DISCONNECT:; @@ -1096,6 +1110,7 @@ if (!osync_client_proxy_disconnect(sinkengine->proxy, _osync_obj_engine_disconnect_callback, sinkengine, engine->objtype, error)) goto error; + osync_sink_engine_ref(sinkengine); // Note that disconnect callback has a reference } /* If no client needs to be disconnected, we MUST NOT expected any Modified: trunk/opensync/engine/opensync_sink_engine.c ============================================================================== --- trunk/opensync/engine/opensync_sink_engine.c Tue Feb 3 20:26:06 2009 (r5255) +++ trunk/opensync/engine/opensync_sink_engine.c Tue Feb 3 20:35:06 2009 (r5256) @@ -55,6 +55,7 @@ sinkengine->proxy = proxy; sinkengine->engine = objengine; + osync_obj_engine_ref(objengine); osync_trace(TRACE_EXIT, "%s: %p", __func__, sinkengine); return sinkengine; @@ -92,6 +93,8 @@ engine->entries = osync_list_remove(engine->entries, engine->entries->data); } + osync_obj_engine_unref(engine->engine); + osync_free(engine); } } |
From: <dg...@su...> - 2009-02-03 19:27:53
|
Author: Graham Cobb Date: Tue Feb 3 20:26:06 2009 New Revision: 5255 URL: http://www.opensync.org/changeset/5255 Log: Timeout merge 2: 3) Add references for cross-linked pointers between queues and remove linkages (and unref) when queue disconnected 2) Limit the number of pending entries so the timeout is not dependent on the number of outstanding requests Modified: trunk/ChangeLog trunk/opensync/client/opensync_client.c trunk/opensync/ipc/opensync_queue.c trunk/opensync/ipc/opensync_queue_internals.h trunk/opensync/ipc/opensync_queue_private.h trunk/tests/CMakeLists.txt trunk/tests/ipc-tests/check_ipc.c Modified: trunk/ChangeLog ============================================================================== --- trunk/ChangeLog Tue Feb 3 20:07:09 2009 (r5254) +++ trunk/ChangeLog Tue Feb 3 20:26:06 2009 (r5255) @@ -1,3 +1,34 @@ +2009-01-24 Graham Cobb <g+...@co...> + + * opensync/ipc/opensync_queue.c (osync_queue_remove_cross_link): Add + osync_queue_remove_cross_link + (osync_queue_disconnect): Call osync_queue_remove_cross_link + + * opensync/ipc/opensync_queue_internals.h: Add osync_queue_remove_cross_link + +2009-01-23 Graham Cobb <g+...@co...> + + * opensync/client/opensync_client.c (osync_client_set_incoming_queue): Call + osync_queue_set_pending_limit + + * tests/ipc-tests/check_ipc.c: Call osync_queue_set_pending_limit in timeout tests. + + * opensync/ipc/opensync_queue_internals.h: Add osync_queue_set_pending_limit + and OSYNC_QUEUE_PENDING_LIMIT + + * opensync/ipc/opensync_queue.c (_incoming_check): Check pendingLimit not exceeded. + Add increments/decrements of pendingCount whenever pendingReplies is manipulated. + (osync_queue_set_pending_limit): Add osync_queue_set_pending_limit + + * opensync/ipc/opensync_queue_private.h: Add pendingCount, pendingLimit to OSyncQueue + + * tests/CMakeLists.txt: Add ipc_loop_timeout_with_idle. + + * tests/ipc-tests/check_ipc.c: Rename callback_handler as callback_handler_check_reply. + Rename server_handler3 as server_handler_abort. + Rename client_handler6 as client_handler_sleep. + Add ipc_loop_timeout_with_idle. + 2009-01-22 Graham Cobb <g+...@co...> * tests/CMakeLists.txt: Add ipc_loop_with_timeout Modified: trunk/opensync/client/opensync_client.c ============================================================================== --- trunk/opensync/client/opensync_client.c Tue Feb 3 20:07:09 2009 (r5254) +++ trunk/opensync/client/opensync_client.c Tue Feb 3 20:26:06 2009 (r5255) @@ -1611,6 +1611,7 @@ osync_queue_set_message_handler(incoming, _osync_client_message_handler, client); osync_queue_setup_with_gmainloop(incoming, client->context); client->incoming = osync_queue_ref(incoming); + osync_queue_set_pending_limit(incoming, OSYNC_QUEUE_PENDING_LIMIT); } void osync_client_set_outgoing_queue(OSyncClient *client, OSyncQueue *outgoing) Modified: trunk/opensync/ipc/opensync_queue.c ============================================================================== --- trunk/opensync/ipc/opensync_queue.c Tue Feb 3 20:07:09 2009 (r5254) +++ trunk/opensync/ipc/opensync_queue.c Tue Feb 3 20:26:06 2009 (r5255) @@ -128,6 +128,7 @@ gets called twice! */ queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); + queue->pendingCount--; /* Unlock the pending lock since the messages might be sent during the callback */ g_mutex_unlock(queue->pendingLock); @@ -163,7 +164,18 @@ static gboolean _incoming_check(GSource *source) { OSyncQueue *queue = *((OSyncQueue **)(source + 1)); - if (g_async_queue_length(queue->incoming) > 0) + + /* As well as checking there is something on the incoming queue, we check + that we are not blocked because we have too many pending commands. + This check is only done if the pendingLimit has been set. + + Note, to avoid taking out the pending lock in order to count + the length of the pending queue we use the pendingCount counter. + This better not get out of line! */ + + if (g_async_queue_length(queue->incoming) > 0 + && (queue->pendingLimit == 0 + || queue->pendingCount < queue->pendingLimit) ) return TRUE; return FALSE; @@ -214,6 +226,7 @@ gets called twice! */ queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); + queue->pendingCount--; /* Unlock the pending lock since the messages might be sent during the callback */ g_mutex_unlock(queue->pendingLock); @@ -247,8 +260,11 @@ OSyncError *error = NULL; osync_trace(TRACE_ENTRY, "%s(%p)", __func__, user_data); + osync_trace(TRACE_INTERNAL, "queue->pendingCount = %d, queue->pendingLimit = %d", queue->pendingCount, queue->pendingLimit); + + while ( (queue->pendingLimit == 0 || queue->pendingCount < queue->pendingLimit) + && (message = g_async_queue_try_pop(queue->incoming)) ) { - while ((message = g_async_queue_try_pop(queue->incoming))) { /* We check if the message is a reply to something */ osync_trace(TRACE_INTERNAL, "Dispatching %p:%i(%s), timeout=%d, id=%lli", message, osync_message_get_cmd(message), osync_message_get_commandstr(message), @@ -290,6 +306,7 @@ g_mutex_lock(queue->pendingLock); queue->pendingReplies = osync_list_append(queue->pendingReplies, pending); + queue->pendingCount++; g_mutex_unlock(queue->pendingLock); } @@ -807,6 +824,7 @@ pending = queue->pendingReplies->data; queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); + queue->pendingCount--; /** @todo Refcounting for OSyncPendingMessage */ if (pending->timeout_info) @@ -815,6 +833,8 @@ osync_free(pending); } + osync_assert(queue->pendingCount == 0); + if (queue->name) osync_free(queue->name); @@ -980,6 +1000,8 @@ osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, queue, error); osync_assert(queue); + osync_queue_remove_cross_link(queue); + g_mutex_lock(queue->disconnectLock); if (queue->thread) { osync_thread_stop(queue->thread); @@ -1048,7 +1070,41 @@ osync_assert(reply_queue->type == OSYNC_QUEUE_SENDER); cmd_queue->reply_queue = reply_queue; + osync_queue_ref(reply_queue); reply_queue->cmd_queue = cmd_queue; + osync_queue_ref(cmd_queue); + + osync_trace(TRACE_EXIT, "%s", __func__); +} + +void osync_queue_remove_cross_link(OSyncQueue *queue) +{ + /* Remove the cross links from this queue and all queues linked + from it, recursively */ + if (queue->cmd_queue) { + OSyncQueue *linked_queue = queue->cmd_queue; + queue->cmd_queue = NULL; + osync_queue_remove_cross_link(linked_queue); + osync_queue_unref(linked_queue); + } + if (queue->reply_queue) { + OSyncQueue *linked_queue = queue->reply_queue; + queue->reply_queue = NULL; + osync_queue_remove_cross_link(linked_queue); + osync_queue_unref(linked_queue); + } +} + +void osync_queue_set_pending_limit(OSyncQueue *queue, unsigned int limit) +{ + /* The pending limit is used on queues which receive commands and run timeouts. + It is used to limit the number of pending transactions so timeouts don't occur + just because there are a lot of commands waiting to complete. + It is not necessary on other queues and, in fact, MUST NOT be set on + queues which receive command replies as it could cause deadlocks. */ + osync_trace(TRACE_ENTRY, "%s(%p, %u)", __func__, queue, limit); + + queue->pendingLimit = limit; osync_trace(TRACE_EXIT, "%s", __func__); } @@ -1189,6 +1245,7 @@ g_mutex_lock(replyqueue->pendingLock); replyqueue->pendingReplies = osync_list_append(replyqueue->pendingReplies, pending); + replyqueue->pendingCount++; g_mutex_unlock(replyqueue->pendingLock); } Modified: trunk/opensync/ipc/opensync_queue_internals.h ============================================================================== --- trunk/opensync/ipc/opensync_queue_internals.h Tue Feb 3 20:07:09 2009 (r5254) +++ trunk/opensync/ipc/opensync_queue_internals.h Tue Feb 3 20:26:06 2009 (r5255) @@ -99,6 +99,37 @@ OSYNC_TEST_EXPORT void osync_queue_cross_link(OSyncQueue *cmd_queue, OSyncQueue *reply_queue); /** + * @brief Remove cross links between command queues and reply queues + * + * Removes the cross-links from this queue and all queues linked + * from it, recursively + * + * @param queue The queue to unlink + * + */ +OSYNC_TEST_EXPORT void osync_queue_remove_cross_link(OSyncQueue *queue); + +/** + * @brief Set pending limit on queue + * + * This should be used on queues used to receive incoming commands to + * limit the number of outstanding commands waiting for replies. + * This avoids timing out commands which are just waiting for previous + * commands to finish. + * + * Note: the pending limit should not be set on other queues and + * MUST NOT be set on command reply queues as it could cause deadlocks. + * + * The recommended value to use is OSYNC_QUEUE_PENDING_LIMIT. + * + * @param queue The command queue used to receive incoming commands + * @param limit The maximum number of waiting commands + * + */ +OSYNC_TEST_EXPORT void osync_queue_set_pending_limit(OSyncQueue *queue, unsigned int limit); +#define OSYNC_QUEUE_PENDING_LIMIT 5 + +/** * @brief Sends a Message to a Queue * @param queue Pointer to the queue * @param replyqueue Modified: trunk/opensync/ipc/opensync_queue_private.h ============================================================================== --- trunk/opensync/ipc/opensync_queue_private.h Tue Feb 3 20:07:09 2009 (r5254) +++ trunk/opensync/ipc/opensync_queue_private.h Tue Feb 3 20:26:06 2009 (r5255) @@ -71,6 +71,7 @@ /** List of pending replies */ OSyncList *pendingReplies; GMutex *pendingLock; + unsigned int pendingCount, pendingLimit; GSourceFuncs *write_functions; GSource *write_source; Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Tue Feb 3 20:07:09 2009 (r5254) +++ trunk/tests/CMakeLists.txt Tue Feb 3 20:26:06 2009 (r5255) @@ -248,6 +248,7 @@ OSYNC_TESTCASE(ipc ipc_timeout) OSYNC_TESTCASE(ipc ipc_loop_with_timeout) OSYNC_TESTCASE(ipc ipc_late_reply) +OSYNC_TESTCASE(ipc ipc_loop_timeout_with_idle) ENDIF (NOT WIN32) BUILD_CHECK_TEST( mapping mapping-tests/check_mapping.c ${TEST_TARGET_LIBRARIES} ) Modified: trunk/tests/ipc-tests/check_ipc.c ============================================================================== --- trunk/tests/ipc-tests/check_ipc.c Tue Feb 3 20:07:09 2009 (r5254) +++ trunk/tests/ipc-tests/check_ipc.c Tue Feb 3 20:26:06 2009 (r5255) @@ -1362,7 +1362,7 @@ } END_TEST -void callback_handler(OSyncMessage *message, void *user_data) +void callback_handler_check_reply(OSyncMessage *message, void *user_data) { osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); OSyncError *error = NULL; @@ -1380,7 +1380,7 @@ osync_trace(TRACE_EXIT, "%s", __func__); } -void server_handler3(OSyncMessage *message, void *user_data) +void server_handler_abort(OSyncMessage *message, void *user_data) { abort(); } @@ -1484,7 +1484,7 @@ GMainContext *context = g_main_context_new(); OSyncThread *thread = osync_thread_new(context, &error); - osync_queue_set_message_handler(server_queue, server_handler3, GINT_TO_POINTER(1)); + osync_queue_set_message_handler(server_queue, server_handler_abort, GINT_TO_POINTER(1)); osync_queue_setup_with_gmainloop(server_queue, context); @@ -1507,7 +1507,7 @@ osync_message_write_long_long_int(message, 400000000); osync_message_write_data(message, data, strlen(data) + 1); - osync_message_set_handler(message, callback_handler, GINT_TO_POINTER(1)); + osync_message_set_handler(message, callback_handler_check_reply, GINT_TO_POINTER(1)); fail_unless(osync_queue_send_message(client_queue, server_queue, message, &error), NULL); fail_unless(!osync_error_is_set(&error), NULL); @@ -2164,6 +2164,7 @@ OSyncThread *thread = osync_thread_new(context, &error); osync_queue_set_message_handler(client_queue, client_handler5, GINT_TO_POINTER(1)); + osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); osync_queue_setup_with_gmainloop(client_queue, context); @@ -2275,7 +2276,8 @@ } END_TEST -void client_handler6(OSyncMessage *message, void *user_data) +int ch_sleep_time = 3; // Seconds +void client_handler_sleep(OSyncMessage *message, void *user_data) { osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); OSyncError *error = NULL; @@ -2300,7 +2302,7 @@ osync_assert(!strcmp(databuf, data5)); // Do some time consuming processing - g_usleep(3*G_USEC_PER_SEC); + g_usleep(ch_sleep_time*G_USEC_PER_SEC); OSyncMessage *reply = osync_message_new_reply(message, &error); @@ -2330,7 +2332,8 @@ num_callback_timeout = 0; num_callback = 0; - + ch_sleep_time = 3; + OSyncError *error = NULL; server_queue = osync_queue_new("/tmp/testpipe-server", &error); client_queue = osync_queue_new("/tmp/testpipe-client", &error); @@ -2348,7 +2351,8 @@ GMainContext *context = g_main_context_new(); OSyncThread *thread = osync_thread_new(context, &error); - osync_queue_set_message_handler(client_queue, client_handler6, GINT_TO_POINTER(1)); + osync_queue_set_message_handler(client_queue, client_handler_sleep, GINT_TO_POINTER(1)); + osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); osync_queue_setup_with_gmainloop(client_queue, context); @@ -2460,72 +2464,211 @@ } END_TEST -void callback_handler7(OSyncMessage *message, void *user_data) +START_TEST (ipc_loop_with_timeout) { - osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); + + /* Even though each action takes 1 second, none of these messages should time out + as they are being sent with a timeout of 3 seconds */ + + num_msgs = 0; + req_msgs = 20; + ch_sleep_time = 1; // Second + + char *testbed = setup_testbed(NULL); + osync_testing_file_remove("/tmp/testpipe-server"); + osync_testing_file_remove("/tmp/testpipe-client"); + OSyncError *error = NULL; + server_queue = osync_queue_new("/tmp/testpipe-server", &error); + client_queue = osync_queue_new("/tmp/testpipe-client", &error); + OSyncMessage *message = NULL; - osync_assert(GPOINTER_TO_INT(user_data) == 1); + osync_queue_create(server_queue, &error); + fail_unless(error == NULL, NULL); - num_msgs++; - osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_REPLY); + osync_queue_create(client_queue, &error); + fail_unless(error == NULL, NULL); + char *data = "this is another test string"; - if (num_msgs >= req_msgs) { - osync_queue_disconnect(server_queue, &error); + pid_t cpid = fork(); + if (cpid == 0) { //Child + + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(client_queue, client_handler_sleep, GINT_TO_POINTER(1)); + osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); + + osync_queue_setup_with_gmainloop(client_queue, context); + + osync_thread_start(thread); + + osync_assert(osync_queue_connect(client_queue, OSYNC_QUEUE_RECEIVER, &error)); osync_assert(error == NULL); + + osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); + osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); + + message = osync_queue_get_message(server_queue); + + if (osync_message_get_command(message) != OSYNC_MESSAGE_QUEUE_HUP) { + exit (1); + } + + osync_message_unref(message); + + if (osync_queue_disconnect(server_queue, &error) != TRUE || error != NULL) + exit(1); + osync_queue_unref(server_queue); + + osync_assert(osync_queue_disconnect(client_queue, &error)); + osync_assert(error == NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + osync_queue_unref(client_queue); + + g_free(testbed); + + exit(0); + } else { + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(server_queue, server_handler_abort, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(server_queue, context); + + osync_thread_start(thread); + + fail_unless(osync_queue_connect(client_queue, OSYNC_QUEUE_SENDER, &error), NULL); + fail_unless(error == NULL, NULL); + + fail_unless(osync_queue_connect(server_queue, OSYNC_QUEUE_RECEIVER, &error), NULL); + fail_unless(error == NULL, NULL); + + int i = 0; + for (i = 0; i < req_msgs; i++) { + message = osync_message_new(OSYNC_MESSAGE_INITIALIZE, 0, &error); + fail_unless(message != NULL, NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_write_int(message, 4000000); + osync_message_write_string(message, "this is a test string"); + osync_message_write_long_long_int(message, 400000000); + osync_message_write_data(message, data, strlen(data) + 1); + + osync_message_set_handler(message, callback_handler_check_reply, GINT_TO_POINTER(1)); + + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 3, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_unref(message); + } + + message = osync_queue_get_message(client_queue); + + fail_unless(osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP); + + osync_message_unref(message); + + osync_queue_disconnect(client_queue, &error); + fail_unless(error == NULL, NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + int status = 0; + wait(&status); + fail_unless(WEXITSTATUS(status) == 0, NULL); } - osync_trace(TRACE_EXIT, "%s", __func__); -} + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == TRUE, NULL); + + fail_unless(osync_queue_remove(client_queue, &error), NULL); + fail_unless(osync_queue_remove(server_queue, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == FALSE, NULL); -void server_handler7(OSyncMessage *message, void *user_data) -{ - abort(); + osync_queue_unref(client_queue); + osync_queue_unref(server_queue); + + destroy_testbed(testbed); } +END_TEST -void client_handler7(OSyncMessage *message, void *user_data) +GSList *ch_pending = NULL; +void client_handler_first_part(OSyncMessage *message, void *user_data) { osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); OSyncError *error = NULL; osync_assert(GPOINTER_TO_INT(user_data) ==1); osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_INITIALIZE); - + int int1; long long int longint1; char *string; - void *databuf; + char databuf[strlen(data5) + 1]; + osync_message_read_int(message, &int1); - osync_message_read_const_string(message, &string); + osync_message_read_string(message, &string); osync_message_read_long_long_int(message, &longint1); - osync_message_read_const_data(message, &databuf, strlen("this is another test string") + 1); + osync_message_read_data(message, databuf, strlen(data5) + 1); osync_assert(int1 == 4000000); osync_assert(!strcmp(string, "this is a test string")); osync_assert(longint1 == 400000000); - osync_assert(!strcmp(databuf, "this is another test string")); + osync_assert(!strcmp(databuf, data5)); - // Do some time consuming processing - g_usleep(1*G_USEC_PER_SEC); - - OSyncMessage *reply = osync_message_new_reply(message, &error); - - osync_queue_send_message(server_queue, NULL, reply, &error); + // Put message on pending queue and return + osync_message_ref(message); + ch_pending = g_slist_append(ch_pending, message); + + osync_trace(TRACE_EXIT, "%s", __func__); +} +gboolean client_handler_second_part(gpointer userdata) +{ + OSyncError *error = NULL; + + osync_trace(TRACE_ENTRY, "%s(%p)", __func__, userdata); + + if (ch_pending) { + + OSyncMessage *message = ch_pending->data; + + OSyncMessage *reply = osync_message_new_reply(message, &error); - osync_message_unref(reply); + osync_queue_send_message(server_queue, NULL, reply, &error); - osync_trace(TRACE_EXIT, "%s", __func__); + osync_message_unref(reply); + + ch_pending = g_slist_remove(ch_pending, message); + osync_message_unref(message); + + osync_trace(TRACE_EXIT, "%s", __func__); + return TRUE; + } + + osync_trace(TRACE_EXIT, "%s: no more entries", __func__); + return FALSE; } -START_TEST (ipc_loop_with_timeout) +START_TEST (ipc_loop_timeout_with_idle) { - /* Even though each action takes 1 second, none of these messages should time out + /* Same as ipc_loop_with_timeout except that the client handler doesn't sleep, + so the queue dispatchers can run while the operation is waiting. + Even though each action takes 1 second, none of these messages should time out as they are being sent with a timeout of 3 seconds */ num_msgs = 0; - req_msgs = 20; + req_msgs = 30; char *testbed = setup_testbed(NULL); osync_testing_file_remove("/tmp/testpipe-server"); @@ -2549,7 +2692,8 @@ GMainContext *context = g_main_context_new(); OSyncThread *thread = osync_thread_new(context, &error); - osync_queue_set_message_handler(client_queue, client_handler7, GINT_TO_POINTER(1)); + osync_queue_set_message_handler(client_queue, client_handler_first_part, GINT_TO_POINTER(1)); + osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); osync_queue_setup_with_gmainloop(client_queue, context); @@ -2562,6 +2706,12 @@ osync_assert(error == NULL); osync_queue_cross_link(client_queue, server_queue); + + GSource *tsource = g_timeout_source_new(1000); + osync_assert(tsource); + g_source_set_callback(tsource, client_handler_second_part, NULL, NULL); + osync_assert(g_source_attach(tsource, context)); + g_source_unref(tsource); message = osync_queue_get_message(server_queue); @@ -2590,7 +2740,7 @@ GMainContext *context = g_main_context_new(); OSyncThread *thread = osync_thread_new(context, &error); - osync_queue_set_message_handler(server_queue, server_handler7, GINT_TO_POINTER(1)); + osync_queue_set_message_handler(server_queue, server_handler_abort, GINT_TO_POINTER(1)); osync_queue_setup_with_gmainloop(server_queue, context); @@ -2613,9 +2763,9 @@ osync_message_write_long_long_int(message, 400000000); osync_message_write_data(message, data, strlen(data) + 1); - osync_message_set_handler(message, callback_handler7, GINT_TO_POINTER(1)); + osync_message_set_handler(message, callback_handler_check_reply, GINT_TO_POINTER(1)); - fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 3, &error), NULL); + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 10, &error), NULL); fail_unless(!osync_error_is_set(&error), NULL); osync_message_unref(message); @@ -2681,5 +2831,6 @@ OSYNC_TESTCASE_ADD(ipc_timeout) OSYNC_TESTCASE_ADD(ipc_late_reply) OSYNC_TESTCASE_ADD(ipc_loop_with_timeout) +OSYNC_TESTCASE_ADD(ipc_loop_timeout_with_idle) OSYNC_TESTCASE_END |
From: <dg...@su...> - 2009-02-03 19:08:54
|
Author: Graham Cobb Date: Tue Feb 3 20:07:09 2009 New Revision: 5254 URL: http://www.opensync.org/changeset/5254 Log: Merge of basic timeout changes Modified: trunk/ChangeLog trunk/opensync/client/opensync_client.c trunk/opensync/client/opensync_client_proxy.c trunk/opensync/ipc/opensync_message.c trunk/opensync/ipc/opensync_message_internals.h trunk/opensync/ipc/opensync_message_private.h trunk/opensync/ipc/opensync_queue.c trunk/opensync/ipc/opensync_queue_internals.h trunk/opensync/ipc/opensync_queue_private.h trunk/tests/CMakeLists.txt trunk/tests/ipc-tests/check_ipc.c Modified: trunk/ChangeLog ============================================================================== --- trunk/ChangeLog Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/ChangeLog Tue Feb 3 20:07:09 2009 (r5254) @@ -1,3 +1,57 @@ +2009-01-22 Graham Cobb <g+...@co...> + + * tests/CMakeLists.txt: Add ipc_loop_with_timeout + Add ipc_late_reply + + * tests/ipc-tests/check_ipc.c: Call osync_queue_cross_link every time + client mainloop is setup. + (ipc_timeout): Rewrite client to use a mainloop and a callback so new + timeout processing can run + Rewrite server to use a mainloop so message callback gets called + (ipc_loop_with_timeout): Add ipc_loop_with_timeout + (ipc_late_reply): Add ipc_late_reply + + * opensync/ipc/opensync_queue.c (_timeout_dispatch): Restart timeout search at start of + pending list as list may have been modified while unlocked. + (_timeout_dispatch): Set message id in error message + (_timeout_dispatch): Undo change to restart timeout search (above) + +2009-01-21 Graham Cobb <g+...@co...> + + * opensync/ipc/opensync_queue.c (osync_queue_send_message_with_timeout): If this is + a reply, remove pending command + + * opensync/client/opensync_client_proxy.c (_osync_client_proxy_hup_handler): treat + a queue error as a disconnect + (osync_client_proxy_spawn): cross-link command and reply queues + + * opensync/client/opensync_client.c (_osync_client_handle_initialize): cross-link + command and reply queues + (_osync_client_hup_handler): treat a queue error as a disconnect + +2009-01-20 Graham Cobb <g+...@co...> + + * opensync/ipc/opensync_queue_internals.h: Add osync_queue_cross_link + + * opensync/ipc/opensync_queue.c (osync_queue_cross_link): Cross-link command and reply queues + + * opensync/ipc/opensync_queue.c (_osync_send_timeout_response): + Callback function for timeouts: send the timeout error reponse + (_incoming_dispatch): For incoming messages which have timeouts, + create a pending list entry + + * opensync/ipc/opensync_queue_private.h: Add reply_queue for pointer to + queue used for replies to incoming messages, if any. + Add cmd_queue for pointer to queue used to store pending commands. + +2009-01-19 Graham Cobb <g+...@co...> + + * opensync/ipc/opensync_message.c: Add opensync_message_set/get_timeout + + * opensync/ipc/opensync_message_internals.h: Add opensync_message_set/get_timeout + + * opensync/ipc/opensync_message_private.h: Add timeout to message + 2008-05-04 Graham Cobb <g+...@co...> * opensync/helper/opensync_hashtable.c (osync_hashtable_get_deleted): Modified: trunk/opensync/client/opensync_client.c ============================================================================== --- trunk/opensync/client/opensync_client.c Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/client/opensync_client.c Tue Feb 3 20:07:09 2009 (r5254) @@ -604,6 +604,7 @@ } osync_client_set_outgoing_queue(client, outgoing); + osync_queue_cross_link(client->incoming, client->outgoing); osync_queue_unref(outgoing); osync_trace(TRACE_INTERNAL, "done connecting to engine"); } @@ -1519,9 +1520,8 @@ osync_trace(TRACE_INTERNAL, "plugin received command %i on sending queue", osync_message_get_command(message)); - if (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_ERROR) { - /* Houston, we have a problem */ - } else if (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP) { + if ( (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_ERROR) + || (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP) ) { /* The remote side disconnected. So we can now disconnect as well and then * shutdown */ if (!osync_queue_disconnect(client->outgoing, &error)) Modified: trunk/opensync/client/opensync_client_proxy.c ============================================================================== --- trunk/opensync/client/opensync_client_proxy.c Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/client/opensync_client_proxy.c Tue Feb 3 20:07:09 2009 (r5254) @@ -227,9 +227,8 @@ osync_trace(TRACE_INTERNAL, "client received command %i on sending queue", osync_message_get_command(message)); - if (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_ERROR) { - /* Houston, we have a problem */ - } else if (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP) { + if ( (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_ERROR) /* Treat an error as a disconnect */ + || (osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP) ) { /* The remote side disconnected. So we can now disconnect as well and then * shutdown */ if (!osync_queue_disconnect(proxy->outgoing, &error)) @@ -916,6 +915,7 @@ osync_client_set_incoming_queue(proxy->client, read1); osync_client_set_outgoing_queue(proxy->client, write2); + osync_queue_cross_link(read1, write2); if (!osync_client_run(proxy->client, error)) goto error_free_pipe2; Modified: trunk/opensync/ipc/opensync_message.c ============================================================================== --- trunk/opensync/ipc/opensync_message.c Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/ipc/opensync_message.c Tue Feb 3 20:07:09 2009 (r5254) @@ -74,6 +74,18 @@ return message->cmd; } +void osync_message_set_timeout(OSyncMessage *message, unsigned int timeout) +{ + osync_assert(message); + message->timeout = timeout; +} + +unsigned int osync_message_get_timeout(OSyncMessage *message) +{ + osync_assert(message); + return message->timeout; +} + void osync_message_set_id(OSyncMessage *message, long long int id) { osync_assert(message); Modified: trunk/opensync/ipc/opensync_message_internals.h ============================================================================== --- trunk/opensync/ipc/opensync_message_internals.h Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/ipc/opensync_message_internals.h Tue Feb 3 20:07:09 2009 (r5254) @@ -193,6 +193,21 @@ */ OSYNC_TEST_EXPORT void osync_message_get_buffer(OSyncMessage *message, char **data, unsigned int *size); +/** @brief Set timeout (in seconds) for the message object + * + * @param message The message to modify + * @param timeout The new message timeout + * + */ +OSYNC_TEST_EXPORT void osync_message_set_timeout(OSyncMessage *message, unsigned int timeout); + +/** @brief Get timeout (in seconds) for the message object + * + * @param message The message + * + */ +OSYNC_TEST_EXPORT unsigned int osync_message_get_timeout(OSyncMessage *message); + /** @brief Sets the handler that will receive the reply * * @param message The message to work on Modified: trunk/opensync/ipc/opensync_message_private.h ============================================================================== --- trunk/opensync/ipc/opensync_message_private.h Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/ipc/opensync_message_private.h Tue Feb 3 20:07:09 2009 (r5254) @@ -45,7 +45,7 @@ /** The user data */ gpointer user_data; /** The timeout associated with this message */ - //timeout_info *to_info; + unsigned int timeout; /** If this message has already been answered */ osync_bool is_answered; /** The internal OSyncMarshal object **/ Modified: trunk/opensync/ipc/opensync_queue.c ============================================================================== --- trunk/opensync/ipc/opensync_queue.c Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/ipc/opensync_queue.c Tue Feb 3 20:07:09 2009 (r5254) @@ -2,6 +2,7 @@ * libosengine - A synchronization engine for the opensync framework * Copyright (C) 2004-2005 Armin Bauer <arm...@op...> * Copyright (C) 2007 Daniel Friedrich <dan...@op...> + * Copyright (C) 2009 Graham R. Cobb <g+o...@co...> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -110,11 +111,15 @@ OSyncError *timeouterr = NULL; OSyncMessage *errormsg = NULL; + osync_trace(TRACE_INTERNAL, "Timeout for message with id %lli", pending->id); + + /* Call the callback of the pending message */ osync_assert(pending->callback); osync_error_set(&timeouterr, OSYNC_ERROR_IO_ERROR, "Timeout."); errormsg = osync_message_new_errorreply(NULL, timeouterr, &error); osync_error_unref(&timeouterr); + osync_message_set_id(errormsg, pending->id); /* Remove first the pending message! To avoid that _incoming_dispatch catchs this message @@ -137,6 +142,9 @@ /* Lock again, to keep the iteration of the pendingReplies list atomic. */ g_mutex_lock(queue->pendingLock); + /* The queue may have been modified while it was unlocked so don't go + looking for any more entries. If there are more, they will be found + on the next call */ break; } } @@ -161,67 +169,146 @@ return FALSE; } +static void _osync_send_timeout_response(OSyncMessage *errormsg, void *user_data) +{ + OSyncQueue *queue = user_data; + + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, errormsg, queue); + + if (queue->reply_queue) { + osync_queue_send_message_with_timeout(queue->reply_queue, NULL, errormsg, 0, NULL); + } else { + osync_message_unref(errormsg); + /* TODO: as we can't send the timeout response, disconnect the queue to signal to + the sender that they aren't going to get a response. Note: we can't just + call osync_queue_disconnect as that tries to kill the thread and hits a deadlock! */ + osync_trace(TRACE_EXIT_ERROR, "%s: cannot find reply queue to send timeout error", __func__); + return; + } + osync_trace(TRACE_EXIT, "%s", __func__); +} + +/* Find and remove a pending message that this message is a reply to */ +static void _osync_queue_remove_pending_reply(OSyncQueue *queue, OSyncMessage *reply, gboolean callback) +{ + OSyncPendingMessage *pending = NULL; + OSyncList *p = NULL; + + osync_trace(TRACE_ENTRY, "%s(%p, %p, %d)", __func__, queue, reply, callback); + osync_trace(TRACE_INTERNAL, "Searching for pending message id=%lli", osync_message_get_id(reply)); + + /* Search for the pending reply. We have to lock the + * list since another thread might be duing the updates */ + g_mutex_lock(queue->pendingLock); + + for (p = queue->pendingReplies; p; p = p->next) { + pending = p->data; + + if (pending->id == osync_message_get_id(reply)) { + + osync_trace(TRACE_INTERNAL, "Found pending message id=%lli: %p", osync_message_get_id(reply), pending); + /* Remove first the pending message! + To avoid that _timeout_dispatch catchs this message + when we're releasing the lock. If _timeout_dispatch + would catch this message, the pending callback + gets called twice! */ + + queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); + + /* Unlock the pending lock since the messages might be sent during the callback */ + g_mutex_unlock(queue->pendingLock); + + if (callback) { + /* Call the callback of the pending message */ + osync_assert(pending->callback); + pending->callback(reply, pending->user_data); + } + + // TODO: Refcounting for OSyncPendingMessage + if (pending->timeout_info) + g_free(pending->timeout_info); + osync_free(pending); + + osync_trace(TRACE_EXIT, "%s", __func__); + return; + } + } + + g_mutex_unlock(queue->pendingLock); + osync_trace(TRACE_EXIT, "%s", __func__); +} + /* This function is called from the master thread. The function dispatched incoming data from * the remote end */ static gboolean _incoming_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { - OSyncPendingMessage *pending = NULL; OSyncQueue *queue = user_data; - OSyncList *p = NULL; OSyncMessage *message = NULL; + OSyncError *error = NULL; osync_trace(TRACE_ENTRY, "%s(%p)", __func__, user_data); while ((message = g_async_queue_try_pop(queue->incoming))) { /* We check if the message is a reply to something */ - osync_trace(TRACE_INTERNAL, "Dispatching %p:%i(%s)", message, osync_message_get_cmd(message), osync_message_get_commandstr(message)); + osync_trace(TRACE_INTERNAL, "Dispatching %p:%i(%s), timeout=%d, id=%lli", message, + osync_message_get_cmd(message), osync_message_get_commandstr(message), + osync_message_get_timeout(message), osync_message_get_id(message)); if (osync_message_get_cmd(message) == OSYNC_MESSAGE_REPLY || osync_message_get_cmd(message) == OSYNC_MESSAGE_ERRORREPLY) { - - /* Search for the pending reply. We have to lock the - * list since another thread might be duing the updates */ - g_mutex_lock(queue->pendingLock); - - for (p = queue->pendingReplies; p; p = p->next) { - pending = p->data; - - if (pending->id == osync_message_get_id(message)) { + /* Remove pending reply and call callback */ + _osync_queue_remove_pending_reply(queue, message, TRUE); + } else { + unsigned int timeout = osync_message_get_timeout(message); + if (timeout) { + /* This message has a timeout. Put message on pending list and run timeout */ + /* NOTE: We really want to put it on the pending list for the corresponding + outgoing queue but there may not be one at this time (if this is an Initialise, + for example). So we put it on the pending list of the incoming queue and deal with + finding the outgoing queue if the timeout fires. This also complicates removing + pending items when sending the responses. Oh well. */ + + OSyncPendingMessage *pending = osync_try_malloc0(sizeof(OSyncPendingMessage), &error); + if (!pending) + goto error; - /* Remove first the pending message! - To avoid that _timeout_dispatch catchs this message - when we're releasing the lock. If _timeout_dispatch - would catch this message, the pending callback - gets called twice! */ + pending->id = osync_message_get_id(message); - queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); + OSyncTimeoutInfo *toinfo = osync_try_malloc0(sizeof(OSyncTimeoutInfo), &error); + if (!toinfo) + goto error; - /* Unlock the pending lock since the messages might be sent during the callback */ - g_mutex_unlock(queue->pendingLock); - - /* Call the callback of the pending message */ - osync_assert(pending->callback); - pending->callback(message, pending->user_data); - - // TODO: Refcounting for OSyncPendingMessage - if (pending->timeout_info) - g_free(pending->timeout_info); - osync_free(pending); - - /* Lock again, to keep the iteration of the pendingReplies list atomic. */ - g_mutex_lock(queue->pendingLock); - break; - } + GTimeVal current_time; + g_source_get_current_time(queue->timeout_source, ¤t_time); + + toinfo->expiration = current_time; + toinfo->expiration.tv_sec += timeout; + + pending->timeout_info = toinfo; + + pending->callback = _osync_send_timeout_response; + pending->user_data = queue; + + g_mutex_lock(queue->pendingLock); + queue->pendingReplies = osync_list_append(queue->pendingReplies, pending); + g_mutex_unlock(queue->pendingLock); } - - g_mutex_unlock(queue->pendingLock); - } else + queue->message_handler(message, queue->user_data); + } osync_message_unref(message); } osync_trace(TRACE_EXIT, "%s: Done dispatching", __func__); return TRUE; + + error: + /* TODO: as we can't send the timeout response, disconnect the queue to signal to + the sender that they aren't going to get a response. Note: we can't just + call osync_queue_disconnect as that tries to kill the thread and hits a deadlock! */ + + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error)); + return TRUE; } static void _osync_queue_stop_incoming(OSyncQueue *queue) @@ -328,6 +415,10 @@ if (!_osync_queue_write_long_long_int(queue, osync_message_get_id(message), &error)) goto error; + /* The timeout (integer) */ + if (!_osync_queue_write_int(queue, (int) osync_message_get_timeout(message), &error)) + goto error; + osync_message_get_buffer(message, &data, &length); if (length) { @@ -498,7 +589,7 @@ do { int size = 0; - int cmd = 0; + int cmd = 0, timeout = 0; long long int id = 0; char *buffer = NULL; @@ -514,11 +605,16 @@ if (!_osync_queue_read_long_long_int(queue, &id, &error)) goto error; + /* The timeout */ + if (!_osync_queue_read_int(queue, &timeout, &error)) + goto error; + message = osync_message_new(cmd, size, &error); if (!message) goto error; osync_message_set_id(message, id); + osync_message_set_timeout(message, (unsigned int) timeout); /* We now get the buffer from the message which will already * have the correct size for the read */ @@ -933,7 +1029,7 @@ void osync_queue_set_message_handler(OSyncQueue *queue, OSyncMessageHandler handler, gpointer user_data) { - osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, queue, handler, user_data); + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, queue, handler, user_data); queue->message_handler = handler; queue->user_data = user_data; @@ -941,6 +1037,22 @@ osync_trace(TRACE_EXIT, "%s", __func__); } +void osync_queue_cross_link(OSyncQueue *cmd_queue, OSyncQueue *reply_queue) +{ + /* Cross-linking is needed to make timeouts work when commands are + being received on one queue and replies sent on another. + Note that cross-linking is not needed when commands are being sent. */ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, cmd_queue, reply_queue); + + osync_assert(cmd_queue->type == OSYNC_QUEUE_RECEIVER); + osync_assert(reply_queue->type == OSYNC_QUEUE_SENDER); + + cmd_queue->reply_queue = reply_queue; + reply_queue->cmd_queue = cmd_queue; + + osync_trace(TRACE_EXIT, "%s", __func__); +} + void osync_queue_setup_with_gmainloop(OSyncQueue *queue, GMainContext *context) { OSyncQueue **queueptr = NULL; @@ -1035,6 +1147,19 @@ { osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %u, %p)", __func__, queue, replyqueue, message, timeout, error); + if (queue->cmd_queue) { + /* This queue is a reply queue for some command receiving queue */ + + /* If this is actually a reply message, we check to see if there is + message to remove from the command queue's pending list */ + + if (osync_message_get_cmd(message) == OSYNC_MESSAGE_REPLY || osync_message_get_cmd(message) == OSYNC_MESSAGE_ERRORREPLY) { + /* Remove pending reply but do not call callback + (real callback will be called by the receiver of this reply later) */ + _osync_queue_remove_pending_reply(queue->cmd_queue, message, FALSE); + } + } + if (osync_message_get_handler(message)) { OSyncPendingMessage *pending = NULL; GTimeVal current_time; @@ -1053,14 +1178,8 @@ osync_trace(TRACE_INTERNAL, "Setting id %lli for pending reply", id); if (timeout) { - OSyncTimeoutInfo *toinfo = osync_try_malloc0(sizeof(OSyncTimeoutInfo), error); - if (!toinfo) - goto error; - - toinfo->expiration = current_time; - toinfo->expiration.tv_sec += timeout; - - pending->timeout_info = toinfo; + /* Send timeout info to other end to handle */ + osync_message_set_timeout(message, timeout); } else { osync_trace(TRACE_INTERNAL, "handler message got sent without timeout!: %s", osync_message_get_commandstr(message)); } @@ -1118,6 +1237,7 @@ { osync_assert(queue); return queue->name; + } int osync_queue_get_fd(OSyncQueue *queue) Modified: trunk/opensync/ipc/opensync_queue_internals.h ============================================================================== --- trunk/opensync/ipc/opensync_queue_internals.h Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/ipc/opensync_queue_internals.h Tue Feb 3 20:07:09 2009 (r5254) @@ -85,6 +85,20 @@ OSYNC_TEST_EXPORT void osync_queue_set_message_handler(OSyncQueue *queue, OSyncMessageHandler handler, gpointer user_data); /** + * @brief Cross links command queue and reply queue + * + * Stores the queue used for replies in the command queue object so + * that timeout responses can be sent if necessary. + * And stores the command queue in the reply queue object so that + * replies can remove pending messages before they time out. + * + * @param cmd_queue The command queue used to receive incoming commands + * @param reply_queue The queue used to send replies + * + */ +OSYNC_TEST_EXPORT void osync_queue_cross_link(OSyncQueue *cmd_queue, OSyncQueue *reply_queue); + +/** * @brief Sends a Message to a Queue * @param queue Pointer to the queue * @param replyqueue Modified: trunk/opensync/ipc/opensync_queue_private.h ============================================================================== --- trunk/opensync/ipc/opensync_queue_private.h Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/opensync/ipc/opensync_queue_private.h Tue Feb 3 20:07:09 2009 (r5254) @@ -89,6 +89,12 @@ /** Reference count **/ int ref_count; + + /* Queue for replies to incoming messages */ + OSyncQueue *reply_queue; + + /* Queue for receiving commands we are replying to */ + OSyncQueue *cmd_queue; }; Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/tests/CMakeLists.txt Tue Feb 3 20:07:09 2009 (r5254) @@ -246,6 +246,8 @@ OSYNC_TESTCASE(ipc ipc_pipes_stress) OSYNC_TESTCASE_DISABLED(ipc ipc_callback_break_pipes "1039") OSYNC_TESTCASE(ipc ipc_timeout) +OSYNC_TESTCASE(ipc ipc_loop_with_timeout) +OSYNC_TESTCASE(ipc ipc_late_reply) ENDIF (NOT WIN32) BUILD_CHECK_TEST( mapping mapping-tests/check_mapping.c ${TEST_TARGET_LIBRARIES} ) Modified: trunk/tests/ipc-tests/check_ipc.c ============================================================================== --- trunk/tests/ipc-tests/check_ipc.c Tue Feb 3 19:17:50 2009 (r5253) +++ trunk/tests/ipc-tests/check_ipc.c Tue Feb 3 20:07:09 2009 (r5254) @@ -1087,6 +1087,8 @@ osync_assert(error == NULL); osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); message = osync_queue_get_message(server_queue); @@ -1272,6 +1274,8 @@ osync_assert(error == NULL); osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); message = osync_queue_get_message(server_queue); @@ -1450,6 +1454,8 @@ osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); message = osync_queue_get_message(server_queue); @@ -1644,6 +1650,8 @@ osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); while (osync_queue_is_connected(client_queue)) { g_usleep(100); } @@ -1849,6 +1857,8 @@ osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); message = osync_queue_get_message(server_queue); if (osync_message_get_command(message) != OSYNC_MESSAGE_QUEUE_HUP) { @@ -1984,6 +1994,8 @@ osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); while (osync_queue_is_connected(client_queue)) { g_usleep(100); } @@ -2081,11 +2093,39 @@ num_callback_timeout++; else num_callback++; +} +char *data5 = "this is another test string"; +void client_handler5(OSyncMessage *message, void *user_data) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); OSyncError *error = NULL; - OSyncMessage *reply = osync_message_new_reply(message, &error); - osync_queue_send_message(client_queue, NULL, reply, &error); - osync_message_unref(reply); + + osync_assert(GPOINTER_TO_INT(user_data) ==1); + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_INITIALIZE); + + int int1; + long long int longint1; + char *string; + char databuf[strlen(data5) + 1]; + + + osync_message_read_int(message, &int1); + osync_message_read_string(message, &string); + osync_message_read_long_long_int(message, &longint1); + osync_message_read_data(message, databuf, strlen(data5) + 1); + + osync_assert(int1 == 4000000); + osync_assert(!strcmp(string, "this is a test string")); + osync_assert(longint1 == 400000000); + osync_assert(!strcmp(databuf, data5)); + + /* TIMEOUT TIMEOUT TIMEOUT (no reply...) */ + + /* Proper code would reply to this message, but for testing + purposes we don't reply and simulate a "timeout" situation */ + + osync_trace(TRACE_EXIT, "%s", __func__); } START_TEST (ipc_timeout) @@ -2116,78 +2156,245 @@ osync_queue_create(client_queue, &error); fail_unless(error == NULL, NULL); - char *data = "this is another test string"; pid_t cpid = fork(); if (cpid == 0) { //Child - g_usleep(1*G_USEC_PER_SEC); + + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(client_queue, client_handler5, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(client_queue, context); + + osync_thread_start(thread); + osync_assert(osync_queue_connect(client_queue, OSYNC_QUEUE_RECEIVER, &error)); osync_assert(error == NULL); osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); - while (!(message = osync_queue_get_message(client_queue))) { - g_usleep(10000); - } + message = osync_queue_get_message(server_queue); - if (osync_message_get_command(message) != OSYNC_MESSAGE_INITIALIZE) { + if (osync_message_get_command(message) != OSYNC_MESSAGE_QUEUE_HUP) { exit (1); } - int int1; - long long int longint1; - char *string; - char databuf[strlen(data) + 1]; - - osync_message_read_int(message, &int1); - osync_message_read_string(message, &string); - osync_message_read_long_long_int(message, &longint1); - osync_message_read_data(message, databuf, strlen(data) + 1); + osync_message_unref(message); + + if (osync_queue_disconnect(server_queue, &error) != TRUE || error != NULL) + exit(1); + osync_queue_unref(server_queue); - osync_assert(int1 == 4000000); - osync_assert(!strcmp(string, "this is a test string")); + osync_assert(osync_queue_disconnect(client_queue, &error)); + osync_assert(error == NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + osync_queue_unref(client_queue); + + g_free(testbed); + + exit(0); + } else { + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(server_queue, server_handler4, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(server_queue, context); + + osync_thread_start(thread); - osync_assert(longint1 == 400000000); - osync_assert(!strcmp(databuf, "this is another test string")); + fail_unless(osync_queue_connect(client_queue, OSYNC_QUEUE_SENDER, &error), NULL); + fail_unless(error == NULL, NULL); + + fail_unless(osync_queue_connect(server_queue, OSYNC_QUEUE_RECEIVER, &error), NULL); + fail_unless(error == NULL, NULL); - /* TIMEOUT TIMEOUT TIMEOUT (no reply...) */ + message = osync_message_new(OSYNC_MESSAGE_INITIALIZE, 0, &error); + fail_unless(message != NULL, NULL); + fail_unless(!osync_error_is_set(&error), NULL); - /* Proper code would reply to this message, but for testing - purposes we don't reply and simulate a "timeout" situation */ - + osync_message_set_handler(message, _message_handler, NULL); + + osync_message_write_int(message, 4000000); + osync_message_write_string(message, "this is a test string"); + osync_message_write_long_long_int(message, 400000000); + osync_message_write_data(message, data5, strlen(data5) + 1); + + // Send with timeout of one second + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 1, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_unref(message); + + // Block + g_usleep(5*G_USEC_PER_SEC); + + osync_queue_disconnect(server_queue, &error); + fail_unless(error == NULL, NULL); + while (!(message = osync_queue_get_message(client_queue))) { g_usleep(10000); } + + if (osync_message_get_command(message) != OSYNC_MESSAGE_QUEUE_HUP) { + exit (1); + } + osync_message_unref(message); + + osync_queue_disconnect(client_queue, &error); + fail_unless(error == NULL, NULL); + + int status = 0; + wait(&status); + fail_unless(WEXITSTATUS(status) == 0, NULL); + } + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == TRUE, NULL); + + fail_unless(osync_queue_remove(client_queue, &error), NULL); + fail_unless(osync_queue_remove(server_queue, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); - OSyncMessage *reply = osync_message_new_reply(message, &error); + /* Check if the timeout handler replied with an error */ + fail_unless(num_callback_timeout == 1, NULL); + fail_unless(num_callback == 0, NULL); - osync_queue_send_message(server_queue, NULL, reply, &error); + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == FALSE, NULL); + + osync_queue_unref(client_queue); + osync_queue_unref(server_queue); + + destroy_testbed(testbed); +} +END_TEST +void client_handler6(OSyncMessage *message, void *user_data) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); + OSyncError *error = NULL; + + osync_assert(GPOINTER_TO_INT(user_data) ==1); + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_INITIALIZE); - if (osync_queue_disconnect(client_queue, &error) != TRUE || error != NULL) - exit(1); - osync_queue_unref(client_queue); + int int1; + long long int longint1; + char *string; + char databuf[strlen(data5) + 1]; - while (!(message = osync_queue_get_message(server_queue))) { - g_usleep(10000); - } + + osync_message_read_int(message, &int1); + osync_message_read_string(message, &string); + osync_message_read_long_long_int(message, &longint1); + osync_message_read_data(message, databuf, strlen(data5) + 1); + + osync_assert(int1 == 4000000); + osync_assert(!strcmp(string, "this is a test string")); + osync_assert(longint1 == 400000000); + osync_assert(!strcmp(databuf, data5)); + + // Do some time consuming processing + g_usleep(3*G_USEC_PER_SEC); + + OSyncMessage *reply = osync_message_new_reply(message, &error); + + osync_queue_send_message(server_queue, NULL, reply, &error); + + osync_message_unref(reply); + + osync_trace(TRACE_EXIT, "%s", __func__); +} + +START_TEST (ipc_late_reply) +{ + /* This testcase is inteded to test osync_queue_send_message_with_timeout(). + Client got forked and listens for messages from Server and replies. + + To simulate a "timeout" situation the Client delays 3 seconds and then replies + + The timeout handler will call the _message_handler() with an error and the late reply + will be discarded. + + JFYI, every timed out message calls the callback/message_handler with an (timeout) error. + */ + + char *testbed = setup_testbed(NULL); + osync_testing_file_remove("/tmp/testpipe-server"); + osync_testing_file_remove("/tmp/testpipe-client"); + + num_callback_timeout = 0; + num_callback = 0; + + OSyncError *error = NULL; + server_queue = osync_queue_new("/tmp/testpipe-server", &error); + client_queue = osync_queue_new("/tmp/testpipe-client", &error); + OSyncMessage *message = NULL; + + osync_queue_create(server_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_create(client_queue, &error); + fail_unless(error == NULL, NULL); + + pid_t cpid = fork(); + if (cpid == 0) { //Child + + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(client_queue, client_handler6, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(client_queue, context); + + osync_thread_start(thread); + + osync_assert(osync_queue_connect(client_queue, OSYNC_QUEUE_RECEIVER, &error)); + osync_assert(error == NULL); + + osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); + osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); + + message = osync_queue_get_message(server_queue); if (osync_message_get_command(message) != OSYNC_MESSAGE_QUEUE_HUP) { exit (1); } - - osync_message_unref(message); - g_usleep(1*G_USEC_PER_SEC); + osync_message_unref(message); + if (osync_queue_disconnect(server_queue, &error) != TRUE || error != NULL) exit(1); osync_queue_unref(server_queue); + osync_assert(osync_queue_disconnect(client_queue, &error)); + osync_assert(error == NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + osync_queue_unref(client_queue); + g_free(testbed); exit(0); } else { + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(server_queue, server_handler4, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(server_queue, context); + + osync_thread_start(thread); + fail_unless(osync_queue_connect(client_queue, OSYNC_QUEUE_SENDER, &error), NULL); fail_unless(error == NULL, NULL); @@ -2203,7 +2410,7 @@ osync_message_write_int(message, 4000000); osync_message_write_string(message, "this is a test string"); osync_message_write_long_long_int(message, 400000000); - osync_message_write_data(message, data, strlen(data) + 1); + osync_message_write_data(message, data5, strlen(data5) + 1); // Send with timeout of one second fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 1, &error), NULL); @@ -2212,13 +2419,7 @@ osync_message_unref(message); // Block - while (!(message = osync_queue_get_message(server_queue))) { - g_usleep(100000); - } - - fail_unless(osync_message_get_command(message) == OSYNC_MESSAGE_REPLY); - - osync_message_unref(message); + g_usleep(5*G_USEC_PER_SEC); osync_queue_disconnect(server_queue, &error); fail_unless(error == NULL, NULL); @@ -2259,6 +2460,199 @@ } END_TEST +void callback_handler7(OSyncMessage *message, void *user_data) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); + OSyncError *error = NULL; + + osync_assert(GPOINTER_TO_INT(user_data) == 1); + + num_msgs++; + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_REPLY); + + if (num_msgs >= req_msgs) { + osync_queue_disconnect(server_queue, &error); + osync_assert(error == NULL); + } + + osync_trace(TRACE_EXIT, "%s", __func__); +} + +void server_handler7(OSyncMessage *message, void *user_data) +{ + abort(); +} + +void client_handler7(OSyncMessage *message, void *user_data) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, user_data); + OSyncError *error = NULL; + + osync_assert(GPOINTER_TO_INT(user_data) ==1); + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_INITIALIZE); + + int int1; + long long int longint1; + char *string; + void *databuf; + + osync_message_read_int(message, &int1); + osync_message_read_const_string(message, &string); + osync_message_read_long_long_int(message, &longint1); + osync_message_read_const_data(message, &databuf, strlen("this is another test string") + 1); + + osync_assert(int1 == 4000000); + osync_assert(!strcmp(string, "this is a test string")); + osync_assert(longint1 == 400000000); + osync_assert(!strcmp(databuf, "this is another test string")); + + // Do some time consuming processing + g_usleep(1*G_USEC_PER_SEC); + + OSyncMessage *reply = osync_message_new_reply(message, &error); + + osync_queue_send_message(server_queue, NULL, reply, &error); + + osync_message_unref(reply); + + osync_trace(TRACE_EXIT, "%s", __func__); +} + +START_TEST (ipc_loop_with_timeout) +{ + + /* Even though each action takes 1 second, none of these messages should time out + as they are being sent with a timeout of 3 seconds */ + + num_msgs = 0; + req_msgs = 20; + + char *testbed = setup_testbed(NULL); + osync_testing_file_remove("/tmp/testpipe-server"); + osync_testing_file_remove("/tmp/testpipe-client"); + + OSyncError *error = NULL; + server_queue = osync_queue_new("/tmp/testpipe-server", &error); + client_queue = osync_queue_new("/tmp/testpipe-client", &error); + OSyncMessage *message = NULL; + + osync_queue_create(server_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_create(client_queue, &error); + fail_unless(error == NULL, NULL); + char *data = "this is another test string"; + + pid_t cpid = fork(); + if (cpid == 0) { //Child + + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(client_queue, client_handler7, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(client_queue, context); + + osync_thread_start(thread); + + osync_assert(osync_queue_connect(client_queue, OSYNC_QUEUE_RECEIVER, &error)); + osync_assert(error == NULL); + + osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); + osync_assert(error == NULL); + + osync_queue_cross_link(client_queue, server_queue); + + message = osync_queue_get_message(server_queue); + + if (osync_message_get_command(message) != OSYNC_MESSAGE_QUEUE_HUP) { + exit (1); + } + + osync_message_unref(message); + + if (osync_queue_disconnect(server_queue, &error) != TRUE || error != NULL) + exit(1); + osync_queue_unref(server_queue); + + osync_assert(osync_queue_disconnect(client_queue, &error)); + osync_assert(error == NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + osync_queue_unref(client_queue); + + g_free(testbed); + + exit(0); + } else { + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(server_queue, server_handler7, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(server_queue, context); + + osync_thread_start(thread); + + fail_unless(osync_queue_connect(client_queue, OSYNC_QUEUE_SENDER, &error), NULL); + fail_unless(error == NULL, NULL); + + fail_unless(osync_queue_connect(server_queue, OSYNC_QUEUE_RECEIVER, &error), NULL); + fail_unless(error == NULL, NULL); + + int i = 0; + for (i = 0; i < req_msgs; i++) { + message = osync_message_new(OSYNC_MESSAGE_INITIALIZE, 0, &error); + fail_unless(message != NULL, NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_write_int(message, 4000000); + osync_message_write_string(message, "this is a test string"); + osync_message_write_long_long_int(message, 400000000); + osync_message_write_data(message, data, strlen(data) + 1); + + osync_message_set_handler(message, callback_handler7, GINT_TO_POINTER(1)); + + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 3, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_unref(message); + } + + message = osync_queue_get_message(client_queue); + + fail_unless(osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP); + + osync_message_unref(message); + + osync_queue_disconnect(client_queue, &error); + fail_unless(error == NULL, NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + int status = 0; + wait(&status); + fail_unless(WEXITSTATUS(status) == 0, NULL); + } + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == TRUE, NULL); + + fail_unless(osync_queue_remove(client_queue, &error), NULL); + fail_unless(osync_queue_remove(server_queue, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == FALSE, NULL); + + osync_queue_unref(client_queue); + osync_queue_unref(server_queue); + + destroy_testbed(testbed); +} +END_TEST + OSYNC_TESTCASE_START("ipc") OSYNC_TESTCASE_ADD(ipc_new) OSYNC_TESTCASE_ADD(ipc_ref) @@ -2285,5 +2679,7 @@ OSYNC_TESTCASE_ADD(ipc_callback_break_pipes) OSYNC_TESTCASE_ADD(ipc_timeout) +OSYNC_TESTCASE_ADD(ipc_late_reply) +OSYNC_TESTCASE_ADD(ipc_loop_with_timeout) OSYNC_TESTCASE_END |
From: <dg...@su...> - 2009-02-03 18:19:46
|
Author: Graham Cobb Date: Tue Feb 3 19:17:50 2009 New Revision: 5253 URL: http://www.opensync.org/changeset/5253 Log: Fix ipc_loop_timeout_with_idle so it fails for the old timeou code and passes with the new code Modified: branches/timeout/ChangeLog branches/timeout/tests/ipc-tests/check_ipc.c Modified: branches/timeout/ChangeLog ============================================================================== --- branches/timeout/ChangeLog Tue Feb 3 00:37:13 2009 (r5252) +++ branches/timeout/ChangeLog Tue Feb 3 19:17:50 2009 (r5253) @@ -1,3 +1,8 @@ +2009-02-03 Graham Cobb <g+...@co...> + + * tests/ipc-tests/check_ipc.c (ipc_loop_timeout_with_idle): Change test parameters + so test completes within 30 second limit. + 2009-02-02 Graham Cobb <g+...@co...> * opensync/ipc/opensync_queue_private.h (OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT): Define Modified: branches/timeout/tests/ipc-tests/check_ipc.c ============================================================================== --- branches/timeout/tests/ipc-tests/check_ipc.c Tue Feb 3 00:37:13 2009 (r5252) +++ branches/timeout/tests/ipc-tests/check_ipc.c Tue Feb 3 19:17:50 2009 (r5253) @@ -2667,11 +2667,12 @@ /* Same as ipc_loop_with_timeout except that the client handler doesn't sleep, so the queue dispatchers can run while the operation is waiting. - Even though each action takes 1 second, none of these messages should time out - as they are being sent with a timeout of 3 seconds */ + Even though each action takes 1 second, and might be delayed by 3 seconds + due to the messages already processed on the pending queue, none of these + messages should time out as they are being sent with a timeout of 5 seconds */ num_msgs = 0; - req_msgs = 30; + req_msgs = 10; char *testbed = setup_testbed(NULL); osync_testing_file_remove("/tmp/testpipe-server"); @@ -2696,7 +2697,8 @@ OSyncThread *thread = osync_thread_new(context, &error); osync_queue_set_message_handler(client_queue, client_handler_first_part, GINT_TO_POINTER(1)); - osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); + // Set pending limit to 3 so response wil be delayed at most 3 seconds + osync_queue_set_pending_limit(client_queue, 3); osync_queue_setup_with_gmainloop(client_queue, context); @@ -2768,7 +2770,8 @@ osync_message_set_handler(message, callback_handler_check_reply, GINT_TO_POINTER(1)); - fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 10, &error), NULL); + // Timeout of 5 will do as pending limit is 3 + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 5, &error), NULL); fail_unless(!osync_error_is_set(&error), NULL); osync_message_unref(message); |
From: <dg...@su...> - 2009-02-02 23:38:58
|
Author: Graham Cobb Date: Tue Feb 3 00:37:13 2009 New Revision: 5252 URL: http://www.opensync.org/changeset/5252 Log: Add minimum value for pending queue timeout. Modified: branches/timeout/ChangeLog branches/timeout/opensync/ipc/opensync_queue.c branches/timeout/opensync/ipc/opensync_queue_private.h branches/timeout/tests/ipc-tests/check_ipc.c Modified: branches/timeout/ChangeLog ============================================================================== --- branches/timeout/ChangeLog Sun Feb 1 19:57:43 2009 (r5251) +++ branches/timeout/ChangeLog Tue Feb 3 00:37:13 2009 (r5252) @@ -1,3 +1,11 @@ +2009-02-02 Graham Cobb <g+...@co...> + + * opensync/ipc/opensync_queue_private.h (OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT): Define + minimum pending queue timeout. + + * opensync/ipc/opensync_queue.c (_osync_queue_restart_pending_timeout): Apply + minimum value to pending queue timeout. + 2009-02-01 Graham Cobb <g+...@co...> * tests/ipc-tests/check_ipc.c: Add ipc_timeout_noreceiver test. Modified: branches/timeout/opensync/ipc/opensync_queue.c ============================================================================== --- branches/timeout/opensync/ipc/opensync_queue.c Sun Feb 1 19:57:43 2009 (r5251) +++ branches/timeout/opensync/ipc/opensync_queue.c Tue Feb 3 00:37:13 2009 (r5252) @@ -268,8 +268,12 @@ by the caller before calling this function */ if (queue->max_timeout) { + unsigned int timeout; + timeout = queue->max_timeout + OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY; + if (timeout < OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT) + timeout = OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT; g_source_get_current_time(queue->timeout_source, &queue->pending_timeout); - queue->pending_timeout.tv_sec += queue->max_timeout + OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY; + queue->pending_timeout.tv_sec += timeout; } } Modified: branches/timeout/opensync/ipc/opensync_queue_private.h ============================================================================== --- branches/timeout/opensync/ipc/opensync_queue_private.h Sun Feb 1 19:57:43 2009 (r5251) +++ branches/timeout/opensync/ipc/opensync_queue_private.h Tue Feb 3 00:37:13 2009 (r5252) @@ -111,6 +111,9 @@ */ #define OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY 1 +/** @brief Pending queue minimum timeout + */ +#define OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT 20 /** @brief Timeout object */ Modified: branches/timeout/tests/ipc-tests/check_ipc.c ============================================================================== --- branches/timeout/tests/ipc-tests/check_ipc.c Sun Feb 1 19:57:43 2009 (r5251) +++ branches/timeout/tests/ipc-tests/check_ipc.c Tue Feb 3 00:37:13 2009 (r5252) @@ -3086,7 +3086,8 @@ osync_message_unref(message); - g_usleep(4*G_USEC_PER_SEC); + /* Note: OSYNC_QUEUE_PENDING_QUEUE_MIN_TIMEOUT is 20 */ + g_usleep(25*G_USEC_PER_SEC); /* Check if the timeout handler replied with an error. Note: it is important we check **before** we start disconnecting |
From: <dg...@su...> - 2009-02-01 18:59:31
|
Author: Graham Cobb Date: Sun Feb 1 19:57:43 2009 New Revision: 5251 URL: http://www.opensync.org/changeset/5251 Log: Completed: 6) Implement a mechanism to protect the queue itself: i.e. is the receiver still reading the queue? And added unit test (ipc_timeout_noreceiver) The timeout changes now seem to be completed. Modified: branches/timeout/ChangeLog branches/timeout/opensync/ipc/opensync_queue.c branches/timeout/opensync/ipc/opensync_queue_private.h branches/timeout/tests/CMakeLists.txt branches/timeout/tests/ipc-tests/check_ipc.c Modified: branches/timeout/ChangeLog ============================================================================== --- branches/timeout/ChangeLog Sun Feb 1 00:00:34 2009 (r5250) +++ branches/timeout/ChangeLog Sun Feb 1 19:57:43 2009 (r5251) @@ -1,3 +1,17 @@ +2009-02-01 Graham Cobb <g+...@co...> + + * tests/ipc-tests/check_ipc.c: Add ipc_timeout_noreceiver test. + + * opensync/ipc/opensync_queue.c (osync_queue_send_message_with_timeout): Track maximum + timeout seen. Start pending queue timeout. + (_osync_queue_remove_pending_reply): restart pending queue timeout if necessary + (_osync_queue_restart_pending_timeout): Add function to start/restart pending queue timeout + (_timeout_check): Fix calculation of expiry of timeout. Add pending queue timeout. + (_timeout_dispatch): Fix calculation of expiry of timeout. Add pending queue timeout. + + * opensync/ipc/opensync_queue_private.h: Add max_timeout and pending_timeout fields (to queue). + (OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY): Add value to assume for IPC delay in pending queue timout. + 2009-01-25 Graham Cobb <g+...@co...> * opensync/engine/opensync_sink_engine.c (osync_sink_engine_new): Ref objengine [Bug #1052] Modified: branches/timeout/opensync/ipc/opensync_queue.c ============================================================================== --- branches/timeout/opensync/ipc/opensync_queue.c Sun Feb 1 00:00:34 2009 (r5250) +++ branches/timeout/opensync/ipc/opensync_queue.c Sun Feb 1 19:57:43 2009 (r5251) @@ -29,6 +29,30 @@ #include "opensync_queue_internals.h" #include "opensync_queue_private.h" +static gboolean _osync_queue_generate_error(OSyncQueue *queue, OSyncMessageCommand errcode, OSyncError **error) +{ + OSyncMessage *message; + + queue->connected = FALSE; + + /* Now we can send the hup message, and wake up the consumer thread so + * it can pickup the messages in the incoming queue */ + message = osync_message_new(errcode, 0, error); + if (!message) { + return FALSE; + } + osync_trace(TRACE_INTERNAL, "Generating incoming error message %p(%s), id= %lli", message, osync_message_get_commandstr(message), osync_message_get_id(message)); + + osync_message_ref(message); + + g_async_queue_push(queue->incoming, message); + + if (queue->incomingContext) + g_main_context_wakeup(queue->incomingContext); + + return TRUE; +} + static gboolean _timeout_prepare(GSource *source, gint *timeout_) { /* TODO adapt *timeout_ value to shortest message timeout value... @@ -55,6 +79,16 @@ * list since another thread might be duing the updates */ g_mutex_lock(queue->pendingLock); + /* First check the overall queue timer */ + if (queue->pendingCount> 0 && queue->pending_timeout.tv_sec > 0) { + if (current_time.tv_sec > queue->pending_timeout.tv_sec + || (current_time.tv_sec == queue->pending_timeout.tv_sec + && current_time.tv_usec >= queue->pending_timeout.tv_usec) ) { + g_mutex_unlock(queue->pendingLock); + return TRUE; + } + } + for (p = queue->pendingReplies; p; p = p->next) { pending = p->data; @@ -63,7 +97,7 @@ toinfo = pending->timeout_info; - if (current_time.tv_sec >= toinfo->expiration.tv_sec + if (current_time.tv_sec > toinfo->expiration.tv_sec || (current_time.tv_sec == toinfo->expiration.tv_sec && current_time.tv_usec >= toinfo->expiration.tv_usec)) { /* Unlock the pending lock since the messages might be sent during the callback */ @@ -96,6 +130,18 @@ * list since another thread might be duing the updates */ g_mutex_lock(queue->pendingLock); + /* First check the overall queue timer */ + if (queue->pendingCount> 0 && queue->pending_timeout.tv_sec > 0) { + if (current_time.tv_sec > queue->pending_timeout.tv_sec + || (current_time.tv_sec == queue->pending_timeout.tv_sec + && current_time.tv_usec >= queue->pending_timeout.tv_usec) ) { + /* The queue has died. Generate an error */ + osync_trace(TRACE_INTERNAL, "%s: Pending queue timer expired: receiver must have died", __func__); + _osync_queue_generate_error(queue, OSYNC_MESSAGE_QUEUE_ERROR, NULL); + queue->pending_timeout.tv_sec = 0; // Stop timer + } + } + for (p = queue->pendingReplies; p; p = p->next) { pending = p->data; @@ -104,8 +150,8 @@ toinfo = pending->timeout_info; - if (current_time.tv_sec == toinfo->expiration.tv_sec || - (current_time.tv_sec >= toinfo->expiration.tv_sec + if (current_time.tv_sec > toinfo->expiration.tv_sec || + (current_time.tv_sec == toinfo->expiration.tv_sec && current_time.tv_usec >= toinfo->expiration.tv_usec)) { OSyncError *error = NULL; OSyncError *timeouterr = NULL; @@ -182,30 +228,6 @@ return FALSE; } -static gboolean _osync_queue_generate_error(OSyncQueue *queue, OSyncMessageCommand errcode, OSyncError **error) -{ - OSyncMessage *message; - - queue->connected = FALSE; - - /* Now we can send the hup message, and wake up the consumer thread so - * it can pickup the messages in the incoming queue */ - message = osync_message_new(errcode, 0, error); - if (!message) { - return FALSE; - } - osync_trace(TRACE_INTERNAL, "Generating incoming error message %p(%s), id= %lli", message, osync_message_get_commandstr(message), osync_message_get_id(message)); - - osync_message_ref(message); - - g_async_queue_push(queue->incoming, message); - - if (queue->incomingContext) - g_main_context_wakeup(queue->incomingContext); - - return TRUE; -} - static void _osync_send_timeout_response(OSyncMessage *errormsg, void *user_data) { OSyncQueue *queue = user_data; @@ -229,6 +251,28 @@ osync_trace(TRACE_EXIT, "%s", __func__); } +/* Restart the pending queue timeout */ +static void _osync_queue_restart_pending_timeout(OSyncQueue *queue) +{ + /* Note that the pending queue timeout is just to make sure that progress is being made. + It does not time individual commands -- it just makes sure that responses are being + received for outstanding commands at some rate. Individual message timeouts are + handled at the receiver. The main purpose of this timer is to detect if the + receiver has stopped receiving for some reason. + + The timer is started when the first message is put on the pending queue and is reset + and restarted whenever a response is received. The timeout value is based on the + largest message timeout seen to date. */ + + /* Note: queue->pending_timout is protected by the pending lock, which should be held + by the caller before calling this function */ + + if (queue->max_timeout) { + g_source_get_current_time(queue->timeout_source, &queue->pending_timeout); + queue->pending_timeout.tv_sec += queue->max_timeout + OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY; + } +} + /* Find and remove a pending message that this message is a reply to */ static void _osync_queue_remove_pending_reply(OSyncQueue *queue, OSyncMessage *reply, gboolean callback) { @@ -255,7 +299,8 @@ gets called twice! */ queue->pendingReplies = osync_list_remove(queue->pendingReplies, pending); - queue->pendingCount--; + if (--queue->pendingCount != 0) + _osync_queue_restart_pending_timeout(queue); /* Unlock the pending lock since the messages might be sent during the callback */ g_mutex_unlock(queue->pendingLock); @@ -300,7 +345,7 @@ osync_message_get_timeout(message), osync_message_get_id(message)); if (osync_message_get_cmd(message) == OSYNC_MESSAGE_REPLY || osync_message_get_cmd(message) == OSYNC_MESSAGE_ERRORREPLY) { - /* Remove pending reply and call callback */ + /* Remove pending reply and call callback*/ _osync_queue_remove_pending_reply(queue, message, TRUE); } else { unsigned int timeout = osync_message_get_timeout(message); @@ -1312,6 +1357,9 @@ if (timeout) { /* Send timeout info to other end to handle */ osync_message_set_timeout(message, timeout); + /* Note largest timeout seen */ + if (timeout > replyqueue->max_timeout) + replyqueue->max_timeout = timeout; } else { osync_trace(TRACE_INTERNAL, "handler message got sent without timeout!: %s", osync_message_get_commandstr(message)); } @@ -1320,7 +1368,10 @@ pending->user_data = osync_message_get_handler_data(message); replyqueue->pendingReplies = osync_list_append(replyqueue->pendingReplies, pending); - replyqueue->pendingCount++; + if (replyqueue->pendingCount++ == 0) { + /* Start queue timeout */ + _osync_queue_restart_pending_timeout(replyqueue); + } g_mutex_unlock(replyqueue->pendingLock); } Modified: branches/timeout/opensync/ipc/opensync_queue_private.h ============================================================================== --- branches/timeout/opensync/ipc/opensync_queue_private.h Sun Feb 1 00:00:34 2009 (r5250) +++ branches/timeout/opensync/ipc/opensync_queue_private.h Sun Feb 1 19:57:43 2009 (r5251) @@ -99,8 +99,18 @@ /* Disconnect in progress */ gboolean disc_in_progress; + + /* Largest timeout value seen so far */ + unsigned int max_timeout; + + /* Expiration time of pending queue timeout */ + GTimeVal pending_timeout; }; +/** @brief Pending queue timeout addition for ipc delay + */ +#define OSYNC_QUEUE_PENDING_QUEUE_IPC_DELAY 1 + /** @brief Timeout object */ Modified: branches/timeout/tests/CMakeLists.txt ============================================================================== --- branches/timeout/tests/CMakeLists.txt Sun Feb 1 00:00:34 2009 (r5250) +++ branches/timeout/tests/CMakeLists.txt Sun Feb 1 19:57:43 2009 (r5251) @@ -250,6 +250,7 @@ OSYNC_TESTCASE(ipc ipc_late_reply) OSYNC_TESTCASE(ipc ipc_loop_timeout_with_idle) OSYNC_TESTCASE(ipc ipc_timeout_noreplyq) +OSYNC_TESTCASE(ipc ipc_timeout_noreceiver) ENDIF (NOT WIN32) BUILD_CHECK_TEST( mapping mapping-tests/check_mapping.c ${TEST_TARGET_LIBRARIES} ) Modified: branches/timeout/tests/ipc-tests/check_ipc.c ============================================================================== --- branches/timeout/tests/ipc-tests/check_ipc.c Sun Feb 1 00:00:34 2009 (r5250) +++ branches/timeout/tests/ipc-tests/check_ipc.c Sun Feb 1 19:57:43 2009 (r5251) @@ -2985,6 +2985,141 @@ } END_TEST +START_TEST (ipc_timeout_noreceiver) +{ + /* This testcase is intended to test the case where the receiver is not even listening, + and so does not run the timeout. + */ + + char *testbed = setup_testbed(NULL); + osync_testing_file_remove("/tmp/testpipe-server"); + osync_testing_file_remove("/tmp/testpipe-client"); + + num_callback_timeout = 0; + num_callback = 0; + + OSyncError *error = NULL; + server_queue = osync_queue_new("/tmp/testpipe-server", &error); + client_queue = osync_queue_new("/tmp/testpipe-client", &error); + OSyncMessage *message = NULL; + + osync_queue_create(server_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_create(client_queue, &error); + fail_unless(error == NULL, NULL); + + pid_t cpid = fork(); + if (cpid == 0) { //Child + + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(client_queue, client_handler1, GINT_TO_POINTER(1)); + osync_queue_set_pending_limit(client_queue, OSYNC_QUEUE_PENDING_LIMIT); + + /* Do not start receiver */ + /* osync_queue_setup_with_gmainloop(client_queue, context); */ + + osync_thread_start(thread); + + osync_assert(osync_queue_connect(client_queue, OSYNC_QUEUE_RECEIVER, &error)); + osync_assert(error == NULL); + + osync_assert(osync_queue_connect(server_queue, OSYNC_QUEUE_SENDER, &error)); + osync_assert(error == NULL); + + /* Do not cross-link */ + osync_queue_cross_link(client_queue, server_queue); + + message = osync_queue_get_message(server_queue); + + osync_assert(osync_message_get_command(message) == OSYNC_MESSAGE_QUEUE_HUP); + + osync_message_unref(message); + + if (osync_queue_disconnect(server_queue, &error) != TRUE || error != NULL) + exit(1); + osync_queue_unref(server_queue); + + osync_assert(osync_queue_disconnect(client_queue, &error)); + osync_assert(error == NULL); + + osync_thread_stop(thread); + osync_thread_unref(thread); + + osync_queue_unref(client_queue); + + g_free(testbed); + + exit(0); + } else { + GMainContext *context = g_main_context_new(); + OSyncThread *thread = osync_thread_new(context, &error); + + osync_queue_set_message_handler(server_queue, server_handler4, GINT_TO_POINTER(1)); + + osync_queue_setup_with_gmainloop(server_queue, context); + + osync_thread_start(thread); + + fail_unless(osync_queue_connect(client_queue, OSYNC_QUEUE_SENDER, &error), NULL); + fail_unless(error == NULL, NULL); + + fail_unless(osync_queue_connect(server_queue, OSYNC_QUEUE_RECEIVER, &error), NULL); + fail_unless(error == NULL, NULL); + + message = osync_message_new(OSYNC_MESSAGE_INITIALIZE, 0, &error); + fail_unless(message != NULL, NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_set_handler(message, _message_handler, NULL); + + osync_message_write_int(message, 4000000); + osync_message_write_string(message, "this is a test string"); + osync_message_write_long_long_int(message, 400000000); + osync_message_write_data(message, data5, strlen(data5) + 1); + + // Send with timeout of one second + fail_unless(osync_queue_send_message_with_timeout(client_queue, server_queue, message, 1, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + osync_message_unref(message); + + g_usleep(4*G_USEC_PER_SEC); + + /* Check if the timeout handler replied with an error. + Note: it is important we check **before** we start disconnecting + otherwise we are not testing the right thing */ + fail_unless(num_callback_timeout == 1, NULL); + fail_unless(num_callback == 0, NULL); + + osync_queue_disconnect(client_queue, &error); + fail_unless(error == NULL, NULL); + + osync_queue_disconnect(server_queue, &error); + fail_unless(error == NULL, NULL); + + int status = 0; + wait(&status); + fail_unless(WEXITSTATUS(status) == 0, NULL); + } + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == TRUE, NULL); + + fail_unless(osync_queue_remove(client_queue, &error), NULL); + fail_unless(osync_queue_remove(server_queue, &error), NULL); + fail_unless(!osync_error_is_set(&error), NULL); + + fail_unless(osync_testing_file_exists("/tmp/testpipe-client") == FALSE, NULL); + + osync_queue_unref(client_queue); + osync_queue_unref(server_queue); + + destroy_testbed(testbed); +} +END_TEST + OSYNC_TESTCASE_START("ipc") OSYNC_TESTCASE_ADD(ipc_new) OSYNC_TESTCASE_ADD(ipc_ref) @@ -3015,5 +3150,6 @@ OSYNC_TESTCASE_ADD(ipc_loop_with_timeout) OSYNC_TESTCASE_ADD(ipc_loop_timeout_with_idle) OSYNC_TESTCASE_ADD(ipc_timeout_noreplyq) +OSYNC_TESTCASE_ADD(ipc_timeout_noreceiver) OSYNC_TESTCASE_END |
From: <dg...@su...> - 2009-01-31 23:02:10
|
Author: henrik Date: Sun Feb 1 00:00:34 2009 New Revision: 5250 URL: http://www.opensync.org/changeset/5250 Log: Add test just to log platform info Added: plugins/mozilla-sync/trunk/tests/blackbox_test_platform.sh (contents, props changed) Modified: plugins/mozilla-sync/trunk/tests/CMakeLists.txt Modified: plugins/mozilla-sync/trunk/tests/CMakeLists.txt ============================================================================== --- plugins/mozilla-sync/trunk/tests/CMakeLists.txt Sat Jan 31 23:58:15 2009 (r5249) +++ plugins/mozilla-sync/trunk/tests/CMakeLists.txt Sun Feb 1 00:00:34 2009 (r5250) @@ -28,6 +28,7 @@ ADD_TEST( unit_test_abook "unit_test_abook" ) CONFIGURE_FILE( "blackbox_test_common.shinc.in" "tests/blackbox_test_common.shinc" @ONLY ) +CONFIGURE_FILE( "blackbox_test_platform.sh" "tests/blackbox_test_platform.sh" @ONLY ) CONFIGURE_FILE( "blackbox_test_init_thunderbird.sh" "tests/blackbox_test_init_thunderbird.sh" COPYONLY) CONFIGURE_FILE( "blackbox_test_init_osynctool.sh" "tests/blackbox_test_init_osynctool.sh" COPYONLY) CONFIGURE_FILE( "blackbox_test_abook_vcard_compare.sh" "tests/blackbox_test_abook_vcard_compare.sh" COPYONLY) @@ -57,6 +58,7 @@ CONFIGURE_FILE( "blackbox_test_cal_vcard_base/2" "tests/blackbox_test_cal_vcard_base/2" COPYONLY) CONFIGURE_FILE( "blackbox_test_cal_vevent_additional/add1" "tests/blackbox_test_cal_vevent_additional/add1" COPYONLY) +ADD_TEST( blackbox_test_platform bash "blackbox_test_platform.sh" ) ADD_TEST( blackbox_test_init_thunderbird bash "blackbox_test_init_thunderbird.sh" ) ADD_TEST( blackbox_test_init_osynctool bash "blackbox_test_init_osynctool.sh" ) ADD_TEST( blackbox_test_abook_vcard_compare bash "blackbox_test_abook_vcard_compare.sh" ) Added: plugins/mozilla-sync/trunk/tests/blackbox_test_platform.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ plugins/mozilla-sync/trunk/tests/blackbox_test_platform.sh Sun Feb 1 00:00:34 2009 (r5250) @@ -0,0 +1,31 @@ +#!/bin/bash + +# ====================================================== +# This file is part of the mozilla-sync plugin for OpenSync +# See http://www.KaarPoSoft.dk/bluezync +# $Id$ +# ====================================================== + +# Show info about platform +# This test should not fail, and is just included +# to show info about the platform where the tests are executed + +SCRIPT_NAME=`basename $0`; SCRIPT_NAME=${SCRIPT_NAME%.sh} +SRC_DIR=`(cd \`dirname $0\`; pwd)` +source "${SRC_DIR}/blackbox_test_common.shinc" + +initialize_test "Platform information" + +echo "uname -a" +uname -a + +echo "lsb_release -a" +lsb_release -a || true + +echo "thunderbird --version" +thunderbird --version + +echo "sunbird --version" +sunbird --version + +success_exit |