decreased the code size to less than 5000 bytes. (msp430 code)
improved clarity in read and write code. added negative offset check in cfs_seek(). removed unnecessary multiplication.
This commit is contained in:
parent
bc6c9410cc
commit
2978270e43
1 changed files with 58 additions and 63 deletions
|
@ -81,6 +81,8 @@
|
||||||
#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND)
|
#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND)
|
||||||
|
|
||||||
#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)
|
#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)
|
||||||
|
#define FILE_FREE(file) ((file)->max_pages == 0)
|
||||||
|
#define FILE_UNREFERENCED(file) ((file)->references == 0)
|
||||||
|
|
||||||
/* File header flags. */
|
/* File header flags. */
|
||||||
#define HDR_FLAG_VALID 0x1 /* Completely written header. */
|
#define HDR_FLAG_VALID 0x1 /* Completely written header. */
|
||||||
|
@ -333,10 +335,10 @@ load_file(coffee_page_t start, struct file_header *hdr)
|
||||||
* value INVALID_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(FILE_FREE(&coffee_files[i])) {
|
||||||
free = i;
|
free = i;
|
||||||
break;
|
break;
|
||||||
} else if(coffee_files[i].references == 0) {
|
} else if(FILE_UNREFERENCED(&coffee_files[i])) {
|
||||||
unreferenced = i;
|
unreferenced = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,7 +373,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(FILE_FREE(&coffee_files[i])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +471,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(remove_log && HDR_MODIFIED(hdr)) {
|
if(remove_log && HDR_MODIFIED(hdr)) {
|
||||||
if (remove_by_page(hdr.log_page, 0, 0) < 0) {
|
if(remove_by_page(hdr.log_page, 0, 0) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -512,7 +514,8 @@ page_count(cfs_offset_t size)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static struct file *
|
static struct file *
|
||||||
reserve(const char *name, coffee_page_t pages, int allow_duplicates)
|
reserve(const char *name, coffee_page_t pages,
|
||||||
|
int allow_duplicates, unsigned flags)
|
||||||
{
|
{
|
||||||
struct file_header hdr;
|
struct file_header hdr;
|
||||||
coffee_page_t page;
|
coffee_page_t page;
|
||||||
|
@ -543,7 +546,7 @@ reserve(const char *name, coffee_page_t pages, int allow_duplicates)
|
||||||
memcpy(hdr.name, name, sizeof(hdr.name) - 1);
|
memcpy(hdr.name, name, sizeof(hdr.name) - 1);
|
||||||
hdr.name[sizeof(hdr.name) - 1] = '\0';
|
hdr.name[sizeof(hdr.name) - 1] = '\0';
|
||||||
hdr.max_pages = pages;
|
hdr.max_pages = pages;
|
||||||
hdr.flags = HDR_FLAG_ALLOCATED;
|
hdr.flags = HDR_FLAG_ALLOCATED | flags;
|
||||||
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",
|
||||||
|
@ -561,9 +564,9 @@ adjust_log_config(struct file_header *hdr,
|
||||||
uint16_t *log_record_size, uint16_t *log_records)
|
uint16_t *log_record_size, uint16_t *log_records)
|
||||||
{
|
{
|
||||||
*log_record_size = hdr->log_record_size == 0 ?
|
*log_record_size = hdr->log_record_size == 0 ?
|
||||||
COFFEE_PAGE_SIZE : hdr->log_record_size;
|
COFFEE_PAGE_SIZE : hdr->log_record_size;
|
||||||
*log_records = hdr->log_records == 0 ?
|
*log_records = hdr->log_records == 0 ?
|
||||||
COFFEE_LOG_SIZE / *log_record_size : hdr->log_records;
|
COFFEE_LOG_SIZE / *log_record_size : hdr->log_records;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static uint16_t
|
static uint16_t
|
||||||
|
@ -660,7 +663,7 @@ create_log(struct file *file, struct file_header *hdr)
|
||||||
size = log_records * sizeof(uint16_t); /* Log index size. */
|
size = log_records * sizeof(uint16_t); /* Log index size. */
|
||||||
size += log_records * log_record_size; /* Log data size. */
|
size += log_records * log_record_size; /* Log data size. */
|
||||||
|
|
||||||
log_file = reserve(hdr->name, page_count(size), 1);
|
log_file = reserve(hdr->name, page_count(size), 1, HDR_FLAG_LOG);
|
||||||
if(log_file == NULL) {
|
if(log_file == NULL) {
|
||||||
return INVALID_PAGE;
|
return INVALID_PAGE;
|
||||||
}
|
}
|
||||||
|
@ -669,9 +672,6 @@ create_log(struct file *file, struct file_header *hdr)
|
||||||
hdr->flags |= HDR_FLAG_MODIFIED;
|
hdr->flags |= HDR_FLAG_MODIFIED;
|
||||||
hdr->log_page = log_page;
|
hdr->log_page = log_page;
|
||||||
write_header(hdr, file->page);
|
write_header(hdr, file->page);
|
||||||
read_header(hdr, log_page);
|
|
||||||
hdr->flags |= HDR_FLAG_LOG;
|
|
||||||
write_header(hdr, log_page);
|
|
||||||
|
|
||||||
file->flags |= COFFEE_FILE_MODIFIED;
|
file->flags |= COFFEE_FILE_MODIFIED;
|
||||||
return log_page;
|
return log_page;
|
||||||
|
@ -701,7 +701,7 @@ merge_log(coffee_page_t file_page, int extend)
|
||||||
* already been calculated with in the previous reservation.
|
* already been calculated with in the previous reservation.
|
||||||
*/
|
*/
|
||||||
max_pages = hdr.max_pages << extend;
|
max_pages = hdr.max_pages << extend;
|
||||||
new_file = reserve(hdr.name, max_pages, 1);
|
new_file = reserve(hdr.name, max_pages, 1, 0);
|
||||||
if(new_file == NULL) {
|
if(new_file == NULL) {
|
||||||
cfs_close(fd);
|
cfs_close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -796,7 +796,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;
|
||||||
cfs_offset_t table_base, record_base;
|
cfs_offset_t offset;
|
||||||
struct log_param lp_out;
|
struct log_param lp_out;
|
||||||
|
|
||||||
read_header(&hdr, file->page);
|
read_header(&hdr, file->page);
|
||||||
|
@ -829,26 +829,26 @@ write_log_page(struct file *file, struct log_param *lp)
|
||||||
{
|
{
|
||||||
unsigned char copy_buf[log_record_size];
|
unsigned char copy_buf[log_record_size];
|
||||||
|
|
||||||
lp_out.offset = region * log_record_size;
|
lp_out.offset = offset = region * log_record_size;
|
||||||
lp_out.buf = copy_buf;
|
lp_out.buf = copy_buf;
|
||||||
lp_out.size = log_record_size;
|
lp_out.size = log_record_size;
|
||||||
|
|
||||||
if((lp->offset > 0 || lp->size != log_record_size) &&
|
if((lp->offset > 0 || lp->size != log_record_size) &&
|
||||||
read_log_page(&hdr, log_record, &lp_out) < 0) {
|
read_log_page(&hdr, log_record, &lp_out) < 0) {
|
||||||
COFFEE_READ(copy_buf, sizeof(copy_buf),
|
COFFEE_READ(copy_buf, sizeof(copy_buf),
|
||||||
absolute_offset(file->page, region * log_record_size));
|
absolute_offset(file->page, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy((char *) ©_buf + lp->offset, lp->buf, lp->size);
|
memcpy((char *) ©_buf + lp->offset, lp->buf, lp->size);
|
||||||
|
|
||||||
table_base = absolute_offset(log_page, 0);
|
offset = absolute_offset(log_page, 0);
|
||||||
++region;
|
++region;
|
||||||
COFFEE_WRITE(®ion, sizeof(region),
|
COFFEE_WRITE(®ion, sizeof(region),
|
||||||
table_base + log_record * sizeof(region));
|
offset + log_record * sizeof(region));
|
||||||
|
|
||||||
record_base = table_base + log_records * sizeof(region);
|
offset += log_records * sizeof(region);
|
||||||
COFFEE_WRITE(copy_buf, sizeof(copy_buf),
|
COFFEE_WRITE(copy_buf, sizeof(copy_buf),
|
||||||
record_base + log_record * log_record_size);
|
offset + log_record * log_record_size);
|
||||||
file->next_log_record = log_record + 1;
|
file->next_log_record = log_record + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,7 +888,7 @@ cfs_open(const char *name, int flags)
|
||||||
if((flags & (CFS_READ | CFS_WRITE)) == CFS_READ) {
|
if((flags & (CFS_READ | CFS_WRITE)) == CFS_READ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fdp->file = reserve(name, page_count(COFFEE_DYN_SIZE), 1);
|
fdp->file = reserve(name, page_count(COFFEE_DYN_SIZE), 1, 0);
|
||||||
if(fdp->file == NULL) {
|
if(fdp->file == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -917,20 +917,12 @@ cfs_close(int fd)
|
||||||
cfs_offset_t
|
cfs_offset_t
|
||||||
cfs_seek(int fd, cfs_offset_t offset, int whence)
|
cfs_seek(int fd, cfs_offset_t offset, int whence)
|
||||||
{
|
{
|
||||||
struct file_header hdr;
|
|
||||||
struct file_desc *fdp;
|
struct file_desc *fdp;
|
||||||
|
|
||||||
if(!FD_VALID(fd)) {
|
if(!FD_VALID(fd)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fdp = &coffee_fd_set[fd];
|
fdp = &coffee_fd_set[fd];
|
||||||
read_header(&hdr, fdp->file->page);
|
|
||||||
|
|
||||||
/* Check if the offset is within the file boundary. */
|
|
||||||
if(sizeof(hdr) + offset >= hdr.max_pages * COFFEE_PAGE_SIZE ||
|
|
||||||
sizeof(hdr) + offset < offset) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(whence == CFS_SEEK_SET) {
|
if(whence == CFS_SEEK_SET) {
|
||||||
fdp->offset = offset;
|
fdp->offset = offset;
|
||||||
|
@ -942,6 +934,11 @@ cfs_seek(int fd, cfs_offset_t offset, int whence)
|
||||||
return (cfs_offset_t)-1;
|
return (cfs_offset_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(fdp->offset < 0 || fdp->offset > fdp->file->max_pages * COFFEE_PAGE_SIZE) {
|
||||||
|
fdp->offset = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(fdp->file->end < fdp->offset) {
|
if(fdp->file->end < fdp->offset) {
|
||||||
fdp->file->end = fdp->offset;
|
fdp->file->end = fdp->offset;
|
||||||
}
|
}
|
||||||
|
@ -974,9 +971,8 @@ cfs_read(int fd, void *buf, unsigned size)
|
||||||
struct file_header hdr;
|
struct file_header hdr;
|
||||||
struct file_desc *fdp;
|
struct file_desc *fdp;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
unsigned remains, read_chunk;
|
unsigned bytes_left;
|
||||||
int r;
|
int r;
|
||||||
cfs_offset_t base, offset;
|
|
||||||
struct log_param lp;
|
struct log_param lp;
|
||||||
|
|
||||||
if(!(FD_VALID(fd) && FD_READABLE(fd))) {
|
if(!(FD_VALID(fd) && FD_READABLE(fd))) {
|
||||||
|
@ -989,41 +985,34 @@ cfs_read(int fd, void *buf, unsigned size)
|
||||||
size = file->end - fdp->offset;
|
size = file->end - fdp->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_chunk = COFFEE_PAGE_SIZE;
|
bytes_left = size;
|
||||||
if(FILE_MODIFIED(file)) {
|
if(FILE_MODIFIED(file)) {
|
||||||
read_header(&hdr, file->page);
|
read_header(&hdr, file->page);
|
||||||
if(hdr.log_record_size > 0) {
|
|
||||||
read_chunk = hdr.log_record_size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remains = size;
|
|
||||||
base = fdp->offset;
|
|
||||||
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 record.
|
* ordinary file if the page has no log record.
|
||||||
*/
|
*/
|
||||||
while(remains) {
|
while(bytes_left) {
|
||||||
watchdog_periodic();
|
watchdog_periodic();
|
||||||
r = -1;
|
r = -1;
|
||||||
if(FILE_MODIFIED(file)) {
|
if(FILE_MODIFIED(file)) {
|
||||||
lp.offset = base + offset;
|
lp.offset = fdp->offset;
|
||||||
lp.buf = (char *)buf + offset;
|
lp.buf = buf;
|
||||||
lp.size = remains;
|
lp.size = bytes_left;
|
||||||
r = read_log_page(&hdr, file->next_log_record, &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. */
|
/* Read from the original file if we cannot find the data in the log. */
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
r = remains > read_chunk ? read_chunk : remains;
|
r = bytes_left;
|
||||||
COFFEE_READ((char *) buf + offset, r,
|
COFFEE_READ(buf, r, absolute_offset(file->page, fdp->offset));
|
||||||
absolute_offset(file->page, base + offset));
|
|
||||||
}
|
}
|
||||||
remains -= r;
|
bytes_left -= r;
|
||||||
offset += r;
|
fdp->offset += r;
|
||||||
|
buf += r;
|
||||||
}
|
}
|
||||||
fdp->offset += offset;
|
return size;
|
||||||
return offset;
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
|
@ -1033,7 +1022,7 @@ cfs_write(int fd, const void *buf, unsigned size)
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int i;
|
int i;
|
||||||
struct log_param lp;
|
struct log_param lp;
|
||||||
cfs_offset_t remains;
|
cfs_offset_t bytes_left;
|
||||||
|
|
||||||
if(!(FD_VALID(fd) && FD_WRITABLE(fd))) {
|
if(!(FD_VALID(fd) && FD_WRITABLE(fd))) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1053,26 +1042,32 @@ cfs_write(int fd, const void *buf, unsigned size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(FILE_MODIFIED(file) || fdp->offset < file->end) {
|
if(FILE_MODIFIED(file) || fdp->offset < file->end) {
|
||||||
remains = size;
|
bytes_left = size;
|
||||||
while(remains) {
|
while(bytes_left) {
|
||||||
lp.offset = fdp->offset;
|
lp.offset = fdp->offset;
|
||||||
lp.buf = (char *)buf + size - remains;
|
lp.buf = buf;
|
||||||
lp.size = remains;
|
lp.size = bytes_left;
|
||||||
i = write_log_page(file, &lp);
|
i = write_log_page(file, &lp);
|
||||||
if(i == 0) {
|
|
||||||
file = fdp->file;
|
|
||||||
/* The file was merged with the log. Try again. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(i < 0) {
|
if(i < 0) {
|
||||||
return size - remains > 0 ? size - remains : -1;
|
/* Return -1 if we wrote nothing because the log write failed. */
|
||||||
|
if(size == bytes_left) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if(i == 0) {
|
||||||
|
/* The file was merged with the log. */
|
||||||
|
file = fdp->file;
|
||||||
|
} else {
|
||||||
|
/* A log record was written. */
|
||||||
|
bytes_left -= i;
|
||||||
|
fdp->offset += i;
|
||||||
|
buf += i;
|
||||||
}
|
}
|
||||||
remains -= i;
|
|
||||||
fdp->offset += i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fdp->offset > file->end) {
|
if(fdp->offset > file->end) {
|
||||||
/* Update the original file's end with a dummy write. */
|
/* Update the original file's end with a dummy write. */
|
||||||
|
*(char *)buf = 0xff;
|
||||||
COFFEE_WRITE(buf, 1, absolute_offset(file->page, fdp->offset));
|
COFFEE_WRITE(buf, 1, absolute_offset(file->page, fdp->offset));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1129,7 +1124,7 @@ cfs_closedir(struct cfs_dir *dir)
|
||||||
int
|
int
|
||||||
cfs_coffee_reserve(const char *name, cfs_offset_t size)
|
cfs_coffee_reserve(const char *name, cfs_offset_t size)
|
||||||
{
|
{
|
||||||
return reserve(name, page_count(size), 0) == NULL ? -1 : 0;
|
return reserve(name, page_count(size), 0, 0) == NULL ? -1 : 0;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in a new issue