refactored the code and reduced the ROM size a few dozen of bytes

This commit is contained in:
nvt-se 2008-11-04 23:09:55 +00:00
parent ae8c93d0aa
commit e6a7089942

View file

@ -102,7 +102,7 @@ struct file_desc {
coffee_offset_t end; coffee_offset_t end;
coffee_page_t file_page; coffee_page_t file_page;
coffee_page_t max_pages; coffee_page_t max_pages;
uint16_t next_log_entry; uint16_t next_log_record;
uint8_t flags; uint8_t flags;
}; };
@ -113,8 +113,8 @@ struct dir_cache {
struct file_header { struct file_header {
coffee_page_t log_page; coffee_page_t log_page;
uint16_t log_entries; uint16_t log_records;
uint16_t log_entry_size; uint16_t log_record_size;
coffee_page_t max_pages; coffee_page_t max_pages;
uint8_t eof_hint; uint8_t eof_hint;
uint8_t flags; uint8_t flags;
@ -132,7 +132,7 @@ struct log_param {
((file_page) * COFFEE_PAGE_SIZE + \ ((file_page) * COFFEE_PAGE_SIZE + \
sizeof(struct file_header) + (file_offset)) sizeof(struct file_header) + (file_offset))
static struct dir_cache dir_cache[COFFEE_DIR_CACHE_ENTRIES]; static struct dir_cache dir_cache[COFFEE_DIR_CACHE_RECORDS];
static struct file_desc coffee_fd_set[COFFEE_FD_SET_SIZE]; static struct file_desc coffee_fd_set[COFFEE_FD_SET_SIZE];
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -232,7 +232,7 @@ dir_cache_add(char c, coffee_offset_t page)
{ {
int i; int i;
for(i = 0; i < COFFEE_DIR_CACHE_ENTRIES; i++) { for(i = 0; i < COFFEE_DIR_CACHE_RECORDS; i++) {
if(dir_cache[i].filename_start == '\0') { if(dir_cache[i].filename_start == '\0') {
dir_cache[i].filename_start = c; dir_cache[i].filename_start = c;
dir_cache[i].page = page; dir_cache[i].page = page;
@ -246,7 +246,7 @@ dir_cache_del(coffee_offset_t page)
{ {
int i; int i;
for(i = 0; i < COFFEE_DIR_CACHE_ENTRIES; i++) { for(i = 0; i < COFFEE_DIR_CACHE_RECORDS; i++) {
if(dir_cache[i].page == page) { if(dir_cache[i].page == page) {
dir_cache[i].filename_start = '\0'; dir_cache[i].filename_start = '\0';
} }
@ -259,7 +259,7 @@ dir_cache_find(const char *name)
int i; int i;
struct file_header hdr; struct file_header hdr;
for(i = 0; i < COFFEE_DIR_CACHE_ENTRIES; i++) { for(i = 0; i < COFFEE_DIR_CACHE_RECORDS; i++) {
if(*name == dir_cache[i].filename_start) { if(*name == dir_cache[i].filename_start) {
read_header(&hdr, dir_cache[i].page); read_header(&hdr, dir_cache[i].page);
if(!COFFEE_PAGE_ACTIVE(hdr)) { if(!COFFEE_PAGE_ACTIVE(hdr)) {
@ -490,8 +490,8 @@ reserve(const char *name, uint32_t size, int allow_duplicates)
hdr.flags = COFFEE_FLAG_ALLOCATED | COFFEE_FLAG_VALID; hdr.flags = COFFEE_FLAG_ALLOCATED | COFFEE_FLAG_VALID;
hdr.log_page = 0; hdr.log_page = 0;
hdr.eof_hint = 0; hdr.eof_hint = 0;
hdr.log_entries = 0; hdr.log_records = 0;
hdr.log_entry_size = 0; hdr.log_record_size = 0;
write_header(&hdr, page); write_header(&hdr, page);
PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n", PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n",
@ -503,72 +503,86 @@ reserve(const char *name, uint32_t size, int allow_duplicates)
return page; return page;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static void
read_log_page(struct file_header *hdr, int16_t last_entry, struct log_param *lp) adjust_log_config(struct file_header *hdr,
uint16_t *log_record_size, uint16_t *log_records)
{
*log_record_size = hdr->log_record_size == 0 ?
COFFEE_PAGE_SIZE : hdr->log_record_size;
*log_records = hdr->log_records == 0 ?
COFFEE_LOG_SIZE / *log_record_size : hdr->log_records;
}
/*---------------------------------------------------------------------------*/
static int
get_record_index(coffee_page_t log_page, uint16_t record_count,
uint16_t search_records, uint16_t region)
{ {
coffee_page_t page;
int16_t match_index;
int16_t i;
uint16_t log_entry_size;
uint16_t log_entries;
unsigned long base; unsigned long base;
uint16_t entry_count; uint16_t indices[record_count];
uint16_t search_entries; uint16_t processed;
uint16_t current_batch_size, i;
int16_t match_index;
log_entries = hdr->log_entries == 0 ? base = ABS_OFFSET(log_page, sizeof(indices[0]) * search_records);
COFFEE_LOG_SIZE / COFFEE_PAGE_SIZE : hdr->log_entries; processed = 0;
log_entry_size = hdr->log_entry_size == 0 ? match_index = -1;
COFFEE_PAGE_SIZE : hdr->log_entry_size; while(processed < search_records && match_index < 0) {
if(record_count + processed > search_records) {
page = lp->offset / log_entry_size; current_batch_size = search_records - processed;
lp->offset %= log_entry_size; } else {
if(lp->size > log_entry_size - lp->offset) { current_batch_size = record_count;
lp->size = log_entry_size - lp->offset;
}
search_entries = last_entry < 0 ? log_entries : last_entry + 1;
entry_count = search_entries > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : search_entries;
{
uint16_t indices[entry_count];
uint16_t processed;
uint16_t current_batch_size;
base = ABS_OFFSET(hdr->log_page, sizeof(indices[0]) * search_entries);
processed = 0;
match_index = -1;
while(processed < search_entries && match_index < 0) {
if(entry_count + processed > search_entries) {
current_batch_size = search_entries - processed;
} else {
current_batch_size = entry_count;
}
base -= current_batch_size * sizeof(indices[0]);
COFFEE_READ(&indices, sizeof(indices[0]) * current_batch_size, base);
for(i = current_batch_size - 1; i >= 0; i--) {
if(indices[i] - 1 == page) {
match_index = search_entries - processed - (current_batch_size - i);
break;
}
}
processed += current_batch_size;
} }
if(match_index == -1) { base -= current_batch_size * sizeof(indices[0]);
return -1; COFFEE_READ(&indices, sizeof(indices[0]) * current_batch_size, base);
for(i = current_batch_size - 1; i >= 0; i--) {
if(indices[i] - 1 == region) {
match_index = search_records - processed - (current_batch_size - i);
break;
}
} }
base = hdr->log_page * COFFEE_PAGE_SIZE; processed += current_batch_size;
base += sizeof(struct file_header) + log_entries * sizeof(page);
base += (unsigned long)match_index * log_entry_size;
base += lp->offset;
COFFEE_READ(lp->buf, lp->size, base);
} }
return match_index;
}
/*---------------------------------------------------------------------------*/
static int
read_log_page(struct file_header *hdr, int16_t last_record, struct log_param *lp)
{
uint16_t region;
int16_t match_index;
uint16_t log_record_size;
uint16_t log_records;
unsigned long base;
uint16_t record_count;
uint16_t search_records;
adjust_log_config(hdr, &log_record_size, &log_records);
region = lp->offset / log_record_size;
lp->offset %= log_record_size;
if(lp->size > log_record_size - lp->offset) {
lp->size = log_record_size - lp->offset;
}
search_records = last_record < 0 ? log_records : last_record + 1;
record_count = search_records > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : search_records;
match_index = get_record_index(hdr->log_page, record_count, search_records, region);
if(match_index < 0) {
return -1;
}
base = hdr->log_page * COFFEE_PAGE_SIZE;
base += sizeof(struct file_header) + log_records * sizeof(region);
base += (unsigned long)match_index * log_record_size;
base += lp->offset;
COFFEE_READ(lp->buf, lp->size, base);
return lp->size; return lp->size;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -593,17 +607,14 @@ create_log(coffee_page_t file_page, struct file_header *hdr)
{ {
coffee_page_t log_page; coffee_page_t log_page;
unsigned char log_name[sizeof(hdr->name)]; unsigned char log_name[sizeof(hdr->name)];
uint16_t log_entry_size, log_entries; uint16_t log_record_size, log_records;
coffee_offset_t size; coffee_offset_t size;
int i; int i;
log_entry_size = hdr->log_entry_size == 0 ? adjust_log_config(hdr, &log_record_size, &log_records);
COFFEE_PAGE_SIZE : hdr->log_entry_size;
log_entries = hdr->log_entries == 0 ?
COFFEE_LOG_SIZE / log_entry_size : hdr->log_entries;
size = log_entries * sizeof(uint16_t); size = log_records * sizeof(uint16_t);
size += log_entries * log_entry_size; size += log_records * log_record_size;
log_page = reserve(create_log_name(log_name, sizeof(log_name), hdr->name), log_page = reserve(create_log_name(log_name, sizeof(log_name), hdr->name),
size, 0); size, 0);
@ -656,7 +667,7 @@ merge_log(coffee_page_t file_page)
offset = 0; offset = 0;
do { do {
char buf[hdr.log_entry_size == 0 ? COFFEE_PAGE_SIZE : hdr.log_entry_size]; char buf[hdr.log_record_size == 0 ? COFFEE_PAGE_SIZE : hdr.log_record_size];
watchdog_periodic(); watchdog_periodic();
n = cfs_read(fd, buf, sizeof(buf)); n = cfs_read(fd, buf, sizeof(buf));
if(n < 0) { if(n < 0) {
@ -678,8 +689,8 @@ merge_log(coffee_page_t file_page)
/* Copy the log configuration and the EOF hint. */ /* Copy the log configuration and the EOF hint. */
read_header(&hdr2, new_file_page); read_header(&hdr2, new_file_page);
hdr2.log_entry_size = hdr.log_entry_size; hdr2.log_record_size = hdr.log_record_size;
hdr2.log_entries = hdr.log_entries; hdr2.log_records = hdr.log_records;
hdr2.eof_hint = hdr.eof_hint; hdr2.eof_hint = hdr.eof_hint;
write_header(&hdr2, new_file_page); write_header(&hdr2, new_file_page);
@ -688,7 +699,7 @@ merge_log(coffee_page_t file_page)
if(coffee_fd_set[n].file_page == file_page) { if(coffee_fd_set[n].file_page == file_page) {
coffee_fd_set[n].file_page = new_file_page; coffee_fd_set[n].file_page = new_file_page;
coffee_fd_set[n].flags &= ~COFFEE_FD_MODIFIED; coffee_fd_set[n].flags &= ~COFFEE_FD_MODIFIED;
coffee_fd_set[n].next_log_entry = 0; coffee_fd_set[n].next_log_record = 0;
} }
} }
@ -703,60 +714,56 @@ write_log_page(struct file_desc *fdp, struct log_param *lp)
struct file_header hdr; struct file_header hdr;
coffee_page_t page; coffee_page_t page;
coffee_page_t log_page; coffee_page_t log_page;
int16_t log_entry; int16_t log_record;
uint16_t log_entry_size; uint16_t log_record_size;
uint16_t log_entries; uint16_t log_records;
int16_t i; int16_t i;
unsigned long base; unsigned long base;
struct log_param lp_out; struct log_param lp_out;
uint16_t entry_count; uint16_t record_count;
read_header(&hdr, fdp->file_page); read_header(&hdr, fdp->file_page);
adjust_log_config(&hdr, &log_record_size, &log_records);
log_entries = hdr.log_entries == 0 ? page = lp->offset / log_record_size;
COFFEE_LOG_SIZE / COFFEE_PAGE_SIZE : hdr.log_entries; lp->offset %= log_record_size;
log_entry_size = hdr.log_entry_size == 0 ? if(lp->size > log_record_size - lp->offset) {
COFFEE_PAGE_SIZE : hdr.log_entry_size; lp->size = log_record_size - lp->offset;
page = lp->offset / log_entry_size;
lp->offset %= log_entry_size;
if(lp->size > log_entry_size - lp->offset) {
lp->size = log_entry_size - lp->offset;
} }
log_page = 0; log_page = 0;
if(COFFEE_PAGE_MODIFIED(hdr)) { if(COFFEE_PAGE_MODIFIED(hdr)) {
/* A log structure has already been created. */ /* A log structure has already been created. */
entry_count = log_entries > COFFEE_LOG_TABLE_LIMIT ? record_count = log_records > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : log_entries; COFFEE_LOG_TABLE_LIMIT : log_records;
log_page = hdr.log_page; log_page = hdr.log_page;
if(fdp->next_log_entry == 0) { if(fdp->next_log_record == 0) {
/* The next log entry is unknown. Search for it. */ /* The next log record is unknown. Search for it. */
uint16_t indices[entry_count]; uint16_t indices[record_count];
uint16_t processed; uint16_t processed;
uint16_t current_batch_size; uint16_t current_batch_size;
log_entry = log_entries; log_record = log_records;
for(processed = 0; processed < log_entries;) { for(processed = 0; processed < log_records;) {
current_batch_size = log_entries - processed >= entry_count ? current_batch_size = log_records - processed >= record_count ?
entry_count : log_entries - processed; record_count : log_records - processed;
COFFEE_READ(&indices, current_batch_size * sizeof(indices[0]), COFFEE_READ(&indices, current_batch_size * sizeof(indices[0]),
ABS_OFFSET(log_page, processed * sizeof(indices[0]))); ABS_OFFSET(log_page, processed * sizeof(indices[0])));
for(i = 0; i < current_batch_size && indices[i] != 0; i++); for(i = 0; i < current_batch_size && indices[i] != 0; i++);
log_entry = i; log_record = i;
if(log_entry < current_batch_size) { if(log_record < current_batch_size) {
log_entry += processed; log_record += processed;
break; break;
} }
processed += current_batch_size; processed += current_batch_size;
} }
} else { } else {
log_entry = fdp->next_log_entry; log_record = fdp->next_log_record;
} }
if(log_entry >= log_entries) { 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);
return merge_log(fdp->file_page); return merge_log(fdp->file_page);
@ -770,34 +777,34 @@ write_log_page(struct file_desc *fdp, struct log_param *lp)
PRINTF("Coffee: Created a log structure for file %s at page %u\n", PRINTF("Coffee: Created a log structure for file %s at page %u\n",
hdr.name, log_page); hdr.name, log_page);
hdr.log_page = log_page; hdr.log_page = log_page;
log_entry = 0; log_record = 0;
} }
{ {
unsigned char copy_buf[log_entry_size]; unsigned char copy_buf[log_record_size];
lp_out.offset = page * log_entry_size; lp_out.offset = page * log_record_size;
lp_out.buf = copy_buf; lp_out.buf = copy_buf;
lp_out.size = log_entry_size; lp_out.size = log_record_size;
if((lp->offset > 0 || lp->size != log_entry_size) && if((lp->offset > 0 || lp->size != log_record_size) &&
read_log_page(&hdr, fdp->next_log_entry > 0 ? fdp->next_log_entry - 1 : -1, &lp_out) < 0) { read_log_page(&hdr, fdp->next_log_record > 0 ? fdp->next_log_record - 1 : -1, &lp_out) < 0) {
COFFEE_READ(copy_buf, sizeof(copy_buf), COFFEE_READ(copy_buf, sizeof(copy_buf),
ABS_OFFSET(fdp->file_page, page * log_entry_size)); ABS_OFFSET(fdp->file_page, page * log_record_size));
} }
memcpy((char *) &copy_buf + lp->offset, lp->buf, lp->size); memcpy((char *) &copy_buf + lp->offset, lp->buf, lp->size);
base = (unsigned long)log_page * COFFEE_PAGE_SIZE; base = (unsigned long)log_page * COFFEE_PAGE_SIZE;
base += sizeof(hdr); base += sizeof(hdr);
base += log_entries * sizeof(page); base += log_records * sizeof(page);
base += (unsigned long)log_entry * log_entry_size; base += (unsigned long)log_record * log_record_size;
COFFEE_WRITE(copy_buf, sizeof(copy_buf), base); COFFEE_WRITE(copy_buf, sizeof(copy_buf), base);
++page; ++page;
COFFEE_WRITE(&page, sizeof(page), COFFEE_WRITE(&page, sizeof(page),
ABS_OFFSET(log_page, log_entry * sizeof(page))); ABS_OFFSET(log_page, log_record * sizeof(page)));
fdp->next_log_entry = log_entry + 1; fdp->next_log_record = log_record + 1;
} }
return lp->size; return lp->size;
@ -853,7 +860,7 @@ cfs_open(const char *name, int flags)
fdp->flags |= flags; fdp->flags |= flags;
fdp->end = find_offset_in_file(page); fdp->end = find_offset_in_file(page);
fdp->offset = flags & CFS_APPEND ? fdp->end : 0; fdp->offset = flags & CFS_APPEND ? fdp->end : 0;
fdp->next_log_entry = 0; fdp->next_log_record = 0;
return fd; return fd;
} }
@ -944,8 +951,8 @@ cfs_read(int fd, void *buf, unsigned size)
read_chunk = COFFEE_PAGE_SIZE; read_chunk = COFFEE_PAGE_SIZE;
if(FD_MODIFIED(fd)) { if(FD_MODIFIED(fd)) {
read_header(&hdr, fdp->file_page); read_header(&hdr, fdp->file_page);
if(hdr.log_entry_size > 0) { if(hdr.log_record_size > 0) {
read_chunk = hdr.log_entry_size; read_chunk = hdr.log_record_size;
} }
} }
@ -954,7 +961,7 @@ cfs_read(int fd, void *buf, unsigned size)
offset = 0; offset = 0;
/* /*
* Fill the buffer by copying from the log in first hand, or the * Fill the buffer by copying from the log in first hand, or the
* ordinary file if the page has no log entry. * ordinary file if the page has no log record.
*/ */
while(remains) { while(remains) {
watchdog_periodic(); watchdog_periodic();
@ -964,7 +971,7 @@ cfs_read(int fd, void *buf, unsigned size)
lp.buf = (char *)buf + offset; lp.buf = (char *)buf + offset;
lp.size = remains; lp.size = remains;
r = read_log_page(&hdr, r = read_log_page(&hdr,
fdp->next_log_entry > 0 ? fdp->next_log_entry - 1 : -1, &lp); fdp->next_log_record > 0 ? fdp->next_log_record - 1 : -1, &lp);
} }
/* Read from the original file if we cannot find the data in the log. */ /* Read from the original file if we cannot find the data in the log. */
if(r < 0) { if(r < 0) {
@ -1052,7 +1059,7 @@ cfs_opendir(struct cfs_dir *dir, const char *name)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *entry) cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record)
{ {
struct file_header hdr; struct file_header hdr;
coffee_page_t page; coffee_page_t page;
@ -1065,9 +1072,9 @@ cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *entry)
} else if(COFFEE_PAGE_ISOLATED(hdr)) { } else if(COFFEE_PAGE_ISOLATED(hdr)) {
++page; ++page;
} else if(COFFEE_PAGE_ACTIVE(hdr) && !COFFEE_PAGE_LOG(hdr)) { } else if(COFFEE_PAGE_ACTIVE(hdr) && !COFFEE_PAGE_LOG(hdr)) {
memcpy(entry->name, hdr.name, sizeof(entry->name)); memcpy(record->name, hdr.name, sizeof(record->name));
entry->name[sizeof(entry->name) - 1] = '\0'; record->name[sizeof(record->name) - 1] = '\0';
entry->size = find_offset_in_file(page); record->size = find_offset_in_file(page);
page += hdr.max_pages; page += hdr.max_pages;
*(coffee_page_t *)dir->dummy_space = page; *(coffee_page_t *)dir->dummy_space = page;
return 0; return 0;
@ -1092,12 +1099,12 @@ cfs_coffee_reserve(const char *name, uint32_t size)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
cfs_coffee_configure_log(const char *file, unsigned log_size, unsigned log_entry_size) cfs_coffee_configure_log(const char *file, unsigned log_size, unsigned log_record_size)
{ {
coffee_page_t page; coffee_page_t page;
struct file_header hdr; struct file_header hdr;
if(log_entry_size == 0 || log_entry_size > COFFEE_PAGE_SIZE || log_size < log_entry_size) { if(log_record_size == 0 || log_record_size > COFFEE_PAGE_SIZE || log_size < log_record_size) {
return -1; return -1;
} }
@ -1112,8 +1119,8 @@ cfs_coffee_configure_log(const char *file, unsigned log_size, unsigned log_entry
return -1; return -1;
} }
hdr.log_entries = log_size / log_entry_size; hdr.log_records = log_size / log_record_size;
hdr.log_entry_size = log_entry_size; hdr.log_record_size = log_record_size;
write_header(&hdr, page); write_header(&hdr, page);
return 0; return 0;