You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/09/21 02:03:46 UTC

[GitHub] ccollins476ad closed pull request #1407: sys/log: Execute callback when log is appended to

ccollins476ad closed pull request #1407: sys/log: Execute callback when log is appended to
URL: https://github.com/apache/mynewt-core/pull/1407
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/sys/log/common/include/log_common/log_common.h b/sys/log/common/include/log_common/log_common.h
index 16010af6db..de4c7970f1 100644
--- a/sys/log/common/include/log_common/log_common.h
+++ b/sys/log/common/include/log_common/log_common.h
@@ -27,6 +27,8 @@
 extern "C" {
 #endif
 
+struct log;
+
 #define LOG_VERSION_V3  3
 #define LOG_VERSION_V2  2
 #define LOG_VERSION_V1  1
@@ -105,6 +107,15 @@ struct log_info {
 
 extern struct log_info g_log_info;
 
+/** @typedef log_append_cb
+ * @brief Callback that is executed each time the corresponding log is appended
+ * to.
+ *
+ * @param log                   The log that was just appended to.
+ * @param idx                   The index of newly appended log entry.
+ */
+typedef void log_append_cb(struct log *log, uint32_t idx);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/log/full/include/log/log.h b/sys/log/full/include/log/log.h
index 2d7657dfca..a2d028c354 100644
--- a/sys/log/full/include/log/log.h
+++ b/sys/log/full/include/log/log.h
@@ -176,6 +176,7 @@ struct log {
     const struct log_handler *l_log;
     void *l_arg;
     STAILQ_ENTRY(log) l_next;
+    log_append_cb *l_append_cb;
     uint8_t l_level;
 };
 
@@ -216,6 +217,26 @@ const char *log_module_get_name(uint8_t id);
 int log_register(char *name, struct log *log, const struct log_handler *,
                  void *arg, uint8_t level);
 
+/**
+ * @brief Configures the given log with the specified append callback.
+ *
+ * A log's append callback is executed each time an entry is appended to the
+ * log.
+ *
+ * @param log                   The log to configure.
+ * @param cb                    The callback to associate with the log.
+ */
+void log_set_append_cb(struct log *log, log_append_cb *cb);
+
+/**
+ * @brief Searches the list of registered logs for one with the specified name.
+ *
+ * @param name                  The name of the log to search for.
+ *
+ * @return                      The sought after log if found, NULL otherwise.
+ */
+struct log *log_find(const char *name);
+
 /**
  * @brief Writes the raw contents of a flat buffer to the specified log.
  *
diff --git a/sys/log/full/src/log.c b/sys/log/full/src/log.c
index 3c0da89679..dec5dabcf0 100644
--- a/sys/log/full/src/log.c
+++ b/sys/log/full/src/log.c
@@ -248,6 +248,22 @@ log_registered(struct log *log)
     return 0;
 }
 
+struct log *
+log_find(const char *name)
+{
+    struct log *log;
+
+    log = NULL;
+    do {
+        log = log_list_get_next(log);
+        if (strcmp(log->l_name, name) == 0) {
+            break;
+        }
+    } while (log != NULL);
+
+    return log;
+}
+
 struct log_read_hdr_arg {
     struct log_entry_hdr *hdr;
     int read_success;
@@ -319,6 +335,7 @@ log_register(char *name, struct log *log, const struct log_handler *lh,
     log->l_log = lh;
     log->l_arg = arg;
     log->l_level = level;
+    log->l_append_cb = NULL;
 
     if (!log_registered(log)) {
         STAILQ_INSERT_TAIL(&g_log_list, log, l_next);
@@ -347,6 +364,12 @@ log_register(char *name, struct log *log, const struct log_handler *lh,
     return (0);
 }
 
+void
+log_set_append_cb(struct log *log, log_append_cb *cb)
+{
+    log->l_append_cb = cb;
+}
+
 static int
 log_append_prepare(struct log *log, uint8_t module, uint8_t level,
                    uint8_t etype, struct log_entry_hdr *ue)
@@ -408,14 +431,37 @@ log_append_prepare(struct log *log, uint8_t module, uint8_t level,
     return (rc);
 }
 
+/**
+ * Calls the given log's append callback, if it has one.
+ */
+static void
+log_call_append_cb(struct log *log, uint32_t idx)
+{
+    /* Qualify this as `volatile` to prevent a race condition.  This prevents
+     * the compiler from optimizing this temp variable away.  We copy the
+     * original pointer value into this variable, then inspect and use the temp
+     * variable.  This allows us to read the original pointer only once,
+     * preventing a TOCTTOU race.
+     * (This all assumes that function pointer reads and writes are atomic.)
+     */
+    log_append_cb * volatile cb;
+
+    cb = log->l_append_cb;
+    if (cb != NULL) {
+        cb(log, idx);
+    }
+}
+
 int
 log_append_typed(struct log *log, uint8_t module, uint8_t level, uint8_t etype,
                  void *data, uint16_t len)
 {
+    struct log_entry_hdr *hdr;
     int rc;
 
-    rc = log_append_prepare(log, module, level, etype,
-                            (struct log_entry_hdr *)data);
+    hdr = (struct log_entry_hdr *)data;
+
+    rc = log_append_prepare(log, module, level, etype, hdr);
     if (rc != 0) {
         goto err;
     }
@@ -425,6 +471,8 @@ log_append_typed(struct log *log, uint8_t module, uint8_t level, uint8_t etype,
         goto err;
     }
 
+    log_call_append_cb(log, hdr->ue_index);
+
     return (0);
 err:
     return (rc);
@@ -447,6 +495,8 @@ log_append_body(struct log *log, uint8_t module, uint8_t level, uint8_t etype,
         return rc;
     }
 
+    log_call_append_cb(log, hdr.ue_index);
+
     return 0;
 }
 
@@ -454,6 +504,7 @@ int
 log_append_mbuf_typed_no_free(struct log *log, uint8_t module, uint8_t level,
                               uint8_t etype, struct os_mbuf **om_ptr)
 {
+    struct log_entry_hdr *hdr;
     struct os_mbuf *om;
     int rc;
 
@@ -471,8 +522,9 @@ log_append_mbuf_typed_no_free(struct log *log, uint8_t module, uint8_t level,
         goto err;
     }
 
-    rc = log_append_prepare(log, module, level, etype,
-                            (struct log_entry_hdr *)om->om_data);
+    hdr = (struct log_entry_hdr *)om->om_data;
+
+    rc = log_append_prepare(log, module, level, etype, hdr);
     if (rc != 0) {
         goto err;
     }
@@ -482,6 +534,8 @@ log_append_mbuf_typed_no_free(struct log *log, uint8_t module, uint8_t level,
         goto err;
     }
 
+    log_call_append_cb(log, hdr->ue_index);
+
     *om_ptr = om;
 
     return 0;
@@ -531,6 +585,8 @@ log_append_mbuf_body_no_free(struct log *log, uint8_t module, uint8_t level,
         return rc;
     }
 
+    log_call_append_cb(log, hdr.ue_index);
+
     return 0;
 }
 
diff --git a/sys/log/full/test/util/include/log_test_util/log_test_util.h b/sys/log/full/test/util/include/log_test_util/log_test_util.h
index 161697e19e..97861905b7 100644
--- a/sys/log/full/test/util/include/log_test_util/log_test_util.h
+++ b/sys/log/full/test/util/include/log_test_util/log_test_util.h
@@ -60,6 +60,7 @@ TEST_CASE_DECL(log_test_case_fcb_append_mbuf_body);
 
 TEST_SUITE_DECL(log_test_suite_misc);
 TEST_CASE_DECL(log_test_case_level);
+TEST_CASE_DECL(log_test_case_append_cb);
 
 #ifdef __cplusplus
 }
diff --git a/sys/log/full/test/util/src/log_test.c b/sys/log/full/test/util/src/log_test.c
index d4d06bfd43..885abff9cb 100644
--- a/sys/log/full/test/util/src/log_test.c
+++ b/sys/log/full/test/util/src/log_test.c
@@ -49,4 +49,5 @@ TEST_SUITE(log_test_suite_fcb_mbuf)
 TEST_SUITE(log_test_suite_misc)
 {
     log_test_case_level();
+    log_test_case_append_cb();
 }
diff --git a/sys/log/full/test/util/src/testcases/log_test_case_append_cb.c b/sys/log/full/test/util/src/testcases/log_test_case_append_cb.c
new file mode 100644
index 0000000000..b94e048aca
--- /dev/null
+++ b/sys/log/full/test/util/src/testcases/log_test_case_append_cb.c
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 "log_test_util/log_test_util.h"
+
+struct ltcwc_entry {
+    struct log *log;
+    uint32_t idx;
+};
+
+#define LTCWC_MAX_ENTRIES   16
+struct ltcwc_entry ltcwc_entries[LTCWC_MAX_ENTRIES];
+int ltcwc_num_entries;
+
+static void
+ltcwc_append_cb(struct log *log, uint32_t idx)
+{
+    struct ltcwc_entry *entry;
+
+    TEST_ASSERT_FATAL(ltcwc_num_entries < LTCWC_MAX_ENTRIES);
+
+    entry = &ltcwc_entries[ltcwc_num_entries++];
+    entry->log = log;
+    entry->idx = idx;
+}
+
+TEST_CASE(log_test_case_append_cb)
+{
+    struct fcb_log fcb_log;
+    struct log log;
+
+    ltu_setup_fcb(&fcb_log, &log);
+
+    /*** No callback; num entries remains 0. */
+
+    log_append_body(&log, 0, 0, LOG_ETYPE_STRING, "0", 1);
+    TEST_ASSERT(ltcwc_num_entries == 0);
+
+    /*** Set callback; num entries increases to 1. */
+
+    log_set_append_cb(&log, ltcwc_append_cb);
+
+    log_append_body(&log, 0, 0, LOG_ETYPE_STRING, "1", 1);
+    TEST_ASSERT(ltcwc_num_entries == 1);
+    TEST_ASSERT(ltcwc_entries[0].log == &log);
+    TEST_ASSERT(ltcwc_entries[0].idx == 1);
+
+    /*** No callback; num entries remains 1. */
+
+    log_set_append_cb(&log, NULL);
+
+    log_append_body(&log, 0, 0, LOG_ETYPE_STRING, "2", 1);
+    TEST_ASSERT(ltcwc_num_entries == 1);
+}
diff --git a/sys/log/stub/include/log/log.h b/sys/log/stub/include/log/log.h
index 62cf1af314..6c87510e2d 100644
--- a/sys/log/stub/include/log/log.h
+++ b/sys/log/stub/include/log/log.h
@@ -46,6 +46,17 @@ log_register(char *name, struct log *log, const struct log_handler *h,
     return 0;
 }
 
+static inline void
+log_set_append_cb(struct log *log, log_append_cb *cb)
+{
+}
+
+static inline struct log *
+log_find(const char *name)
+{
+    return NULL;
+}
+
 static inline int
 log_append_typed(struct log *log, uint8_t module, uint8_t level, uint8_t etype,
                  void *data, uint16_t len)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services