Skip to content

Commit

Permalink
Fixed a stat bug with obj id. Added user callback file func.
Browse files Browse the repository at this point in the history
New API functions:
  SPIFFS_set_file_callback_func
  • Loading branch information
pellepl committed Feb 15, 2016
1 parent e7e27e2 commit 05354fa
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 5 deletions.
35 changes: 33 additions & 2 deletions src/spiffs.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ typedef u16_t spiffs_mode;
// object type
typedef u8_t spiffs_obj_type;

#if SPIFFS_HAL_CALLBACK_EXTRA
struct spiffs_t;

#if SPIFFS_HAL_CALLBACK_EXTRA

/* spi read call function type */
typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst);
/* spi write call function type */
Expand Down Expand Up @@ -115,6 +116,19 @@ typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_repor
u32_t arg1, u32_t arg2);
#endif // SPIFFS_HAL_CALLBACK_EXTRA

/* file system listener callback operation */
typedef enum {
/* the file has been created */
SPIFFS_CB_CREATED = 0,
/* the file has been updated or moved to another page */
SPIFFS_CB_UPDATED,
/* the file has been deleted */
SPIFFS_CB_DELETED,
} spiffs_fileop_type;

/* file system listener callback function */
typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix);

#ifndef SPIFFS_DBG
#define SPIFFS_DBG(...) \
print(__VA_ARGS__)
Expand Down Expand Up @@ -252,7 +266,8 @@ typedef struct spiffs_t {

// check callback function
spiffs_check_callback check_cb_f;

// file callback function
spiffs_file_callback file_cb_f;
// mounted flag
u8_t mounted;
// user data
Expand All @@ -266,6 +281,7 @@ typedef struct {
spiffs_obj_id obj_id;
u32_t size;
spiffs_obj_type type;
spiffs_page_ix pix;
u8_t name[SPIFFS_OBJ_NAME_LEN];
} spiffs_stat;

Expand Down Expand Up @@ -616,6 +632,21 @@ s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
*/
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);

/**
* Registers a callback function that keeps track on operations on file
* headers. Do note, that this callback is called from within internal spiffs
* mechanisms. Any operations on the actual file system being callbacked from
* in this callback will mess things up for sure - do not do this.
* This can be used to track where files are and move around during garbage
* collection, which in turn can be used to build location tables in ram.
* Used in conjuction with SPIFFS_open_by_page this may improve performance
* when opening a lot of files.
*
* @param fs the file system struct
* @param cb_func the callback on file operations
*/
s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func);

