static int read_log_page(struct file_header *hdr, int16_t record_count, struct log_param *lp) { uint16_t region; int16_t match_index; uint16_t log_record_size; uint16_t log_records; cfs_offset_t base; uint16_t search_records; adjust_log_config(hdr, &log_record_size, &log_records); region = modify_log_buffer(log_record_size, &lp->offset, &lp->size); search_records = record_count < 0 ? log_records : record_count; match_index = get_record_index(hdr->log_page, search_records, region); if(match_index < 0) { return -1; } base = absolute_offset(hdr->log_page, log_records * sizeof(region)); base += (cfs_offset_t)match_index * log_record_size; base += lp->offset; COFFEE_READ(lp->buf, lp->size, base); return lp->size; }
/*---------------------------------------------------------------------------*/ static coffee_page_t create_log(struct file *file, struct file_header *hdr) { coffee_page_t log_page; uint16_t log_record_size, log_records; cfs_offset_t size; struct file *log_file; adjust_log_config(hdr, &log_record_size, &log_records); /* Log index size + log data size. */ size = log_records * (sizeof(uint16_t) + log_record_size); log_file = reserve(hdr->name, page_count(size), 1, HDR_FLAG_LOG); if(log_file == NULL) { return INVALID_PAGE; } log_page = log_file->page; hdr->flags |= HDR_FLAG_MODIFIED; hdr->log_page = log_page; write_header(hdr, file->page); file->flags |= COFFEE_FILE_MODIFIED; return log_page; }
static int write_log_page(struct file *file, struct log_param *lp) { struct file_header hdr; uint16_t region; coffee_page_t log_page; int16_t log_record; uint16_t log_record_size; uint16_t log_records; cfs_offset_t offset; struct log_param lp_out; read_header(&hdr, file->page); adjust_log_config(&hdr, &log_record_size, &log_records); region = modify_log_buffer(log_record_size, &lp->offset, &lp->size); log_page = 0; if(HDR_MODIFIED(hdr)) { /* A log structure has already been created. */ log_page = hdr.log_page; log_record = find_next_record(file, log_page, log_records); if(log_record >= log_records) { /* The log is full; merge the log. */ PRINTF(("Coffee: Merging the file %s with its log\n", hdr.name)); return merge_log(file->page, 0); } } else { /* Create a log structure. */ log_page = create_log(file, &hdr); if(log_page == INVALID_PAGE) { return -1; } PRINTF(("Coffee: Created a log structure for file %s at page %u\n", hdr.name, (unsigned)log_page)); hdr.log_page = log_page; log_record = 0; } { char copy_buf[log_record_size]; lp_out.offset = offset = region * log_record_size; lp_out.buf = copy_buf; lp_out.size = log_record_size; if((lp->offset > 0 || lp->size != log_record_size) && read_log_page(&hdr, log_record, &lp_out) < 0) { COFFEE_READ(copy_buf, sizeof(copy_buf), absolute_offset(file->page, offset)); } memcpy(©_buf[lp->offset], lp->buf, lp->size); /* * Write the region number in the region index table. * The region number is incremented to avoid values of zero. */ offset = absolute_offset(log_page, 0); ++region; COFFEE_WRITE(®ion, sizeof(region), offset + log_record * sizeof(region)); offset += log_records * sizeof(region); COFFEE_WRITE(copy_buf, sizeof(copy_buf), offset + log_record * log_record_size); file->record_count = log_record + 1; } return lp->size; }