/* * servicedir_listener.c * * Created on: Sep 25, 2010 * Author: lamikr */ #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "servicedir_listener.h" static pthread_t _listener_thread; static bool _listener_stop_requested; static bool _listener_running = false; static int _dir_handle = -1; static int _inotify_handle = -1; static pthread_mutex_t _listener_mutex; static void init_servicedir_listener() { //_listener_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_init(&_listener_mutex, NULL); } static void deinit_servicedir_listener() { pthread_mutex_destroy(&_listener_mutex); } static void *servicedir_listener_thread(void *thread_args_pointer) { int b_count; int ii; char *buffer; struct inotify_event *event; int buffer_max_size; /* * Size of each i-notify event read: size of event structure + filename length that caused the event. (name follows the struct). * We create a buffer that could in theory handle 16 events for files which name would be in maximum 1024 chars. (=CONST_MAX_EXPECTED_INOTIFY_EVENT_SIZE) */ buffer_max_size = CONST_MAX_INOTIFY_EVENT_COUNT_READ * (sizeof(struct inotify_event) + CONST_MAX_EXPECTED_INOTIFY_EVENT_SIZE); buffer = calloc(1, buffer_max_size); if (buffer != NULL) { _inotify_handle = inotify_init(); if (_inotify_handle >= 0) { _dir_handle = inotify_add_watch(_inotify_handle, CONST_SERVICE_DIRECTORY_LOCATION, IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_DELETE); if (_dir_handle >= 0) { log_info("Waiting service directory file events\n"); while (_listener_stop_requested == false) { ii = 0; log_debug("Waiting service directory file event\n"); b_count = read(_inotify_handle, buffer, buffer_max_size); log_debug("Service directory file event received\n"); if (b_count >= 0) { while (ii < b_count) { event = (struct inotify_event *)&buffer[ii]; log_debug("event length = %d\n", event->len); if (event->len) { if (event->mask & IN_CREATE) { if ((event->mask & IN_ISDIR) == 0) { log_info("file create event: %s\n", event->name); } else { log_debug("sub-directory create event: %s, no need to process\n", event->name); } } else if (event->mask & IN_ATTRIB) { if ((event->mask & IN_ISDIR) == 0) { log_info("file attribute change event: %s\n", event->name); } else { log_debug("sub-directory attribute change event: %s, no need to process\n", event->name); } } else if (event->mask & IN_MODIFY) { if ((event->mask & IN_ISDIR) == 0) { log_info("file modify event: %s\n", event->name); } else { log_debug("sub-directory modify event: %s, no need to process\n", event->name); } } else if (event->mask & IN_DELETE) { if ((event->mask & IN_ISDIR) == 0) { log_info("file delete event: %s\n", event->name); } else { log_debug("sub-directory delete event: %s, no need to process\n", event->name); } } } ii = ii + sizeof(struct inotify_event) + event->len; } } else { log_error("Failed to initialize service directory listener: %s, event read failed.\n", CONST_SERVICE_DIRECTORY_LOCATION); } } log_info("Closing service directory listener: %s, close request received.\n", CONST_SERVICE_DIRECTORY_LOCATION); pthread_mutex_lock(&_listener_mutex); if ((_inotify_handle > 0) && (_dir_handle)) { inotify_rm_watch(_inotify_handle, _dir_handle); _dir_handle = -1; } pthread_mutex_unlock(&_listener_mutex); } else { log_error("Failed to initialize service directory listener: %s, event listener start-up error.\n", CONST_SERVICE_DIRECTORY_LOCATION); } pthread_mutex_lock(&_listener_mutex); if (_inotify_handle > 0) { close(_inotify_handle); _inotify_handle = -1; } pthread_mutex_unlock(&_listener_mutex); } else { log_error("Failed to initialize service directory listener: %s\n", CONST_SERVICE_DIRECTORY_LOCATION); } if (buffer != NULL) { free(buffer); buffer = NULL; } } else { log_error("Failed to initialize service directory listener: %s, buffer allocation error.\n", CONST_SERVICE_DIRECTORY_LOCATION); } _listener_running = false; pthread_exit(NULL); } void start_servicedir_listener() { log_debug("listen_closed_processes()\n"); init_servicedir_listener(); if (_listener_running == false) { _listener_thread = 0; _listener_stop_requested = false; _listener_running = true; pthread_create(&_listener_thread, NULL, servicedir_listener_thread, (void *)NULL); } } void stop_servicedir_listener() { _listener_stop_requested = true; pthread_mutex_lock(&_listener_mutex); if ((_inotify_handle > 0) && (_dir_handle)) { inotify_rm_watch(_inotify_handle, _dir_handle); close(_inotify_handle); _dir_handle = -1; _inotify_handle = -1; } pthread_mutex_unlock(&_listener_mutex); pthread_join(_listener_thread, NULL); deinit_servicedir_listener(); }