You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2019/10/21 09:30:22 UTC

[mynewt-core] 01/23: Added capability to recognize when a fcb sector is about to rotate and provide the application an opportunity to read logs before the rotation.

This is an automated email from the ASF dual-hosted git repository.

marko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit daf09ee90c17f32dd2528b07ed8b77227d8b63f4
Author: Nolan Lau <no...@juul.com>
AuthorDate: Wed Sep 25 21:56:17 2019 -0700

    Added capability to recognize when a fcb sector is about to rotate and
    provide the application an opportunity to read logs before the rotation.
---
 fs/fcb/include/fcb/fcb.h                       | 21 ++++----
 fs/fcb/src/fcb.c                               | 23 +++++++-
 fs/fcb/src/fcb_append.c                        | 10 +++-
 fs/fcb/src/fcb_getnext.c                       | 57 ++++++++++++++++++++
 fs/fcb/src/fcb_rotate.c                        |  3 +-
 sys/log/common/include/log_common/log_common.h |  7 +++
 sys/log/full/include/log/log.h                 | 28 ++++++++++
 sys/log/full/src/log.c                         | 22 ++++++++
 sys/log/full/src/log_fcb.c                     | 75 ++++++++++++++++++++------
 9 files changed, 217 insertions(+), 29 deletions(-)

