Beispiel #1
0
/*---------------------------------------------------------------------------*/
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;
}
Beispiel #2
0
/*---------------------------------------------------------------------------*/
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;
}
Beispiel #4
0
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(&copy_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(&region, 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;
}