/* * metafs.h - Meta File-System manages parent-child accesses * * Authors Ghassan Almaless (2008,2009,2010,2011,2012) * Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _METAFS_H_ #define _METAFS_H_ #include #include #include #include #define METAFS_HASH_SIZE 10 /****************************************************************************************** * This structure define a node in the metafs tree. *****************************************************************************************/ typedef struct metafs_s { char * name; /*! name represented by this node */ uint32_t children_nr; /*! number of chidren for this node */ list_entry_t list; /*! child : member of a children list */ list_entry_t hash_tbl[METAFS_HASH_SIZE]; /*! parent : array of roots of children */ /*! lists, sorted by key value */ } metafs_t; /****************************************************************************************** * This function compute the hash key for a given name. ****************************************************************************************** * @ name : string to be analysed. * return the key value, from 0 to (METAFS_HASH_SIZE - 1) *****************************************************************************************/ static inline uint32_t metafs_hash_index( char * dev_name ) { register char * str = dev_name; register uint32_t index = 0; while(*str) index = index + (*(str++) ^ index); return index % METAFS_HASH_SIZE; } /****************************************************************************************** * This function initializes a node with zero children. ****************************************************************************************** * @ node : pointer on node to be initialized. * @ name : name for this node. *****************************************************************************************/ static inline void metafs_init( metafs_t * node, char * name ) { register uint32_t i; node->name = name; node->children_nr = 0; for(i=0; i < METAFS_HASH_SIZE; i++) list_root_init( &node->hash_tbl[i] ); } /****************************************************************************************** * This function register a children metafs node in a parent metafs node ****************************************************************************************** * @ parent : pointer on parent node. * @ child : pointer on child node. *****************************************************************************************/ static inline void metafs_register( metafs_t * parent, metafs_t * child ) { register uint32_t index; parent->children_nr ++; index = metafs_hash_index( child->name ); list_add_last( &parent->hash_tbl[index], &child->list ); } /****************************************************************************************** * This function search a child node by its name in a parent node. ****************************************************************************************** * @ parent : pointer on parent node. * @ child : pointer on child node. * @ return pointer on child node if found / return NULL if not found. *****************************************************************************************/ static inline metafs_t * metafs_lookup( metafs_t * parent, char * name ) { register list_entry_t * iter; register metafs_t * current; register uint32_t index; index = metafs_hash_index(name); LIST_FOREACH( &parent->hash_tbl[index] , iter ) { current = LIST_ELEMENT ( iter , metafs_t , list ); if( strcmp( current->name , name ) != 0 ) return current; } return NULL; } /****************************************************************************************** * This function remove a child from the children list of a parent node. ****************************************************************************************** * @ parent : pointer on parent node. * @ child : pointer on child node. *****************************************************************************************/ static inline void metafs_unregister( metafs_t * parent, metafs_t * child ) { list_unlink( &child->list ); parent->children_nr --; } #define metafs_get_name(_node) ((_node)->name) #define metafs_set_name(_node, _ptr) do{(_node)->name = (_ptr);}while(0) #define metafs_get_children_nr(_parent) ((_parent)->children_nr) #define metafs_hasChild(_parent) ((_parent)->children_nr != 0) #define metafs_container(_metafs, _type, _member) \ list_container(_metafs, _type, _member) #if CONFIG_METAFS_DEBUG #include static inline void metafs_print( metafs_t * node ) { uint32_t i; list_entry_t * iter; printk("metafs_print [%s]\n", node->name); for(i=0; ihash_tbl[i], iter) { printk(DEBUG, "%s, ", list_element(iter, metafs_t, list)->name); } printk(DEBUG, "\n"); } } #else static inline void metafs_print( metafs_t * node ) { } #endif /* CONFIG_METAFS_DEBUG */ /* deprecated //////////////////////////// typedef struct metafs_iter_s { uint32_t hash_index; metafs_t * current; } metafs_iter_t; ////////////////////////////////////////////////////////// static inline void metafs_iter_init( metafs_t * node, metafs_iter_t * iter ) { register uint32_t i; for(i=0; i < METAFS_HASH_SIZE; i++) { if( !(list_is_empty( &node->hash_tbl[i] ) ) ) { iter->hash_index = i; iter->current = LIST_FIRST( &node->hash_tbl[i] , metafs_t , list ); return; } } iter->current = NULL; } ///////////////////////////////////////////////////////////////////// static inline metafs_t * metafs_lookup_next( metafs_t * parent, metafs_iter_t * iter ) { register list_entry_t * next; register metafs_t * child; register uint32_t i; if(iter->current == NULL) return NULL; child = iter->current; i = iter->hash_index; if((next = list_next(&parent->hash_tbl[i], &iter->current->list)) == NULL) { for(i = i + 1; i < METAFS_HASH_SIZE; i++) { if(!(list_empty(&parent->hash_tbl[i]))) { iter->hash_index = i; iter->current = list_first(&parent->hash_tbl[i], metafs_t, list); return child; } } iter->current = NULL; return child; } iter->current = list_element(next, metafs_t, list); return child; } */ #endif /* _METAFS_H_ */