diff --git a/fs/fcb/include/fcb/fcb.h b/fs/fcb/include/fcb/fcb.h
index f198e18..d06a705 100644
--- a/fs/fcb/include/fcb/fcb.h
+++ b/fs/fcb/include/fcb/fcb.h
@@ -60,6 +60,7 @@ struct fcb {
     /* Flash circular buffer internal state */
     struct os_mutex f_mtx;	/* Locking for accessing the FCB data */
     struct flash_area *f_oldest;
+    struct flash_area *f_scratch;
     struct fcb_entry f_active;
     uint16_t f_active_id;
     uint8_t f_align;		/* writes to flash have to aligned to this */
@@ -68,15 +69,16 @@ struct fcb {
 /**
  * Error codes.
  */
-#define FCB_OK		0
-#define FCB_ERR_ARGS	-1
-#define FCB_ERR_FLASH	-2
-#define FCB_ERR_NOVAR   -3
-#define FCB_ERR_NOSPACE	-4
-#define FCB_ERR_NOMEM	-5
-#define FCB_ERR_CRC	-6
-#define FCB_ERR_MAGIC   -7
-#define FCB_ERR_VERSION -8
+#define FCB_OK             0
+#define FCB_ERR_ARGS      -1
+#define FCB_ERR_FLASH     -2
+#define FCB_ERR_NOVAR     -3
+#define FCB_ERR_NOSPACE   -4
+#define FCB_ERR_NOMEM     -5
+#define FCB_ERR_CRC       -6
+#define FCB_ERR_MAGIC     -7
+#define FCB_ERR_VERSION   -8
+#define FCB_ERR_NEXT_SECT -9
 
 int fcb_init(struct fcb *fcb);
 
@@ -100,6 +102,7 @@ int fcb_append_finish(struct fcb *, struct fcb_entry *append_loc);
 typedef int (*fcb_walk_cb)(struct fcb_entry *loc, void *arg);
 int fcb_walk(struct fcb *, struct flash_area *, fcb_walk_cb cb, void *cb_arg);
 int fcb_getnext(struct fcb *, struct fcb_entry *loc);
+int fcb_getnext_sector(struct fcb *fcb, struct fcb_entry *loc);
 
 /**
  * Erases the data from oldest sector.
diff --git a/fs/fcb/src/fcb.c b/fs/fcb/src/fcb.c
index 0fe7e1f..40b218b 100644
--- a/fs/fcb/src/fcb.c
+++ b/fs/fcb/src/fcb.c
@@ -32,7 +32,7 @@ fcb_init(struct fcb *fcb)
     int max_align = 1;
     int align;
     int oldest = -1, newest = -1;
-    struct flash_area *oldest_fap = NULL, *newest_fap = NULL;
+    struct flash_area *oldest_fap = NULL, *newest_fap = NULL, *scratch_fap = NULL;
     struct fcb_disk_area fda;
 
     if (!fcb->f_sectors || fcb->f_sector_cnt - fcb->f_scratch_cnt < 1) {
@@ -56,11 +56,26 @@ fcb_init(struct fcb *fcb)
         if (oldest < 0) {
             oldest = newest = fda.fd_id;
             oldest_fap = newest_fap = fap;
+
+            fap++;
+            if (fap >= &fcb->f_sectors[fcb->f_sector_cnt]) {
+                scratch_fap = &fcb->f_sectors[0];
+            } else {
+                scratch_fap = fap;
+            }
             continue;
         }
         if (FCB_ID_GT(fda.fd_id, newest)) {
             newest = fda.fd_id;
             newest_fap = fap;
+           
+            fap++;
+            if (fap >= &fcb->f_sectors[fcb->f_sector_cnt]) {
+                scratch_fap = &fcb->f_sectors[0];
+            } else {
+                scratch_fap = fap;
+            }
+
         } else if (FCB_ID_GT(oldest, fda.fd_id)) {
             oldest = fda.fd_id;
             oldest_fap = fap;
@@ -76,7 +91,13 @@ fcb_init(struct fcb *fcb)
             return rc;
         }
         newest = oldest = 0;
+        scratch_fap = &fcb->f_sectors[fcb->f_sector_cnt-1];
     }
+
+    if (fcb->f_scratch) {
+        fcb->f_scratch = scratch_fap;
+    }
+
     fcb->f_align = max_align;
     fcb->f_oldest = oldest_fap;
     fcb->f_active.fe_area = newest_fap;
diff --git a/fs/fcb/src/fcb_append.c b/fs/fcb/src/fcb_append.c
index 6d1bc86..dcdf2a7 100644
--- a/fs/fcb/src/fcb_append.c
+++ b/fs/fcb/src/fcb_append.c
@@ -36,8 +36,14 @@ fcb_new_area(struct fcb *fcb, int cnt)
         if (!rfa) {
             rfa = fa;
         }
-        if (fa == fcb->f_oldest) {
-            return NULL;
+        if (fcb->f_scratch) {
+            if (fa == fcb->f_scratch) {
+                return NULL;
+            }
+        } else {
+            if (fa == fcb->f_oldest) {
+                return NULL;
+            }
         }
     } while (i++ < cnt);
     return rfa;
diff --git a/fs/fcb/src/fcb_getnext.c b/fs/fcb/src/fcb_getnext.c
index 6ca08ce..931432d 100644
--- a/fs/fcb/src/fcb_getnext.c
+++ b/fs/fcb/src/fcb_getnext.c
@@ -111,6 +111,48 @@ next_sector:
 }
 
 int
+fcb_getnext_nolock_sector(struct fcb *fcb, struct fcb_entry *loc)
+{
+    int rc;
+
+    if (loc->fe_area == NULL) {
+        /*
+         * Find the first one we have in flash.
+         */
+        loc->fe_area = fcb->f_oldest;
+    }
+    if (loc->fe_elem_off == 0) {
+        /*
+         * If offset is zero, we serve the first entry from the area.
+         */
+        loc->fe_elem_off = sizeof(struct fcb_disk_area);
+        rc = fcb_elem_info(fcb, loc);
+    } else {
+        rc = fcb_getnext_in_area(fcb, loc);
+    }
+    switch (rc) {
+    case 0:
+        return 0;
+    case FCB_ERR_CRC:
+        break;
+    default:
+        return FCB_ERR_NEXT_SECT;
+    }
+    while (rc == FCB_ERR_CRC) {
+        rc = fcb_getnext_in_area(fcb, loc);
+        if (rc == 0) {
+            return 0;
+        }
+
+        if (rc != FCB_ERR_CRC) {
+            return FCB_ERR_NEXT_SECT;
+        }
+    }
+
+    return FCB_ERR_NEXT_SECT;
+}
+
+int
 fcb_getnext(struct fcb *fcb, struct fcb_entry *loc)
 {
     int rc;
@@ -124,3 +166,18 @@ fcb_getnext(struct fcb *fcb, struct fcb_entry *loc)
 
     return rc;
 }
+
+int
+fcb_getnext_sector(struct fcb *fcb, struct fcb_entry *loc)
+{
+    int rc;
+
+    rc = os_mutex_pend(&fcb->f_mtx, OS_WAIT_FOREVER);
+    if (rc && rc != OS_NOT_STARTED) {
+        return FCB_ERR_ARGS;
+    }
+    rc = fcb_getnext_nolock_sector(fcb, loc);
+    os_mutex_release(&fcb->f_mtx);
+
+    return rc;
+}
diff --git a/fs/fcb/src/fcb_rotate.c b/fs/fcb/src/fcb_rotate.c
index 7135fa6..d9c7bf2 100644
--- a/fs/fcb/src/fcb_rotate.c
+++ b/fs/fcb/src/fcb_rotate.c
@@ -16,7 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 #include "fcb/fcb.h"
 #include "fcb_priv.h"
 
@@ -49,6 +48,8 @@ fcb_rotate(struct fcb *fcb)
         fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
         fcb->f_active_id++;
     }
