From: Michael Sills Lavoie Date: Fri, 26 Mar 2010 18:54:29 +0000 (-0400) Subject: Create utility methods in the library to support local write to disk X-Git-Tag: 0.81~3 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=d9cbca2728d5c8df929fe464e698abc07d1876ab;p=ltt-control.git Create utility methods in the library to support local write to disk Signed-off-by: Mathieu Desnoyers --- diff --git a/liblttd/Makefile.am b/liblttd/Makefile.am index 3c1eeda..43859be 100644 --- a/liblttd/Makefile.am +++ b/liblttd/Makefile.am @@ -1,7 +1,7 @@ lib_LTLIBRARIES = liblttd.la -liblttd_la_SOURCES = liblttd.c +liblttd_la_SOURCES = liblttd.c liblttdutils.c liblttdinclude_HEADERS = \ - liblttd.h + liblttd.h liblttdutils.h diff --git a/liblttd/liblttd.c b/liblttd/liblttd.c index 0f703f5..7ae01f8 100644 --- a/liblttd/liblttd.c +++ b/liblttd/liblttd.c @@ -1,4 +1,4 @@ -/* lttd +/* libttd * * Linux Trace Toolkit Daemon * @@ -9,6 +9,9 @@ * * Copyright 2005 - * Mathieu Desnoyers + * Copyright 2010 - + * Michael Sills-Lavoie + * Oumarou Dicko */ #ifdef HAVE_CONFIG_H @@ -75,40 +78,6 @@ static inline int inotify_rm_watch (int fd, __u32 wd) #undef HAS_INOTIFY #endif -struct channel_trace_fd { - struct fd_pair *pair; - int num_pairs; -}; - -struct inotify_watch { - int wd; - char path_channel[PATH_MAX]; - char *base_path_channel; -}; - -struct inotify_watch_array { - struct inotify_watch *elem; - int num; -}; - -struct liblttd_instance { - struct liblttd_callbacks *callbacks; - - int inotify_fd; - struct channel_trace_fd fd_pairs; - struct inotify_watch_array inotify_watch_array; - - /* protects fd_pairs and inotify_watch_array */ - pthread_rwlock_t fd_pairs_lock; - - char channel_name[PATH_MAX]; - unsigned long num_threads; - int quit_program; /* For signal handler */ - int dump_flight_only; - int dump_normal_only; - int verbose_mode; -}; - struct liblttd_thread_data { int thread_num; struct liblttd_instance *instance; @@ -189,7 +158,7 @@ int open_channel_trace_pairs(struct liblttd_instance *instance, goto end; } - printf_verbose("Calling on new channels folder\n"); + printf_verbose("Calling : on new channels folder\n"); if(instance->callbacks->on_new_channels_folder) ret = instance->callbacks-> on_new_channels_folder(instance->callbacks, base_subchannel_name); @@ -742,7 +711,7 @@ int liblttd_start_instance(struct liblttd_instance *instance) close(instance->inotify_fd); if(instance->callbacks->on_trace_end) - instance->callbacks->on_trace_end(instance->callbacks); + instance->callbacks->on_trace_end(instance); delete_instance(instance); diff --git a/liblttd/liblttd.h b/liblttd/liblttd.h index 02e7e9c..d871dd7 100644 --- a/liblttd/liblttd.h +++ b/liblttd/liblttd.h @@ -1,10 +1,11 @@ /* liblttd header file * + * Copyright 2005 - + * Mathieu Desnoyers * Copyright 2010- * Oumarou Dicko * Michael Sills-Lavoie * - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -21,6 +22,7 @@ #define _LIBLTTD_H #include +#include /** * struct fd_pair - Contains the data associated with the channel file @@ -43,7 +45,46 @@ struct fd_pair { void *user_data; }; -struct liblttd_instance; +struct channel_trace_fd { + struct fd_pair *pair; + int num_pairs; +}; + +struct inotify_watch { + int wd; + char path_channel[PATH_MAX]; + char *base_path_channel; +}; + +struct inotify_watch_array { + struct inotify_watch *elem; + int num; +}; + +struct liblttd_callbacks; + +/** + * struct liblttd_instance - Contains the data associated with a trace instance. + * The lib user can read but MUST NOT change any attributes but callbacks. + * @callbacks: Contains the necessary callbacks for a tracing session. + */ +struct liblttd_instance { + struct liblttd_callbacks *callbacks; + + int inotify_fd; + struct channel_trace_fd fd_pairs; + struct inotify_watch_array inotify_watch_array; + + /* protects fd_pairs and inotify_watch_array */ + pthread_rwlock_t fd_pairs_lock; + + char channel_name[PATH_MAX]; + unsigned long num_threads; + int quit_program; + int dump_flight_only; + int dump_normal_only; + int verbose_mode; +}; /** * struct liblttd_callbacks - Contains the necessary callbacks for a tracing @@ -116,17 +157,16 @@ struct liblttd_callbacks { * this time, all the channels have been closed and the threads have * been destroyed. * - * @data: pointeur to the callbacks struct that has been passed to the - * lib. + * @instance: pointeur to the instance struct that has been passed to + * the lib. * * Returns 0 if the callback succeeds else not 0. * - * It has to be thread safe, it'll be called by many threads. * After this callback is called, no other callback will be called * again and the tracing instance will be deleted automatically by * liblttd. After this call, the user must not use the liblttd instance. */ - int(*on_trace_end)(struct liblttd_callbacks *data); + int(*on_trace_end)(struct liblttd_instance *instance); /** * on_new_thread - Is called after a new thread has been created. diff --git a/liblttd/liblttdutils.c b/liblttd/liblttdutils.c new file mode 100644 index 0000000..3368aba --- /dev/null +++ b/liblttd/liblttdutils.c @@ -0,0 +1,229 @@ +/* liblttdutils + * + * Linux Trace Toolkit utility library + * + * This is a simple daemon implementation that reads a few relay+debugfs + * channels and save them in a trace. + * + * CPU hot-plugging is supported using inotify. + * + * Copyright 2005 - + * Mathieu Desnoyers + * Copyright 2010 - + * Michael Sills-Lavoie + * Oumarou Dicko + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _REENTRANT +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "liblttdutils.h" + +struct liblttdutils_channel_data { + int trace; +}; + +struct liblttdutils_data { + char path_trace[PATH_MAX]; + char *end_path_trace; + int path_trace_len; + int append_mode; + int verbose_mode; +}; + +static __thread int thread_pipe[2]; + +#define printf_verbose(fmt, args...) \ + do { \ + if (callbacks_data->verbose_mode) \ + printf(fmt, ##args); \ + } while (0) + +int liblttdutils_local_on_open_channel(struct liblttd_callbacks *data, struct fd_pair *pair, char *relative_channel_path) +{ + int open_ret = 0; + int ret; + struct stat stat_buf; + struct liblttdutils_channel_data *channel_data; + + pair->user_data = malloc(sizeof(struct liblttdutils_channel_data)); + channel_data = pair->user_data; + + struct liblttdutils_data* callbacks_data = data->user_data; + + strncpy(callbacks_data->end_path_trace, relative_channel_path, PATH_MAX - callbacks_data->path_trace_len); + printf_verbose("Creating trace file %s\n", callbacks_data->path_trace); + + ret = stat(callbacks_data->path_trace, &stat_buf); + if(ret == 0) { + if(callbacks_data->append_mode) { + printf_verbose("Appending to file %s as requested\n", + callbacks_data->path_trace); + + channel_data->trace = open(callbacks_data->path_trace, O_WRONLY, S_IRWXU|S_IRWXG|S_IRWXO); + if(channel_data->trace == -1) { + perror(callbacks_data->path_trace); + open_ret = -1; + goto end; + } + ret = lseek(channel_data->trace, 0, SEEK_END); + if (ret < 0) { + perror(callbacks_data->path_trace); + open_ret = -1; + close(channel_data->trace); + goto end; + } + } else { + printf("File %s exists, cannot open. Try append mode.\n", callbacks_data->path_trace); + open_ret = -1; + goto end; + } + } else { + if(errno == ENOENT) { + channel_data->trace = + open(callbacks_data->path_trace, O_WRONLY|O_CREAT|O_EXCL, S_IRWXU|S_IRWXG|S_IRWXO); + if(channel_data->trace == -1) { + perror(callbacks_data->path_trace); + open_ret = -1; + goto end; + } + } + } + +end: + return open_ret; + +} + +int liblttdutils_local_on_close_channel(struct liblttd_callbacks *data, struct fd_pair *pair) +{ + int ret; + ret = close(((struct liblttdutils_channel_data *)(pair->user_data))->trace); + free(pair->user_data); + return ret; +} + +int liblttdutils_local_on_new_channels_folder(struct liblttd_callbacks *data, char *relative_folder_path) +{ + int ret; + int open_ret = 0; + struct liblttdutils_data* callbacks_data = data->user_data; + + strncpy(callbacks_data->end_path_trace, relative_folder_path, PATH_MAX - callbacks_data->path_trace_len); + printf_verbose("Creating trace subdirectory %s\n", callbacks_data->path_trace); + + ret = mkdir(callbacks_data->path_trace, S_IRWXU|S_IRWXG|S_IRWXO); + if(ret == -1) { + if(errno != EEXIST) { + perror(callbacks_data->path_trace); + open_ret = -1; + goto end; + } + } + +end: + return open_ret; +} + +int liblttdutils_local_on_read_subbuffer(struct liblttd_callbacks *data, struct fd_pair *pair, unsigned int len) +{ + long ret; + off_t offset = 0; + + struct liblttdutils_data* callbacks_data = data->user_data; + + while (len > 0) { + printf_verbose("splice chan to pipe offset %lu\n", + (unsigned long)offset); + ret = splice(pair->channel, &offset, thread_pipe[1], NULL, + len, SPLICE_F_MOVE | SPLICE_F_MORE); + printf_verbose("splice chan to pipe ret %ld\n", ret); + if (ret < 0) { + perror("Error in relay splice"); + goto write_error; + } + ret = splice(thread_pipe[0], NULL, + ((struct liblttdutils_channel_data *)(pair->user_data))->trace, + NULL, ret, SPLICE_F_MOVE | SPLICE_F_MORE); + printf_verbose("splice pipe to file %ld\n", ret); + if (ret < 0) { + perror("Error in file splice"); + goto write_error; + } + len -= ret; + } + +write_error: + return ret; +} + +int liblttdutils_local_on_new_thread(struct liblttd_callbacks *data, unsigned long thread_num) +{ + int ret; + ret = pipe(thread_pipe); + if (ret < 0) { + perror("Error creating pipe"); + return ret; + } + return 0; +} + +int liblttdutils_local_on_close_thread(struct liblttd_callbacks *data, unsigned long thread_num) +{ + close(thread_pipe[0]); /* close read end */ + close(thread_pipe[1]); /* close write end */ + return 0; +} + +int liblttdutils_local_on_trace_end(struct liblttd_instance *instance) +{ + struct liblttd_callbacks *callbacks = instance->callbacks; + struct liblttdutils_data *data = callbacks->user_data; + + free(data); + free(callbacks); +} + +struct liblttd_callbacks* liblttdutils_local_new_callbacks(char* trace_name, + int append_mode, int verbose_mode) +{ + struct liblttdutils_data *data; + struct liblttd_callbacks *callbacks; + + if(!trace_name) return NULL; + + data = malloc(sizeof(struct liblttdutils_data)); + + strncpy(data->path_trace, trace_name, PATH_MAX-1); + data->path_trace_len = strlen(data->path_trace); + data->end_path_trace = data->path_trace + data->path_trace_len; + data->append_mode = append_mode; + data->verbose_mode = verbose_mode; + + callbacks = malloc(sizeof(struct liblttd_callbacks)); + + callbacks->on_open_channel = liblttdutils_local_on_open_channel; + callbacks->on_close_channel = liblttdutils_local_on_close_channel; + callbacks->on_new_channels_folder = liblttdutils_local_on_new_channels_folder; + callbacks->on_read_subbuffer = liblttdutils_local_on_read_subbuffer; + callbacks->on_trace_end = liblttdutils_local_on_trace_end; + callbacks->on_new_thread = liblttdutils_local_on_new_thread; + callbacks->on_close_thread = liblttdutils_local_on_close_thread; + callbacks->user_data = data; + + return callbacks; +} + diff --git a/liblttd/liblttdutils.h b/liblttd/liblttdutils.h new file mode 100644 index 0000000..78439d2 --- /dev/null +++ b/liblttd/liblttdutils.h @@ -0,0 +1,38 @@ +/* liblttdutils header file + * + * Copyright 2010- + * Oumarou Dicko + * Michael Sills-Lavoie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _LIBLTTDUTILS_H +#define _LIBLTTDUTILS_H + +#include "liblttd.h" + +/** + * liblttdutils_new_callbacks - Is a utility function called to create a new + * callbacks struct used by liblttd to write trace data to the disk. + * + * @trace_name: Directory name of the trace to write to. It will be created. + * @append_mode: Append to a possibly existing trace. + * @verbose_mode: Verbose mode. + * + * Returns the callbacks if the function succeeds else NULL. + */ +struct liblttd_callbacks* liblttdutils_local_new_callbacks(char* trace_name, + int append_mode, int verbose_mode); + +#endif /*_LIBLTTDUTILS_H */ + diff --git a/lttd/lttd.c b/lttd/lttd.c index d3c12d5..b43b637 100644 --- a/lttd/lttd.c +++ b/lttd/lttd.c @@ -8,6 +8,8 @@ * CPU hot-plugging is supported using inotify. * * Copyright 2009-2010 - Mathieu Desnoyers + * Copyright 2010 - Michael Sills-Lavoie + * Copyright 2010 - Oumarou Dicko * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +24,7 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * */ #ifdef HAVE_CONFIG_H @@ -33,23 +36,14 @@ #include #include -#include #include #include -#include -#include -#include #include +#include -struct lttd_channel_data { - int trace; -}; +struct liblttd_instance* instance; -struct liblttd_instance *instance; -static char path_trace[PATH_MAX]; -static char *end_path_trace; -static int path_trace_len = 0; static char *trace_name = NULL; static char *channel_name = NULL; static int daemon_mode = 0; @@ -59,13 +53,6 @@ static int dump_flight_only = 0; static int dump_normal_only = 0; static int verbose_mode = 0; -static __thread int thread_pipe[2]; - -#define printf_verbose(fmt, args...) \ - do { \ - if (verbose_mode) \ - printf(fmt, ##args); \ - } while (0) /* Args : * @@ -195,152 +182,11 @@ static void handler(int signo) liblttd_stop_instance(instance); } -int lttd_on_open_channel(struct liblttd_callbacks *data, struct fd_pair *pair, char *relative_channel_path) -{ - int open_ret = 0; - int ret; - struct stat stat_buf; - struct lttd_channel_data *channel_data; - - pair->user_data = malloc(sizeof(struct lttd_channel_data)); - channel_data = pair->user_data; - - strncpy(end_path_trace, relative_channel_path, PATH_MAX - path_trace_len); - printf_verbose("Creating trace file %s\n", path_trace); - - ret = stat(path_trace, &stat_buf); - if(ret == 0) { - if(append_mode) { - printf_verbose("Appending to file %s as requested\n", - path_trace); - - channel_data->trace = open(path_trace, O_WRONLY, S_IRWXU|S_IRWXG|S_IRWXO); - if(channel_data->trace == -1) { - perror(path_trace); - open_ret = -1; - goto end; - } - ret = lseek(channel_data->trace, 0, SEEK_END); - if (ret < 0) { - perror(path_trace); - open_ret = -1; - close(channel_data->trace); - goto end; - } - } else { - printf("File %s exists, cannot open. Try append mode.\n", path_trace); - open_ret = -1; - goto end; - } - } else { - if(errno == ENOENT) { - channel_data->trace = open(path_trace, O_WRONLY|O_CREAT|O_EXCL, S_IRWXU|S_IRWXG|S_IRWXO); - if(channel_data->trace == -1) { - perror(path_trace); - open_ret = -1; - goto end; - } - } - } - -end: - return open_ret; - -} - -int lttd_on_close_channel(struct liblttd_callbacks *data, struct fd_pair *pair) -{ - int ret; - ret = close(((struct lttd_channel_data *)(pair->user_data))->trace); - free(pair->user_data); - return ret; -} - -int lttd_on_new_channels_folder(struct liblttd_callbacks *data, char *relative_folder_path) -{ - int ret; - int open_ret = 0; - - strncpy(end_path_trace, relative_folder_path, PATH_MAX - path_trace_len); - printf_verbose("Creating trace subdirectory %s\n", path_trace); - - ret = mkdir(path_trace, S_IRWXU|S_IRWXG|S_IRWXO); - if(ret == -1) { - if(errno != EEXIST) { - perror(path_trace); - open_ret = -1; - goto end; - } - } - -end: - return open_ret; -} - -int lttd_on_read_subbuffer(struct liblttd_callbacks *data, struct fd_pair *pair, unsigned int len) -{ - long ret; - off_t offset = 0; - - while (len > 0) { - printf_verbose("splice chan to pipe offset %lu\n", - (unsigned long)offset); - ret = splice(pair->channel, &offset, thread_pipe[1], NULL, - len, SPLICE_F_MOVE | SPLICE_F_MORE); - printf_verbose("splice chan to pipe ret %ld\n", ret); - if (ret < 0) { - perror("Error in relay splice"); - goto write_error; - } - ret = splice(thread_pipe[0], NULL, - ((struct lttd_channel_data *)(pair->user_data))->trace, - NULL, ret, SPLICE_F_MOVE | SPLICE_F_MORE); - printf_verbose("splice pipe to file %ld\n", ret); - if (ret < 0) { - perror("Error in file splice"); - goto write_error; - } - len -= ret; - } - -write_error: - return ret; -} - -int lttd_on_new_thread(struct liblttd_callbacks *data, unsigned long thread_num) -{ - int ret; - ret = pipe(thread_pipe); - if (ret < 0) { - perror("Error creating pipe"); - return ret; - } - return 0; -} - -int lttd_on_close_thread(struct liblttd_callbacks *data, unsigned long thread_num) -{ - close(thread_pipe[0]); /* close read end */ - close(thread_pipe[1]); /* close write end */ - return 0; -} - int main(int argc, char ** argv) { int ret = 0; struct sigaction act; - struct liblttd_callbacks callbacks = { - lttd_on_open_channel, - lttd_on_close_channel, - lttd_on_new_channels_folder, - lttd_on_read_subbuffer, - NULL, - lttd_on_new_thread, - lttd_on_close_thread, - NULL - }; - ret = parse_arguments(argc, argv); if(ret != 0) show_arguments(); @@ -368,12 +214,13 @@ int main(int argc, char ** argv) exit(-1); } } - strncpy(path_trace, trace_name, PATH_MAX-1); - path_trace_len = strlen(path_trace); - end_path_trace = path_trace + path_trace_len; - instance = liblttd_new_instance(&callbacks, channel_name, num_threads, + struct liblttd_callbacks* callbacks = liblttdutils_local_new_callbacks( + trace_name, append_mode, verbose_mode); + + instance = liblttd_new_instance(callbacks, channel_name, num_threads, dump_flight_only, dump_normal_only, verbose_mode); + if(!instance) { perror("An error occured while creating the liblttd instance"); return ret;