diff --git a/fs/fcb/include/fcb/fcb.h b/fs/fcb/include/fcb/fcb.h index 7f97b9ee17..5eb0679367 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 fa 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 *fa, + struct fcb_entry *loc); + +/** + * Get next area pointer from the FCB pointer to by 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 967f5b4600..89856ef69d 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 196a9c4571..5046242c45 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 *fa, + struct fcb_entry *loc) { int rc; + /* If a flash area is specified, find first entry in that area */ + if (fa) { + loc->fe_area = fa; + 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 352aa969a7..064a435d07 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 ff81fcc286..12c4e2224d 100644 --- a/sys/log/full/include/log/log_fcb.h +++ b/sys/log/full/include/log/log_fcb.h @@ -39,6 +39,8 @@ struct log_fcb_bmark { #endif /* The index of the log entry that the FCB entry contains. */ uint32_t lfb_index; + /* Is this a sector boundary bookmark */ + bool lfb_sect_bmark; }; /** A set of fcb log bookmarks. */ @@ -49,11 +51,17 @@ struct log_fcb_bset { /** The maximum number of bookmarks. */ int lfs_cap; + /** The number of currently used non-sector bookmarks. */ + int lfs_non_s_size; + /** The number of currently usable bookmarks. */ int lfs_size; /** The index where the next bookmark will get written. */ - int lfs_next; + uint32_t lfs_next; + + /** The index where the next non-sector bmark will get written */ + uint32_t lfs_next_non_s; }; /** @@ -72,6 +80,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) @@ -113,9 +122,18 @@ struct fcb_log { * @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. + * + * @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 bmark_count); + +/** @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 +143,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 +158,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); +struct log_fcb_bmark * +log_fcb_closest_bmark(struct fcb_log *fcb_log, uint32_t index, int *min_diff); /** * Inserts a bookmark into the provided log. @@ -151,13 +173,14 @@ 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. */ #if MYNEWT_VAL(LOG_FCB) -void log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb_entry *entry, - uint32_t index); +void 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); +void 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/src/log_fcb.c b/sys/log/full/src/log_fcb.c index 12b8cb060c..ee4c3c1715 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; @@ -108,6 +110,7 @@ fcb_walk_back_find_start(struct fcb *fcb, struct log *log, struct log_offset *lo * ignored; the "index" field is used instead. * * XXX: We should rename "timestamp" or make it an actual timestamp. + * If bmark is found, fill up min_diff. * * The "index" field corresponds to a log entry index. * @@ -119,10 +122,10 @@ fcb_walk_back_find_start(struct fcb *fcb, struct log *log, struct log_offset *lo */ 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; + struct log_fcb_bmark *bmark; #endif struct log_entry_hdr hdr; struct fcb_log *fcb_log; @@ -166,7 +169,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 +212,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_sector_cnt = 0; + uint32_t idx = 0; +#endif #if MYNEWT_VAL(LOG_STATS) int cnt; #endif @@ -216,6 +223,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 sector count before appending */ +#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS) + active_sector_cnt = fcb->f_active_sector_entry_count; +#endif while (1) { rc = fcb_append(fcb, len, loc); if (rc == 0) { @@ -250,8 +261,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 +273,14 @@ 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); +#endif + #if MYNEWT_VAL(LOG_STORAGE_WATERMARK) /* * FCB was rotated successfully so let's check if watermark was within @@ -273,6 +294,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 (active_sector_cnt > fcb->f_active_sector_entry_count) { +#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 +617,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 +647,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 +713,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 b307acfe94..77e0ae8dff 100644 --- a/sys/log/full/src/log_fcb2.c +++ b/sys/log/full/src/log_fcb2.c @@ -63,6 +63,7 @@ log_fcb2_find_gte(struct log *log, struct log_offset *log_offset, struct fcb_log *fcb_log; struct fcb2 *fcb; int rc; + int min_diff = -1; fcb_log = log->l_arg; fcb = &fcb_log->fl_fcb; @@ -103,7 +104,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; } @@ -169,7 +170,7 @@ log_fcb2_start_append(struct log *log, int len, struct fcb2_entry *loc) } #endif -#if MYNEWT_VAL(LOG_FCB_BOOKMARKS) +#if MYNEWT_VAL(LOG_FCB_BOOKMARKS) && !MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS) /* The FCB needs to be rotated. */ log_fcb_rotate_bmarks(fcb_log); #endif @@ -179,6 +180,14 @@ log_fcb2_start_append(struct log *log, int len, struct fcb2_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); +#endif + #if MYNEWT_VAL(LOG_STORAGE_WATERMARK) /* * FCB was rotated successfully so let's check if watermark was within @@ -497,8 +506,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 diff --git a/sys/log/full/src/log_fcb_bmark.c b/sys/log/full/src/log_fcb_bmark.c index e9282771a1..476480043a 100644 --- a/sys/log/full/src/log_fcb_bmark.c +++ b/sys/log/full/src/log_fcb_bmark.c @@ -22,10 +22,51 @@ #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; + struct fcb_entry loc = {0}; + struct log_entry_hdr ueh = {0}; + struct flash_area *fa = NULL; + + rc = fcb_getnext(&fcb_log->fl_fcb, &loc); + if (rc) { + return -1; + } + + for (i = 0; i < fcb_log->fl_fcb.f_sector_cnt; 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; + } + + log_fcb_add_bmark(fcb_log, &loc, ueh.ue_index, true); + + fa = fcb_getnext_area(&fcb_log->fl_fcb, loc.fe_area); + if (!fa) { + break; + } + + /* First entry in the next area */ + rc = fcb_getnext_in_area(&fcb_log->fl_fcb, fa, &loc); + if (rc) { + break; + } + } + + return rc; +} +#endif + +int log_fcb_init_bmarks(struct fcb_log *fcb_log, struct log_fcb_bmark *buf, int bmark_count) { @@ -33,6 +74,13 @@ log_fcb_init_bmarks(struct fcb_log *fcb_log, .lfs_bmarks = buf, .lfs_cap = bmark_count, }; + + memset(buf, 0, sizeof(struct log_fcb_bmark) * bmark_count); +#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS) + return log_fcb_init_sector_bmarks(fcb_log); +#else + return 0; +#endif } void @@ -70,27 +118,66 @@ 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_s = 0; + fcb_log->fl_bset.lfs_non_s_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) +struct log_fcb_bmark * +log_fcb_closest_bmark(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; + struct log_fcb_bmark *closest; + struct log_fcb_bmark *bmark; uint32_t diff; int i; - min_diff = UINT32_MAX; + *min_diff = -1; closest = NULL; + /* 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 = 0; i < 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) { + /* Previous closest bookmark is the closest one */ + break; + } +#elif MYNEWT_VAL(LOG_FCB2) + if (!fcb_log->fl_bset.lfs_bmarks[i].lfb_entry.fe_range) { + /* Previous closest bookmark is the closest one */ + break; + } +#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_INFO(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,27 +185,33 @@ log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index) return closest; } +#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS) #if MYNEWT_VAL(LOG_FCB) -void -log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb_entry *entry, - uint32_t index) +static void +log_fcb_insert_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry, + uint32_t index, bool sect_bmark, int pos) #elif MYNEWT_VAL(LOG_FCB2) -void -log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb2_entry *entry, - uint32_t index) +static void +log_fcb_insert_bmark(struct fcb_log *fcb_log, fcb2_entry *entry, + uint32_t index, bool sect_bmark, int pos) #endif { struct log_fcb_bset *bset; bset = &fcb_log->fl_bset; - if (bset->lfs_cap == 0) { - return; + if (pos == bset->lfs_cap - 1) { + goto add; } - bset->lfs_bmarks[bset->lfs_next] = (struct log_fcb_bmark) { + memcpy(&bset->lfs_bmarks[pos + 1], &bset->lfs_bmarks[pos], + sizeof(bset->lfs_bmarks[0]) * bset->lfs_size - pos - 1); + +add: + bset->lfs_bmarks[pos] = (struct log_fcb_bmark) { .lfb_entry = *entry, .lfb_index = index, + .lfb_sect_bmark = sect_bmark }; if (bset->lfs_size < bset->lfs_cap) { @@ -126,9 +219,144 @@ log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb2_entry *entry, } bset->lfs_next++; - if (bset->lfs_next >= bset->lfs_cap) { - bset->lfs_next = 0; + bset->lfs_next %= bset->lfs_cap; +} +#endif + +#if MYNEWT_VAL(LOG_FCB) +static void +log_fcb_replace_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry, + uint32_t index, bool sect_bmark, int pos) +#elif MYNEWT_VAL(LOG_FCB2) +log_fcb_replace_bmark(struct fcb_log *fcb_log, struct fcb2_entry *entry, + uint32_t index, bool sect_bmark, int pos) +#endif +{ + int i = 0; + struct log_fcb_bset *bset; + + bset = &fcb_log->fl_bset; +#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS) + if (!sect_bmark) { + for (i = fcb_log->fl_fcb.f_sector_cnt; + i < (bset->lfs_non_s_size + fcb_log->fl_fcb.f_sector_cnt); + i++) +#else + if (!sect_bmark) { + for (i = 0; i < bset->lfs_non_s_size; i++) +#endif + { + if (index == bset->lfs_bmarks[i].lfb_index) { + /* If index matches, no need to replace */ + return; + } + } + } + + bset->lfs_bmarks[pos] = (struct log_fcb_bmark) { + .lfb_entry = *entry, + .lfb_index = index, + .lfb_sect_bmark = sect_bmark + }; +} + +#if MYNEWT_VAL(LOG_FCB) +void +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, struct fcb2_entry *entry, + uint32_t index, bool sect_bmark) +#endif +{ + struct log_fcb_bset *bset; + int i = 0; + int pos = 0; + + (void)i; + bset = &fcb_log->fl_bset; + + if (bset->lfs_cap == 0) { + return; + } + +#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS) + if (sect_bmark) { + for (i = 0; i < bset->lfs_size; i++) { + if (index > bset->lfs_bmarks[i].lfb_index) { + pos = i; + break; + } else { + pos = i + 1; + } + } + log_fcb_insert_bmark(fcb_log, entry, index, sect_bmark, pos); + if (pos >= fcb_log->fl_fcb.f_sector_cnt - 1) { + /* Make sure inserts do not trickle into the non-sector + * bookmarks + */ + memset(&bset->lfs_bmarks[pos], 0, sizeof(bset->lfs_bmarks[0])); + } else { + MODLOG_DEBUG(LOG_MODULE_DEFAULT, "insert bmark index: %u, pos: %u, \n", + (unsigned int)index, + (unsigned int)pos); + } + } else { + if (bset->lfs_non_s_size >= MYNEWT_VAL(LOG_FCB_NUM_ABS_BMARKS)) { + /* Replace oldest non-sector bmark */ + log_fcb_replace_bmark(fcb_log, entry, index, sect_bmark, + bset->lfs_next_non_s + + fcb_log->fl_fcb.f_sector_cnt); + MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, pos: %u, \n", + (unsigned int)index, + (unsigned int)bset->lfs_next_non_s + fcb_log->fl_fcb.f_sector_cnt); + bset->lfs_next_non_s = (bset->lfs_next_non_s + 1) % + MYNEWT_VAL(LOG_FCB_NUM_ABS_BMARKS); + } else { + log_fcb_replace_bmark(fcb_log, entry, index, sect_bmark, + fcb_log->fl_fcb.f_sector_cnt + + bset->lfs_non_s_size); + MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, pos: %u, \n", + (unsigned int)index, + (unsigned int)fcb_log->fl_fcb.f_sector_cnt + bset->lfs_non_s_size); + if (!bset->lfs_non_s_size) { + /* First non-sector bmark position */ + bset->lfs_next_non_s = pos; + } + bset->lfs_non_s_size++; + bset->lfs_size++; + } + + assert(bset->lfs_non_s_size <= MYNEWT_VAL(LOG_FCB_NUM_ABS_BMARKS)); } +#else + if (!sect_bmark) { + if (bset->lfs_size >= MYNEWT_VAL(LOG_FCB_NUM_ABS_BMARKS)) { + /* Replace oldest non-sector bmark */ + log_fcb_replace_bmark(fcb_log, entry, index, sect_bmark, + bset->lfs_next_non_s); + MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, pos: %u, \n", + (unsigned int)index, + (unsigned int)bset->lfs_next_non_s); + bset->lfs_next_non_s = (bset->lfs_next_non_s + 1) % + MYNEWT_VAL(LOG_FCB_NUM_ABS_BMARKS); + } else { + log_fcb_replace_bmark(fcb_log, entry, index, sect_bmark, + bset->lfs_size); + MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, pos: %u, \n", + (unsigned int)index, + bset->lfs_size); + if (!bset->lfs_size) { + /* First non-sector bmark position */ + bset->lfs_next_non_s = pos; + } + bset->lfs_size++; + } + + assert(bset->lfs_size <= MYNEWT_VAL(LOG_FCB_NUM_ABS_BMARKS)); + } +#endif } #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 a10c08eb11..bfb8950aa5 100644 --- a/sys/log/full/src/log_shell.c +++ b/sys/log/full/src/log_shell.c @@ -39,7 +39,7 @@ #include "tinycbor/compilersupport_p.h" #include "log_cbor_reader/log_cbor_reader.h" -void log_console_print_hdr(const struct log_entry_hdr *hdr); +void log_console_print_hdr(struct log_entry_hdr *hdr); static uint32_t shell_log_count; @@ -51,6 +51,8 @@ struct walk_arg { uint32_t count_limit; /* Entry number */ uint32_t count; + /* Entry index */ + uint32_t idx; }; static int @@ -109,7 +111,7 @@ shell_log_dump_entry(struct log *log, struct log_offset *log_offset, /* When LOG_CONSOLE_PRETTY is set use same function to dump log header that * is used when logs are printed in real time */ if (MYNEWT_VAL(LOG_CONSOLE_PRETTY)) { - log_console_print_hdr(ueh); + log_console_print_hdr((struct log_entry_hdr *)ueh); } else { if (read_hash) { console_printf("[ih=0x%02x%02x%02x%02x]", ueh->ue_imghash[0], ueh->ue_imghash[1], @@ -172,11 +174,18 @@ 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; clear_log = false; + (void)dump_bmarks; + (void)bmarks; + (void)bmarks_size; + for (i = 1; i < argc; ++i) { if (0 == strcmp(argv[i], "-l")) { list_only = true; @@ -208,6 +217,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], 1, 1000000, &rc); + if (rc) { + arg.idx = 0; + } + log_offset.lo_arg = &arg; + } + ++i; + continue; + } if (0 == strcmp(argv[i], "-r")) { reverse = true; continue; @@ -251,6 +276,28 @@ 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) + console_printf("%u: index:%lu entry: %x fa: %x fe_elem_off: %lx\n", i, + bmarks[i].lfb_index, + (uintptr_t)&bmarks[i].lfb_entry, + (uintptr_t)bmarks[i].lfb_entry.fe_area, + bmarks[i].lfb_entry.fe_elem_off); +#else + console_printf("%u: index: %lu entry: %x fr: %x fe_sector: %x fe_data_off: %lx\n", i, + bmarks[i].lfb_index, + (uintptr_t)&bmarks[i].lfb_entry, + (uintptr_t)bmarks[i].lfb_entry.fe_range, + (uintptr_t)bmarks[i].lfb_entry.fe_sector, + bmarks[i].lfb_entry.fe_data_off); +#endif + } + } +#endif + if (clear_log) { console_printf("Clearing log %s\n", log->l_name); rc = log_flush(log); @@ -278,11 +325,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 dc35b6c549..a6b937738e 100644 --- a/sys/log/full/syscfg.yml +++ b/sys/log/full/syscfg.yml @@ -179,6 +179,18 @@ syscfg.defs: the global index to be sequentially increasing for persisted logs. value: 0 + LOG_FCB_NUM_ABS_BMARKS: + description: > + Number of absolute bookmarks excluding sector bookmarks + value: 2 + + LOG_FCB_SECTOR_BOOKMARKS: + description: > + Enable sector bookmarks + value: 0 + restrictions: + - LOG_FCB_BOOKMARKS + syscfg.vals.CONSOLE_TICKS: LOG_CONSOLE_PRETTY_WITH_TIMESTAMP: 0