From e0dbd4c248a94201ac4a54d24a86fcbe8912a143 Mon Sep 17 00:00:00 2001 From: killing Date: Sun, 25 Dec 2011 11:07:36 +0800 Subject: [PATCH] Multiple services support in searpc server. --- demo/demo-async-client.c | 2 +- demo/searpc-demo-server.c | 6 ++-- lib/searpc-server.c | 75 +++++++++++++++++++++++++++++++++------ lib/searpc-server.h | 30 +++++++++++++--- tests/test-searpc.c | 17 ++++----- 5 files changed, 104 insertions(+), 26 deletions(-) diff --git a/demo/demo-async-client.c b/demo/demo-async-client.c index 0c7c6c4..76a983f 100644 --- a/demo/demo-async-client.c +++ b/demo/demo-async-client.c @@ -77,7 +77,7 @@ static void strlen_callback(void *vresult, void *user_data, GError *error) { const char *str = user_data; - int len = (int)(long)vresult; + int len = *((int *)vresult); g_assert (strcmp(str, "user data") == 0); printf("the length of string 'hello searpc' is %d.\n", len); diff --git a/demo/searpc-demo-server.c b/demo/searpc-demo-server.c index 76ca891..adb9902 100644 --- a/demo/searpc-demo-server.c +++ b/demo/searpc-demo-server.c @@ -29,13 +29,15 @@ static void start_rpc_service(void) { searpc_server_init(); + searpc_create_service("searpc-demo"); /* The first parameter is the implementation function. * The second parameter is the name of the rpc function the * client would call. * The third parameter is the signature. */ - searpc_server_register_function(searpc_strlen, + searpc_server_register_function("searpc-demo", + searpc_strlen, "searpc_strlen", searpc_signature_int__string()); } @@ -106,7 +108,7 @@ main(int argc, char *argv[]) gsize ret_len; int fcall_len = ntohs(pac->length); /* Execute the RPC function */ - char *res = searpc_server_call_function (pac->data, fcall_len, + char *res = searpc_server_call_function ("searpc-demo", pac->data, fcall_len, &ret_len, &error); pac_ret = (packet *)buf; diff --git a/lib/searpc-server.c b/lib/searpc-server.c index 9b0fe74..95d44dc 100644 --- a/lib/searpc-server.c +++ b/lib/searpc-server.c @@ -27,6 +27,13 @@ typedef struct FuncItem { MarshalItem *marshal; } FuncItem; +typedef struct { + char *name; + GHashTable *func_table; +} SearpcService; + +static GHashTable *marshal_table; +static GHashTable *service_table; static void func_item_free (FuncItem *item) @@ -42,9 +49,42 @@ marshal_item_free (MarshalItem *item) g_free (item); } -static GHashTable *marshal_table; -static GHashTable *func_table; +int +searpc_create_service (const char *svc_name) +{ + SearpcService *service; + if (!svc_name) + return -1; + + if (g_hash_table_lookup (service_table, svc_name) != NULL) + return 0; + + service = g_new0 (SearpcService, 1); + service->name = g_strdup(svc_name); + service->func_table = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, (GDestroyNotify)func_item_free); + + g_hash_table_insert (service_table, service->name, service); + + return 0; +} + +static void +service_free (SearpcService *service) +{ + g_free (service->name); + g_hash_table_destroy (service->func_table); + g_free (service); +} + +void +searpc_remove_service (const char *svc_name) +{ + if (!svc_name) + return; + g_hash_table_remove (service_table, svc_name); +} /* Marshal functions */ static inline void @@ -124,10 +164,10 @@ marshal_set_ret_common (JsonObject *object, gsize *len, GError *error) void searpc_server_init () { - func_table = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, (GDestroyNotify)func_item_free); marshal_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)marshal_item_free); + service_table = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, (GDestroyNotify)service_free); /* register buildin marshal functions */ register_marshals(marshal_table); @@ -136,7 +176,7 @@ searpc_server_init () void searpc_server_final() { - g_hash_table_destroy (func_table); + g_hash_table_destroy (service_table); g_hash_table_destroy (marshal_table); } @@ -162,12 +202,18 @@ searpc_server_register_marshal (gchar *signature, SearpcMarshalFunc marshal) } gboolean -searpc_server_register_function (void *func, const gchar *fname, gchar *signature) +searpc_server_register_function (const char *svc_name, + void *func, const gchar *fname, gchar *signature) { + SearpcService *service; FuncItem *item; MarshalItem *mitem; - g_assert (func != NULL && fname != NULL && signature != NULL); + g_assert (svc_name != NULL && func != NULL && fname != NULL && signature != NULL); + + service = g_hash_table_lookup (service_table, svc_name); + if (!service) + return FALSE; mitem = g_hash_table_lookup (marshal_table, signature); if (!mitem) { @@ -180,7 +226,7 @@ searpc_server_register_function (void *func, const gchar *fname, gchar *signatur item->fname = g_strdup(fname); item->func = func; - g_hash_table_insert (func_table, (gpointer)item->fname, item); + g_hash_table_insert (service->func_table, (gpointer)item->fname, item); g_free (signature); return TRUE; @@ -188,8 +234,10 @@ searpc_server_register_function (void *func, const gchar *fname, gchar *signatur /* Called by RPC transport. */ gchar* -searpc_server_call_function (gchar *func, gsize len, gsize *ret_len, GError **error) +searpc_server_call_function (const char *svc_name, + gchar *func, gsize len, gsize *ret_len, GError **error) { + SearpcService *service; JsonParser *parser; JsonNode *root; JsonArray *array; @@ -200,6 +248,13 @@ searpc_server_call_function (gchar *func, gsize len, gsize *ret_len, GError **er #endif g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + service = g_hash_table_lookup (service_table, svc_name); + if (!service) { + g_warning ("[SeaRPC] cannot find service %s.\n", svc_name); + g_set_error (error, 0, 501, "cannot find service %s.", svc_name); + return NULL; + } parser = json_parser_new (); @@ -213,7 +268,7 @@ searpc_server_call_function (gchar *func, gsize len, gsize *ret_len, GError **er array = json_node_get_array (root); const char *fname = json_array_get_string_element(array, 0); - FuncItem *fitem = g_hash_table_lookup(func_table, fname); + FuncItem *fitem = g_hash_table_lookup(service->func_table, fname); if (!fitem) { g_warning ("[SeaRPC] cannot find function %s.\n", fname); g_set_error (error, 0, 500, "cannot find function %s.", fname); diff --git a/lib/searpc-server.h b/lib/searpc-server.h index cfb87a2..bcdf1cf 100644 --- a/lib/searpc-server.h +++ b/lib/searpc-server.h @@ -22,6 +22,23 @@ void searpc_server_init (); */ void searpc_server_final (); +/** + * searpc_create_service: + * + * Create a new service. Service is a set of functions. + * The new service will be registered to the server. + * + * @svc_name: Service name. + */ +int searpc_create_service (const char *svc_name); + +/** + * searpc_remove_service: + * + * Remove the service from the server. + */ +void searpc_remove_service (const char *svc_name); + /** * searpc_server_register_marshal: * @@ -36,26 +53,29 @@ gboolean searpc_server_register_marshal (gchar *signature, /** * searpc_server_register_function: * - * Register a rpc function with given signature. - * + * Register a rpc function with given signature to a service. + * * @signature: the signature of the function, register_function() will take * owner of this string. */ -gboolean searpc_server_register_function (void* func, +gboolean searpc_server_register_function (const char *service, + void* func, const gchar *fname, gchar *signature); /** * searpc_server_call_function: + * @service: service name. * @func: the serialized representation of the function to call. * @len: length of @func. * @ret_len: the length of the returned string. * - * Call a registered function @func. + * Call a registered function @func of a service. * * Returns the serialized representatio of the returned value. */ -gchar *searpc_server_call_function (gchar *func, gsize len, gsize *ret_len, +gchar *searpc_server_call_function (const char *service, + gchar *func, gsize len, gsize *ret_len, GError **error); /** diff --git a/tests/test-searpc.c b/tests/test-searpc.c index 20f285f..557f26d 100644 --- a/tests/test-searpc.c +++ b/tests/test-searpc.c @@ -172,7 +172,7 @@ void test_simple_call (void *fixture, const void *data) fcall = searpc_client_fcall__string_int ("get_substring", "hello", 2, &fcall_len); - fret = searpc_server_call_function (fcall, fcall_len, &ret_len, &error); + fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error); g_assert (error == NULL); result = searpc_client_fret__string (fret, ret_len, &error); g_assert (strcmp(result, "he") == 0); @@ -184,7 +184,7 @@ void test_simple_call (void *fixture, const void *data) result = NULL; fcall = searpc_client_fcall__string_int ("get_substring", "hello", 7, &fcall_len); - fret = searpc_server_call_function (fcall, fcall_len, &ret_len, &error); + fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error); g_assert (error == NULL); result = searpc_client_fret__string (fret, ret_len, &error); g_assert (error->message); @@ -208,7 +208,7 @@ void test_object_call (void *fixture, const void *data) fcall = searpc_client_fcall__string ("get_maman_bar", "kitty", &fcall_len); - fret = searpc_server_call_function (fcall, fcall_len, &ret_len, &error); + fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error); g_assert (error == NULL); result = searpc_client_fret__object (MAMAN_TYPE_BAR, fret, ret_len, &error); @@ -254,7 +254,7 @@ void test_objlist_call (void *fixture, const void *data) fcall = searpc_client_fcall__string_int ("get_maman_bar_list", "kitty", 10, &fcall_len); - fret = searpc_server_call_function (fcall, fcall_len, &ret_len, &error); + fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error); g_assert (error == NULL); result = searpc_client_fret__objlist (MAMAN_TYPE_BAR, fret, ret_len, &error); g_free (fcall); @@ -266,7 +266,7 @@ void test_objlist_call (void *fixture, const void *data) fcall = searpc_client_fcall__string_int ("get_maman_bar_list", "kitty", 0, &fcall_len); - fret = searpc_server_call_function (fcall, fcall_len, &ret_len, &error); + fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error); g_assert (error == NULL); result = searpc_client_fret__objlist (MAMAN_TYPE_BAR, fret, ret_len, &error); g_free (fcall); @@ -284,11 +284,12 @@ main (int argc, char *argv[]) g_test_init (&argc, &argv, NULL); searpc_server_init (); - searpc_server_register_function (get_substring, "get_substring", + searpc_create_service ("test"); + searpc_server_register_function ("test", get_substring, "get_substring", searpc_signature_string__string_int()); - searpc_server_register_function (get_maman_bar, "get_maman_bar", + searpc_server_register_function ("test", get_maman_bar, "get_maman_bar", searpc_signature_object__string()); - searpc_server_register_function (get_maman_bar_list, "get_maman_bar_list", + searpc_server_register_function ("test", get_maman_bar_list, "get_maman_bar_list", searpc_signature_objlist__string_int()); g_test_add ("/searpc/simple", void, NULL,