Change client message processing
authorDavid Goulet <david.goulet@polymtl.ca>
Wed, 20 Apr 2011 19:33:23 +0000 (15:33 -0400)
committerDavid Goulet <david.goulet@polymtl.ca>
Wed, 20 Apr 2011 19:46:19 +0000 (15:46 -0400)
ltt-sessiond can now send multiple response to the client for only one
command.

The list traceable apps command was modified accordingly to that
modification and now send one response per pid.

The liblttnctl was also changed to handle multiple reply and the
recvfrom_sessiond internal function is added removing the recv from the
ask_sessiond() function. Fine grained control helps.

Signed-off-by: David Goulet <david.goulet@polymtl.ca>
liblttngctl/liblttngctl.c
liblttsessiondcomm/liblttsessiondcomm.c
liblttsessiondcomm/liblttsessiondcomm.h
ltt-sessiond/ltt-sessiond.c
lttng/lttng.c

index 2b4b8febc082b81c5daa3d708dac6b1c9aa9e519..d8481496d042b6c3c2b2c9375edf9c374e1a0aae 100644 (file)
@@ -40,6 +40,7 @@ static struct lttcomm_session_msg lsm;
 /* Prototypes */
 static int check_tracing_group(const char *grp_name);
 static int ask_sessiond(void);
+static int recvfrom_sessiond(void);
 static int set_session_daemon_path(void);
 static void reset_data_struct(void);
 
@@ -54,8 +55,7 @@ static int connected;
 /*
  *  ask_sessiond
  *
- *  Send lttcomm_session_msg to the daemon and wait
- *  for the reply. Data replied will be put in llm
+ *  Send lttcomm_session_msg to the session daemon.
  *
  *  On success, return 0
  *  On error, return error code
@@ -65,29 +65,45 @@ static int ask_sessiond(void)
        int ret;
 
        if (!connected) {
-               ret = -ECONNREFUSED;
-               goto error;
+               ret = -ENOTCONN;
+               goto end;
        }
 
        ret = lttcomm_send_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
-       if (ret < 0) {
-               goto error;
+
+end:
+       return ret;
+}
+
+/*
+ *  recvfrom_sessiond
+ *
+ *  Receive data from the sessiond socket.
+ *
+ *  On success, return 0
+ *  On error, return recv() error code
+ */
+static int recvfrom_sessiond(void)
+{
+       int ret;
+
+       if (!connected) {
+               ret = -ENOTCONN;
+               goto end;
        }
 
        ret = lttcomm_recv_unix_sock(sessiond_socket, &llm, sizeof(llm));
        if (ret < 0) {
-               goto error;
+               goto end;
        }
 
        /* Check return code */
        if (llm.ret_code != LTTCOMM_OK) {
                ret = -llm.ret_code;
-               goto error;
+               goto end;
        }
 
-       return 0;
-
-error:
+end:
        return ret;
 }
 
@@ -152,7 +168,9 @@ end:
  */
 size_t lttng_ust_list_apps(pid_t **pids)
 {
-       int ret;
+       int ret, first = 0;
+       size_t size = 0;
+       pid_t *p = NULL;
 
        lsm.cmd_type = UST_LIST_APPS;
 
@@ -161,9 +179,23 @@ size_t lttng_ust_list_apps(pid_t **pids)
                goto error;
        }
 
-       *pids = llm.u.list_apps.pids;
+       do {
+               ret = recvfrom_sessiond();
+               if (ret < 0) {
+                       goto error;
+               }
+
+               if (first == 0) {
+                       first = 1;
+                       size = llm.num_pckt;
+                       p = malloc(sizeof(pid_t) * size);
+               }
+               p[size - llm.num_pckt] = llm.u.list_apps.pid;
+       } while ((llm.num_pckt-1) != 0);
+
+       *pids = p;
 
-       return llm.u.list_apps.size;
+       return size;
 
 error:
        return ret;
