1 /*
2  * SNMPStats Module
3  * Copyright (C) 2006 SOMA Networks, INC.
4  * Written by: Jeffrey Magder (jmagder@somanetworks.com)
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21  * USA
22  *
23  */
24 
25 /*!
26  * \file
27  * \brief SNMP statistic module, hash table
28  *
29  * This file describes several structure.  In general, it was necessary to map
30  * between Kamailio's "aor" (Address of Record) and string indexing mechanisms,
31  * and the SNMPStats modules integer indexing scheme for users and contacts.
32  * While it would have been a more natural fit to use string indexes in the
33  * SNMPStats module, SNMP limitations precluded this.
34  *
35  * aorToIndexStruct: maps an aor to:
36  *  - a userIndex, to uniquely identify each RegUserTable SNMP row
37  *  - a contactList, containing all contacts for the user specified by
38  *    userIndex.
39  *
40  * The aorToIndexStruct also contains a numContacts counter. Each time a new
41  * contact is associated with the aor (user), the counter is incremented.  Each
42  * time a contact is dissasociated (due to an expiration), the counter is
43  * decremented.  When the counter reaches zero the structure will be deleted.
44  *
45  *  contactToIndexStruct: maps a contact name to:
46  *   - a contactIndex, used to uniquely identify each ContactTable SNMP row.
47  * \ingroup snmpstats
48  * - Module: \ref snmpstats
49  */
50 
51 
52 #ifndef HASHSLOT_H
53 #define HASHSLOT_H
54 
55 /*!
56  * Used to map between a 'contact' name (Kamailio's index) and a contact index.
57  * (SNMPStats Index)
58  */
59 typedef struct contactToIndexStruct
60 {
61 	char *contactName;
62 
63 	int contactIndex;
64 
65 	struct contactToIndexStruct *next;
66 
67 } contactToIndexStruct_t;
68 
69 
70 /*!
71  * Used to map between an 'aor' (Kamailio index) and a user index. (SNMPStats
72  * index).  Since each user can have multiple contacts, the structure also has a
73  * 'contactIndex', and a reference to the contactToIndexStruct list.
74  */
75 typedef struct aorToIndexStruct
76 {
77 	/* Pointer to the actual address record in the given SNMP row. */
78 	char *aor;
79 	int aorLength;
80 
81 	/* Points to the user index, which is used to uniquely identify each
82 	 * SNMP row in a table. */
83 	int userIndex;
84 
85 	/* Each contact needs a unique index, for each user.  This value should
86 	 * be incremented each time a contact is added.  This way, we can know
87 	 * what index to use for the next addition to the contactList.  */
88 	int contactIndex;
89 
90 	/* Pointer to the contact list. */
91 	contactToIndexStruct_t *contactList;
92 
93 	struct aorToIndexStruct *prev;
94 
95 	/* The structure is part of a hash table, so this element is needed so
96 	 * that we can point to the next element in the colission slot. */
97 	struct aorToIndexStruct *next;
98 
99 	/* This counter will be incremented when a new contact is associated
100 	 * with this user record, and will be decremented each time an
101 	 * associated contact is removed.  When the count reaches 0, it is safe
102 	 * to remove this record. */
103 	int numContacts;
104 
105 } aorToIndexStruct_t;
106 
107 
108 typedef struct hashSlot
109 {
110 	/*! Number of elements in this list. */
111 	int numberOfElements;
112 
113 	/*! First element in the list. */
114 	struct aorToIndexStruct *first;
115 
116 	/*! Last element in the list.  This is here for optimization purposes.
117 	 * It stands to reason that things added later will need to be deleted
118 	 * later.  So they should be added to the end of the list.  This way,
119 	 * things that are to be deleted sooner will be at the front of the
120 	 * list. */
121 	struct aorToIndexStruct *last;
122 
123 } hashSlot_t;
124 
125 /*******************************************************************
126 * More detailed function definitions can be found in hashTable.c   */
127 
128 
129 /*! Returns a aorToIndexStruct_t, holding the given 'userIndex' and 'aor'.  The
130  * structure is used to map between the "aor" (Kamailio's way of indexing
131  * users/contacts), and the SNMPStats user and contact integer indexes.
132  *
133  * \note This record does not make a copy of aor, but instead points
134  * directly to the parameter.  Therefore make sure that aor is not on the stack,
135  * and is not going to disappear before this record is deleted.
136  */
137 aorToIndexStruct_t *createHashRecord(int userIndex, char *aor);
138 
139 
140 /*! Returns a chunk of memory large enough to store 'size' hashSlot's.  The
141  * table will contain mappings between Kamailio's "aor" user/contact indexing
142  * scheme, and SNMPStats integer indexing scheme */
143 hashSlot_t *createHashTable(int size);
144 
145 
146 /*! Calculates and returns a hash index to a hash table.  The index is calculated
147  * by summing up all the characters specified with theString, and using the
148  * hashTableSize as the modulus.  */
149 int calculateHashSlot(char *theString, int hashTableSize);
150 
151 
152 /*! Searches the hash table specified as theTable, of size 'size', for a record
153  * indexed with 'aor'.  If a match is found, then an aorToIndextStruct_t
154  * structure is returned.
155  *
156  * This function is called to discover the map between Kamailio's "aor"
157  * (Address of Records) indexing scheme, and the SNMPStats modules integer
158  * indexing scheme for its contact/user data.
159  *
160  * Returns: the aorToIndexStruct_t mapping structure if a match was found,
161  *          or NULL otherwise.
162  */
163 aorToIndexStruct_t *findHashRecord(hashSlot_t *theTable, char *aor, int size);
164 
165 
166 /*! Inserts theRecord into an appropriate place in theTable, when size is given. */
167 void insertHashRecord(
168 		hashSlot_t *theTable, aorToIndexStruct_t *theRecord, int size);
169 
170 
171 /*! Debugging function.  Prints off an entire hash slot. */
172 void printHashSlot(hashSlot_t *theTable, int index);
173 
174 
175 /*! If a record is found with string aor in theTable, it is deleted and its
176  * SNMPStats user integer index is returned. */
177 int deleteHashRecord(hashSlot_t *theTable, char *aor, int hashTableSize);
178 
179 /*!
180  * This function will search the provided hash table for an entry indexed by
181  * 'aor'.  If an entry is found then:
182  *
183  *   - Its numContacts counter will be decremented.
184  *   - If its numContacts counter reaches zero, then the entry will be removed
185  *     from the hash table.
186  *
187  */
188 void deleteUser(hashSlot_t *theTable, char *aor, int hashTableSize);
189 
190 #endif