Navigation



Ignore:
Timestamp:
Mar 24, 2014, 9:21:41 PM (10 years ago)
Author:
Thomas Klausner <tk@giga.or.at>
Branch:
default
Phase:
public
Message:

Store redirect information for ALL_SESSION and ALL_USER in a hash.

This is a speedup if many of these exist (compared to checking a
linked list for matches as before).

Refactor a bit while here.

Use the uthash code from Troy D. Hanson,
http://troydhanson.github.com/uthash/

File:
1 edited

Legend:

Unmodified
Added
Removed
  • extensions/rt_redirect/redir_entries.c

    r1259 r1260  
    11/*********************************************************************************************************
    22* Software License Agreement (BSD License)                                                               *
    3 * Author: Sebastien Decugis <sdecugis@freediameter.net>                                                  *
     3* Authors: Sebastien Decugis <sdecugis@freediameter.net>                                                 *
     4* and Thomas Klausner <tk@giga.or.at>                                                                    *
    45*                                                                                                        *
    5 * Copyright (c) 2011, WIDE Project and NICT                                                              *
     6* Copyright (c) 2011, 2014, WIDE Project and NICT                                                        *
    67* All rights reserved.                                                                                   *
    78*                                                                                                        *
     
    3536
    3637#include "rt_redir.h"
     38#include "uthash.h"
    3739
    3840/* The array with all entries ordered by their data */
    3941struct redir_line redirects_usages[H_U_MAX + 1];
     42
     43/* for symmetry reasons, hash tables for all types exist, but only ALL_SESSION and ALL_USER will be used */
     44struct redir_entry *redirect_hash_table[H_U_MAX+1];
    4045
    4146/* Initialize the array */
     
    5055
    5156        for (i = 0; i <= H_U_MAX; i++) {
     57                /* only one of the two will be used for each type, but initialize both to be on the safe side */
     58
     59                /* initialize list */
    5260                CHECK_POSIX( pthread_rwlock_init( &redirects_usages[i].lock, NULL) );
    5361                fd_list_init( &redirects_usages[i].sentinel, &redirects_usages[i] );
     62
     63                /* initialize hash table */
     64                redirect_hash_table[i] = NULL;
    5465        }
    5566
     
    6677}
    6778
     79int redir_entry_fini()
     80{
     81        int i;
     82        struct redir_entry *current_entry, *tmp;
     83
     84        /* Empty all entries */
     85        CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock),   );
     86        for (i = 0; i <= H_U_MAX; i++) {
     87                CHECK_POSIX_DO( pthread_rwlock_wrlock( &redirects_usages[i].lock), );
     88                switch(i) {
     89                case ALL_SESSION:
     90                case ALL_USER:
     91                        HASH_ITER(hh, redirect_hash_table[i], current_entry, tmp) {
     92                                HASH_DEL(redirect_hash_table[i], current_entry);
     93                                CHECK_FCT_DO( redir_entry_destroy(current_entry), );
     94                        }
     95                        break;
     96                default:
     97                        while (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) {
     98                                struct redir_entry * e = redirects_usages[i].sentinel.next->o;
     99                                fd_list_unlink(&e->redir_list);
     100                                CHECK_FCT_DO( redir_entry_destroy(e), );
     101                        }
     102                }
     103                CHECK_POSIX_DO( pthread_rwlock_unlock( &redirects_usages[i].lock), );
     104                CHECK_POSIX_DO( pthread_rwlock_destroy( &redirects_usages[i].lock), );
     105        }
     106        CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock),   );
     107
     108        return 0;
     109}
    68110
    69111/* Create a new redir_entry and add the correct data */
     
    91133
    92134        entry->type = rhu;
     135        /* list entry for putting into redirects_usage; also doubles as pointer into that list so it can be removed easily */
    93136        fd_list_init(&entry->redir_list, entry);
    94137        /* finally initialize the data */
     
    238281{
    239282        struct fd_list * li;
     283        struct redir_entry * r = NULL;
    240284
    241285        TRACE_ENTRY("%p", e);
     
    245289        CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
    246290
    247         for (li = redirects_usages[e->type].sentinel.next; li != &redirects_usages[e->type].sentinel; li = li->next) {
    248                 struct redir_entry * n = li->o;
    249                 int cmp = redir_entry_cmp_key[e->type](&e->data, &n->data);
    250                 if (cmp <= 0)
    251                         break;
    252         }
    253 
    254         fd_list_insert_before(li, &e->redir_list);
     291        switch (e->type) {
     292        case ALL_SESSION:
     293                HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, r);
     294                if (r) {
     295                        /* previously existing entry, delete it from hash and free it */
     296                        HASH_DELETE(hh, redirect_hash_table[e->type], r);
     297                        CHECK_FCT_DO( redir_entry_destroy(r), );
     298                }
     299                HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, e);
     300                break;
     301        case ALL_USER:
     302                HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, r);
     303                if (r) {
     304                        /* previously existing entry, delete it from hash and free it */
     305                        HASH_DELETE(hh, redirect_hash_table[e->type], r);
     306                        CHECK_FCT_DO( redir_entry_destroy(r), );
     307                }
     308                HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, e);
     309                break;
     310        default:
     311                for (li = redirects_usages[e->type].sentinel.next; li != &redirects_usages[e->type].sentinel; li = li->next) {
     312                        struct redir_entry * n = li->o;
     313                        int cmp = redir_entry_cmp_key[e->type](&e->data, &n->data);
     314                        if (cmp <= 0)
     315                                break;
     316                }
     317
     318                fd_list_insert_before(li, &e->redir_list);
     319                break;
     320        }
    255321
    256322        /* unLock the line */
     
    263329int redir_entry_destroy(struct redir_entry * e)
    264330{
     331        struct redir_entry *match;
    265332        TRACE_ENTRY("%p", e);
    266333        CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC));
    267334
    268         /* If the entry is linked, lock the rwlock also */
    269         if (!FD_IS_LIST_EMPTY(&e->redir_list)) {
    270                 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
    271                 fd_list_unlink(&e->redir_list);
    272                 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
     335        switch (e->type) {
     336        case ALL_SESSION:
     337                /* If the entry is in the hash table, lock the rwlock also */
     338                HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, match);
     339                if (match) {
     340                        /* TODO: check if e == match? */
     341                        CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
     342                        HASH_DELETE(hh, redirect_hash_table[e->type], match);
     343                        CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
     344                }
     345                break;
     346        case ALL_USER:
     347                /* If the entry is in the hash table, lock the rwlock also */
     348                HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, match);
     349                if (match) {
     350                        /* TODO: check if e == match? */
     351                        CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
     352                        HASH_DELETE(hh, redirect_hash_table[e->type], match);
     353                        CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
     354                }
     355                break;
     356        default:
     357                /* If the entry is linked, lock the rwlock also */
     358                if (!FD_IS_LIST_EMPTY(&e->redir_list)) {
     359                        CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
     360                        fd_list_unlink(&e->redir_list);
     361                        CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
     362                }
     363                break;
    273364        }
    274365
Note: See TracChangeset for help on using the changeset viewer.