Clarified and cleaned up Coffee's documentation and the debug statements. Formatted some source code for easier reading.
This commit is contained in:
parent
7586195b79
commit
86733e8702
|
@ -114,8 +114,7 @@
|
|||
#define GC_RELUCTANT 1
|
||||
|
||||
/* File descriptor macros. */
|
||||
#define FD_VALID(fd) \
|
||||
((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
|
||||
#define FD_VALID(fd) ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
|
||||
coffee_fd_set[(fd)].flags != COFFEE_FD_FREE)
|
||||
#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ)
|
||||
#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE)
|
||||
|
@ -127,10 +126,10 @@
|
|||
#define FILE_UNREFERENCED(file) ((file)->references == 0)
|
||||
|
||||
/* File header flags. */
|
||||
#define HDR_FLAG_VALID 0x1 /* Completely written header. */
|
||||
#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */
|
||||
#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */
|
||||
#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */
|
||||
#define HDR_FLAG_VALID 0x01 /* Completely written header. */
|
||||
#define HDR_FLAG_ALLOCATED 0x02 /* Allocated file. */
|
||||
#define HDR_FLAG_OBSOLETE 0x04 /* File marked for GC. */
|
||||
#define HDR_FLAG_MODIFIED 0x08 /* Modified file, log exists. */
|
||||
#define HDR_FLAG_LOG 0x10 /* Log file. */
|
||||
#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */
|
||||
|
||||
|
@ -148,7 +147,8 @@
|
|||
!HDR_ISOLATED(hdr))
|
||||
|
||||
/* Shortcuts derived from the hardware-dependent configuration of Coffee. */
|
||||
#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE)
|
||||
#define COFFEE_SECTOR_COUNT \
|
||||
(coffee_page_t)(COFFEE_SIZE / COFFEE_SECTOR_SIZE)
|
||||
#define COFFEE_PAGE_COUNT \
|
||||
((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE))
|
||||
#define COFFEE_PAGES_PER_SECTOR \
|
||||
|
@ -235,7 +235,7 @@ absolute_offset(coffee_page_t page, cfs_offset_t offset)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static coffee_page_t
|
||||
get_sector_status(uint16_t sector, struct sector_status *stats)
|
||||
get_sector_status(coffee_page_t sector, struct sector_status *stats)
|
||||
{
|
||||
static coffee_page_t skip_pages;
|
||||
static char last_pages_are_active;
|
||||
|
@ -305,7 +305,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
|||
/*
|
||||
* Determine the amount of pages in the following sectors that
|
||||
* should be remembered for the next iteration. This is necessary
|
||||
* because no page except the first of a file contains information
|
||||
* because no file page except the first contains information
|
||||
* about what type of page it is. A side effect of remembering this
|
||||
* amount is that there is no need to read in the headers of each
|
||||
* of these pages from the storage.
|
||||
|
@ -356,11 +356,11 @@ isolate_pages(coffee_page_t start, coffee_page_t skip_pages)
|
|||
static void
|
||||
collect_garbage(int mode)
|
||||
{
|
||||
uint16_t sector;
|
||||
coffee_page_t sector;
|
||||
struct sector_status stats;
|
||||
coffee_page_t first_page, isolation_count;
|
||||
|
||||
PRINTF("Coffee: Running the file system garbage collector in %s mode\n",
|
||||
PRINTF("Coffee: Running the garbage collector in %s mode\n",
|
||||
mode == GC_RELUCTANT ? "reluctant" : "greedy");
|
||||
/*
|
||||
* The garbage collector erases as many sectors as possible. A sector is
|
||||
|
@ -369,7 +369,7 @@ collect_garbage(int mode)
|
|||
for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
|
||||
isolation_count = get_sector_status(sector, &stats);
|
||||
PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n",
|
||||
sector, (unsigned)stats.active,
|
||||
(unsigned)sector, (unsigned)stats.active,
|
||||
(unsigned)stats.obsolete, (unsigned)stats.free);
|
||||
|
||||
if(stats.active > 0) {
|
||||
|
@ -402,7 +402,7 @@ next_file(coffee_page_t page, struct file_header *hdr)
|
|||
{
|
||||
/*
|
||||
* The quick-skip algorithm for finding file extents is the most
|
||||
* essential part of Coffee. The file allocation rules enables this
|
||||
* essential part of Coffee. The file allocation rules enable this
|
||||
* algorithm to quickly jump over free areas and allocated extents
|
||||
* after reading single headers and determining their status.
|
||||
*
|
||||
|
@ -648,7 +648,7 @@ reserve(const char *name, coffee_page_t pages,
|
|||
write_header(&hdr, page);
|
||||
|
||||
PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n",
|
||||
pages, page, name);
|
||||
(unsigned)pages, (unsigned)page, name);
|
||||
|
||||
file = load_file(page, &hdr);
|
||||
if(file != NULL) {
|
||||
|
@ -843,7 +843,7 @@ merge_log(coffee_page_t file_page, int extend)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Copy the log configuration and the EOF hint. */
|
||||
/* Copy the log configuration. */
|
||||
read_header(&hdr2, new_file->page);
|
||||
hdr2.log_record_size = hdr.log_record_size;
|
||||
hdr2.log_records = hdr.log_records;
|
||||
|
@ -1102,7 +1102,7 @@ cfs_read(int fd, void *buf, unsigned size)
|
|||
size = file->end - fdp->offset;
|
||||
}
|
||||
|
||||
/* If the file is allocated, read directly in the file. */
|
||||
/* 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;
|
||||
|
@ -1113,8 +1113,9 @@ cfs_read(int fd, void *buf, unsigned size)
|
|||
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.
|
||||
* 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;
|
||||
|
@ -1242,8 +1243,8 @@ int
|
|||
cfs_opendir(struct cfs_dir *dir, const char *name)
|
||||
{
|
||||
/*
|
||||
* Coffee is only guaranteed to support "/" and ".", but it does not
|
||||
* currently enforce this.
|
||||
* Coffee is only guaranteed to support the directory names "/" and ".",
|
||||
* but it does not enforce this currently.
|
||||
*/
|
||||
memset(dir->dummy_space, 0, sizeof(coffee_page_t));
|
||||
return 0;
|
||||
|
@ -1254,13 +1255,13 @@ cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record)
|
|||
{
|
||||
struct file_header hdr;
|
||||
coffee_page_t page;
|
||||
coffee_page_t next_page;
|
||||
|
||||
memcpy(&page, dir->dummy_space, sizeof(coffee_page_t));
|
||||
|
||||
while(page < COFFEE_PAGE_COUNT) {
|
||||
read_header(&hdr, page);
|
||||
if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr)) {
|
||||
coffee_page_t next_page;
|
||||
memcpy(record->name, hdr.name, sizeof(record->name));
|
||||
record->name[sizeof(record->name) - 1] = '\0';
|
||||
record->size = file_end(page);
|
||||
|
@ -1334,9 +1335,9 @@ cfs_coffee_set_io_semantics(int fd, unsigned flags)
|
|||
int
|
||||
cfs_coffee_format(void)
|
||||
{
|
||||
unsigned i;
|
||||
coffee_page_t i;
|
||||
|
||||
PRINTF("Coffee: Formatting %u sectors", COFFEE_SECTOR_COUNT);
|
||||
PRINTF("Coffee: Formatting %u sectors", (unsigned)COFFEE_SECTOR_COUNT);
|
||||
|
||||
for(i = 0; i < COFFEE_SECTOR_COUNT; i++) {
|
||||
COFFEE_ERASE(i);
|
||||
|
|
|
@ -46,15 +46,15 @@
|
|||
* invoke its own micro logs when file modifications occur.
|
||||
*
|
||||
* This semantical I/O setting is useful when implementing flash storage
|
||||
* algorithms on top of Coffee.
|
||||
* algorithms such as database indices on top of Coffee.
|
||||
*
|
||||
* \sa cfs_coffee_set_io_semantics()
|
||||
*/
|
||||
#define CFS_COFFEE_IO_FLASH_AWARE 0x1
|
||||
|
||||
/**
|
||||
* Instruct Coffee not to attempt to extend the file when there is
|
||||
* an attempt to write past the reserved file size.
|
||||
* Instruct Coffee not to attempt to extend the file upon a request
|
||||
* to write past the reserved file size.
|
||||
*
|
||||
* A case when this is necessary is when the file has a firm size limit,
|
||||
* and a safeguard is needed to protect against writes beyond this limit.
|
||||
|
@ -75,8 +75,8 @@
|
|||
|
||||
/**
|
||||
* \brief Reserve space for a file.
|
||||
* \param name The filename.
|
||||
* \param size The size of the file.
|
||||
* \param name The file name.
|
||||
* \param size The initial size to be reserved for the file.
|
||||
* \return 0 on success, -1 on failure.
|
||||
*
|
||||
* Coffee uses sequential page structures for files. The sequential
|
||||
|
@ -88,15 +88,15 @@ int cfs_coffee_reserve(const char *name, cfs_offset_t size);
|
|||
|
||||
/**
|
||||
* \brief Configure the on-demand log file.
|
||||
* \param file The filename.
|
||||
* \param log_size The total log size.
|
||||
* \param file The file name.
|
||||
* \param log_size The total log file size.
|
||||
* \param log_entry_size The log entry size.
|
||||
* \return 0 on success, -1 on failure.
|
||||
*
|
||||
* When file data is first modified, Coffee creates a micro log for the
|
||||
* file. The micro log stores a table of modifications whose
|
||||
* parameters--the log size and the log entry size--can be modified
|
||||
* through the cfs_coffee_configure_log function.
|
||||
* file. The micro log stores a table of modifications whose parameters --
|
||||
* the log size and the log entry size -- can be modified through the
|
||||
* cfs_coffee_configure_log function.
|
||||
*/
|
||||
int cfs_coffee_configure_log(const char *file, unsigned log_size,
|
||||
unsigned log_entry_size);
|
||||
|
@ -109,8 +109,8 @@ int cfs_coffee_configure_log(const char *file, unsigned log_size,
|
|||
*
|
||||
* Coffee is used on a wide range of storage types, and the default
|
||||
* I/O file semantics may not be optimal for the access pattern
|
||||
* of a certain file. Hence, this functions allows programmers to
|
||||
* switch the /O semantics on a file that is accessed through a
|
||||
* of a certain file. Hence, this function allows programmers to
|
||||
* switch the I/O semantics on a file that is accessed through a
|
||||
* particular file descriptor.
|
||||
*
|
||||
*/
|
||||
|
@ -123,21 +123,14 @@ int cfs_coffee_set_io_semantics(int fd, unsigned flags);
|
|||
* Coffee formats the underlying storage by setting all bits to zero.
|
||||
* Formatting must be done before using Coffee for the first time in
|
||||
* a mote.
|
||||
*
|
||||
* Notice that the erased bits may be set to 1 on the physical storage
|
||||
* when using flash memory. In this case, Coffee requires that the
|
||||
* COFFEE_READ and COFFEE_WRITE functions used to access the flash memory
|
||||
* invert all bits.
|
||||
*/
|
||||
int cfs_coffee_format(void);
|
||||
|
||||
/**
|
||||
* \brief Points out a memory region that may not be altered during
|
||||
* checkpointing operations that use the file system.
|
||||
* \param size
|
||||
* \return A pointer to the protected memory.
|
||||
*
|
||||
* This function returns the protected memory pointer and writes its size
|
||||
* to the given parameter. Mainly used by sensornet checkpointing to protect
|
||||
* the coffee state during CFS-based checkpointing operations.
|
||||
*/
|
||||
void *cfs_coffee_get_protected_mem(unsigned *size);
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
|
|
Loading…
Reference in a new issue