libdlog: runtime filtering 43/184643/14
authorMichal Bloch <m.bloch@samsung.com>
Mon, 23 Jul 2018 16:35:43 +0000 (18:35 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Tue, 21 Aug 2018 10:29:33 +0000 (12:29 +0200)
Change-Id: I5d82d5db6022e6d1617ad3414d817376c4429450
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
Makefile.am
include/log_filters.h [new file with mode: 0644]
src/libdlog/log.c
src/libdlog/log_filters.c [new file with mode: 0644]

index b0a1ff7..e7fab6f 100644 (file)
@@ -27,6 +27,7 @@ libdlog_la_SOURCES =  \
        src/shared/parsers.c \
        src/shared/queued_entry.c \
        src/shared/translate_syslog.c \
+       src/libdlog/log_filters.c \
        src/libdlog/loglimiter.c \
        src/libdlog/log_pipe.c \
        src/libdlog/log_android.c
diff --git a/include/log_filters.h b/include/log_filters.h
new file mode 100644 (file)
index 0000000..925ba86
--- /dev/null
@@ -0,0 +1,36 @@
+#pragma once
+
+/*
+ * DLOG
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <logconfig.h>
+
+#define DYNAMIC_FILTERS_CONF_KEY "dynamic_filters_path"
+#define DYNAMIC_FILTERS_FILENAME "FILTERS"
+
+void __dynamic_filters_create(struct log_config *config);
+void __dynamic_filters_destroy();
+void __dynamic_filters_update();
+
+#ifdef __cplusplus
+}
+#endif
+
index c09e5a3..2ec9c9b 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdio.h>
 
 #include <logcommon.h>
+#include <log_filters.h>
 #include "loglimiter.h"
 #include "logconfig.h"
 #include <assert.h>
@@ -74,7 +75,11 @@ static void __configure_limiter(struct log_config *config)
        if (!limiter)
                return;
 
+       __dynamic_filters_create(config);
        limiter = __log_limiter_create(config);
+
+       if (!limiter)
+               __dynamic_filters_destroy();
 }
 
 static int __configure_backend(struct log_config *config)
@@ -187,8 +192,12 @@ static int dlog_should_log(log_id_t log_id, int prio, const char *tag)
                return DLOG_ERROR_NOT_PERMITTED;
 
        if (limiter) {
+               __dynamic_filters_update();
+
                // LCOV_EXCL_START : disabled feature (limiter)
+               pthread_mutex_lock(&log_init_lock);
                int should_log = __log_limiter_pass_log(tag, prio);
+               pthread_mutex_unlock(&log_init_lock);
 
                if (!should_log) {
                        return DLOG_ERROR_NOT_PERMITTED;
@@ -275,8 +284,11 @@ int dlog_print(log_priority prio, const char *tag, const char *fmt, ...)
 /**
  * @brief Finalize DLog
  * @details Finalizes and deallocates the library
+ * @notes Assumes it has exclusive thread access,
+ *        i.e. no other library function can run in parallel
  */
 void __attribute__((destructor)) __dlog_fini(void)
 {
        __log_limiter_destroy();
+       __dynamic_filters_destroy();
 }
diff --git a/src/libdlog/log_filters.c b/src/libdlog/log_filters.c
new file mode 100644 (file)
index 0000000..fc5c1c1
--- /dev/null
@@ -0,0 +1,128 @@
+/* DLOG
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <limits.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/inotify.h>
+
+#include <logcommon.h>
+#include <logconfig.h>
+#include <log_filters.h>
+#include <loglimiter.h>
+
+static int inotify_fd = -1;
+static typeof(((struct inotify_event *)0)->wd) inotify_wd = -1;
+static char *inotify_path;
+
+extern pthread_mutex_t log_init_lock;
+
+static void __setup_runtime_watch(char const *path)
+{
+       assert(path);
+       assert(inotify_fd == -1);
+       assert(inotify_wd == -1);
+
+       inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+       if (inotify_fd == -1)
+               return;
+
+       inotify_wd = inotify_add_watch(inotify_fd, path, IN_CREATE | IN_CLOSE_WRITE | IN_MOVE | IN_DELETE);
+       if (inotify_wd == -1) {
+               close(inotify_fd);
+               inotify_fd = -1;
+               return;
+       }
+}
+
+static void __update_filters()
+{
+       assert(inotify_path);
+
+       struct log_config config = {NULL, NULL};
+       const int r = log_config_read_file(&config, inotify_path);
+       if (!r)
+               __log_limiter_update(&config);
+
+       log_config_free(&config);
+}
+
+/// caller has to guarantee exclusive access
+void __dynamic_filters_create(struct log_config *config)
+{
+       assert(config);
+       assert(!inotify_path);
+
+       const char *const extra_filters_path = log_config_get(config, DYNAMIC_FILTERS_CONF_KEY);
+       if (!extra_filters_path)
+               return;
+
+       if (asprintf(&inotify_path, "%s/%s", extra_filters_path, DYNAMIC_FILTERS_FILENAME) < 0) {
+               inotify_path = NULL;
+               return;
+       }
+
+       const int r = log_config_read_file(config, inotify_path);
+       if (r < 0)
+               return;
+
+       __setup_runtime_watch(extra_filters_path);
+}
+
+/// caller has to guarantee exclusive access
+void __dynamic_filters_destroy()
+{
+       assert(inotify_fd < 0 || inotify_path);
+       assert(inotify_wd < 0 || inotify_fd >= 0);
+       assert(inotify_fd < 0 || inotify_wd >= 0);
+
+       if (!inotify_path)
+               return;
+
+       free(inotify_path);
+       inotify_path = NULL;
+
+       if (inotify_fd < 0)
+               return;
+
+       inotify_rm_watch(inotify_fd, inotify_wd);
+       inotify_wd = -1;
+
+       close(inotify_fd);
+       inotify_fd = -1;
+}
+
+void __dynamic_filters_update()
+{
+       if (inotify_fd < 0)
+               return;
+
+       struct ievent_with_filename {
+               struct inotify_event ie;
+               char filename[NAME_MAX + 1];
+       } ievent;
+       const int r = read(inotify_fd, &ievent, sizeof ievent);
+       if (r < 0)
+               return;
+       assert(ievent.ie.wd == inotify_wd);
+
+       pthread_mutex_lock(&log_init_lock);
+       __update_filters();
+       pthread_mutex_unlock(&log_init_lock);
+}