Difference between revisions of "Contiki Coffee File System"
From Contiki
(→Data Structure Used In The System) |
(→find_file) |
||
Line 81: | Line 81: | ||
=== find_file === | === find_file === | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<source lang="c"> | <source lang="c"> | ||
static struct file * | static struct file * |
Revision as of 18:07, 8 November 2014
Contents
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];
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];
};
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;
}