Difference between revisions of "Contiki Coffee File System"

From Contiki
Jump to: navigation, search
(Data Structure Used In The System)
(find_file)
Line 81: Line 81:
  
 
=== find_file ===
 
=== find_file ===
<source lang="c">
 
static struct protected_mem_t {
 
  struct file coffee_files[COFFEE_MAX_OPEN_FILES];
 
  struct file_desc coffee_fd_set[COFFEE_FD_SET_SIZE];
 
  coffee_page_t next_free;
 
  char gc_wait;
 
} protected_mem;
 
static struct file * const coffee_files = protected_mem.coffee_files;
 
</source>
 
 
 
<source lang="c">
 
<source lang="c">
 
static struct file *
 
static struct file *

Revision as of 19:07, 8 November 2014

Introduction

This tutorial is a introduction to cfs_open function of Coffee file system on Contiki OS 2.7.

You Will Learn

Through this tutorial you will learn about how the Coffee file system works.

Source Code

~/contiki-2.7/core/cfs/cfs-coffee.h
~/contiki-2.7/core/cfs/cfs-coffee.c

Coffee File System Open File

Data Structure Used In The System

struct file_desc {
  cfs_offset_t offset; 
  struct file *file; //  a file pointer which point to the corresponding file.
  uint8_t flags; //flag used to indicate the open mode of the file and whether the fd is free.
#if COFFEE_IO_SEMANTICS
  uint8_t io_flags;
#endif
};
struct file_desc coffee_fd_set[COFFEE_FD_SET_SIZE];

Datastr.png

struct file {
  cfs_offset_t end;
  coffee_page_t page;
  coffee_page_t max_pages;
  int16_t record_count;
  uint8_t references;
  uint8_t flags;
};
/* The file header structure mimics the representation of file headers 
   in the physical storage medium. */
struct file_header {
  coffee_page_t log_page;
  uint16_t log_records;
  uint16_t log_record_size;
  coffee_page_t max_pages;
  uint8_t deprecated_eof_hint;
  uint8_t flags;
  char name[COFFEE_NAME_LENGTH];
};


File.png

get_available_fd

static int
get_available_fd(void)
{
  int i;

  for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
    if(coffee_fd_set[i].flags == COFFEE_FD_FREE) {
      return i;
    }
  }
  return -1;
}

Contiki is a Linux like system, everything is a file, and the opened file is represented by the file descriptor. The get_available_fd will return the smallest available fd by check the file_desc array in an ascending order, the first one with flag == 0(COFFEE_FD_FREE) is what we want. If all the flags are set, then return -1.


find_file

static struct file *
find_file(const char *name)
{
  int i;
  struct file_header hdr;
  coffee_page_t page;
  
  /* First check if the file metadata is cached. */
  for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) {
    if(FILE_FREE(&coffee_files[i])) {
      continue;
    }

    read_header(&hdr, coffee_files[i].page);
    if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr) && strcmp(name, hdr.name) == 0) {
      return &coffee_files[i];
    }
  }
  
  /* Scan the flash memory sequentially otherwise. */
  for(page = 0; page < COFFEE_PAGE_COUNT; page = next_file(page, &hdr)) {
    read_header(&hdr, page);
    if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr) && strcmp(name, hdr.name) == 0) {
      return load_file(page, &hdr);
    }
  }

  return NULL;
}

cfs_open

cf_open is used to open a file. If it successfully open the file then it returns the file descriptor(fd), otherwise it returns -1.
cfs_open source code:

int
cfs_open(const char *name, int flags)
{
  int fd;
  struct file_desc *fdp;

  fd = get_available_fd(); //find the smallest available fd, see section 4.2
  if(fd < 0) {
    PRINTF("Coffee: Failed to allocate a new file descriptor!\n");
    return -1;
  }

  fdp = &coffee_fd_set[fd];
  fdp->flags = 0; //set the fd to FREE

  fdp->file = find_file(name); //find the file corresponding to name(not exist, In flash but not cached, cached)

  /*** if there isn't any corresponding file, then try to create new file ***/
  if(fdp->file == NULL) {
    if((flags & (CFS_READ | CFS_WRITE)) == CFS_READ) {
      return -1;
    }
    fdp->file = reserve(name, page_count(COFFEE_DYN_SIZE), 1, 0);
    if(fdp->file == NULL) {
      return -1;
    }
    fdp->file->end = 0; // Since it's a new created file, the end will be set to 0
  }
   /*** find the file,seek for the end of the file***/ 
   else if(fdp->file->end == UNKNOWN_OFFSET) {
    fdp->file->end = file_end(fdp->file->page);
  }

  fdp->flags |= flags;
  fdp->offset = flags & CFS_APPEND ? fdp->file->end : 0; //if the flag is set to APPEND, then the offset is set to the end of the file, otherwise set to 0
  fdp->file->references++; //reference count will increment

  return fd;
}

Flowchart.png