mirror of
https://github.com/pellepl/spiffs.git
synced 2026-09-11 19:50:02 +00:00
Fixed a stat bug with obj id. Added user callback file func.
New API functions: SPIFFS_set_file_callback_func
This commit is contained in:
+33
-2
@@ -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 */
|
||||
@@ -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__)
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
+11
-1
@@ -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)];
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
|
||||
+18
-2
@@ -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++) {
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user