/*---------------------------------------------------------------------------*/ int cfs_read(int fd, void *buf, unsigned size) { struct file_desc *fdp; struct file *file; #if COFFEE_MICRO_LOGS struct file_header hdr; struct log_param lp; unsigned bytes_left; int r; #endif if(!(FD_VALID(fd) && FD_READABLE(fd))) { return -1; } fdp = &coffee_fd_set[fd]; file = fdp->file; if(fdp->offset + size > file->end) { size = file->end - fdp->offset; } /* If the file is allocated, read directly in the file. */ if(!FILE_MODIFIED(file)) { COFFEE_READ(buf, size, absolute_offset(file->page, fdp->offset)); fdp->offset += size; return size; } #if COFFEE_MICRO_LOGS read_header(&hdr, file->page); /* * Fill the buffer by copying from the log in first hand, or the * ordinary file if the page has no log record. */ for(bytes_left = size; bytes_left > 0; bytes_left -= r) { r = -1; lp.offset = fdp->offset; lp.buf = buf; lp.size = bytes_left; r = read_log_page(&hdr, file->record_count, &lp); /* Read from the original file if we cannot find the data in the log. */ if(r < 0) { COFFEE_READ(buf, lp.size, absolute_offset(file->page, fdp->offset)); r = lp.size; } fdp->offset += r; buf = (char *)buf + r; } #endif /* COFFEE_MICRO_LOGS */ return size; }
/*---------------------------------------------------------------------------*/ int cfs_read(int fd, void *buf, unsigned size) { struct file_desc *fdp; struct file *file; #if COFFEE_MICRO_LOGS struct file_header hdr; struct log_param lp; unsigned bytes_left; int r; #endif if(!(FD_VALID(fd) && FD_READABLE(fd))) { return -1; } fdp = &coffee_fd_set[fd]; file = fdp->file; if(fdp->offset + size > file->end) { size = file->end - fdp->offset; } /* If the file is not modified, read directly from the file extent. */ if(!FILE_MODIFIED(file)) { COFFEE_READ(buf, size, absolute_offset(file->page, fdp->offset)); fdp->offset += size; return size; } #if COFFEE_MICRO_LOGS read_header(&hdr, file->page); /* * Copy the contents of the most recent log record. If there is * no log record for the file area to read from, we simply read * from the original file extent. */ for(bytes_left = size; bytes_left > 0; bytes_left -= r) { lp.offset = fdp->offset; lp.buf = buf; lp.size = bytes_left; r = read_log_page(&hdr, file->record_count, &lp); /* Read from the original file if we cannot find the data in the log. */ if(r < 0) { COFFEE_READ(buf, lp.size, absolute_offset(file->page, fdp->offset)); r = lp.size; } fdp->offset += r; buf = (char *)buf + r; } #endif /* COFFEE_MICRO_LOGS */ return size; }
/*---------------------------------------------------------------------------*/ int cfs_read(int fd, void *buf, unsigned size) { struct file_header hdr; struct file_desc *fdp; struct file *file; unsigned bytes_left; int r; #if COFFEE_MICRO_LOGS struct log_param lp; #endif if(!(FD_VALID(fd) && FD_READABLE(fd))) { return -1; } fdp = &coffee_fd_set[fd]; file = fdp->file; if(fdp->offset + size > file->end) { size = file->end - fdp->offset; } bytes_left = size; if(FILE_MODIFIED(file)) { read_header(&hdr, file->page); } /* * Fill the buffer by copying from the log in first hand, or the * ordinary file if the page has no log record. */ while(bytes_left) { watchdog_periodic(); r = -1; #if COFFEE_MICRO_LOGS if(FILE_MODIFIED(file)) { lp.offset = fdp->offset; lp.buf = buf; lp.size = bytes_left; r = read_log_page(&hdr, file->record_count, &lp); } #endif /* COFFEE_MICRO_LOGS */ /* Read from the original file if we cannot find the data in the log. */ if(r < 0) { r = bytes_left; COFFEE_READ(buf, r, absolute_offset(file->page, fdp->offset)); } bytes_left -= r; fdp->offset += r; buf += r; } return size; }
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; }