mkiiskila commented on a change in pull request #1974: Logging to FCB2 URL: https://github.com/apache/mynewt-core/pull/1974#discussion_r320720659
########## File path: sys/log/full/src/log_fcb2.c ########## @@ -0,0 +1,890 @@ +/* + * 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" + +#if MYNEWT_VAL(LOG_FCB2) + +#include <string.h> + +#include "flash_map/flash_map.h" +#include "log/log.h" +#include "fcb/fcb.h" + +/* Assume the flash alignment requirement is no stricter than 8. */ +#define LOG_FCB2_MAX_ALIGN 8 + +static int log_fcb2_rtr_erase(struct log *log, void *arg); + +/** + * Finds the first log entry whose "offset" is >= the one specified. A log + * offset consists of two parts: + * o timestamp + * o index + * + * The "timestamp" field is misnamed. If it has a value of -1, then the offset + * always points to the latest entry. If this value is not -1, then it is + * ignored; the "index" field is used instead. + * + * XXX: We should rename "timestamp" or make it an actual timestamp. + * + * The "index" field corresponds to a log entry index. + * + * If bookmarks are enabled, this function uses them in the search. + * + * @return 0 if an entry was found + * SYS_ENOENT if there are no suitable entries. + * Other error on failure. + */ +static int +log_fcb2_find_gte(struct log *log, struct log_offset *log_offset, + struct fcb_entry *out_entry) +{ +#if MYNEWT_VAL(LOG_FCB_BOOKMARKS) + const struct log_fcb_bmark *bmark; +#endif + struct log_entry_hdr hdr; + struct fcb_log *fcb_log; + struct fcb *fcb; + int rc; + + fcb_log = log->l_arg; + fcb = &fcb_log->fl_fcb; + + /* Attempt to read the last entry. If this fails, the FCB is empty. */ + memset(out_entry, 0, sizeof(*out_entry)); + rc = fcb_getprev(fcb, out_entry); + if (rc == FCB_ERR_NOVAR) { + return SYS_ENOENT; + } else if (rc != 0) { + return SYS_EUNKNOWN; + } + + /* + * if timestamp for request is < 0, return last log entry (already read). + */ + if (log_offset->lo_ts < 0) { + return 0; + } + + /* If the requested index is beyond the end of the log, there is nothing to + * retrieve. + */ + rc = log_read_hdr(log, out_entry, &hdr); + if (rc != 0) { + return rc; + } + if (log_offset->lo_index > hdr.ue_index) { + return SYS_ENOENT; + } + + /* + * Start from beginning. + */ + memset(out_entry, 0, sizeof(*out_entry)); + rc = fcb_getnext(fcb, out_entry); + if (rc != 0) { + return SYS_EUNKNOWN; + } +#if MYNEWT_VAL(LOG_FCB_BOOKMARKS) + bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index); + if (bmark != NULL) { + *out_entry = bmark->lfb_entry; + } +#endif + + /* Keep advancing until we find an entry with a great enough index. */ + do { + rc = log_read_hdr(log, out_entry, &hdr); + if (rc != 0) { + return rc; + } + + if (hdr.ue_index >= log_offset->lo_index) { + return 0; + } + } while (fcb_getnext(fcb, out_entry) == 0); + + return SYS_ENOENT; +} + +static int +log_fcb2_start_append(struct log *log, int len, struct fcb_entry *loc) +{ + struct fcb *fcb; + struct fcb_log *fcb_log; +#if MYNEWT_VAL(LOG_STORAGE_WATERMARK) + int old_sec; +#endif + int rc = 0; +#if MYNEWT_VAL(LOG_STATS) + int cnt; +#endif + + fcb_log = (struct fcb_log *)log->l_arg; + fcb = &fcb_log->fl_fcb; + + while (1) { + rc = fcb_append(fcb, len, loc); + if (rc == 0) { + break; + } + + if (rc != FCB_ERR_NOSPACE) { + goto err; + } + + if (fcb_log->fl_entries) { + rc = log_fcb2_rtr_erase(log, fcb_log); + if (rc) { + goto err; + } + continue; + } + +#if MYNEWT_VAL(LOG_STORAGE_WATERMARK) + old_sec = fcb->f_oldest_sec; +#endif + +#if MYNEWT_VAL(LOG_STATS) + rc = fcb_area_info(fcb, FCB_SECTOR_OLDEST, &cnt, NULL); + if (rc == 0) { + LOG_STATS_INCN(log, lost, cnt); + } +#endif + +#if MYNEWT_VAL(LOG_FCB_BOOKMARKS) + /* The FCB needs to be rotated. Invalidate all bookmarks. */ + log_fcb_clear_bmarks(fcb_log); +#endif + + rc = fcb_rotate(fcb); + if (rc) { + goto err; + } + +#if MYNEWT_VAL(LOG_STORAGE_WATERMARK) + /* + * FCB was rotated successfully so let's check if watermark was within + * oldest flash area which was erased. If yes, then move watermark to + * beginning of current oldest area. + */ + if (fcb_log->fl_watermark_sec == old_sec) { + fcb_log->fl_watermark_sec = fcb->f_oldest_sec; + fcb_log->fl_watermark_off = 0; + } +#endif + } + +err: + return (rc); +} + +/** + * Calculates the number of message body bytes that should be included after + * the entry header in the first write. Inclusion of body bytes is necessary + * to satisfy the flash hardware's write alignment restrictions. + */ +static int +log_fcb2_hdr_body_bytes(uint8_t align, uint8_t hdr_len) +{ + uint8_t mod; + + /* Assume power-of-two alignment for faster modulo calculation. */ + assert((align & (align - 1)) == 0); + + mod = hdr_len & (align - 1); + if (mod == 0) { + return 0; + } + + return align - mod; +} + +static int +log_fcb2_append_body(struct log *log, const struct log_entry_hdr *hdr, + const void *body, int body_len) +{ + uint8_t buf[LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN + + LOG_FCB2_MAX_ALIGN - 1]; + struct fcb_entry loc; + const uint8_t *u8p; + int hdr_alignment; + int chunk_sz; + int rc; + uint16_t hdr_len; + + hdr_len = 0; Review comment: That's true. There's few other occasions like this. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected] With regards, Apache Git Services