index 581d5c4199a23d69de3f21e0e73ba60e76dba7c5..d2d22bc5d69ca1946ae6270c30cdb889c5da5661 100644 (file)
@@ -38,6 +38,7 @@ static const char *lttcomm_readable_code[] = {
        [ LTTCOMM_ERR_INDEX(LTTCOMM_UND) ] = "Undefined command",
        [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_SESSION) ] = "No session found",
        [ LTTCOMM_ERR_INDEX(LTTCOMM_LIST_FAIL) ] = "Unable to list traceable apps",
+       [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_APPS) ] = "No traceable apps found",
 };
 
 /*
index 0e2c4f07f8814b0c290e1366b8861b7a3fd4e71c..84385ce71d077de12bdccfa95f4d787d931afb30 100644 (file)
 /* Queue size of listen(2) */
 #define MAX_LISTEN 10
 
-/* Maximum amount of PID the list_apps command
- * can send back to the lttng client.
- */
-#define MAX_APPS_PID 20
-
 /* Get the error code index from 0 since
  * LTTCOMM_OK start at 1000
  */
@@ -78,6 +73,7 @@ enum lttcomm_return_code {
        LTTCOMM_SESSION_FAIL,   /* Create session fail */
        LTTCOMM_START_FAIL,             /* Start tracing fail */
        LTTCOMM_LIST_FAIL,              /* Listing apps fail */
+       LTTCOMM_NO_APPS,                /* No traceable application */
        LTTCOMM_NR,                             /* Last element */
 };
 
@@ -126,11 +122,15 @@ struct lttcomm_lttng_msg {
        uuid_t session_id;
        pid_t pid;
        char trace_name[NAME_MAX];
+       /* This flag indicates how many packet are in
+        * the transmission. Ex: If list apps is requested,
+        * and there is 4 pids registered, num_pckt will be 4
+        */
+       unsigned int num_pckt;
        union {
                /* UST_LIST_APPS */
                struct {
-                       size_t size;
-                       pid_t pids[MAX_APPS_PID];
+                       pid_t pid;
                } list_apps;
        } u;
 };
index 6877acccbef7b8f106685c268679381c714c095f..d846c89e58293016b3ffa4abb4c15b96655d8991 100644 (file)
@@ -50,11 +50,13 @@ static int set_socket_perms(void);
 static void sighandler(int);
 static void daemonize(void);
 static void cleanup(void);
+static void copy_common_data(struct lttcomm_lttng_msg *llm, struct lttcomm_session_msg *lsm);
 static int check_existing_daemon(void);
 static int notify_apps(const char*);
 static int connect_app(pid_t);
 static int init_daemon_socket(void);
-static struct lttcomm_lttng_msg *process_client_msg(struct lttcomm_session_msg*);
+static int process_client_msg(int sock, struct lttcomm_session_msg*);
+static int send_unix_sock(int sock, void *buf, size_t len);
 
 static void *thread_manage_clients(void *);
 static void *thread_manage_apps(void *);
@@ -77,13 +79,17 @@ static int client_socket;
 static int apps_socket;
 
 static struct ltt_session *current_session;
-static int session_count;
+
+/* Number of element for the list below. */
+static unsigned int session_count;
+static unsigned int traceable_app_count;
 
 /* Init session's list */
 static struct ltt_session_list ltt_session_list = {
        .head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
 };
 
+/* Init ust traceabl application's list */
 static struct ltt_traceable_app_list ltt_traceable_app_list = {
        .head = CDS_LIST_HEAD_INIT(ltt_traceable_app_list.head),
 };
@@ -136,12 +142,17 @@ static void *thread_manage_apps(void *data)
                        lta->pid = reg_msg.pid;
                        lta->uid = reg_msg.uid;
                        cds_list_add(&lta->list, &ltt_traceable_app_list.head);
