Fixed append->modify->append bug.

Approximately doubled the speed of file reservations.

Reduced the compiled code size by about 100 bytes by removing redundant code.
This commit is contained in:
nvt-se 2009-05-11 16:35:49 +00:00
parent 74e9bc8789
commit 995e788d73
1 changed files with 43 additions and 62 deletions

View File

@ -54,9 +54,8 @@
#include "cfs/cfs-coffee.h"
#include "dev/watchdog.h"
#if COFFEE_PAGES_PER_SECTOR & (COFFEE_PAGES_PER_SECTOR - 1)
#error COFFEE_PAGES_PER_SECTOR must be a power of two.
#error Change COFFEE_PAGES_PER_SECTOR in cfs-coffee-arch.h.
#if COFFEE_START & (COFFEE_SECTOR_SIZE - 1)
#error COFFEE_START must point to the first byte in a sector.
#endif
#define COFFEE_FD_FREE 0x0
@ -323,7 +322,7 @@ next_file(coffee_page_t page, struct file_header *hdr)
}
/*---------------------------------------------------------------------------*/
static struct file *
load_file(const char *name, struct file_header *hdr, coffee_page_t start)
load_file(coffee_page_t start, struct file_header *hdr)
{
int i, unreferenced, free;
struct file *file;
@ -342,18 +341,22 @@ load_file(const char *name, struct file_header *hdr, coffee_page_t start)
}
}
if(free != -1) {
i = free;
} else if(unreferenced != -1) {
i = unreferenced;
} else {
return NULL;
if(free == -1) {
if(unreferenced != -1) {
i = unreferenced;
} else {
return NULL;
}
}
file = &coffee_files[i];
file->page = start;
file->end = UNKNOWN_OFFSET;
file->max_pages = hdr->max_pages;
file->flags = 0;
if(HDR_MODIFIED(*hdr)) {
file->flags |= COFFEE_FILE_MODIFIED;
}
file->next_log_record = -1;
return file;
@ -365,7 +368,7 @@ 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(coffee_files[i].max_pages == 0) {
@ -373,16 +376,16 @@ find_file(const char *name)
}
read_header(&hdr, coffee_files[i].page);
if(HDR_ACTIVE(hdr) && strcmp(name, hdr.name) == 0) {
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) && strcmp(name, hdr.name) == 0) {
return load_file(name, &hdr, page);
if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr) && strcmp(name, hdr.name) == 0) {
return load_file(page, &hdr);
}
}
@ -546,7 +549,7 @@ reserve(const char *name, coffee_page_t pages, int allow_duplicates)
PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n",
pages, page, name);
file = load_file(name, &hdr, page);
file = load_file(page, &hdr);
file->end = 0;
watchdog_start();
@ -585,22 +588,19 @@ get_record_index(coffee_page_t log_page, uint16_t search_records,
uint16_t processed;
uint16_t batch_size;
int16_t match_index, i;
uint16_t record_count;
base = absolute_offset(log_page, sizeof(uint16_t) * search_records);
record_count = search_records > COFFEE_LOG_TABLE_LIMIT ?
batch_size = search_records > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : search_records;
processed = 0;
match_index = -1;
{
uint16_t indices[record_count];
uint16_t indices[batch_size];
while(processed < search_records && match_index < 0) {
if(record_count + processed > search_records) {
if(batch_size + processed > search_records) {
batch_size = search_records - processed;
} else {
batch_size = record_count;
}
base -= batch_size * sizeof(indices[0]);
@ -647,27 +647,10 @@ read_log_page(struct file_header *hdr, int16_t last_record, struct log_param *lp
return lp->size;
}
/*---------------------------------------------------------------------------*/
static unsigned char *
create_log_name(unsigned char *new, int max_size, unsigned char *old)
{
const unsigned char suffix[] = ".log";
int len;
len = strlen(old);
if(len > max_size - sizeof(suffix)) {
len = max_size - sizeof(suffix);
}
memcpy(new, old, len);
memcpy(&new[len], suffix, sizeof(suffix));
return new;
}
/*---------------------------------------------------------------------------*/
static coffee_page_t
create_log(struct file *file, struct file_header *hdr)
{
coffee_page_t log_page;
unsigned char log_name[sizeof(hdr->name)];
uint16_t log_record_size, log_records;
cfs_offset_t size;
struct file *log_file;
@ -677,9 +660,8 @@ create_log(struct file *file, struct file_header *hdr)
size = log_records * sizeof(uint16_t); /* Log index size. */
size += log_records * log_record_size; /* Log data size. */
log_file = reserve(create_log_name(log_name, sizeof(log_name), hdr->name),
page_count(size), 0);
if(file == NULL) {
log_file = reserve(hdr->name, page_count(size), 1);
if(log_file == NULL) {
return INVALID_PAGE;
}
log_page = log_file->page;
@ -761,6 +743,7 @@ merge_log(coffee_page_t file_page, int extend)
hdr2.log_records = hdr.log_records;
write_header(&hdr2, new_file->page);
new_file->flags &= ~COFFEE_FILE_MODIFIED;
new_file->end = offset;
cfs_close(fd);
@ -772,12 +755,12 @@ static int
find_next_record(struct file *file, coffee_page_t log_page,
int log_records)
{
int log_record, i, preferred_batch_size;
int log_record, preferred_batch_size;
preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : log_records;
if(file->next_log_record == 0) {
if(file->next_log_record == -1) {
/* The next log record is unknown. Search for it. */
uint16_t indices[preferred_batch_size];
uint16_t processed;
@ -790,12 +773,11 @@ find_next_record(struct file *file, coffee_page_t log_page,
COFFEE_READ(&indices, batch_size * sizeof(indices[0]),
absolute_offset(log_page, processed * sizeof(indices[0])));
for(i = 0; i < batch_size && indices[i] != 0; i++);
log_record = i;
if(log_record < batch_size) {
log_record += processed;
break;
for(log_record = 0; log_record < batch_size; log_record++) {
if(indices[log_record] == 0) {
log_record += processed;
break;
}
}
}
} else {
@ -852,7 +834,7 @@ write_log_page(struct file *file, struct log_param *lp)
lp_out.size = log_record_size;
if((lp->offset > 0 || lp->size != log_record_size) &&
read_log_page(&hdr, file->next_log_record - 1, &lp_out) < 0) {
read_log_page(&hdr, log_record, &lp_out) < 0) {
COFFEE_READ(copy_buf, sizeof(copy_buf),
absolute_offset(file->page, region * log_record_size));
}
@ -1029,7 +1011,7 @@ cfs_read(int fd, void *buf, unsigned size)
lp.offset = base + offset;
lp.buf = (char *)buf + offset;
lp.size = remains;
r = read_log_page(&hdr, file->next_log_record - 1, &lp);
r = read_log_page(&hdr, file->next_log_record, &lp);
}
/* Read from the original file if we cannot find the data in the log. */
if(r < 0) {
@ -1070,7 +1052,7 @@ cfs_write(int fd, const void *buf, unsigned size)
PRINTF("Extended the file at page %u\n", (unsigned)file->page);
}
if(fdp->offset < file->end) {
if(FILE_MODIFIED(file) || fdp->offset < file->end) {
remains = size;
while(remains) {
lp.offset = fdp->offset;
@ -1088,6 +1070,11 @@ cfs_write(int fd, const void *buf, unsigned size)
remains -= i;
fdp->offset += i;
}
if(fdp->offset > file->end) {
/* Update the original file's end with a dummy write. */
COFFEE_WRITE(buf, 1, absolute_offset(file->page, fdp->offset));
}
} else {
COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
fdp->offset += size;
@ -1178,20 +1165,14 @@ cfs_coffee_configure_log(const char *filename, unsigned log_size,
int
cfs_coffee_format(void)
{
int nsectors, i;
int i;
nsectors = COFFEE_SECTOR_COUNT;
/* Reject format requests when the configuration is incorrect. */
if(nsectors < 1 || (COFFEE_START & (COFFEE_SECTOR_SIZE - 1))) {
return -1;
}
PRINTF("Coffee: Formatting %d sectors", nsectors);
PRINTF("Coffee: Formatting %d sectors", COFFEE_SECTOR_COUNT);
*next_free = 0;
watchdog_stop();
for(i = 0; i < nsectors; i++) {
for(i = 0; i < COFFEE_SECTOR_COUNT; i++) {
COFFEE_ERASE(i);
PRINTF(".");
}