diff options
author | Anders Broman <anders.broman@ericsson.com> | 2012-02-04 12:23:51 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2012-02-04 12:23:51 +0000 |
commit | 37dec6fcad2db152601d53b618885e8c5f97dfe0 (patch) | |
tree | 7cc099a812350ba59c72cba0d71f6a36b4fccf03 /epan | |
parent | 5f891470ac4dc871abfdc81807bf7cc66bd54ff4 (diff) |
From Cristian Constantin:
Slow loading/processing of conversations with over 500k frames.
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6755
svn path=/trunk/; revision=40837
Diffstat (limited to 'epan')
-rw-r--r-- | epan/conversation.c | 63 | ||||
-rw-r--r-- | epan/conversation.h | 1 |
2 files changed, 49 insertions, 15 deletions
diff --git a/epan/conversation.c b/epan/conversation.c index d40ee7677d..63579f6a4d 100644 --- a/epan/conversation.c +++ b/epan/conversation.c @@ -509,10 +509,10 @@ conversation_new(const guint32 setup_frame, const address *addr1, const address "A conversation template may not be constructed without wildcard options"); */ GHashTable* hashtable; - conversation_t *conversation; - conversation_t *tc; + conversation_t *conversation=NULL, *prev=NULL; conversation_key existing_key; conversation_key *new_key; + guint conv_in_ht=0; if (options & NO_ADDR2) { if (options & (NO_PORT2|NO_PORT2_FORCE)) { @@ -535,7 +535,8 @@ conversation_new(const guint32 setup_frame, const address *addr1, const address existing_key.port2 = port2; conversation = g_hash_table_lookup(hashtable, &existing_key); - tc = conversation; /* Remember if lookup was successful */ + if(NULL!=conversation) + conv_in_ht=1; new_key = se_alloc(sizeof(struct conversation_key)); new_key->next = conversation_keys; @@ -547,15 +548,37 @@ conversation_new(const guint32 setup_frame, const address *addr1, const address new_key->port2 = port2; if (conversation) { - for (; conversation->next; conversation = conversation->next) - ; - conversation->next = se_alloc(sizeof(conversation_t)); - conversation = conversation->next; + /* the list is ordered on setup_frame */ + if(setup_frame>=conversation->last->setup_frame) { + /* add it to the end */ + conversation->last->next=se_alloc(sizeof(conversation_t)); + prev=conversation->last->next; + prev->next=NULL; + conversation->last=prev; + conversation = prev; + } else { + for (prev=NULL; (setup_frame>conversation->setup_frame) && conversation->next; prev=conversation, conversation = conversation->next) + ; + if(prev) { + prev->next = se_alloc(sizeof(conversation_t)); + prev->next->next = conversation; + conversation = prev->next; + } else { + /* change the head of the list */ + prev = se_alloc(sizeof(conversation_t)); + prev->next = conversation; + prev->last = conversation->last; + conversation->last=NULL; + conversation = prev; + conv_in_ht=0; + } + } } else { conversation = se_alloc(sizeof(conversation_t)); + conversation->next = NULL; + conversation->last = conversation; } - conversation->next = NULL; conversation->index = new_index; conversation->setup_frame = setup_frame; conversation->data_list = NULL; @@ -571,7 +594,7 @@ conversation_new(const guint32 setup_frame, const address *addr1, const address /* only insert a hash table entry if this * is the first conversation with this key */ - if (!tc) + if (!conv_in_ht) g_hash_table_insert(hashtable, new_key, conversation); return conversation; @@ -653,9 +676,10 @@ static conversation_t * conversation_lookup_hashtable(GHashTable *hashtable, const guint32 frame_num, const address *addr1, const address *addr2, const port_type ptype, const guint32 port1, const guint32 port2) { - conversation_t* conversation; - conversation_t* match; + conversation_t* conversation=NULL; + conversation_t* match=NULL; conversation_key key; + guint found=0; /* * We don't make a copy of the address data, we just copy the @@ -668,15 +692,24 @@ conversation_lookup_hashtable(GHashTable *hashtable, const guint32 frame_num, co key.port2 = port2; match = g_hash_table_lookup(hashtable, &key); + + if (match && (match->setup_frame > frame_num)) + match = NULL; if (match) { + if(match->last->setup_frame<=frame_num) + return match; for (conversation = match->next; conversation; conversation = conversation->next) { if ((conversation->setup_frame <= frame_num) - && (conversation->setup_frame > match->setup_frame)) - match = conversation; + && (conversation->setup_frame > match->setup_frame)) { + match = conversation; + found=1; + } else if(conversation->setup_frame>frame_num) + /* we are past the frame_num */ + break; } - if (match->setup_frame > frame_num) - match = NULL; + if(!found) + match=NULL; } return match; diff --git a/epan/conversation.h b/epan/conversation.h index c330ce7fb9..f7a0f38dd3 100644 --- a/epan/conversation.h +++ b/epan/conversation.h @@ -71,6 +71,7 @@ typedef struct conversation_key { typedef struct conversation { struct conversation *next; /** pointer to next conversation on hash chain */ + struct conversation *last; /** pointer to the last conversation on hash chain */ guint32 index; /** unique ID for conversation */ guint32 setup_frame; /** frame number that setup this conversation */ GSList *data_list; /** list of data associated with conversation */ |