#if SPIFFS_TEST_VISUALISATION
/**
* Prints out a visualization of the filesystem.
Expand Down
12 changes: 11 additions & 1 deletion src/spiffs_hydrogen.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,14 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
void *cache, u32_t cache_size,
spiffs_check_callback check_cb_f) {
void *user_data;
spiffs_file_callback fcb;
SPIFFS_LOCK(fs);
user_data = fs->user_data;
fcb = fs->file_cb_f;
memset(fs, 0, sizeof(spiffs));
memcpy(&fs->cfg, config, sizeof(spiffs_config));
fs->user_data = user_data;
fs->file_cb_f = fcb;
fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs);
fs->work = &work[0];
fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)];
Expand Down Expand Up @@ -692,9 +695,10 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi
obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
SPIFFS_API_CHECK_RES(fs, res);

s->obj_id = obj_id;
s->obj_id = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
s->type = objix_hdr.type;
s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
s->pix = pix;
strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN);

return res;
Expand Down Expand Up @@ -1081,6 +1085,12 @@ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
return res;
}

s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func) {
SPIFFS_LOCK(fs);
fs->file_cb_f = cb_func;
SPIFFS_UNLOCK(fs);
return 0;
}

#if SPIFFS_TEST_VISUALISATION
s32_t SPIFFS_vis(spiffs *fs) {
Expand Down
20 changes: 18 additions & 2 deletions src/spiffs_nucleus.c
Original file line number Diff line number Diff line change
Expand Up @@ -871,13 +871,13 @@ void spiffs_cb_object_event(
spiffs *fs,
spiffs_fd *fd,
int ev,
spiffs_obj_id obj_id,
spiffs_obj_id obj_id_raw,
spiffs_span_ix spix,
spiffs_page_ix new_pix,
u32_t new_size) {
(void)fd;
// update index caches in all file descriptors
obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
spiffs_obj_id obj_id = obj_id_raw & ~SPIFFS_OBJ_ID_IX_FLAG;
u32_t i;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) {
Expand All @@ -904,6 +904,22 @@ void spiffs_cb_object_event(
}
}
}

// callback to user if object index header
if (fs->file_cb_f && spix == 0 && (obj_id_raw & SPIFFS_OBJ_ID_IX_FLAG)) {
spiffs_fileop_type op;
if (ev == SPIFFS_EV_IX_NEW) {
op = SPIFFS_CB_CREATED;
} else if (ev == SPIFFS_EV_IX_UPD) {
op = SPIFFS_CB_UPDATED;
} else if (ev == SPIFFS_EV_IX_DEL) {
op = SPIFFS_CB_DELETED;
} else {
SPIFFS_DBG(" callback: WARNING unknown callback event %02x\n", ev);
return; // bail out
}
fs->file_cb_f(fs, op, obj_id, new_pix);
}
}

// Open object by id
Expand Down
125 changes: 125 additions & 0 deletions src/test/test_hydrogen.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,131 @@ TEST(open_by_page) {
} TEST_END(open_by_page)


static struct {
u32_t calls;
spiffs_fileop_type op;
spiffs_obj_id obj_id;
spiffs_page_ix pix;
} ucb;

void test_cb(spiffs *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix) {
ucb.calls++;
ucb.op = op;
ucb.obj_id = obj_id;
ucb.pix = pix;
//printf("%4i op:%i objid:%04x pix:%04x\n", ucb.calls, ucb.op, ucb.obj_id, ucb.pix);
}

TEST(user_callback_basic) {
SPIFFS_set_file_callback_func(FS, test_cb);
int res;
memset(&ucb, 0, sizeof(ucb));
spiffs_file fd = SPIFFS_open(FS, "foo", SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_RDWR, 0);
TEST_CHECK_GE(fd, 0);
TEST_CHECK_EQ(ucb.calls, 1);
TEST_CHECK_EQ(ucb.op, SPIFFS_CB_CREATED);
spiffs_stat s;
res = SPIFFS_fstat(FS, fd, &s);
TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.obj_id, s.obj_id);
TEST_CHECK_EQ(ucb.pix, s.pix);

res = SPIFFS_write(FS, fd, "howdy partner", 14);
TEST_CHECK_GE(res, 0);
res = SPIFFS_fflush(FS, fd);
TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.calls, 2);
TEST_CHECK_EQ(ucb.op, SPIFFS_CB_UPDATED);
TEST_CHECK_EQ(ucb.obj_id, s.obj_id);
TEST_CHECK_EQ(ucb.pix, s.pix);

res = SPIFFS_fremove(FS, fd);
TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.calls, 3);
TEST_CHECK_EQ(ucb.op, SPIFFS_CB_DELETED);
TEST_CHECK_EQ(ucb.obj_id, s.obj_id);
TEST_CHECK_EQ(ucb.pix, s.pix);

return TEST_RES_OK;
} TEST_END(user_callback_basic)


TEST(user_callback_gc) {
SPIFFS_set_file_callback_func(FS, test_cb);

char name[32];
int f;
int size = SPIFFS_DATA_PAGE_SIZE(FS);
int pages_per_block = SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS);
int files = (pages_per_block-1)/2;
int res;

// fill block with files
for (f = 0; f < files; f++) {
sprintf(name, "file%i", f);
res = test_create_and_write_file(name, size, 1);
TEST_CHECK(res >= 0);
}
for (f = 0; f < files; f++) {
sprintf(name, "file%i", f);
res = read_and_verify(name);
TEST_CHECK(res >= 0);
}
// remove all files in block
for (f = 0; f < files; f++) {
sprintf(name, "file%i", f);
res = SPIFFS_remove(FS, name);
TEST_CHECK(res >= 0);
}

memset(&ucb, 0, sizeof(ucb));
spiffs_file fd = SPIFFS_open(FS, "foo", SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_RDWR, 0);
TEST_CHECK_GE(fd, 0);
TEST_CHECK_EQ(ucb.calls, 1);
TEST_CHECK_EQ(ucb.op, SPIFFS_CB_CREATED);
spiffs_stat s;
res = SPIFFS_fstat(FS, fd, &s);
TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.obj_id, s.obj_id);
TEST_CHECK_EQ(ucb.pix, s.pix);

res = SPIFFS_write(FS, fd, "howdy partner", 14);
TEST_CHECK_GE(res, 0);
res = SPIFFS_fflush(FS, fd);
TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.calls, 2);
TEST_CHECK_EQ(ucb.op, SPIFFS_CB_UPDATED);
TEST_CHECK_EQ(ucb.obj_id, s.obj_id);
TEST_CHECK_EQ(ucb.pix, s.pix);

u32_t tot, us;
SPIFFS_info(FS, &tot, &us);

// do a hard gc, should move our file
res = SPIFFS_gc(FS, tot-us*2);
TEST_CHECK_GE(res, 0);

TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.calls, 3);
TEST_CHECK_EQ(ucb.op, SPIFFS_CB_UPDATED);
TEST_CHECK_EQ(ucb.obj_id, s.obj_id);
TEST_CHECK_NEQ(ucb.pix, s.pix);

res = SPIFFS_fstat(FS, fd, &s);
TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.pix, s.pix);

res = SPIFFS_fremove(FS, fd);
TEST_CHECK_GE(res, 0);
TEST_CHECK_EQ(ucb.calls, 4);
TEST_CHECK_EQ(ucb.op, SPIFFS_CB_DELETED);
TEST_CHECK_EQ(ucb.obj_id, s.obj_id);
TEST_CHECK_EQ(ucb.pix, s.pix);

return TEST_RES_OK;
} TEST_END(user_callback_gc)


TEST(rename) {
int res;

Expand Down

0 comments on commit 05354fa

Please sign in to comment.