+    fcb->f_scratch = fcb->f_oldest;
+
     fcb->f_oldest = fcb_getnext_area(fcb, fcb->f_oldest);
 out:
     os_mutex_release(&fcb->f_mtx);
diff --git a/sys/log/common/include/log_common/log_common.h b/sys/log/common/include/log_common/log_common.h
index 9a42354..356d170 100644
--- a/sys/log/common/include/log_common/log_common.h
+++ b/sys/log/common/include/log_common/log_common.h
@@ -134,6 +134,13 @@ extern struct log_info g_log_info;
  */
 typedef void log_append_cb(struct log *log, uint32_t idx);
 
+/** @typdef log_notify_rotate_cb
+ * @brief Callback that is executed each time we are about to rotate a log.
+ * 
+ * @param log                   The log that is about to rotate 
+ */
+typedef void log_notify_rotate_cb(struct log *log);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/log/full/include/log/log.h b/sys/log/full/include/log/log.h
index 4cf3240..853446f 100644
--- a/sys/log/full/include/log/log.h
+++ b/sys/log/full/include/log/log.h
@@ -114,6 +114,7 @@ struct log_handler {
     lh_append_mbuf_func_t log_append_mbuf;
     lh_append_mbuf_body_func_t log_append_mbuf_body;
     lh_walk_func_t log_walk;
+    lh_walk_func_t log_walk_sector;
     lh_flush_func_t log_flush;
 #if MYNEWT_VAL(LOG_STORAGE_INFO)
     lh_storage_info_func_t log_storage_info;
@@ -213,6 +214,7 @@ struct log {
     void *l_arg;
     STAILQ_ENTRY(log) l_next;
     log_append_cb *l_append_cb;
+    log_notify_rotate_cb *l_notify_erase_done_cb;
     uint8_t l_level;
     uint16_t l_max_entry_len;   /* Log body length; if 0 disables check. */
 #if !MYNEWT_VAL(LOG_GLOBAL_IDX)
@@ -597,6 +599,21 @@ int log_walk_body(struct log *log, log_walk_body_func_t walk_body_func,
         struct log_offset *log_offset);
 int log_flush(struct log *log);
 
+/**
+ * @brief      Walking a section of FCB.
+ *
+ * @param log                   The log to iterate.
+ * @param walk_body_func        The function to apply to each log entry.
+ * @param log_offset            Specifies the range of entries to process.
+ *                                  Entries not matching these criteria are
+ *                                  skipped during the walk.
+ *
+ * @return                      0 if the walk completed successfully;
+ *                              nonzero on error or if the walk was aborted.
+ */
+int log_walk_body_section(struct log *log, log_walk_body_func_t walk_body_func,
+              struct log_offset *log_offset);
+
 #if MYNEWT_VAL(LOG_MODULE_LEVELS)
 /**
  * @brief Retrieves the globally configured minimum log level for the specified
@@ -680,6 +697,17 @@ void log_set_max_entry_len(struct log *log, uint16_t max_entry_len);
  */
 int log_storage_info(struct log *log, struct log_storage_info *info);
 #endif
+
+/**
+ * Assign a callback function to be notified once the log deletes the oldest
+ * data to write in new data.
+ *
+ * @param log   The log
+ * @param cb    The callback function to be executed.
+ */
+void
+log_set_rotate_done_cb(struct log *log, log_notify_rotate_cb *cb);
+
 #if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
 /**
  * Set watermark on log
diff --git a/sys/log/full/src/log.c b/sys/log/full/src/log.c
index 3b992e7..32bd7ff 100644
--- a/sys/log/full/src/log.c
+++ b/sys/log/full/src/log.c
@@ -458,6 +458,11 @@ log_hdr_len(const struct log_entry_hdr *hdr)
     return LOG_BASE_ENTRY_HDR_SIZE;
 }
 
+void
+log_set_rotate_done_cb(struct log *log, log_notify_rotate_cb *cb)
+{
+    log->l_notify_erase_done_cb = cb;
+}
 
 static int
 log_chk_type(uint8_t etype)
@@ -916,6 +921,23 @@ log_walk_body(struct log *log, log_walk_body_func_t walk_body_func,
     return rc;
 }
 
+int
+log_walk_body_section(struct log *log, log_walk_body_func_t walk_body_func,
+              struct log_offset *log_offset)
+{
+    struct log_walk_body_arg lwba = {
+        .fn = walk_body_func,
+        .arg = log_offset->lo_arg,
+    };
+    int rc;
+
+    log_offset->lo_arg = &lwba;
+    rc = log->l_log->log_walk_sector(log, log_walk_body_fn, log_offset);
+    log_offset->lo_arg = lwba.arg;
+
+    return rc;
+}
+
 /**
  * Reads from the specified log.
  *
diff --git a/sys/log/full/src/log_fcb.c b/sys/log/full/src/log_fcb.c
index c2ffcef..e708b65 100644
--- a/sys/log/full/src/log_fcb.c
+++ b/sys/log/full/src/log_fcb.c
@@ -159,6 +159,11 @@ log_fcb_start_append(struct log *log, int len, struct fcb_entry *loc)
         }
 #endif
 
+        /* Check to see if the active region is in the scratch region */
+        if (log->l_notify_erase_done_cb != NULL) {
+            log->l_notify_erase_done_cb(log);
+        }
+
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
         /* The FCB needs to be rotated.  Invalidate all bookmarks. */
         log_fcb_clear_bmarks(fcb_log);
@@ -180,8 +185,6 @@ log_fcb_start_append(struct log *log, int len, struct fcb_entry *loc)
             fcb_log->fl_watermark_off = fcb->f_oldest->fa_off;
         }
 #endif
-
-
     }
 
 err:
