client: Split client_open() and client_close().
authorAndre Noll <maan@systemlinux.org>
Sun, 4 Sep 2011 16:41:40 +0000 (18:41 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 20 Nov 2011 14:08:41 +0000 (15:08 +0100)
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.

client.h
client_common.c

index 3aa048a..f2d9ecb 100644 (file)
--- a/client.h
+++ b/client.h
@@ -46,7 +46,12 @@ struct client_task {
        struct btr_node *btrn;
 };
 
        struct btr_node *btrn;
 };
 
+void client_disconnect(struct client_task *ct);
 void client_close(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);
 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);
index 85978c8..8c8d662 100644 (file)
 #define CLIENT_BUFSIZE 4000
 
 /**
 #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);
 {
        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);
        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);
        free(ct->user);
        free(ct->config_file);
        free(ct->key_file);
-       btr_free_node(ct->btrn);
        client_cmdline_parser_free(&ct->conf);
        free(ct);
 }
        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;
 
 {
        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->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;
        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.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;
        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 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 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));
 
 {
        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);
        *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) :
 
        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_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));
 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;
 }
                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;
+}