cleaned up mostly the GC code.

made EOF hints optional.

default build is now ~500 bytes smaller.
This commit is contained in:
nvt-se 2009-02-17 16:56:32 +00:00
parent a2d651af72
commit d029dd8240
1 changed files with 64 additions and 48 deletions

View File

@ -37,12 +37,6 @@
* Nicolas Tsiftes <nvt@sics.se> * Nicolas Tsiftes <nvt@sics.se>
*/ */
#include <contiki-conf.h>
#include <cfs/cfs.h>
#include <cfs-coffee-arch.h>
#include <cfs/cfs-coffee.h>
#include <dev/watchdog.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
@ -54,6 +48,12 @@
#define PRINTF(...) #define PRINTF(...)
#endif #endif
#include "contiki-conf.h"
#include "cfs/cfs.h"
#include "cfs-coffee-arch.h"
#include "cfs/cfs-coffee.h"
#include "dev/watchdog.h"
#if COFFEE_PAGES_PER_SECTOR & (COFFEE_PAGES_PER_SECTOR - 1) #if COFFEE_PAGES_PER_SECTOR & (COFFEE_PAGES_PER_SECTOR - 1)
#error COFFEE_PAGES_PER_SECTOR must be a power of two. #error COFFEE_PAGES_PER_SECTOR must be a power of two.
#error Change COFFEE_PAGES_PER_SECTOR in cfs-coffee-arch.h. #error Change COFFEE_PAGES_PER_SECTOR in cfs-coffee-arch.h.
@ -176,12 +176,12 @@ absolute_offset(coffee_page_t page, coffee_offset_t offset)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
get_sector_status(uint16_t sector, struct sector_stats *stats) { get_sector_status(uint16_t sector, struct sector_stats *stats) {
static coffee_page_t skip_pages, active, obsolete, free; static coffee_page_t skip_pages;
static char last_pages_are_active; static char last_pages_are_active;
coffee_offset_t offset, sector_start, end;
struct file_header hdr; struct file_header hdr;
coffee_page_t jump; coffee_page_t active, obsolete, free;
int i; coffee_page_t sector_start, sector_end;
coffee_page_t page;
active = obsolete = free = 0; active = obsolete = free = 0;
@ -191,14 +191,18 @@ get_sector_status(uint16_t sector, struct sector_stats *stats) {
} else if(skip_pages > COFFEE_PAGES_PER_SECTOR) { } else if(skip_pages > COFFEE_PAGES_PER_SECTOR) {
skip_pages -= COFFEE_PAGES_PER_SECTOR; skip_pages -= COFFEE_PAGES_PER_SECTOR;
if(last_pages_are_active) { if(last_pages_are_active) {
active = COFFEE_PAGES_PER_SECTOR; stats->active = COFFEE_PAGES_PER_SECTOR;
stats->obsolete = 0;
} else { } else {
obsolete = COFFEE_PAGES_PER_SECTOR; stats->active = 0;
stats->obsolete = COFFEE_PAGES_PER_SECTOR;
} }
stats->free = 0;
return; return;
} }
sector_start = sector * COFFEE_SECTOR_SIZE; sector_start = sector * COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE;
sector_end = sector_start + COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE;
if(last_pages_are_active) { if(last_pages_are_active) {
active = skip_pages; active = skip_pages;
@ -207,39 +211,32 @@ get_sector_status(uint16_t sector, struct sector_stats *stats) {
/* Split an obsolete file starting in the previous sector and mark /* Split an obsolete file starting in the previous sector and mark
the following pages as isolated. */ the following pages as isolated. */
offset = sector_start; memset(&hdr, 0, sizeof(hdr));
for(i = 0; i < skip_pages; i++) { hdr.flags = HDR_FLAG_ALLOCATED | HDR_FLAG_ISOLATED;
COFFEE_READ(&hdr, sizeof(hdr), offset); for(page = sector_start; page < skip_pages; page++) {
hdr.flags |= HDR_FLAG_ALLOCATED | HDR_FLAG_ISOLATED; write_header(&hdr, page);
COFFEE_WRITE(&hdr, sizeof(hdr), offset);
offset += COFFEE_PAGE_SIZE;
} }
PRINTF("Coffee: Isolated %u pages starting in sector %d\n", PRINTF("Coffee: Isolated %u pages starting in sector %d\n",
(unsigned)skip_pages, (int)sector); (unsigned)skip_pages, (int)sector);
} }
offset = sector_start + (skip_pages * COFFEE_PAGE_SIZE); for(page = sector_start + skip_pages; page < sector_end;) {
end = (sector + 1) * COFFEE_SECTOR_SIZE; read_header(&hdr, page);
jump = 0;
while(offset < end) {
COFFEE_READ(&hdr, sizeof(hdr), offset);
last_pages_are_active = 0; last_pages_are_active = 0;
if(HDR_ACTIVE(hdr)) { if(HDR_ACTIVE(hdr)) {
last_pages_are_active = 1; last_pages_are_active = 1;
jump = hdr.max_pages; page += hdr.max_pages;
active += jump; active += hdr.max_pages;
} else if(HDR_ISOLATED(hdr)) { } else if(HDR_ISOLATED(hdr)) {
jump = 1; page++;
obsolete++; obsolete++;
} else if(HDR_OBSOLETE(hdr)) { } else if(HDR_OBSOLETE(hdr)) {
jump = hdr.max_pages; page += hdr.max_pages;
obsolete += jump; obsolete += hdr.max_pages;
} else { } else {
free = COFFEE_PAGES_PER_SECTOR - active - obsolete; free = COFFEE_PAGES_PER_SECTOR - active - obsolete;
break; break;
} }
offset += jump * COFFEE_PAGE_SIZE;
} }
skip_pages = active + obsolete + free - COFFEE_PAGES_PER_SECTOR; skip_pages = active + obsolete + free - COFFEE_PAGES_PER_SECTOR;
@ -288,6 +285,11 @@ load_file(const char *name, struct file_header *hdr, coffee_page_t start)
int i, unreferenced, free; int i, unreferenced, free;
struct file *file; struct file *file;
/*
* We prefer to overwrite a free slot since unreferences ones
* contain usable data. Free slots are designated by the page
* value INVALID_PAGE.
*/
for(i = 0, unreferenced = free = -1; i < COFFEE_MAX_OPEN_FILES; i++) { for(i = 0, unreferenced = free = -1; i < COFFEE_MAX_OPEN_FILES; i++) {
if(coffee_files[i].page == INVALID_PAGE) { if(coffee_files[i].page == INVALID_PAGE) {
free = i; free = i;
@ -323,7 +325,7 @@ find_file(const char *name)
/* First check if the file metadata is cached. */ /* First check if the file metadata is cached. */
for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) { for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) {
if(coffee_files[i].max_pages == 0) { if(coffee_files[i].page == INVALID_PAGE) {
continue; continue;
} }
@ -358,6 +360,7 @@ find_file(const char *name)
return NULL; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if COFFEE_CONF_EOF_HINT
static void static void
refresh_eof_hint(struct file *file) refresh_eof_hint(struct file *file)
{ {
@ -381,6 +384,7 @@ refresh_eof_hint(struct file *file)
write_header(&hdr, file->page); write_header(&hdr, file->page);
} }
} }
#endif /* COFFEE_CONF_EOF_HINT */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static coffee_offset_t static coffee_offset_t
file_end(coffee_page_t start) file_end(coffee_page_t start)
@ -389,10 +393,14 @@ file_end(coffee_page_t start)
unsigned char buf[COFFEE_PAGE_SIZE]; unsigned char buf[COFFEE_PAGE_SIZE];
coffee_page_t page; coffee_page_t page;
int i; int i;
coffee_page_t range_start, range_end;
#if COFFEE_CONF_EOF_HINT
coffee_page_t part_size;
int search_limit; int search_limit;
coffee_page_t range_start, range_end, part_size; #endif
read_header(&hdr, start); read_header(&hdr, start);
#if COFFEE_CONF_EOF_HINT
search_limit = 0; search_limit = 0;
for(i = 0; i < sizeof(hdr.eof_hint) * CHAR_BIT; i++) { for(i = 0; i < sizeof(hdr.eof_hint) * CHAR_BIT; i++) {
if(hdr.eof_hint >> i) { if(hdr.eof_hint >> i) {
@ -408,6 +416,10 @@ file_end(coffee_page_t start)
if(range_end + 1 > hdr.max_pages) { if(range_end + 1 > hdr.max_pages) {
range_end = hdr.max_pages - 1; range_end = hdr.max_pages - 1;
} }
#else
range_start = 0;
range_end = hdr.max_pages - 1;
#endif /* COFFEE_CONF_EOF_HINT */
/* /*
* Move from the end of the range towards the beginning and look for * Move from the end of the range towards the beginning and look for
@ -494,8 +506,6 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds)
if(last_valid >= 0) { if(last_valid >= 0) {
coffee_fd_set[last_valid].file->page = INVALID_PAGE; coffee_fd_set[last_valid].file->page = INVALID_PAGE;
coffee_fd_set[last_valid].file->max_pages = 0;
coffee_fd_set[last_valid].file->references = 0;
} }
} }
@ -755,7 +765,9 @@ merge_log(coffee_page_t file_page, int extend)
if(extend) { if(extend) {
new_file->end = offset; new_file->end = offset;
#if COFFEE_CONF_EOF_HINT
refresh_eof_hint(new_file); refresh_eof_hint(new_file);
#endif
} }
cfs_close(fd); cfs_close(fd);
@ -792,7 +804,7 @@ find_next_record(struct file *file, coffee_page_t log_page,
preferred_batch_size : log_records - processed; preferred_batch_size : log_records - processed;
COFFEE_READ(&indices, batch_size * sizeof(indices[0]), COFFEE_READ(&indices, batch_size * sizeof(indices[0]),
absolute_offset(log_page, processed * sizeof(indices[0]))); absolute_offset(log_page, processed * sizeof(indices[0])));
for(i = 0; i < batch_size && indices[i] != 0; i++); for(i = 0; i < batch_size && indices[i] != 0; i++);
log_record = i; log_record = i;
@ -817,7 +829,7 @@ write_log_page(struct file *file, struct log_param *lp)
int16_t log_record; int16_t log_record;
uint16_t log_record_size; uint16_t log_record_size;
uint16_t log_records; uint16_t log_records;
coffee_offset_t base; coffee_offset_t table_base, record_base;
struct log_param lp_out; struct log_param lp_out;
read_header(&hdr, file->page); read_header(&hdr, file->page);
@ -833,7 +845,9 @@ write_log_page(struct file *file, struct log_param *lp)
if(log_record >= log_records) { if(log_record >= log_records) {
/* The log is full; merge the log. */ /* The log is full; merge the log. */
PRINTF("Coffee: Merging the file %s with its log\n", hdr.name); PRINTF("Coffee: Merging the file %s with its log\n", hdr.name);
#if COFFEE_CONF_EOF_HINT
refresh_eof_hint(file); refresh_eof_hint(file);
#endif
return merge_log(file->page, 0); return merge_log(file->page, 0);
} }
} else { } else {
@ -863,15 +877,14 @@ write_log_page(struct file *file, struct log_param *lp)
memcpy((char *) &copy_buf + lp->offset, lp->buf, lp->size); memcpy((char *) &copy_buf + lp->offset, lp->buf, lp->size);
base = (coffee_offset_t)log_page * COFFEE_PAGE_SIZE; table_base = absolute_offset(log_page, 0);
base += sizeof(hdr);
base += log_records * sizeof(region);
base += (coffee_offset_t)log_record * log_record_size;
COFFEE_WRITE(copy_buf, sizeof(copy_buf), base);
++region; ++region;
COFFEE_WRITE(&region, sizeof(region), COFFEE_WRITE(&region, sizeof(region),
absolute_offset(log_page, log_record * sizeof(region))); table_base + log_record * sizeof(region));
record_base = table_base + log_records * sizeof(region);
COFFEE_WRITE(copy_buf, sizeof(copy_buf),
record_base + log_record * log_record_size);
file->next_log_record = log_record + 1; file->next_log_record = log_record + 1;
} }
@ -931,7 +944,9 @@ void
cfs_close(int fd) cfs_close(int fd)
{ {
if(FD_VALID(fd)) { if(FD_VALID(fd)) {
#if COFFEE_CONF_EOF_HINT
refresh_eof_hint(coffee_fd_set[fd].file); refresh_eof_hint(coffee_fd_set[fd].file);
#endif
coffee_fd_set[fd].flags = COFFEE_FD_FREE; coffee_fd_set[fd].flags = COFFEE_FD_FREE;
coffee_fd_set[fd].file->references--; coffee_fd_set[fd].file->references--;
} }
@ -999,6 +1014,7 @@ cfs_read(int fd, void *buf, unsigned size)
fdp = &coffee_fd_set[fd]; fdp = &coffee_fd_set[fd];
file = fdp->file; file = fdp->file;
if(fdp->offset + size > file->end) { if(fdp->offset + size > file->end) {
size = file->end - fdp->offset; size = file->end - fdp->offset;
} }
@ -1059,7 +1075,9 @@ cfs_write(int fd, const void *buf, unsigned size)
/* Attempt to extend the file if we try to write past the end. */ /* Attempt to extend the file if we try to write past the end. */
while(size + fdp->offset + sizeof(struct file_header) > while(size + fdp->offset + sizeof(struct file_header) >
(file->max_pages * COFFEE_PAGE_SIZE)) { (file->max_pages * COFFEE_PAGE_SIZE)) {
#if COFFEE_CONF_EOF_HINT
refresh_eof_hint(file); refresh_eof_hint(file);
#endif
if(merge_log(file->page, 1) < 0) { if(merge_log(file->page, 1) < 0) {
return -1; return -1;
} }
@ -1202,10 +1220,8 @@ cfs_coffee_format(void)
} }
watchdog_start(); watchdog_start();
/* All file descriptors have become invalid. */ /* Formatting invalidates the file information. */
for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { memset(&protected_mem, 0, sizeof(protected_mem));
coffee_fd_set[i].flags = COFFEE_FD_FREE;
}
PRINTF("done!\n"); PRINTF("done!\n");