+                       traceable_app_count++;
                } else {
                        /* Unregistering */
                        lta = NULL;
                        cds_list_for_each_entry(lta, &ltt_traceable_app_list.head, list) {
                                if (lta->pid == reg_msg.pid && lta->uid == reg_msg.uid) {
                                        cds_list_del(&lta->list);
+                                       /* Check to not overflow here */
+                                       if (traceable_app_count != 0) {
+                                               traceable_app_count--;
+                                       }
                                        break;
                                }
                        }
@@ -168,7 +179,6 @@ static void *thread_manage_clients(void *data)
 {
        int sock, ret;
        struct lttcomm_session_msg lsm;
-       struct lttcomm_lttng_msg *llm;
 
        ret = lttcomm_listen_unix_sock(client_socket);
        if (ret < 0) {
@@ -193,29 +203,14 @@ static void *thread_manage_clients(void *data)
                }
 
                /* This function dispatch the work to the LTTng or UST libs
-                * and make sure that the reply structure (llm) is filled.
-                */
-               llm = process_client_msg(&lsm);
-
-               /* Having a valid lttcomm_lttng_msg struct, reply is sent back
-                * to the client directly.
+                * and then sends back the response to the client. This is needed
+                * because there might be more then one lttcomm_lttng_msg to
+                * send out so process_client_msg do both jobs.
                 */
-               if (llm != NULL) {
-                       ret = lttcomm_send_unix_sock(sock, llm,
-                                       sizeof(struct lttcomm_lttng_msg));
-                       free(llm);
-                       if (ret < 0) {
-                               continue;
-                       }
-               } else {
-                       /* The lttcomm_lttng_msg struct was not allocated
-                        * correctly. Fatal error since the daemon is not able
-                        * to respond. However, we still permit client connection.
-                        *
-                        * TODO: We should have a default llm that tells the client
-                        * that the sessiond had a fatal error and thus the client could
-                        * take action to restart ltt-sessiond or inform someone.
-                        */
+               ret = process_client_msg(sock, &lsm);
+               if (ret < 0) {
+                       /* Error detected but still accept command */
+                       continue;
                }
        }
 
@@ -223,6 +218,23 @@ error:
        return NULL;
 }
 
+/*
+ *  send_unix_sock
+ *
+ *  Send data on a unix socket using the liblttsessiondcomm API.
+ *
+ *  Return lttcomm error code.
+ */
+static int send_unix_sock(int sock, void *buf, size_t len)
+{
+       /* Check valid length */
+       if (len <= 0) {
+               return -1;
+       }
+
+       return lttcomm_send_unix_sock(sock, buf, len);
+}
+
 /*
  *     connect_app
  *
@@ -378,75 +390,114 @@ error:
  *
  *  Return size of the array.
  */
-static size_t ust_list_apps(pid_t *pids)
+static size_t ust_list_apps(pid_t **pids)
 {
        size_t size = 0;
        struct ltt_traceable_app *iter = NULL;
+       pid_t *p;
 
-       cds_list_for_each_entry(iter, &ltt_traceable_app_list.head, list) {
-               if (size >= MAX_APPS_PID) {
-                       break;
-               }
+       if (traceable_app_count == 0) {
+               /* No dynamic allocation is done */
+               goto end;
+       }
+
+       p = malloc(sizeof(pid_t) * traceable_app_count);
 
-               pids[size] = iter->pid;
+       /* TODO: Mutex needed to access this list */
+       cds_list_for_each_entry(iter, &ltt_traceable_app_list.head, list) {
+               p[size] = iter->pid;
                size++;
        }
 
+       *pids = p;
+
+end:
        return size;
 }
 
+/*
+ *  copy_common_data
+ *
+ *  Copy common data between lttcomm_lttng_msg and lttcomm_session_msg
+ */
+static void copy_common_data(struct lttcomm_lttng_msg *llm, struct lttcomm_session_msg *lsm)
+{
+       llm->cmd_type = lsm->cmd_type;
+       llm->pid = lsm->pid;
+       if (!uuid_is_null(lsm->session_id)) {
+               uuid_copy(llm->session_id, lsm->session_id);
+       }
+       strncpy(llm->trace_name, lsm->trace_name, sizeof(llm->trace_name));
+}
+
 /*
  *     process_client_msg
  *
  *     This takes the lttcomm_session_msg struct and process the command requested
- *     by the client. It then creates the reply by allocating a lttcomm_lttng_msg
- *     and fill it with the necessary information.
+ *     by the client. It then creates response(s) and send it back to the
+ *     given socket (sock).
  *
- *     It's the caller responsability to free that structure when done with it.
- *     
- *     Return pointer to lttcomm_lttng_msg allocated struct.
+ *     Return any error encountered or 0 for success.
  */
-static struct lttcomm_lttng_msg *process_client_msg(struct lttcomm_session_msg *lsm)
+static int process_client_msg(int sock, struct lttcomm_session_msg *lsm)
 {
-       struct lttcomm_lttng_msg *llm;
-
-       /* Allocate the reply message structure */
-       llm = malloc(sizeof(struct lttcomm_lttng_msg));
-       if (llm == NULL) {
-               perror("malloc");
-               goto end;
-       }
+       int ret;
+       struct lttcomm_lttng_msg llm;
 
        /* Copy common data to identify the response
         * on the lttng client side.
         */
-       llm->cmd_type = lsm->cmd_type;
-       llm->pid = lsm->pid;
-       if (!uuid_is_null(lsm->session_id)) {
-               uuid_copy(llm->session_id, lsm->session_id);
-       }
-       strncpy(llm->trace_name, lsm->trace_name, sizeof(llm->trace_name));
+       copy_common_data(&llm, lsm);
 
        /* Default return code.
-        * In a our world, everything is OK... right?
+        * In our world, everything is OK... right? ;)
         */
-       llm->ret_code = LTTCOMM_OK;
+       llm.ret_code = LTTCOMM_OK;
 
        /* Process by command type */
        switch (lsm->cmd_type) {
                case UST_LIST_APPS:
                {
-                       llm->u.list_apps.size = ust_list_apps(llm->u.list_apps.pids);
+                       pid_t *pids;
+                       llm.num_pckt = ust_list_apps(&pids);
+                       if (llm.num_pckt == 0) {
+                               ret = LTTCOMM_NO_APPS;
+                               goto error;
+                       }
+
+                       /* Send all packets */
+                       while (llm.num_pckt != 0) {
+                               llm.u.list_apps.pid = pids[traceable_app_count - llm.num_pckt];
+                               ret = send_unix_sock(sock, (void*) &llm, sizeof(llm));
+                               if (ret < 0) {
+                                       goto send_error;
+                               }
+                               llm.num_pckt--;
+                       }
+                       /* Allocated array by ust_list_apps() */
+                       free(pids);
+
                        break;
                }
                default:
+               {
                        /* Undefined command */
-                       llm->ret_code = LTTCOMM_UND;
+                       ret = LTTCOMM_UND;
                        break;
+               }
        }
 
-end:
-       return llm;
+       return 0;
+
+send_error:
+       return ret;
+
+error:
+       /* Notify client of error */
+       llm.ret_code = ret;
+       send_unix_sock(sock, (void*) &llm, sizeof(llm));
+
+       return -1;
 }
 
 /*
index f390fddb254933398e649eea0ae1ad0fd801a4bb..6cc540922a77b78ebd29c505255bfa54ad65996b 100644 (file)
@@ -105,6 +105,9 @@ static int process_opt_list_apps(void)
                fclose(fp);
        }
 
+       /* Allocated by lttng_ust_list_apps() */
+       free(pids);
+
        return 0;
 
 error:
This page took 0.045417 seconds and 4 git commands to generate.