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_out.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) 2013, WIDE Project and NICT                                                              *
     6* Copyright (c) 2013, 2014, WIDE Project and NICT                                                        *
    67* All rights reserved.                                                                                   *
    78*                                                                                                        *
     
    218219}
    219220
     221static int redir_exist_for_type(int rule_type)
     222{
     223        int ret;
     224
     225        switch(rule_type) {
     226        case ALL_SESSION:
     227        case ALL_USER:
     228                ret = redirect_hash_table[rule_type] != NULL;
     229                break;
     230        default:
     231                ret = !FD_IS_LIST_EMPTY(&redirects_usages[rule_type].sentinel);
     232                break;
     233        }
     234        return ret;
     235}
     236
     237static int match_message(int rule_type, struct msg *msg, union matchdata *data, struct fd_list * candidates)
     238{
     239        struct fd_list * li;
     240        struct redir_entry * e = NULL;
     241        int ret = 0;
     242
     243        switch(rule_type) {
     244        case ALL_SESSION:
     245                HASH_FIND(hh, redirect_hash_table[rule_type], data->session.s, data->session.l, e);
     246                if (e) {
     247                        /* This message matches a rule, apply */
     248                        CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break );
     249                }
     250                break;
     251        case ALL_USER:
     252                HASH_FIND(hh, redirect_hash_table[rule_type], data->user.s, data->user.l, e);
     253                if (e) {
     254                        /* This message matches a rule, apply */
     255                        CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break );
     256                }
     257                break;
     258        default:
     259                /* Attempt each rule we have stored */
     260                for (li = redirects_usages[rule_type].sentinel.next; li != &redirects_usages[rule_type].sentinel; li = li->next) {
     261                        e = li->o;
     262
     263                        /* Does it match ? */
     264                        if (rule_type != ALL_HOST) { /* this one is an exception, we handle it separately */
     265                                int cmp = redir_entry_cmp_key[rule_type](data, &e->data);
     266                                if (cmp > 0)
     267                                        continue;
     268                                if (cmp < 0)
     269                                        break;
     270                        }
     271
     272                        /* This rule matches (or we are in ALL_HOST), apply */
     273                        CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break );
     274
     275                        /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */
     276                        if (rule_type == DONT_CACHE) {
     277                                li = li->prev;
     278                                fd_list_unlink( li->next );
     279                                /* We cannot delete here without taking the mutex, which would mean we have first to release the lock...
     280                                   just let expiry garbage collect the rule */
     281                        }
     282                }
     283        }
     284
     285        return ret;
     286}
    220287
    221288/* OUT callback */
     
    235302                }
    236303
    237                 if (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) {
     304                if (redir_exist_for_type(i)) {
    238305                        union matchdata data;
    239306                        int nodata; /* The message does not allow to apply this rule, skip */
     
    242309                        CHECK_FCT_DO( ret = get_data_to_match(i, msg, &data, &nodata), goto out );
    243310
    244                         /* If this message may match some of our rules */
    245                         if (!nodata) {
    246                                 struct fd_list * li;
    247                                 /* Attempt each rule we have stored */
    248                                 for (li = redirects_usages[i].sentinel.next; li != &redirects_usages[i].sentinel; li = li->next) {
    249                                         struct redir_entry * e = li->o;
    250 
    251                                         /* Does it match ? */
    252                                         if (i != ALL_HOST) { /* this one is an exception, we handle it separately */
    253                                                 int cmp = redir_entry_cmp_key[i](&data, &e->data);
    254                                                 if (cmp > 0)
    255                                                         continue;
    256                                                 if (cmp < 0)
    257                                                         break;
    258                                         }
    259 
    260                                         /* This rule matches (or we are in ALL_HOST), apply */
    261                                         CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), goto out );
    262 
    263                                         /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */
    264                                         if (i == DONT_CACHE) {
    265                                                 li=li->prev;
    266                                                 fd_list_unlink( li->next );
    267                                                 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock...
    268                                                         just let expiry garbage collet the rule */
    269                                         }
    270                                 }
    271                         }
    272 
     311                        /* If data found for this type of rule, then try matching it */
     312                        if (!nodata)
     313                                ret = match_message(i, msg, &data, candidates);
    273314                }
    274315out:
Note: See TracChangeset for help on using the changeset viewer.