hangs waiting for timer..

git-svn-id: https://protobuf-c.googlecode.com/svn/trunk@125 00440858-1255-0410-a3e6-75ea37f81c3a
This commit is contained in:
lahiker42 2009-01-28 05:29:56 +00:00
parent b4675f4474
commit d2995318bd
4 changed files with 128 additions and 10 deletions

View File

@ -114,6 +114,7 @@ ProtobufCDispatch *protobuf_c_dispatch_new (ProtobufCAllocator *allocator)
rv->base.changes = ALLOC (sizeof (ProtobufC_FDNotify) * rv->changes_alloced);
rv->fd_map_size = 16;
rv->fd_map = ALLOC (sizeof (FDMap) * rv->fd_map_size);
rv->allocator = allocator;
memset (rv->fd_map, 255, sizeof (FDMap) * rv->fd_map_size);
return &rv->base;
}
@ -141,7 +142,7 @@ ProtobufCDispatch *protobuf_c_dispatch_default (void)
{
static ProtobufCDispatch *def = NULL;
if (def == NULL)
def = protobuf_c_dispatch_new (NULL);
def = protobuf_c_dispatch_new (&protobuf_c_default_allocator);
return def;
}

View File

@ -8,6 +8,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
@ -693,6 +694,21 @@ destroy_client_rpc (ProtobufCService *service)
client->allocator->free (client->allocator, client);
}
static void
trivial_sync_libc_resolver (ProtobufCDispatch *dispatch,
const char *name,
ProtobufC_NameLookup_Found found_func,
ProtobufC_NameLookup_Failed failed_func,
void *callback_data)
{
struct hostent *ent;
ent = gethostbyname (name);
if (ent == NULL)
failed_func (hstrerror (h_errno), callback_data);
else
found_func ((const uint8_t *) ent->h_addr_list[0], callback_data);
}
ProtobufCService *protobuf_c_rpc_client_new (ProtobufC_RPC_AddressType type,
const char *name,
const ProtobufCServiceDescriptor *descriptor,
@ -712,10 +728,32 @@ ProtobufCService *protobuf_c_rpc_client_new (ProtobufC_RPC_AddressType type,
rv->name = strcpy (allocator->alloc (allocator, strlen (name) + 1), name);
rv->state = PROTOBUF_C_CLIENT_STATE_INIT;
rv->fd = -1;
rv->autoretry = 1;
rv->autoretry_millis = 2*1000;
rv->resolver = trivial_sync_libc_resolver;
rv->info.init.idle = protobuf_c_dispatch_add_idle (dispatch, handle_init_idle, rv);
return &rv->base_service;
}
protobuf_c_boolean
protobuf_c_rpc_client_is_connected (ProtobufC_RPC_Client *client)
{
return client->state == PROTOBUF_C_CLIENT_STATE_CONNECTED;
}
void
protobuf_c_rpc_client_set_autoretry_period (ProtobufC_RPC_Client *client,
unsigned millis)
{
client->autoretry = 1;
client->autoretry_millis = millis;
}
void
protobuf_c_rpc_client_disable_autoretry (ProtobufC_RPC_Client *client)
{
client->autoretry = 0;
}
/* === Server === */
typedef struct _ServerRequest ServerRequest;
typedef struct _ServerConnection ServerConnection;
@ -1163,3 +1201,23 @@ protobuf_c_rpc_server_new (ProtobufC_RPC_AddressType type,
}
return server_new_from_fd (fd, name, service, dispatch);
}
ProtobufCService *
protobuf_c_rpc_server_destroy (ProtobufC_RPC_Server *server,
protobuf_c_boolean destroy_underlying)
{
ProtobufCService *rv = destroy_underlying ? NULL : server->underlying;
while (server->first_connection != NULL)
server_connection_close (server->first_connection);
server->allocator->free (server->allocator, server->bind_name);
while (server->recycled_requests != NULL)
{
ServerRequest *req = server->recycled_requests;
server->recycled_requests = req->info.recycled.next;
server->allocator->free (server->allocator, req);
}
if (destroy_underlying)
protobuf_c_service_destroy (server->underlying);
server->allocator->free (server->allocator, server);
return rv;
}

View File

@ -78,6 +78,9 @@ void protobuf_c_rpc_client_disable_autoretry (ProtobufC_RPC_Client *client);
void protobuf_c_rpc_client_set_autoretry_period (ProtobufC_RPC_Client *client,
unsigned millis);
/* checking the state of the client */
protobuf_c_boolean protobuf_c_rpc_client_is_connected (ProtobufC_RPC_Client *client);
/* NOTE: we don't actually start connecting til the main-loop runs,
so you may configure the client immediately after creation */

