This is an automated email from the ASF dual-hosted git repository.
janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new 597956000 sys/log: Add optional support for sector bookmarks to
optimize reading logs
597956000 is described below
commit 59795600024aadbf4dde7caa7593e10aaf849c80
Author: Vipul Rahane <[email protected]>
AuthorDate: Thu Mar 13 07:58:00 2025 -0700
sys/log: Add optional support for sector bookmarks to optimize reading logs
- Add sector bookmarks for reading optimization
- CLI: Add '-b' option in log_shell for reading bookmarks
- CLI: Add '-i' option in log_shell for reading logs from given index
---
fs/fcb/include/fcb/fcb.h | 22 ++
fs/fcb/src/fcb.c | 2 +-
fs/fcb/src/fcb_getnext.c | 11 +-
fs/fcb/src/fcb_priv.h | 1 -
sys/log/full/include/log/log_fcb.h | 70 +++-
.../src/log_test_fcb_bookmarks_util.c | 2 +-
.../src/log_test_fcb_bookmarks_util.c | 2 +-
sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml | 29 ++
.../src/log_test_fcb_bookmarks.c | 38 +++
.../src/log_test_fcb_bookmarks.h | 43 +++
.../src/log_test_fcb_bookmarks_util.c | 42 ++-
.../src/testcases/s0_l10_b10_p100.c | 32 ++
.../src/testcases/s0_l1_b0_p100.c | 32 ++
.../src/testcases/s0_l1_b5_p100.c | 32 ++
.../src/testcases/s10_l10_b10_p100.c | 32 ++
.../full/selftest/fcb_bookmarks_mixed/syscfg.yml | 22 ++
sys/log/full/src/log_fcb.c | 65 +++-
sys/log/full/src/log_fcb2.c | 22 +-
sys/log/full/src/log_fcb_bmark.c | 375 +++++++++++++++++++--
sys/log/full/src/log_shell.c | 86 ++++-
sys/log/full/syscfg.yml | 13 +
21 files changed, 894 insertions(+), 79 deletions(-)
diff --git a/fs/fcb/include/fcb/fcb.h b/fs/fcb/include/fcb/fcb.h
index 7f97b9ee1..16d97305a 100644
--- a/fs/fcb/include/fcb/fcb.h
+++ b/fs/fcb/include/fcb/fcb.h
@@ -168,6 +168,28 @@ 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);
+/**
+ * Get first entry in the provided flash area
+ *
+ * @param fcb Pointer to FCB
+ * @param fap Optional pointer to flash area
+ * @param loc Pointer to first FCB entry in the provided flash area
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int fcb_getnext_in_area(struct fcb *fcb, struct flash_area *fap,
+ struct fcb_entry *loc);
+
+/**
+ * Get next area pointer from the FCB pointer
+ *
+ * @param fcb Pointer to the FCB
+ * @param fap Pointer to the flash_area
+ *
+ * @return Pointer to the flash_area that comes next
+ */
+struct flash_area *fcb_getnext_area(struct fcb *fcb, struct flash_area *fap);
+
#if MYNEWT_VAL_FCB_BIDIRECTIONAL
/**
* Call 'cb' for every element in flash circular buffer moving
diff --git a/fs/fcb/src/fcb.c b/fs/fcb/src/fcb.c
index 967f5b460..89856ef69 100644
--- a/fs/fcb/src/fcb.c
+++ b/fs/fcb/src/fcb.c
@@ -90,7 +90,7 @@ fcb_init(struct fcb *fcb)
assert((fcb->f_align & (fcb->f_align - 1)) == 0);
while (1) {
- rc = fcb_getnext_in_area(fcb, &fcb->f_active);
+ rc = fcb_getnext_in_area(fcb, NULL, &fcb->f_active);
if (rc == FCB_ERR_NOVAR) {
rc = FCB_OK;
break;
diff --git a/fs/fcb/src/fcb_getnext.c b/fs/fcb/src/fcb_getnext.c
index 196a9c457..fe2278a8a 100644
--- a/fs/fcb/src/fcb_getnext.c
+++ b/fs/fcb/src/fcb_getnext.c
@@ -63,10 +63,19 @@ fcb_start_offset(struct fcb *fcb)
}
int
-fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc)
+fcb_getnext_in_area(struct fcb *fcb, struct flash_area *fap,
+ struct fcb_entry *loc)
{
int rc;
+ /* If a flash area is specified, find first entry in that area */
+ if (fap) {
+ loc->fe_area = fap;
+ loc->fe_elem_off = fcb_len_in_flash(fcb, sizeof(struct fcb_disk_area));
+ loc->fe_elem_ix = 0;
+ loc->fe_data_len = 0;
+ }
+
rc = fcb_elem_info(fcb, loc);
if (rc == 0 || rc == FCB_ERR_CRC) {
do {
diff --git a/fs/fcb/src/fcb_priv.h b/fs/fcb/src/fcb_priv.h
index 352aa969a..064a435d0 100644
--- a/fs/fcb/src/fcb_priv.h
+++ b/fs/fcb/src/fcb_priv.h
@@ -47,7 +47,6 @@ fcb_len_in_flash(struct fcb *fcb, uint16_t len)
return (len + (fcb->f_align - 1)) & ~(fcb->f_align - 1);
}
-int fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc);
struct flash_area *fcb_getnext_area(struct fcb *fcb, struct flash_area *fap);
int fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc);
diff --git a/sys/log/full/include/log/log_fcb.h
b/sys/log/full/include/log/log_fcb.h
index ff81fcc28..7eca59b8c 100644
--- a/sys/log/full/include/log/log_fcb.h
+++ b/sys/log/full/include/log/log_fcb.h
@@ -46,14 +46,29 @@ struct log_fcb_bset {
/** Array of bookmarks. */
struct log_fcb_bmark *lfs_bmarks;
+ /** Enable sector bookmarks */
+ bool lfs_en_sect_bmarks;
+
/** The maximum number of bookmarks. */
int lfs_cap;
+ /** The maximum number of sector bookmarks. */
+ int lfs_sect_cap;
+
+ /** The number of currently used non-sector bookmarks. */
+ int lfs_non_sect_size;
+
/** The number of currently usable bookmarks. */
int lfs_size;
- /** The index where the next bookmark will get written. */
- int lfs_next;
+ /** The index where the next non-sector bmark will get written */
+ uint32_t lfs_next_non_sect;
+
+ /** The sector interval at which to insert sector bookmarks */
+ int lfs_sect_bmark_itvl;
+
+ /** The index where the next sector bmark will get written */
+ uint32_t lfs_next_sect;
};
/**
@@ -72,6 +87,7 @@ struct fcb_log {
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
struct log_fcb_bset fl_bset;
#endif
+ struct log *fl_log;
};
#elif MYNEWT_VAL(LOG_FCB2)
@@ -87,6 +103,7 @@ struct fcb_log {
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
struct log_fcb_bset fl_bset;
#endif
+ struct log *fl_log;
};
#endif
@@ -103,19 +120,35 @@ struct fcb_log {
* the log is walked, the starting point of the walk is added to the set of
* bookmarks.
*
- * FCB rotation invalidates all bookmarks. It is up to the client code to
+ * FCB rotation invalidates all bookmarks. It is up to the client code to
* clear a log's bookmarks whenever rotation occurs.
*/
/**
* @brief Configures an fcb_log to use the specified buffer for bookmarks.
+ * If sector bookmarks are enabled, buffer should be big enough
+ * to accommodate bookmarks for the entire flash area that is allocated
+ * for the FCB log, i,e; sizeof(struct log_fcb_bmark) *
+ * my_log.fl_fcb.f_sector_cnt + MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS)
*
* @param fcb_log The log to configure.
* @param buf The buffer to use for bookmarks.
- * @param bmark_count The bookmark capacity of the supplied buffer.
+ * @param avl_bmark_cnt The bookmark capacity of the supplied buffer,
+ * available bookmark count
+ * @param en_sect_bmarks Enable sector bookmarks
+ *
+ * @return 0 on success, non-zero on failure
*/
-void log_fcb_init_bmarks(struct fcb_log *fcb_log,
- struct log_fcb_bmark *buf, int bmark_count);
+int log_fcb_init_bmarks(struct fcb_log *fcb_log,
+ struct log_fcb_bmark *buf, int avl_bmark_cnt,
+ bool en_sect_bmarks);
+
+/** @brief Remove bookmarks which point to oldest FCB/FCB2 area. This is
+ * meant to get called just before the area is rotated out.
+ *
+ * @param fcb_log The fcb_log to operate on.
+ */
+void log_fcb_rotate_bmarks(struct fcb_log *fcb_log);
/**
* @brief Erases all bookmarks from the supplied fcb_log.
@@ -125,12 +158,14 @@ void log_fcb_init_bmarks(struct fcb_log *fcb_log,
void log_fcb_clear_bmarks(struct fcb_log *fcb_log);
/**
- * @brief Remove bookmarks which point to oldest FCB/FCB2 area. This is
- * meant to get called just before the area is rotated out.
+ * @brief Get bookmarks for a particular log
*
- * @param fcb_log The fcb_log to operate on.
+ * @param log Pointer to the log we want to read bookmarks from
+ * @param bmarks_size Pointer to the variable we want to read bookmarks into
+ *
+ * @return Pointer to the bookmarks array for the provided log
*/
-void log_fcb_rotate_bmarks(struct fcb_log *fcb_log);
+struct log_fcb_bmark *log_fcb_get_bmarks(struct log *log, uint32_t
*bmarks_size);
/**
* @brief Searches an fcb_log for the closest bookmark that comes before or at
@@ -138,12 +173,14 @@ void log_fcb_rotate_bmarks(struct fcb_log *fcb_log);
*
* @param fcb_log The log to search.
* @param index The index to look for.
+ * @param min_diff If bookmark was found, fill it up with the
difference
+ * else it will return -1.
*
* @return The closest bookmark on success;
* NULL if the log has no applicable bookmarks.
*/
const struct log_fcb_bmark *
-log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index);
+log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index, int
*min_diff);
/**
* Inserts a bookmark into the provided log.
@@ -151,13 +188,16 @@ log_fcb_closest_bmark(const struct fcb_log *fcb_log,
uint32_t index);
* @param fcb_log The log to insert a bookmark into.
* @param entry The entry the bookmark should point to.
* @param index The log entry index of the bookmark.
+ * @paran sect_bmark Bool indicating it is a sector bookmark.
+ *
+ * @return non-zero on failure, 0 on success
*/
#if MYNEWT_VAL(LOG_FCB)
-void log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb_entry *entry,
- uint32_t index);
+int log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry,
+ uint32_t index, bool sect_bmark);
#elif MYNEWT_VAL(LOG_FCB2)
-void log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb2_entry *entry,
- uint32_t index);
+int log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb2_entry *entry,
+ uint32_t index, bool sect_bmark);
#endif
#endif
diff --git
a/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c
b/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c
index c8d5c8ce9..25c40152d 100644
--- a/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c
+++ b/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c
@@ -220,7 +220,7 @@ ltfbu_init(const struct ltfbu_cfg *cfg)
TEST_ASSERT_FATAL(rc == 0);
if (cfg->bmark_count > 0) {
- log_fcb_init_bmarks(<fbu_fcb_log, ltfbu_bmarks, cfg->bmark_count);
+ log_fcb_init_bmarks(<fbu_fcb_log, ltfbu_bmarks, cfg->bmark_count,
false);
}
log_register("log", <fbu_log, &log_fcb_handler, <fbu_fcb_log,
diff --git
a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
b/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
index 854f99b2e..3e416cdcc 100644
--- a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
+++ b/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
@@ -231,7 +231,7 @@ ltfbu_init(const struct ltfbu_cfg *cfg)
TEST_ASSERT_FATAL(rc == 0);
if (cfg->bmark_count > 0) {
- log_fcb_init_bmarks(<fbu_fcb_log, ltfbu_bmarks, cfg->bmark_count);
+ log_fcb_init_bmarks(<fbu_fcb_log, ltfbu_bmarks, cfg->bmark_count,
false);
}
log_register("log", <fbu_log, &log_fcb_handler, <fbu_fcb_log,
diff --git a/sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml
b/sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml
new file mode 100644
index 000000000..07266232c
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml
@@ -0,0 +1,29 @@
+# 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.
+#
+pkg.name: sys/log/full/selftest/fcb_bookmarks_mixed
+pkg.type: unittest
+pkg.description: "Log unit tests; flash-alignment=8."
+pkg.author: "Apache Mynewt <[email protected]>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - "@apache-mynewt-core/sys/console/stub"
+ - "@apache-mynewt-core/sys/log/full"
+ - "@apache-mynewt-core/sys/log/full/selftest/util"
+ - "@apache-mynewt-core/test/testutil"
diff --git
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.c
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.c
new file mode 100644
index 000000000..5ed58ae8f
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.c
@@ -0,0 +1,38 @@
+/*
+ * 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 "os/mynewt.h"
+#include "log_test_util/log_test_util.h"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_SUITE(log_test_suite_fcb_bookmarks)
+{
+ log_test_case_fcb_bookmarks_s0_l1_b0_p100();
+ log_test_case_fcb_bookmarks_s0_l1_b5_p100();
+ log_test_case_fcb_bookmarks_s0_l10_b10_p100();
+ log_test_case_fcb_bookmarks_s10_l10_b10_p100();
+}
+
+int
+main(int argc, char **argv)
+{
+ log_test_suite_fcb_bookmarks();
+
+ return tu_any_failed;
+}
diff --git
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.h
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.h
new file mode 100644
index 000000000..441d842ce
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#ifndef H_LOG_TEST_FCB_BOOKMARKS_
+#define H_LOG_TEST_FCB_BOOKMARKS_
+
+#include "os/mynewt.h"
+#include "testutil/testutil.h"
+
+struct ltfbu_cfg {
+ int skip_mod;
+ int body_len;
+ int bmark_count;
+ int pop_count;
+};
+
+void ltfbu_populate_log(int count);
+void ltfbu_verify_log(uint32_t start_idx);
+void ltfbu_init(const struct ltfbu_cfg *cfg);
+void ltfbu_test_once(const struct ltfbu_cfg *cfg);
+
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s0_l1_b0_p100);
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s0_l1_b5_p100);
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s0_l10_b10_p100);
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s10_l10_b10_p100);
+
+#endif
diff --git
a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks_util.c
similarity index 86%
copy from sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
copy to
sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks_util.c
index 854f99b2e..3464d2504 100644
--- a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
+++
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks_util.c
@@ -48,7 +48,21 @@ static struct flash_area ltfbu_fcb_areas[] = {
[1] = {
.fa_off = 1 * LTFBU_SECTOR_SIZE,
.fa_size = LTFBU_SECTOR_SIZE,
+ },
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ [2] = {
+ .fa_off = 2 * LTFBU_SECTOR_SIZE,
+ .fa_size = LTFBU_SECTOR_SIZE,
+ },
+ [3] = {
+ .fa_off = 3 * LTFBU_SECTOR_SIZE,
+ .fa_size = LTFBU_SECTOR_SIZE,
+ },
+ [4] = {
+ .fa_off = 4 * LTFBU_SECTOR_SIZE,
+ .fa_size = LTFBU_SECTOR_SIZE,
}
+ #endif
};
static int
@@ -136,6 +150,13 @@ ltfbu_write_entry(void)
memset(body, idx, ltfbu_cfg.body_len);
+#if 0
+ printf("log entry: ");
+ for (int i = 0; i < ltfbu_cfg.body_len; i++) {
+ printf("%2x", body[i]);
+ }
+ printf("\n");
+#endif
rc = log_append_body(<fbu_log, 0, 255, LOG_ETYPE_BINARY, body,
ltfbu_cfg.body_len);
TEST_ASSERT_FATAL(rc == 0);
@@ -230,12 +251,9 @@ ltfbu_init(const struct ltfbu_cfg *cfg)
rc = fcb_init(<fbu_fcb_log.fl_fcb);
TEST_ASSERT_FATAL(rc == 0);
- if (cfg->bmark_count > 0) {
- log_fcb_init_bmarks(<fbu_fcb_log, ltfbu_bmarks, cfg->bmark_count);
- }
-
log_register("log", <fbu_log, &log_fcb_handler, <fbu_fcb_log,
LOG_SYSLEVEL);
+
}
void
@@ -243,6 +261,7 @@ ltfbu_test_once(const struct ltfbu_cfg *cfg)
{
uint32_t start_idx;
int i;
+ int rc = 0;
ltfbu_init(cfg);
@@ -253,12 +272,21 @@ ltfbu_test_once(const struct ltfbu_cfg *cfg)
* a. All expected entries are visited.
* b. No extra entries are visited.
*
- * This procedure is repeated three times to ensure that the FCB is rotated
+ * This procedure is repeated six times to ensure that the FCB is rotated
* between walks.
*/
- for (i = 0; i < 3; i++) {
- ltfbu_populate_log(cfg->pop_count);
+ ltfbu_populate_log(cfg->pop_count);
+
+ if (cfg->bmark_count > 0) {
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ rc = log_fcb_init_bmarks(<fbu_fcb_log, ltfbu_bmarks,
cfg->bmark_count, true);
+#else
+ rc = log_fcb_init_bmarks(<fbu_fcb_log, ltfbu_bmarks,
cfg->bmark_count, false);
+#endif
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+ for (i = 0; i < 6; i++) {
start_idx = 0;
while (start_idx < ltfbu_entry_idxs[ltfbu_num_entry_idxs - 1]) {
ltfbu_verify_log(start_idx);
diff --git
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l10_b10_p100.c
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l10_b10_p100.c
new file mode 100644
index 000000000..4555d4f54
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l10_b10_p100.c
@@ -0,0 +1,32 @@
+/*
+ * 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"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s0_l10_b10_p100)
+{
+ struct ltfbu_cfg cfg = {
+ .skip_mod = 0,
+ .body_len = 10,
+ .bmark_count = 10,
+ .pop_count = 100,
+ };
+ ltfbu_test_once(&cfg);
+}
diff --git
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b0_p100.c
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b0_p100.c
new file mode 100644
index 000000000..d21126407
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b0_p100.c
@@ -0,0 +1,32 @@
+/*
+ * 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"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s0_l1_b0_p100)
+{
+ struct ltfbu_cfg cfg = {
+ .skip_mod = 0,
+ .body_len = 10,
+ .bmark_count = 0,
+ .pop_count = 100,
+ };
+ ltfbu_test_once(&cfg);
+}
diff --git
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b5_p100.c
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b5_p100.c
new file mode 100644
index 000000000..13c097d97
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b5_p100.c
@@ -0,0 +1,32 @@
+/*
+ * 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"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s0_l1_b5_p100)
+{
+ struct ltfbu_cfg cfg = {
+ .skip_mod = 0,
+ .body_len = 10,
+ .bmark_count = 5,
+ .pop_count = 100,
+ };
+ ltfbu_test_once(&cfg);
+}
diff --git
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s10_l10_b10_p100.c
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s10_l10_b10_p100.c
new file mode 100644
index 000000000..b8296d38d
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s10_l10_b10_p100.c
@@ -0,0 +1,32 @@
+/*
+ * 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"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s10_l10_b10_p100)
+{
+ struct ltfbu_cfg cfg = {
+ .skip_mod = 10,
+ .body_len = 10,
+ .bmark_count = 10,
+ .pop_count = 100,
+ };
+ ltfbu_test_once(&cfg);
+}
diff --git a/sys/log/full/selftest/fcb_bookmarks_mixed/syscfg.yml
b/sys/log/full/selftest/fcb_bookmarks_mixed/syscfg.yml
new file mode 100644
index 000000000..da0698b62
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/syscfg.yml
@@ -0,0 +1,22 @@
+# 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.
+#
+
+syscfg.vals:
+ LOG_FCB: 1
+ LOG_FCB_BOOKMARKS: 1
+ LOG_FCB_SECTOR_BOOKMARKS: 1
diff --git a/sys/log/full/src/log_fcb.c b/sys/log/full/src/log_fcb.c
index 05dd29e3b..529e8f473 100644
--- a/sys/log/full/src/log_fcb.c
+++ b/sys/log/full/src/log_fcb.c
@@ -53,7 +53,9 @@ fcb_get_fa_hdr(struct fcb *fcb, struct log *log, struct
fcb_entry *fcb_entry, st
* given offset is found, start walking from there.
*/
static int
-fcb_walk_back_find_start(struct fcb *fcb, struct log *log, struct log_offset
*log_offset, struct fcb_entry *fcb_entry)
+fcb_walk_back_find_start(struct fcb *fcb, struct log *log,
+ struct log_offset *log_offset,
+ struct fcb_entry *fcb_entry)
{
struct flash_area *fap;
struct log_entry_hdr hdr;
@@ -111,6 +113,10 @@ found_ent:
*
* The "index" field corresponds to a log entry index.
*
+ * If bookmark is found with the minimum difference in indices, min_diff
contains
+ * the difference else it will contain -1 if no bookmark is found. min_diff is 0
+ * means an exact match.
+ *
* If bookmarks are enabled, this function uses them in the search.
*
* @return 0 if an entry was found
@@ -119,7 +125,7 @@ found_ent:
*/
static int
log_fcb_find_gte(struct log *log, struct log_offset *log_offset,
- struct fcb_entry *out_entry)
+ struct fcb_entry *out_entry, int *min_diff)
{
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
const struct log_fcb_bmark *bmark;
@@ -166,7 +172,7 @@ log_fcb_find_gte(struct log *log, struct log_offset
*log_offset,
}
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
- bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index);
+ bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index, min_diff);
if (bmark != NULL) {
*out_entry = bmark->lfb_entry;
bmark_found = true;
@@ -209,6 +215,10 @@ log_fcb_start_append(struct log *log, int len, struct
fcb_entry *loc)
struct fcb_log *fcb_log;
struct flash_area *old_fa;
int rc = 0;
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ int active_id;
+ uint32_t idx;
+#endif
#if MYNEWT_VAL(LOG_STATS)
int cnt;
#endif
@@ -216,6 +226,10 @@ log_fcb_start_append(struct log *log, int len, struct
fcb_entry *loc)
fcb_log = (struct fcb_log *)log->l_arg;
fcb = &fcb_log->fl_fcb;
+ /* Cache active ID before appending */
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ active_id = fcb->f_active_id;
+#endif
while (1) {
rc = fcb_append(fcb, len, loc);
if (rc == 0) {
@@ -250,8 +264,10 @@ log_fcb_start_append(struct log *log, int len, struct
fcb_entry *loc)
log->l_rotate_notify_cb(log);
}
-#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
- /* The FCB needs to be rotated. */
+#if MYNEWT_VAL(LOG_FCB_BOOKMARKS) && !MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ /* The FCB needs to be rotated. For sector bookmarks
+ * we just re-initialize the bookmarks
+ */
log_fcb_rotate_bmarks(fcb_log);
#endif
@@ -260,6 +276,15 @@ log_fcb_start_append(struct log *log, int len, struct
fcb_entry *loc)
goto err;
}
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ /* The FCB needs to be rotated, reinit previously allocated
+ * bookmarks
+ */
+ log_fcb_init_bmarks(fcb_log, fcb_log->fl_bset.lfs_bmarks,
+ fcb_log->fl_bset.lfs_cap,
+ fcb_log->fl_bset.lfs_en_sect_bmarks);
+#endif
+
#if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
/*
* FCB was rotated successfully so let's check if watermark was within
@@ -273,6 +298,20 @@ log_fcb_start_append(struct log *log, int len, struct
fcb_entry *loc)
#endif
}
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ /* Add bookmark if entry is added to a new sector */
+ if (!rc && log->l_log->log_type != LOG_TYPE_STREAM) {
+ if (fcb->f_active_id != active_id) {
+#if MYNEWT_VAL(LOG_GLOBAL_IDX)
+ idx = g_log_info.li_next_index;
+#else
+ idx = log->l_idx;
+#endif
+ log_fcb_add_bmark(fcb_log, loc, idx, true);
+ }
+ }
+#endif
+
err:
return (rc);
}
@@ -582,12 +621,13 @@ log_fcb_walk_impl(struct log *log, log_walk_func_t
walk_func,
struct flash_area *fap;
int rc;
struct fcb_entry_cache cache;
+ int min_diff = -1;
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);
+ rc = log_fcb_find_gte(log, log_offset, &loc, &min_diff);
switch (rc) {
case 0:
/* Found a starting point. */
@@ -611,9 +651,12 @@ log_fcb_walk_impl(struct log *log, log_walk_func_t
walk_func,
#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.
+ * Only add a bmark if the index is non-zero and an exactly matching bmark
+ * was not found. If an exactly matching bmark was found, min_diff is 0,
+ * else it stays -1 or is great than 0.
*/
- if (log_offset->lo_ts >= 0) {
- log_fcb_add_bmark(fcb_log, &loc, log_offset->lo_index);
+ if ((log_offset->lo_ts >= 0 && log_offset->lo_index > 0) && min_diff != 0)
{
+ log_fcb_add_bmark(fcb_log, &loc, log_offset->lo_index, false);
}
#endif
@@ -674,15 +717,15 @@ log_fcb_flush(struct log *log)
static int
log_fcb_registered(struct log *log)
{
+ struct fcb_log *fl = (struct fcb_log *)log->l_arg;
+
+ fl->fl_log = log;
#if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
- struct fcb_log *fl;
#if MYNEWT_VAL(LOG_PERSIST_WATERMARK)
struct fcb *fcb;
struct fcb_entry loc;
#endif
- fl = (struct fcb_log *)log->l_arg;
-
#if MYNEWT_VAL(LOG_PERSIST_WATERMARK)
fcb = &fl->fl_fcb;
diff --git a/sys/log/full/src/log_fcb2.c b/sys/log/full/src/log_fcb2.c
index b307acfe9..2bb2e604e 100644
--- a/sys/log/full/src/log_fcb2.c
+++ b/sys/log/full/src/log_fcb2.c
@@ -46,7 +46,10 @@ static int log_fcb2_rtr_erase(struct log *log);
*
* The "index" field corresponds to a log entry index.
*
- * If bookmarks are enabled, this function uses them in the search.
+ *
+ * If bookmark is found with the minimum difference in indexes, min_diff
contains
+ * the difference else it will contain -1 if no bookmark is found. min_diff is 0
+ * means an exact match.
*
* @return 0 if an entry was found
* SYS_ENOENT if there are no suitable entries.
@@ -54,7 +57,7 @@ static int log_fcb2_rtr_erase(struct log *log);
*/
static int
log_fcb2_find_gte(struct log *log, struct log_offset *log_offset,
- struct fcb2_entry *out_entry)
+ struct fcb2_entry *out_entry, int *min_diff)
{
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
const struct log_fcb_bmark *bmark;
@@ -67,6 +70,7 @@ log_fcb2_find_gte(struct log *log, struct log_offset
*log_offset,
fcb_log = log->l_arg;
fcb = &fcb_log->fl_fcb;
+ (void)min_diff;
/* Attempt to read the last entry. If this fails, the FCB is empty. */
memset(out_entry, 0, sizeof(*out_entry));
rc = fcb2_getprev(fcb, out_entry);
@@ -103,7 +107,7 @@ log_fcb2_find_gte(struct log *log, struct log_offset
*log_offset,
return SYS_EUNKNOWN;
}
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
- bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index);
+ bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index, min_diff);
if (bmark != NULL) {
*out_entry = bmark->lfb_entry;
}
@@ -476,12 +480,13 @@ log_fcb2_walk(struct log *log, log_walk_func_t walk_func,
struct fcb_log *fcb_log;
struct fcb2_entry loc;
int rc;
+ int min_diff = -1;
fcb_log = log->l_arg;
fcb = &fcb_log->fl_fcb;
/* Locate the starting point of the walk. */
- rc = log_fcb2_find_gte(log, log_off, &loc);
+ rc = log_fcb2_find_gte(log, log_off, &loc, &min_diff);
switch (rc) {
case 0:
/* Found a starting point. */
@@ -497,8 +502,8 @@ log_fcb2_walk(struct log *log, log_walk_func_t walk_func,
/* 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_off->lo_ts >= 0) {
- log_fcb_add_bmark(fcb_log, &loc, log_off->lo_index);
+ if ((log_off->lo_ts >= 0 && log_off->lo_index > 0) && min_diff != 0) {
+ log_fcb_add_bmark(fcb_log, &loc, log_off->lo_index, false);
}
#endif
@@ -537,14 +542,15 @@ log_fcb2_registered(struct log *log)
{
struct fcb2 *fcb;
int i;
- struct fcb_log *fl;
+ struct fcb_log *fl = (struct fcb_log *)log->l_arg;
+
#if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
#if MYNEWT_VAL(LOG_PERSIST_WATERMARK)
struct fcb2_entry loc;
#endif
#endif
+ fl->fl_log = log;
- fl = (struct fcb_log *)log->l_arg;
fcb = &fl->fl_fcb;
for (i = 0; i < fcb->f_range_cnt; i++) {
diff --git a/sys/log/full/src/log_fcb_bmark.c b/sys/log/full/src/log_fcb_bmark.c
index e9282771a..2a210aa94 100644
--- a/sys/log/full/src/log_fcb_bmark.c
+++ b/sys/log/full/src/log_fcb_bmark.c
@@ -22,17 +22,152 @@
#include "os/mynewt.h"
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
-
+#include "log/log.h"
#include "log/log_fcb.h"
-void
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+static int
+log_fcb_init_sector_bmarks(struct fcb_log *fcb_log)
+{
+ int rc = 0;
+ int i = 0;
+ int j = 0;
+ struct log_fcb_bset *bset = &fcb_log->fl_bset;
+ struct log_entry_hdr ueh = {0};
+#if MYNEWT_VAL(LOG_FCB)
+ struct fcb_entry loc = {0};
+ struct flash_area *fa = NULL;
+
+ rc = fcb_getnext(&fcb_log->fl_fcb, &loc);
+ if (rc) {
+ return SYS_EOK;
+ }
+#else
+ struct flash_sector_range *range = NULL;
+ struct fcb2_entry loc = {0};
+
+ rc = fcb2_getnext(&fcb_log->fl_fcb, &loc);
+ if (rc) {
+ return SYS_EOK;
+ }
+#endif
+
+ /* Start adding a bookmark from the end of array just before
+ * non-sector bookmarks
+ */
+ bset->lfs_next_sect = bset->lfs_sect_cap - 1;
+ for (i = 0; i < bset->lfs_sect_cap; i++) {
+ rc = log_read_hdr(fcb_log->fl_log, &loc, &ueh);
+ if (rc) {
+ /* Read failed, don't add a bookmark, done adding bookmarks */
+ rc = SYS_EOK;
+ break;
+ }
+
+ rc = log_fcb_add_bmark(fcb_log, &loc, ueh.ue_index, true);
+ if (rc) {
+ return rc;
+ }
+
+#if MYNEWT_VAL(LOG_FCB)
+ j = 0;
+ fa = loc.fe_area;
+ /* Keep skipping sectors until lfs_sect_bmark_itvl is reached */
+ do {
+ fa = fcb_getnext_area(&fcb_log->fl_fcb, fa);
+ if (!fa) {
+ break;
+ }
+ j++;
+ } while (j < bset->lfs_sect_bmark_itvl);
+
+ if (!fa) {
+ break;
+ }
+
+ /* First entry in the next area */
+ rc = fcb_getnext_in_area(&fcb_log->fl_fcb, fa, &loc);
+ if (rc) {
+ rc = SYS_EOK;
+ break;
+ }
+#else
+ j = 0;
+
+ /* Keep skipping rangess until lfs_sect_bmark_itvl is reached */
+ do {
+ /* Get next range */
+ range = fcb2_getnext_range(&fcb_log->fl_fcb, &loc);
+ if (!range) {
+ break;
+ }
+ j++;
+ } while (j < bset->lfs_sect_bmark_itvl);
+
+ if (!range) {
+ break;
+ }
+
+ /* First entry in the next area */
+ rc = fcb2_getnext_in_area(&fcb_log->fl_fcb, range, &loc);
+ if (rc) {
+ rc = SYS_EOK;
+ break;
+ }
+#endif
+ }
+
+ return rc;
+}
+#endif
+
+int
log_fcb_init_bmarks(struct fcb_log *fcb_log,
- struct log_fcb_bmark *buf, int bmark_count)
+ struct log_fcb_bmark *buf, int avl_bmark_cnt,
+ bool en_sect_bmarks)
{
- fcb_log->fl_bset = (struct log_fcb_bset) {
+ struct log_fcb_bset *bset = &fcb_log->fl_bset;
+ /* Required bookmark count */
+ int reqd_bmark_cnt = MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+
+ (void)reqd_bmark_cnt;
+ if (!bset || !buf || !avl_bmark_cnt) {
+ return SYS_EINVAL;
+ }
+
+ memset(buf, 0, sizeof(struct log_fcb_bmark) * avl_bmark_cnt);
+
+ *bset = (struct log_fcb_bset) {
.lfs_bmarks = buf,
- .lfs_cap = bmark_count,
+ .lfs_cap = avl_bmark_cnt,
+ .lfs_en_sect_bmarks = en_sect_bmarks
};
+
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ if (en_sect_bmarks) {
+ /* Default sector bookmark interval is 1 */
+ bset->lfs_sect_bmark_itvl = 1;
+ reqd_bmark_cnt += fcb_log->fl_fcb.f_sector_cnt;
+ /* Make sure we have allocated the exact number of bookmarks
+ * compare available bookmark count Vs required bookmark count
+ */
+ if (avl_bmark_cnt < reqd_bmark_cnt) {
+ /* Not enough space allocated for sector bookmarks,
+ * add bookmarks at sector intervals
+ */
+ bset->lfs_sect_bmark_itvl =
+ fcb_log->fl_fcb.f_sector_cnt / avl_bmark_cnt;
+ bset->lfs_sect_cap = avl_bmark_cnt -
+ MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+ } else {
+ bset->lfs_sect_cap = fcb_log->fl_fcb.f_sector_cnt;
+ }
+
+ return log_fcb_init_sector_bmarks(fcb_log);
+ }
+#endif
+
+ return 0;
}
void
@@ -61,7 +196,6 @@ log_fcb_rotate_bmarks(struct fcb_log *fcb_log)
i--;
}
bset->lfs_size--;
- bset->lfs_next = bset->lfs_size;
}
}
@@ -69,28 +203,93 @@ void
log_fcb_clear_bmarks(struct fcb_log *fcb_log)
{
fcb_log->fl_bset.lfs_size = 0;
- fcb_log->fl_bset.lfs_next = 0;
+ fcb_log->fl_bset.lfs_next_non_sect = 0;
+ fcb_log->fl_bset.lfs_non_sect_size = 0;
+ memset(fcb_log->fl_bset.lfs_bmarks, 0,
+ sizeof(struct log_fcb_bmark) *
+ fcb_log->fl_bset.lfs_cap);
+}
+
+struct log_fcb_bmark *
+log_fcb_get_bmarks(struct log *log, uint32_t *bmarks_size)
+{
+ struct fcb_log *fcb_log = (struct fcb_log *)log->l_arg;
+
+ *bmarks_size = fcb_log->fl_bset.lfs_cap;
+
+ return fcb_log->fl_bset.lfs_bmarks;
}
const struct log_fcb_bmark *
-log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index)
+log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index,
+ int *min_diff)
{
const struct log_fcb_bmark *closest;
const struct log_fcb_bmark *bmark;
- uint32_t min_diff;
uint32_t diff;
- int i;
+ int i = 0;
+ uint32_t start_idx = 0;
- min_diff = UINT32_MAX;
+ *min_diff = -1;
closest = NULL;
- for (i = 0; i < fcb_log->fl_bset.lfs_size; i++) {
+ if (!fcb_log->fl_bset.lfs_bmarks) {
+ return closest;
+ }
+
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+#if MYNEWT_VAL(LOG_FCB)
+ /* Reason for this is that we want to iterate to the end of the
+ * bmarks sector section of the array where a bookmark is valid,
+ * this is only for the case where the sector bookmarks have not
+ * been fully filled up, if they are filled up, we can iterate
+ * normally to the end of the array
+ */
+ if (!fcb_log->fl_bset.lfs_bmarks[i].lfb_entry.fe_area &&
+ fcb_log->fl_bset.lfs_next_sect < (fcb_log->fl_bset.lfs_sect_cap - 1)) {
+ start_idx = fcb_log->fl_bset.lfs_next_sect + 1;
+ }
+#endif
+#endif
+
+ /* This works for both sector as well as non-sector bmarks
+ * because we calculate the min diff and iterate to the end
+ * of the bmarks array keeping track of min diff
+ */
+ for (i = start_idx; i < (start_idx + fcb_log->fl_bset.lfs_size); i++) {
bmark = &fcb_log->fl_bset.lfs_bmarks[i];
+#if MYNEWT_VAL(LOG_FCB)
+ if (!fcb_log->fl_bset.lfs_bmarks[i].lfb_entry.fe_area) {
+#if !MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ /* Empty non-sector bookmark, nothing more to do
+ * Previous closest bookmark is the closest one */
+ break;
+#endif
+ }
+#elif MYNEWT_VAL(LOG_FCB2)
+ if (!fcb_log->fl_bset.lfs_bmarks[i].lfb_entry.fe_range) {
+#if !MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ /* Empty non-sector bookmark, nothing more to do
+ * Previous closest bookmark is the closest one */
+ break;
+#endif
+ }
+#endif
if (bmark->lfb_index <= index) {
diff = index - bmark->lfb_index;
- if (diff < min_diff) {
- min_diff = diff;
+ if (diff < *min_diff) {
+ *min_diff = diff;
closest = bmark;
+ MODLOG_DEBUG(LOG_MODULE_DEFAULT,
+ "index: %u, closest bmark idx: %u, \n",
+ (unsigned int)index,
+ (unsigned int)bmark->lfb_index);
+ /* We found the exact match, no need to keep searching for a
+ * better match
+ */
+ if (*min_diff == 0) {
+ break;
+ }
}
}
}
@@ -98,37 +297,151 @@ log_fcb_closest_bmark(const struct fcb_log *fcb_log,
uint32_t index)
return closest;
}
-#if MYNEWT_VAL(LOG_FCB)
-void
-log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb_entry *entry,
- uint32_t index)
-#elif MYNEWT_VAL(LOG_FCB2)
-void
-log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb2_entry *entry,
- uint32_t index)
-#endif
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+static int
+log_fcb_insert_sect_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry,
+ uint32_t index)
{
struct log_fcb_bset *bset;
bset = &fcb_log->fl_bset;
- if (bset->lfs_cap == 0) {
- return;
+ if (bset->lfs_size < fcb_log->fl_bset.lfs_sect_cap) {
+ bset->lfs_bmarks[bset->lfs_next_sect] = (struct log_fcb_bmark) {
+ .lfb_entry = *entry,
+ .lfb_index = index,
+ };
+
+ bset->lfs_size++;
+ bset->lfs_next_sect--;
+ if (bset->lfs_next_sect >= fcb_log->fl_bset.lfs_sect_cap) {
+ bset->lfs_next_sect = fcb_log->fl_bset.lfs_sect_cap - 1;
+ }
}
- bset->lfs_bmarks[bset->lfs_next] = (struct log_fcb_bmark) {
+ return 0;
+}
+#endif
+
+#if MYNEWT_VAL(LOG_FCB)
+static int
+log_fcb_replace_non_sect_bmark(struct fcb_log *fcb_log, struct fcb_entry
*entry,
+ uint32_t index, int pos)
+#elif MYNEWT_VAL(LOG_FCB2)
+static int
+log_fcb_replace_non_sect_bmark(struct fcb_log *fcb_log, struct fcb2_entry
*entry,
+ uint32_t index, int pos)
+#endif
+{
+ int i = 0;
+ struct log_fcb_bset *bset = &fcb_log->fl_bset;
+
+#if MYNEWT_VAL(LOG_FCB) && MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ if (bset->lfs_en_sect_bmarks) {
+ for (i = bset->lfs_sect_cap;
+ i < (bset->lfs_non_sect_size + bset->lfs_sect_cap);
+ i++) {
+ if (index == bset->lfs_bmarks[i].lfb_index) {
+ /* If index matches, no need to replace */
+ return SYS_EALREADY;
+ }
+ }
+ } else
+#endif
+ {
+ for (i = 0; i < bset->lfs_non_sect_size; i++) {
+ if (index == bset->lfs_bmarks[i].lfb_index) {
+ /* If index matches, no need to replace */
+ return SYS_EALREADY;
+ }
+ }
+ }
+
+ bset->lfs_bmarks[pos] = (struct log_fcb_bmark) {
.lfb_entry = *entry,
.lfb_index = index,
};
- if (bset->lfs_size < bset->lfs_cap) {
- bset->lfs_size++;
+ return SYS_EOK;
+}
+
+#if MYNEWT_VAL(LOG_FCB)
+int
+log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry,
+ uint32_t index, bool sect_bmark)
+#elif MYNEWT_VAL(LOG_FCB2)
+int
+log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb2_entry *entry,
+ uint32_t index, bool sect_bmark)
+#endif
+{
+ struct log_fcb_bset *bset = &fcb_log->fl_bset;
+ int rc = 0;
+
+ if (bset->lfs_cap == 0) {
+ return SYS_ENOMEM;
}
- bset->lfs_next++;
- if (bset->lfs_next >= bset->lfs_cap) {
- bset->lfs_next = 0;
+#if MYNEWT_VAL(LOG_FCB) && MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+ if (sect_bmark & bset->lfs_en_sect_bmarks) {
+ rc = log_fcb_insert_sect_bmark(fcb_log, entry, index);
+ if (rc) {
+ MODLOG_DEBUG(LOG_MODULE_DEFAULT, "insert bmark failure: %u\n",
+ index);
+ }
+ MODLOG_DEBUG(LOG_MODULE_DEFAULT, "insert bmark index: %u, pos: %u\n",
+ index, bset->lfs_next_sect);
+ } else {
+ /* Replace oldest non-sector bmark */
+ rc = log_fcb_replace_non_sect_bmark(fcb_log, entry, index,
+ bset->lfs_next_non_sect +
+ (bset->lfs_en_sect_bmarks ?
+ bset->lfs_sect_cap : 0));
+ if (rc == SYS_EOK) {
+ MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, pos:
%u\n",
+ index, bset->lfs_next_non_sect +
+ (bset->lfs_en_sect_bmarks ?
+ bset->lfs_sect_cap : 0));
+
+ if (bset->lfs_non_sect_size <
MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS)) {
+ bset->lfs_non_sect_size++;
+ bset->lfs_size++;
+ }
+
+ bset->lfs_next_non_sect = (bset->lfs_next_non_sect + 1) %
+ MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+ }
}
+#else
+ if (!sect_bmark) {
+ if (bset->lfs_size >= MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS)) {
+ /* Replace oldest non-sector bmark */
+ rc = log_fcb_replace_non_sect_bmark(fcb_log, entry, index,
+ bset->lfs_next_non_sect);
+ if (rc == SYS_EOK) {
+ MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u,
pos: %u\n",
+ index, bset->lfs_next_non_sect);
+ bset->lfs_next_non_sect = (bset->lfs_next_non_sect + 1) %
+
MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+ }
+ } else {
+ rc = log_fcb_replace_non_sect_bmark(fcb_log, entry, index,
+ bset->lfs_size);
+ if (rc == SYS_EOK) {
+ MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u,
pos: %u\n",
+ index, bset->lfs_size);
+ if (!bset->lfs_size) {
+ /* First non-sector bmark position */
+ bset->lfs_next_non_sect = 0;
+ }
+ bset->lfs_size++;
+ }
+ }
+
+ assert(bset->lfs_size <= MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS));
+ }
+#endif
+ return SYS_EOK;
}
#endif /* MYNEWT_VAL(LOG_FCB_BOOKMARKS) */
diff --git a/sys/log/full/src/log_shell.c b/sys/log/full/src/log_shell.c
index a10c08eb1..c33be9eae 100644
--- a/sys/log/full/src/log_shell.c
+++ b/sys/log/full/src/log_shell.c
@@ -51,6 +51,8 @@ struct walk_arg {
uint32_t count_limit;
/* Entry number */
uint32_t count;
+ /* Entry index */
+ uint32_t idx;
};
static int
@@ -172,11 +174,22 @@ shell_log_dump_cmd(int argc, char **argv)
bool clear_log;
bool reverse = false;
bool dump_logs = true;
+ bool dump_bmarks = false;
+ uint32_t bmarks_size = 0;
+ struct log_fcb_bmark *bmarks = NULL;
struct walk_arg arg = {};
int i;
- int rc;
+ int rc = 0;
+ int start = -1;
+ int end = -1;
clear_log = false;
+ (void)dump_bmarks;
+ (void)bmarks;
+ (void)bmarks_size;
+ (void)start;
+ (void)end;
+
for (i = 1; i < argc; ++i) {
if (0 == strcmp(argv[i], "-l")) {
list_only = true;
@@ -208,6 +221,22 @@ shell_log_dump_cmd(int argc, char **argv)
dump_logs = false;
continue;
}
+ if (0 == strcmp(argv[i], "-b")) {
+ dump_logs = false;
+ dump_bmarks = true;
+ continue;
+ }
+ if (0 == strcmp(argv[i], "-i")) {
+ if (i + 1 < argc) {
+ arg.idx = parse_ll_bounds(argv[i + 1], 0, UINT32_MAX, &rc);
+ if (rc) {
+ arg.idx = 0;
+ }
+ log_offset.lo_arg = &arg;
+ }
+ ++i;
+ continue;
+ }
if (0 == strcmp(argv[i], "-r")) {
reverse = true;
continue;
@@ -251,6 +280,57 @@ shell_log_dump_cmd(int argc, char **argv)
continue;
}
+#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
+ if (dump_bmarks) {
+ bmarks = log_fcb_get_bmarks(log, &bmarks_size);
+ for (i = 0; i < bmarks_size; i++) {
+#if MYNEWT_VAL(LOG_FCB)
+ if (!bmarks[i].lfb_entry.fe_area) {
+ if (start == -1) {
+ start = i;
+ }
+ end = i;
+ continue;
+ }
+ if (start != -1) {
+ console_printf("bookmarks unused: %d to %d\n", start, end);
+ start = -1;
+ end = -1;
+ }
+ console_printf("%u: index:%lu fa_off:%x fe_elem_off:%lx\n", i,
+ bmarks[i].lfb_index,
+ (uintptr_t)bmarks[i].lfb_entry.fe_area->fa_off,
+ bmarks[i].lfb_entry.fe_elem_off);
+#else
+ if (!bmarks[i].lfb_entry.fe_range) {
+ if (start == -1) {
+ start = i;
+ }
+ end = i;
+ continue;
+ }
+ if (start != -1) {
+ console_printf("bookmarks unused: %d to %d\n", start, end);
+ start = -1;
+ end = -1;
+ }
+ console_printf("%u: index:%lu fa_off:%x fe_sector:%x
fe_data_off:%lx\n", i,
+ bmarks[i].lfb_index,
+
(uintptr_t)bmarks[i].lfb_entry.fe_range->fsr_flash_area.fa_off,
+ (uintptr_t)bmarks[i].lfb_entry.fe_sector,
+ bmarks[i].lfb_entry.fe_data_off);
+#endif
+ }
+
+ if (start != -1) {
+ console_printf("bookmarks unused: %d to %d\n", start, end);
+ start = -1;
+ end = -1;
+ }
+ goto err;
+ }
+#endif
+
if (clear_log) {
console_printf("Clearing log %s\n", log->l_name);
rc = log_flush(log);
@@ -278,11 +358,13 @@ shell_log_dump_cmd(int argc, char **argv)
if (dump_logs) {
arg.count = 0;
+ log_offset.lo_index = arg.idx;
rc = log_walk_body(log, shell_log_dump_entry, &log_offset);
- } else {
+ } else if (!dump_bmarks) {
/* Measure time for log_walk */
shell_log_count = 0;
os_time_t start = os_time_get();
+ log_offset.lo_index = arg.idx;
rc = log_walk_body(log, shell_log_count_entry, &log_offset);
os_time_t end = os_time_get();
console_printf("Log %s %d entries walked in %d ms\n",
log->l_name,
diff --git a/sys/log/full/syscfg.yml b/sys/log/full/syscfg.yml
index dc35b6c54..7170e91ed 100644
--- a/sys/log/full/syscfg.yml
+++ b/sys/log/full/syscfg.yml
@@ -179,6 +179,19 @@ syscfg.defs:
the global index to be sequentially increasing for persisted logs.
value: 0
+ LOG_FCB_NUM_ABS_BOOKMARKS:
+ description: >
+ Number of absolute bookmarks excluding sector bookmarks
+ value: 2
+
+ LOG_FCB_SECTOR_BOOKMARKS:
+ description: >
+ Enable sector bookmarks
+ value: 0
+ restrictions:
+ - LOG_FCB_BOOKMARKS
+ - LOG_FCB
+
syscfg.vals.CONSOLE_TICKS:
LOG_CONSOLE_PRETTY_WITH_TIMESTAMP: 0