@@ -465,7 +468,6 @@ log_fcb_read_mbuf(struct log *log, const void *dptr, struct os_mbuf *om,
         if (rc) {
             goto done;
         }
-
         rc = os_mbuf_append(om, data, read_len);
         if (rc) {
             goto done;
@@ -528,6 +530,48 @@ log_fcb_walk(struct log *log, log_walk_func_t walk_func,
 }
 
 static int
+log_fcb_walk_sector(struct log *log, log_walk_func_t walk_func,
+             struct log_offset *log_offset)
+{
+    struct fcb *fcb;
+    struct fcb_log *fcb_log;
+    struct fcb_entry loc;
+    int rc;
+
+    fcb_log = log->l_arg;
+    fcb = &fcb_log->fl_fcb;
+
+    /* Locate the starting point of the walk. */
+    rc = log_fcb_find_gte(log, log_offset, &loc);
+    switch (rc) {
+    case 0:
+        /* Found a starting point. */
+        break;
+    case SYS_ENOENT:
+        /* No entries match the offset criteria; nothing to walk. */
+        return 0;
+    default:
+        return rc;
+    }
+#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
+    /* If a minimum index was specified (i.e., we are not just retrieving the
+     * last entry), add a bookmark pointing to this walk's start location.
+     */
+    if (log_offset->lo_ts >= 0) {
+        fcb_log_add_bmark(fcb_log, &loc, log_offset->lo_index);
+    }
+#endif
+    do {
+        rc = walk_func(log, log_offset, &loc, loc.fe_data_len);
+        if (rc != 0) {
+            return rc;
+        }
+    } while (fcb_getnext_sector(fcb, &loc) == 0);
+
+    return 0;
+}
+
+static int
 log_fcb_flush(struct log *log)
 {
     struct fcb_log *fcb_log;
@@ -772,9 +816,7 @@ log_fcb_copy(struct log *log, struct fcb *src_fcb, struct fcb *dst_fcb,
 {
     struct fcb_entry entry;
     int rc;
-
     rc = 0;
-
     memset(&entry, 0, sizeof(entry));
     while (!fcb_getnext(src_fcb, &entry)) {
         if (entry.fe_elem_off < offset) {
@@ -860,22 +902,23 @@ err:
 }
 
 const struct log_handler log_fcb_handler = {
-    .log_type = LOG_TYPE_STORAGE,
-    .log_read = log_fcb_read,
-    .log_read_mbuf = log_fcb_read_mbuf,
-    .log_append = log_fcb_append,
-    .log_append_body = log_fcb_append_body,
-    .log_append_mbuf = log_fcb_append_mbuf,
+    .log_type             = LOG_TYPE_STORAGE,
+    .log_read             = log_fcb_read,
+    .log_read_mbuf        = log_fcb_read_mbuf,
+    .log_append           = log_fcb_append,
+    .log_append_body      = log_fcb_append_body,
+    .log_append_mbuf      = log_fcb_append_mbuf,
     .log_append_mbuf_body = log_fcb_append_mbuf_body,
-    .log_walk = log_fcb_walk,
-    .log_flush = log_fcb_flush,
+    .log_walk             = log_fcb_walk,
+    .log_walk_sector      = log_fcb_walk_sector,
+    .log_flush            = log_fcb_flush,
 #if MYNEWT_VAL(LOG_STORAGE_INFO)
-    .log_storage_info = log_fcb_storage_info,
+    .log_storage_info     = log_fcb_storage_info,
 #endif
 #if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
-    .log_set_watermark = log_fcb_set_watermark,
+    .log_set_watermark    = log_fcb_set_watermark,
 #endif
-    .log_registered = log_fcb_registered,
+    .log_registered       = log_fcb_registered,
 };
 
 #endif