From: Andre Noll Date: Sun, 4 Sep 2011 16:41:40 +0000 (+0200) Subject: client: Split client_open() and client_close(). X-Git-Tag: v0.4.9~1^2~6 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=6979083be2c739e5ef66e4e6ccec991d7b2b7908;hp=8aa0f575bcca12ab63ab53141c2144448c457478;ds=inline client: Split client_open() and client_close(). For interactive para_client sessions, we set up the client configuration from the values given at the command line and in the config file just as we do for non-interactive mode. However, in interactive mode we must be able to execute arbitrary many client commands using the same configuration. client_open() sets up the configuration from the command line arguments and client_close() destroys the configuration, so both functions do more than what is needed in interactive mode. This patch splits client_open() into two functions client_parse_config() and client_connect(). The old client_open() remains with the same semantics as before, it just calls both of the new functions(). In the same spirit, client_close() is split into client_disconnect(), which closes the file descriptor and deallocates the ressources of the current command but does not free the configuration. This allows to re-use the client configuration multiple times for interactive sessions. --- diff --git a/client.h b/client.h index 3aa048ac..f2d9ecb1 100644 --- a/client.h +++ b/client.h @@ -46,7 +46,12 @@ struct client_task { struct btr_node *btrn; }; +void client_disconnect(struct client_task *ct); void client_close(struct client_task *ct); +int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr, + int *loglevel); +int client_connect(struct client_task *ct, struct sched *s, + struct btr_node *parent, struct btr_node *child); int client_open(int argc, char *argv[], struct client_task **ct_ptr, int *loglevel, struct btr_node *parent, struct btr_node *child, struct sched *sched); diff --git a/client_common.c b/client_common.c index 85978c8e..8c8d6622 100644 --- a/client_common.c +++ b/client_common.c @@ -27,24 +27,44 @@ #define CLIENT_BUFSIZE 4000 /** - * Close the connection to para_server and free all resources. + * Close the connection to para_server and deallocate per-command ressources. * - * \param ct Pointer to the client data. + * \param ct The client task. * - * \sa client_open. + * This frees all ressources of the current command but keeps the configuration + * in \p ct->conf. + * + * \sa \ref client_close(). */ -void client_close(struct client_task *ct) +void client_disconnect(struct client_task *ct) { if (!ct) return; if (ct->scc.fd >= 0) close(ct->scc.fd); sc_free(ct->scc.recv); + ct->scc.recv = NULL; sc_free(ct->scc.send); + ct->scc.send = NULL; + btr_free_node(ct->btrn); + ct->btrn = NULL; +} + +/** + * Close the connection to para_server and free all resources. + * + * \param ct Pointer to the client data. + * + * \sa \ref client_open(), \ref client_disconnect(). + */ +void client_close(struct client_task *ct) +{ + if (!ct) + return; + client_disconnect(ct); free(ct->user); free(ct->config_file); free(ct->key_file); - btr_free_node(ct->btrn); client_cmdline_parser_free(&ct->conf); free(ct); } @@ -309,23 +329,41 @@ out: } } -/* connect to para_server and register the client task */ -static int client_connect(struct sched *s, struct client_task *ct) +/** + * Connect to para_server and register the client task. + * + * \param ct The initialized client task structure. + * \param s The scheduler instance to register the client task to. + * \param parent The parent node of the client btr node. + * \param child The child node of the client node. + * + * The client task structure given by \a ct must be allocated and initialized + * by \ref client_parse_config() before this function is called. + * + * \return Standard. + */ +int client_connect(struct client_task *ct, struct sched *s, + struct btr_node *parent, struct btr_node *child) { int ret; + PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg, + ct->conf.server_port_arg); ct->scc.fd = -1; ret = para_connect_simple(IPPROTO_TCP, ct->conf.hostname_arg, ct->conf.server_port_arg); if (ret < 0) return ret; ct->scc.fd = ret; - ct->status = CL_CONNECTED; ret = mark_fd_nonblocking(ct->scc.fd); if (ret < 0) goto err_out; + ct->status = CL_CONNECTED; + ct->btrn = btr_new_node(&(struct btr_node_description) + EMBRACE(.name = "client", .parent = parent, .child = child)); ct->task.pre_select = client_pre_select; ct->task.post_select = client_post_select; + ct->task.error = 0; sprintf(ct->task.status, "client"); register_task(s, &ct->task); return 1; @@ -336,42 +374,36 @@ err_out: } /** - * Open connection to para_server. + * Parse a client configuration. * * \param argc Usual argument count. * \param argv Usual argument vector. - * \param ct_ptr Points to dynamically allocated and initialized client task - * struct upon successful return. + * \param ct_ptr Filled in by this function. * \param loglevel If not \p NULL, the number of the loglevel is stored here. - * \param parent Add the new buffer tree node as a child of this node. - * \param child Add the new buffer tree node as a parent of this node. - * \param sched The scheduler instance to register the task to. * - * Check the command line options given by \a argc and argv, set default values - * for user name and rsa key file, read further option from the config file. - * Finally, establish a connection to para_server. + * This checks the command line options given by \a argc and \a argv, sets + * default values for the user name and the name of the rsa key file and reads + * further options from the config file. * - * \return Standard. + * Upon successful return, \a ct_ptr points to a dynamically allocated and + * initialized client task struct. + * + * \return The number of non-option arguments in \a argc/argv on success, + * negative on errors. */ -int client_open(int argc, char *argv[], struct client_task **ct_ptr, - int *loglevel, struct btr_node *parent, struct btr_node *child, - struct sched *sched) +int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr, + int *loglevel) { char *home = para_homedir(); int ret; struct client_task *ct = para_calloc(sizeof(struct client_task)); - ct->btrn = btr_new_node(&(struct btr_node_description) - EMBRACE(.name = "client", .parent = parent, .child = child)); *ct_ptr = ct; ct->scc.fd = -1; ret = -E_CLIENT_SYNTAX; if (client_cmdline_parser(argc, argv, &ct->conf)) goto out; HANDLE_VERSION_FLAG("client", ct->conf); - ret = -E_CLIENT_SYNTAX; - if (!ct->conf.inputs_num) - goto out; ct->config_file = ct->conf.config_file_given? para_strdup(ct->conf.config_file_arg) : @@ -413,16 +445,52 @@ int client_open(int argc, char *argv[], struct client_task **ct_ptr, PARA_INFO_LOG("loglevel: %s\n", ct->conf.loglevel_arg); PARA_INFO_LOG("config_file: %s\n", ct->config_file); PARA_INFO_LOG("key_file: %s\n", ct->key_file); - PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg, - ct->conf.server_port_arg); - ret = client_connect(sched, ct); + ret = ct->conf.inputs_num; out: free(home); if (ret < 0) { PARA_ERROR_LOG("%s\n", para_strerror(-ret)); - btr_remove_node(ct->btrn); client_close(ct); *ct_ptr = NULL; } return ret; } + +/** + * Parse the client configuration and open a connection to para_server. + * + * \param argc See \ref client_parse_config. + * \param argv See \ref client_parse_config. + * \param ct_ptr See \ref client_parse_config. + * \param loglevel See \ref client_parse_config. + * \param parent See \ref client_connect(). + * \param child See \ref client_connect(). + * \param sched See \ref client_connect(). + * + * This function combines client_parse_config() and client_connect(). It is + * considered a syntax error if no command was given, i.e. if the number + * of non-option arguments is zero. + * + * \return Standard. + */ +int client_open(int argc, char *argv[], struct client_task **ct_ptr, + int *loglevel, struct btr_node *parent, struct btr_node *child, + struct sched *sched) +{ + int ret = client_parse_config(argc, argv, ct_ptr, loglevel); + + if (ret < 0) + return ret; + if (ret == 0) { + ret = -E_CLIENT_SYNTAX; + goto fail; + } + ret = client_connect(*ct_ptr, sched, parent, child); + if (ret < 0) + goto fail; + return 1; +fail: + client_close(*ct_ptr); + *ct_ptr = NULL; + return ret; +}