VFS: Add function for search superblock by any condition via callback

This commit is contained in:
Slava Zanko 2013-05-20 23:13:51 +03:00
parent b7ec1db5ae
commit 867687574f
2 changed files with 90 additions and 45 deletions

View File

@ -92,6 +92,13 @@ struct dirhandle
struct vfs_s_inode *dir; struct vfs_s_inode *dir;
}; };
typedef struct
{
vfs_path_t *vpath_archive;
const vfs_path_element_t *path_element;
void *cookie;
} vfs_get_by_vpath_data_t;
/*** file scope variables ************************************************************************/ /*** file scope variables ************************************************************************/
static volatile int total_inodes = 0, total_entries = 0; static volatile int total_inodes = 0, total_entries = 0;
@ -868,56 +875,29 @@ vfs_s_dir_uptodate (struct vfs_class *me, struct vfs_s_inode *ino)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
/** /**
* get superlock object by vpath * Callback for search superblock via subclass->archive_same() call
* *
* @param vpath path * @param me class for search superblocks
* @return superlock object or NULL if not found * @param cb_data some data for callback
* @param super superblock for comparsion
* @return TRUE if superblock is what we need, FALSE otherwise
*/ */
static struct vfs_s_super * static gboolean
vfs_get_sb_by_vpath (const vfs_path_t * vpath) vfs_cb_archive_same (struct vfs_class *me, void *cb_data, struct vfs_s_super *super)
{ {
GList *iter; vfs_get_by_vpath_data_t *vfs_get_by_vpath_data;
void *cookie = NULL;
const vfs_path_element_t *path_element;
struct vfs_s_subclass *subclass; struct vfs_s_subclass *subclass;
struct vfs_s_super *super = NULL; int ret;
vfs_path_t *vpath_archive;
path_element = vfs_path_get_by_index (vpath, -1); vfs_get_by_vpath_data = (vfs_get_by_vpath_data_t *) cb_data;
subclass = ((struct vfs_s_subclass *) path_element->class->data); subclass = (struct vfs_s_subclass *) me->data;
if (subclass == NULL)
return NULL;
vpath_archive = vfs_path_clone (vpath); ret = subclass->archive_same (vfs_get_by_vpath_data->path_element, super,
vfs_path_remove_element_by_index (vpath_archive, -1); vfs_get_by_vpath_data->vpath_archive,
vfs_get_by_vpath_data->cookie);
if (subclass->archive_check != NULL) return (ret != 0);
{
cookie = subclass->archive_check (vpath_archive);
if (cookie == NULL)
goto ret;
}
for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter))
{
int i;
super = (struct vfs_s_super *) iter->data;
/* 0 == other, 1 == same, return it, 2 == other but stop scanning */
i = subclass->archive_same (path_element, super, vpath_archive, cookie);
if (i == 1)
goto ret;
if (i != 0)
break;
super = NULL;
}
ret:
vfs_path_free (vpath_archive);
return super;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -1103,13 +1083,39 @@ struct vfs_s_super *
vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new) vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new)
{ {
int result = -1; int result = -1;
struct vfs_s_super *super; struct vfs_s_super *super = NULL;
const vfs_path_element_t *path_element; const vfs_path_element_t *path_element;
struct vfs_s_subclass *subclass; struct vfs_s_subclass *subclass;
vfs_get_by_vpath_data_t vfs_get_by_vpath_data;
path_element = vfs_path_get_by_index (vpath, -1); path_element = vfs_path_get_by_index (vpath, -1);
subclass = ((struct vfs_s_subclass *) path_element->class->data);
if (subclass == NULL)
return NULL;
vfs_get_by_vpath_data.path_element = path_element;
vfs_get_by_vpath_data.vpath_archive = vfs_path_clone (vpath);
vfs_path_remove_element_by_index (vfs_get_by_vpath_data.vpath_archive, -1);
{
gboolean is_search_called = TRUE;
if (subclass->archive_check != NULL)
{
vfs_get_by_vpath_data.cookie =
subclass->archive_check (vfs_get_by_vpath_data.vpath_archive);
if (vfs_get_by_vpath_data.cookie == NULL)
is_search_called = FALSE;
}
else
vfs_get_by_vpath_data.cookie = NULL;
if (is_search_called)
super =
vfs_get_super_by_cb_conditions (path_element->class, vfs_cb_archive_same,
(void *) &vfs_get_by_vpath_data);
}
vfs_path_free (vfs_get_by_vpath_data.vpath_archive);
super = vfs_get_sb_by_vpath (vpath);
if (super != NULL) if (super != NULL)
goto return_success; goto return_success;
@ -1121,7 +1127,6 @@ vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new)
super = vfs_s_new_super (path_element->class); super = vfs_s_new_super (path_element->class);
subclass = ((struct vfs_s_subclass *) path_element->class->data);
if (subclass->open_archive != NULL) if (subclass->open_archive != NULL)
{ {
vfs_path_t *vpath_archive; vfs_path_t *vpath_archive;
@ -1152,6 +1157,40 @@ vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
/**
* Get superblock by callback function.
*
* @param me class for search superblocks
* @param cb_conditions callback function for getting needed superblock
* @param cb_data some data for callback
*
* @return if found, archive pointer to object for store superblock; NULL otherwise
*/
struct vfs_s_super *
vfs_get_super_by_cb_conditions (struct vfs_class *me, cb_conditions_t * cb_conditions,
void *cb_data)
{
GList *iter;
struct vfs_s_subclass *subclass;
subclass = ((struct vfs_s_subclass *) me->data);
if (subclass == NULL)
return NULL;
for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter))
{
struct vfs_s_super *super;
super = (struct vfs_s_super *) iter->data;
if (cb_conditions (me, cb_data, super))
return super;
}
return NULL;
}
/* --------------------------------------------------------------------------------------------- */
void void
vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super) vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super)
{ {

View File

@ -153,6 +153,9 @@ struct vfs_s_subclass
/* *INDENT-ON* */ /* *INDENT-ON* */
}; };
typedef gboolean (cb_conditions_t) (struct vfs_class * me, void *cb_data,
struct vfs_s_super * super);
/*** global variables defined in .c file *********************************************************/ /*** global variables defined in .c file *********************************************************/
/*** declarations of public functions ************************************************************/ /*** declarations of public functions ************************************************************/
@ -178,6 +181,9 @@ struct vfs_s_inode *vfs_s_find_root (struct vfs_class *me, struct vfs_s_entry *e
/* outside interface */ /* outside interface */
void vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub); void vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub);
struct vfs_s_super *vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new); struct vfs_s_super *vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new);
struct vfs_s_super *vfs_get_super_by_cb_conditions (struct vfs_class *me,
cb_conditions_t * cb_conditions, void *cd_data);
void vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super); void vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super);
char *vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino); char *vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino);