Changeset 0ca7286 in mainline for uspace/srv/fs/cdfs/cdfs_ops.c


Ignore:
Timestamp:
2012-07-21T11:19:27Z (12 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2732c94
Parents:
1c1da4b
Message:

Added resizing to user space (single-threaded) hash_table. Resizes in a way to mitigate effects of bad hash functions. Change of interface affected many files.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/cdfs/cdfs_ops.c

    r1c1da4b r0ca7286  
    6363#define NODE_CACHE_SIZE  200
    6464
    65 #define NODES_BUCKETS  256
    66 
    6765#define NODES_KEY_SRVC   0
    6866#define NODES_KEY_INDEX  1
     
    226224static hash_table_t nodes;
    227225
    228 static hash_index_t nodes_hash(unsigned long key[])
    229 {
    230         return key[NODES_KEY_INDEX] % NODES_BUCKETS;
    231 }
    232 
    233 static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
    234 {
    235         cdfs_node_t *node =
    236             hash_table_get_instance(item, cdfs_node_t, nh_link);
    237        
    238         switch (keys) {
    239         case 1:
     226static size_t nodes_key_hash(unsigned long key[])
     227{
     228        return key[NODES_KEY_INDEX];
     229}
     230
     231static size_t nodes_hash(const link_t *item)
     232{
     233        cdfs_node_t *node = hash_table_get_instance(item, cdfs_node_t, nh_link);
     234       
     235        unsigned long key[] = {
     236                [NODES_KEY_INDEX] = node->index
     237        };
     238       
     239        return nodes_key_hash(key);
     240}
     241
     242static bool nodes_match(unsigned long key[], size_t keys, const link_t *item)
     243{
     244        cdfs_node_t *node = hash_table_get_instance(item, cdfs_node_t, nh_link);
     245       
     246        if (keys == 1) {
    240247                return (node->service_id == key[NODES_KEY_SRVC]);
    241         case 2:
     248        } else {
     249                assert(keys == 2);
    242250                return ((node->service_id == key[NODES_KEY_SRVC]) &&
    243251                    (node->index == key[NODES_KEY_INDEX]));
    244         default:
    245                 assert((keys == 1) || (keys == 2));
    246         }
    247        
    248         return 0;
     252        }
     253}
     254
     255static bool nodes_equal(const link_t *item1, const link_t *item2)
     256{
     257        cdfs_node_t *node1 = hash_table_get_instance(item1, cdfs_node_t, nh_link);
     258        cdfs_node_t *node2 = hash_table_get_instance(item2, cdfs_node_t, nh_link);
     259       
     260        return node1->service_id == node2->service_id
     261                && node1->index == node2->index;
    249262}
    250263
    251264static void nodes_remove_callback(link_t *item)
    252265{
    253         cdfs_node_t *node =
    254             hash_table_get_instance(item, cdfs_node_t, nh_link);
     266        cdfs_node_t *node = hash_table_get_instance(item, cdfs_node_t, nh_link);
    255267       
    256268        assert(node->type == CDFS_DIRECTORY);
     
    268280
    269281/** Nodes hash table operations */
    270 static hash_table_operations_t nodes_ops = {
     282static hash_table_ops_t nodes_ops = {
    271283        .hash = nodes_hash,
    272         .compare = nodes_compare,
     284        .key_hash = nodes_key_hash,
     285        .match = nodes_match,
     286        .equal = nodes_equal,
    273287        .remove_callback = nodes_remove_callback
    274288};
     
    353367       
    354368        /* Insert the new node into the nodes hash table. */
    355         unsigned long key[] = {
    356                 [NODES_KEY_SRVC] = node->service_id,
    357                 [NODES_KEY_INDEX] = node->index
    358         };
    359        
    360         hash_table_insert(&nodes, key, &node->nh_link);
     369        hash_table_insert(&nodes, &node->nh_link);
    361370       
    362371        *rfn = FS_NODE(node);
     
    912921}
    913922
     923static bool cache_remove_closed(link_t *item, void *arg)
     924{
     925        size_t *premove_cnt = (size_t*)arg;
     926       
     927        /* Some nodes were requested to be removed from the cache. */
     928        if (0 < *premove_cnt) {
     929                cdfs_node_t *node =     hash_table_get_instance(item, cdfs_node_t, nh_link);
     930
     931                if (!node->opened) {
     932                        hash_table_remove_item(&nodes, item);
     933                       
     934                        --nodes_cached;
     935                        --*premove_cnt;
     936                }
     937        }
     938       
     939        /* Only continue if more nodes were requested to be removed. */
     940        return 0 < *premove_cnt;
     941}
     942
    914943static void cleanup_cache(service_id_t service_id)
    915944{
    916945        if (nodes_cached > NODE_CACHE_SIZE) {
    917                 size_t remove = nodes_cached - NODE_CACHE_SIZE;
    918                
    919                 // FIXME: this accesses the internals of the hash table
    920                 //        and should be rewritten in a clean way
    921                
    922                 for (hash_index_t chain = 0; chain < nodes.entries; chain++) {
    923                         for (link_t *link = nodes.entry[chain].head.next;
    924                             link != &nodes.entry[chain].head;
    925                             link = link->next) {
    926                                 if (remove == 0)
    927                                         return;
    928                                
    929                                 cdfs_node_t *node =
    930                                     hash_table_get_instance(link, cdfs_node_t, nh_link);
    931                                 if (node->opened == 0) {
    932                                         link_t *tmp = link;
    933                                         link = link->prev;
    934                                        
    935                                         list_remove(tmp);
    936                                         nodes.op->remove_callback(tmp);
    937                                         nodes_cached--;
    938                                         remove--;
    939                                        
    940                                         continue;
    941                                 }
    942                         }
    943                 }
     946                size_t remove_cnt = nodes_cached - NODE_CACHE_SIZE;
     947               
     948                if (0 < remove_cnt)
     949                        hash_table_apply(&nodes, cache_remove_closed, &remove_cnt);
    944950        }
    945951}
     
    10071013bool cdfs_init(void)
    10081014{
    1009         if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))
     1015        if (!hash_table_create(&nodes, 0, 2, &nodes_ops))
    10101016                return false;
    10111017       
Note: See TracChangeset for help on using the changeset viewer.