View File

@ -39,6 +39,7 @@ test__by_name (Foo__DirLookup_Service *service,
person.n_phone = 1;
person.phone = pns;
person.email = email;
person.name = name->name;
result.person = &person;
}
closure (&result, closure_data);
@ -82,6 +83,14 @@ test_not_found_closure (const Foo__LookupResult *result,
* (protobuf_c_boolean *) closure_data = 1;
}
static void
test_defunct_closure (const Foo__LookupResult *result,
void *closure_data)
{
assert (result == NULL);
* (protobuf_c_boolean *) closure_data = 1;
}
static void
test_service (ProtobufCService *service)
@ -93,28 +102,61 @@ test_service (ProtobufCService *service)
is_done = 0;
foo__dir_lookup__by_name (service, &name, test_dave_closure, &is_done);
while (!is_done)
protobuf_c_dispatch_run_once (protobuf_c_dispatch_default ());
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
name.name = "joe the plumber";
is_done = 0;
foo__dir_lookup__by_name (service, &name, test_joe_the_plumber_closure, &is_done);
while (!is_done)
protobuf_c_dispatch_run_once (protobuf_c_dispatch_default ());
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
name.name = "asdfvcvzxsa";
is_done = 0;
foo__dir_lookup__by_name (service, &name, test_not_found_closure, &is_done);
while (!is_done)
protobuf_c_dispatch_run_once (protobuf_c_dispatch_default ());
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
}
static void
test_defunct_client (ProtobufCService *service)
{
Foo__Name name = FOO__NAME__INIT;
protobuf_c_boolean is_done;
name.name = "dave";
is_done = 0;
foo__dir_lookup__by_name (service, &name, test_defunct_closure, &is_done);
while (!is_done)
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
name.name = "joe the plumber";
is_done = 0;
foo__dir_lookup__by_name (service, &name, test_defunct_closure, &is_done);
while (!is_done)
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
name.name = "asdfvcvzxsa";
is_done = 0;
foo__dir_lookup__by_name (service, &name, test_defunct_closure, &is_done);
while (!is_done)
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
}
/* --- main() --- */
static void
set_boolean_true (ProtobufCDispatch *dispatch,
void *func_data)
{
(void) dispatch;
* (protobuf_c_boolean *) func_data = 1;
}
int main()
{
protobuf_c_boolean is_done;
ProtobufCService *local_service = (ProtobufCService *) &the_dir_lookup_service;
ProtobufCService *remote_service;
ProtobufC_RPC_Client *client;
ProtobufC_RPC_Server *server;
test_service (local_service);
@ -132,7 +174,7 @@ int main()
250, set_boolean_true, &is_done);
while (!is_done)
{
protobuf_c_dispatch_run_once (protobuf_c_dispatch_default ());
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
assert (!protobuf_c_rpc_client_is_connected (client));
}
@ -146,7 +188,7 @@ int main()
protobuf_c_dispatch_add_timer_millis (protobuf_c_dispatch_default (),
250, set_boolean_true, &is_done);
while (!is_done && !protobuf_c_rpc_client_is_connected (client))
protobuf_c_dispatch_run_once (protobuf_c_dispatch_default ());
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
/* technically, there's no way to know how long it'll take to connect
if the machine is heavily loaded, so the following
@ -156,17 +198,31 @@ int main()
/* wait for the timer to elapse, since that's laziest way to handle it. */
while (!is_done)
protobuf_c_dispatch_run_once (protobuf_c_dispatch_default ());
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
/* Test the client */
test_service (remote_service);
/* Destroy the server and ensure that a request is failed in
a timely fashion. */
...
protobuf_c_rpc_server_destroy (server, 0);
server = NULL;
test_defunct_client (remote_service);
/* Create a server again and wait for the client to reconnect. */
...
server = protobuf_c_rpc_server_new (PROTOBUF_C_RPC_ADDRESS_LOCAL,
"test.socket",
local_service,
NULL);
assert (server != NULL);
is_done = 0;
while (!is_done)
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
protobuf_c_dispatch_add_timer_millis (protobuf_c_dispatch_default (),
250, set_boolean_true, &is_done);
while (!is_done)
protobuf_c_dispatch_run (protobuf_c_dispatch_default ());
assert (protobuf_c_rpc_client_is_connected (client));
/* Test the client again, for kicks. */
test_service (remote_service);
@ -175,7 +231,7 @@ int main()
protobuf_c_service_destroy (remote_service);
/* Destroy the server */
protobuf_c_rpc_server_destroy (server);
protobuf_c_rpc_server_destroy (server, 0);
return 0;
}