Ver código fonte

htable: Add event route when htable entries expire

- event_route[htable:expired:<table>] called when an entry expires
- pseudo-vars $shtrecord(key) and $shtrecord(value) access the expired content
James Wyatt 11 anos atrás
pai
commit
61af5c6b35

+ 205 - 94
modules/htable/README

@@ -30,58 +30,59 @@ Ovidiu Sas
 
 
    1. Admin Guide
    1. Admin Guide
 
 
-        1.1. Overview
-        1.2. Dependencies
-
-              1.2.1. Kamailio Modules
-              1.2.2. External Libraries or Applications
-              1.2.3. Loading from database
-
-        1.3. Parameters
-
-              1.3.1. htable (str)
-              1.3.2. db_url (str)
-              1.3.3. key_name_column (str)
-              1.3.4. key_type_column (str)
-              1.3.5. value_type_column (str)
-              1.3.6. key_value_column (str)
-              1.3.7. expires_column (str)
-              1.3.8. array_size_suffix (str)
-              1.3.9. fetch_rows (integer)
-              1.3.10. timer_interval (integer)
-              1.3.11. timer_mode (integer)
-              1.3.12. db_expires (integer)
-              1.3.13. enable_dmq (integer)
-
-        1.4. Functions
-
-              1.4.1. sht_print()
-              1.4.2. sht_rm_name_re(htable=>regexp)
-              1.4.3. sht_rm_value_re(htable=>regexp)
-              1.4.4. sht_lock(htable=>key)
-              1.4.5. sht_unlock(htable=>key)
-
-        1.5. Exported pseudo-variables
-        1.6. MI Commands
-
-              1.6.1. sht_reload
-              1.6.2. sht_dump
-              1.6.3. sht_delete
-
-        1.7. Exported RPC Commands
-
-              1.7.1. htable.get htable key
-              1.7.2. htable.delete htable key
-              1.7.3. htable.sets htable key value
-              1.7.4. htable.seti htable key value
-              1.7.5. htable.dump htable
-              1.7.6. htable.reload htable
-              1.7.7. htable.listTables
-              1.7.8. htable.stats
-
-        1.8. Event routes
-
-              1.8.1. htable:mod-init
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+              2.3. Loading from database
+
+        3. Parameters
+
+              3.1. htable (str)
+              3.2. db_url (str)
+              3.3. key_name_column (str)
+              3.4. key_type_column (str)
+              3.5. value_type_column (str)
+              3.6. key_value_column (str)
+              3.7. expires_column (str)
+              3.8. array_size_suffix (str)
+              3.9. fetch_rows (integer)
+              3.10. timer_interval (integer)
+              3.11. timer_mode (integer)
+              3.12. db_expires (integer)
+              3.13. enable_dmq (integer)
+
+        4. Functions
+
+              4.1. sht_print()
+              4.2. sht_rm_name_re(htable=>regexp)
+              4.3. sht_rm_value_re(htable=>regexp)
+              4.4. sht_lock(htable=>key)
+              4.5. sht_unlock(htable=>key)
+
+        5. Exported pseudo-variables
+        6. MI Commands
+
+              6.1. sht_reload
+              6.2. sht_dump
+              6.3. sht_delete
+
+        7. Exported RPC Commands
+
+              7.1. htable.get htable key
+              7.2. htable.delete htable key
+              7.3. htable.sets htable key value
+              7.4. htable.seti htable key value
+              7.5. htable.dump htable
+              7.6. htable.reload htable
+              7.7. htable.listTables
+              7.8. htable.stats
+
+        8. Event routes
+
+              8.1. htable:mod-init
+              8.2. htable:expired:<table>
 
 
    List of Examples
    List of Examples
 
 
@@ -109,7 +110,63 @@ Ovidiu Sas
 
 
 Chapter 1. Admin Guide
 Chapter 1. Admin Guide
 
 
-1.1. Overview
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+        2.3. Loading from database
+
+   3. Parameters
+
+        3.1. htable (str)
+        3.2. db_url (str)
+        3.3. key_name_column (str)
+        3.4. key_type_column (str)
+        3.5. value_type_column (str)
+        3.6. key_value_column (str)
+        3.7. expires_column (str)
+        3.8. array_size_suffix (str)
+        3.9. fetch_rows (integer)
+        3.10. timer_interval (integer)
+        3.11. timer_mode (integer)
+        3.12. db_expires (integer)
+        3.13. enable_dmq (integer)
+
+   4. Functions
+
+        4.1. sht_print()
+        4.2. sht_rm_name_re(htable=>regexp)
+        4.3. sht_rm_value_re(htable=>regexp)
+        4.4. sht_lock(htable=>key)
+        4.5. sht_unlock(htable=>key)
+
+   5. Exported pseudo-variables
+   6. MI Commands
+
+        6.1. sht_reload
+        6.2. sht_dump
+        6.3. sht_delete
+
+   7. Exported RPC Commands
+
+        7.1. htable.get htable key
+        7.2. htable.delete htable key
+        7.3. htable.sets htable key value
+        7.4. htable.seti htable key value
+        7.5. htable.dump htable
+        7.6. htable.reload htable
+        7.7. htable.listTables
+        7.8. htable.stats
+
+   8. Event routes
+
+        8.1. htable:mod-init
+        8.2. htable:expired:<table>
+
+1. Overview
 
 
    The module adds a hash table container to configuration language. The
    The module adds a hash table container to configuration language. The
    hash table is stored in shared memory and the access to it can be done
    hash table is stored in shared memory and the access to it can be done
@@ -293,21 +350,25 @@ $ kamcmd htable.dump htable
         }
         }
 }
 }
 
 
-1.2. Dependencies
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+   2.3. Loading from database
 
 
-1.2.1. Kamailio Modules
+2.1. Kamailio Modules
 
 
    The following modules must be loaded before this module:
    The following modules must be loaded before this module:
      * If DMQ replication is enabled, the DMQ module must be loaded
      * If DMQ replication is enabled, the DMQ module must be loaded
        first..
        first..
 
 
-1.2.2. External Libraries or Applications
+2.2. External Libraries or Applications
 
 
    The following libraries or applications must be installed before
    The following libraries or applications must be installed before
    running Kamailio with this module loaded:
    running Kamailio with this module loaded:
      * None.
      * None.
 
 
-1.2.3. Loading from database
+2.3. Loading from database
 
 
    The module is able to load values in hash table at startup upon
    The module is able to load values in hash table at startup upon
    providing a DB URL and table name.
    providing a DB URL and table name.
@@ -326,9 +387,23 @@ $ kamcmd htable.dump htable
           + 1 - value is integer.
           + 1 - value is integer.
      * key value - string containing the value of the key.
      * key value - string containing the value of the key.
 
 
-1.3. Parameters
+3. Parameters
 
 
-1.3.1. htable (str)
+   3.1. htable (str)
+   3.2. db_url (str)
+   3.3. key_name_column (str)
+   3.4. key_type_column (str)
+   3.5. value_type_column (str)
+   3.6. key_value_column (str)
+   3.7. expires_column (str)
+   3.8. array_size_suffix (str)
+   3.9. fetch_rows (integer)
+   3.10. timer_interval (integer)
+   3.11. timer_mode (integer)
+   3.12. db_expires (integer)
+   3.13. enable_dmq (integer)
+
+3.1. htable (str)
 
 
    The definition of a hash table. The value of the parameter must have
    The definition of a hash table. The value of the parameter must have
    the following format:
    the following format:
@@ -374,7 +449,7 @@ modparam("htable", "htable", "c=>size=4;autoexpire=7200;initval=1;dmqreplicate=
 1;")
 1;")
 ...
 ...
 
 
-1.3.2. db_url (str)
+3.2. db_url (str)
 
 
    The URL to connect to database for loading values in hash table at
    The URL to connect to database for loading values in hash table at
    start up.
    start up.
@@ -386,7 +461,7 @@ modparam("htable", "htable", "c=>size=4;autoexpire=7200;initval=1;dmqreplicate=
 modparam("htable", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
 modparam("htable", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
 ...
 ...
 
 
-1.3.3. key_name_column (str)
+3.3. key_name_column (str)
 
 
    The name of the column containing hash table key name.
    The name of the column containing hash table key name.
 
 
@@ -397,7 +472,7 @@ modparam("htable", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
 modparam("htable", "key_name_column", "kname")
 modparam("htable", "key_name_column", "kname")
 ...
 ...
 
 
-1.3.4. key_type_column (str)
+3.4. key_type_column (str)
 
 
    The name of the column containing hash table key type.
    The name of the column containing hash table key type.
 
 
@@ -408,7 +483,7 @@ modparam("htable", "key_name_column", "kname")
 modparam("htable", "key_type_column", "ktype")
 modparam("htable", "key_type_column", "ktype")
 ...
 ...
 
 
-1.3.5. value_type_column (str)
+3.5. value_type_column (str)
 
 
    The name of the column containing hash table value type.
    The name of the column containing hash table value type.
 
 
@@ -419,7 +494,7 @@ modparam("htable", "key_type_column", "ktype")
 modparam("htable", "value_type_column", "vtype")
 modparam("htable", "value_type_column", "vtype")
 ...
 ...
 
 
-1.3.6. key_value_column (str)
+3.6. key_value_column (str)
 
 
    The name of the column containing hash table key value.
    The name of the column containing hash table key value.
 
 
@@ -430,7 +505,7 @@ modparam("htable", "value_type_column", "vtype")
 modparam("htable", "key_value_column", "kvalue")
 modparam("htable", "key_value_column", "kvalue")
 ...
 ...
 
 
-1.3.7. expires_column (str)
+3.7. expires_column (str)
 
 
    The name of the column containing expires type.
    The name of the column containing expires type.
 
 
@@ -441,7 +516,7 @@ modparam("htable", "key_value_column", "kvalue")
 modparam("htable", "expires", "expiry")
 modparam("htable", "expires", "expiry")
 ...
 ...
 
 
-1.3.8. array_size_suffix (str)
+3.8. array_size_suffix (str)
 
 
    The suffix to be added to store the number of items in an array (see
    The suffix to be added to store the number of items in an array (see
    key type).
    key type).
@@ -453,7 +528,7 @@ modparam("htable", "expires", "expiry")
 modparam("htable", "array_size_suffix", "-count")
 modparam("htable", "array_size_suffix", "-count")
 ...
 ...
 
 
-1.3.9. fetch_rows (integer)
+3.9. fetch_rows (integer)
 
 
    How many rows to fetch at once from database.
    How many rows to fetch at once from database.
 
 
@@ -464,7 +539,7 @@ modparam("htable", "array_size_suffix", "-count")
 modparam("htable", "fetch_rows", 1000)
 modparam("htable", "fetch_rows", 1000)
 ...
 ...
 
 
-1.3.10. timer_interval (integer)
+3.10. timer_interval (integer)
 
 
    Interval in seconds to check for expired htable values.
    Interval in seconds to check for expired htable values.
 
 
@@ -475,7 +550,7 @@ modparam("htable", "fetch_rows", 1000)
 modparam("htable", "timer_interval", 10)
 modparam("htable", "timer_interval", 10)
 ...
 ...
 
 
-1.3.11. timer_mode (integer)
+3.11. timer_mode (integer)
 
 
    If set to 1, will start a new timer process. If set to 0 will use
    If set to 1, will start a new timer process. If set to 0 will use
    default timer process to check for expired htable values.
    default timer process to check for expired htable values.
@@ -487,7 +562,7 @@ modparam("htable", "timer_interval", 10)
 modparam("htable", "timer_mode", 1)
 modparam("htable", "timer_mode", 1)
 ...
 ...
 
 
-1.3.12. db_expires (integer)
+3.12. db_expires (integer)
 
 
    If set to 1, will load/save the expires values of the items in hash
    If set to 1, will load/save the expires values of the items in hash
    table fromm/to database. It applies only to hash tables that have
    table fromm/to database. It applies only to hash tables that have
@@ -500,11 +575,11 @@ modparam("htable", "timer_mode", 1)
 modparam("htable", "db_expires", 1)
 modparam("htable", "db_expires", 1)
 ...
 ...
 
 
-1.3.13. enable_dmq (integer)
+3.13. enable_dmq (integer)
 
 
    If set to 1, will enable DMQ replication of actions performed upon
    If set to 1, will enable DMQ replication of actions performed upon
    entries in all tables having "dmqreplicate" parameter set. Any update
    entries in all tables having "dmqreplicate" parameter set. Any update
-   action performed via psuedo-variables, MI and RPC commands will be
+   action performed via pseudo-variables, MI and RPC commands will be
    repeated on all other nodes. Therefore, it is important to ensure the
    repeated on all other nodes. Therefore, it is important to ensure the
    table definition (size, autoexpire etc.) is identical across all
    table definition (size, autoexpire etc.) is identical across all
    instances.
    instances.
@@ -520,9 +595,15 @@ modparam("htable", "db_expires", 1)
 modparam("htable", "enable_dmq", 1)
 modparam("htable", "enable_dmq", 1)
 ...
 ...
 
 
-1.4. Functions
+4. Functions
+
+   4.1. sht_print()
+   4.2. sht_rm_name_re(htable=>regexp)
+   4.3. sht_rm_value_re(htable=>regexp)
+   4.4. sht_lock(htable=>key)
+   4.5. sht_unlock(htable=>key)
 
 
-1.4.1.  sht_print()
+4.1.  sht_print()
 
 
    Dump content of hash table to L_ERR log level. Intended for debug
    Dump content of hash table to L_ERR log level. Intended for debug
    purposes.
    purposes.
@@ -535,7 +616,7 @@ modparam("htable", "enable_dmq", 1)
 sht_print();
 sht_print();
 ...
 ...
 
 
-1.4.2.  sht_rm_name_re(htable=>regexp)
+4.2.  sht_rm_name_re(htable=>regexp)
 
 
    Delete all entries in the htable that match the name against regular
    Delete all entries in the htable that match the name against regular
    expression.
    expression.
@@ -548,7 +629,7 @@ sht_print();
 sht_rm_name_re("ha=>.*");
 sht_rm_name_re("ha=>.*");
 ...
 ...
 
 
-1.4.3.  sht_rm_value_re(htable=>regexp)
+4.3.  sht_rm_value_re(htable=>regexp)
 
 
    Delete all entries in the htable that match the value against regular
    Delete all entries in the htable that match the value against regular
    expression.
    expression.
@@ -561,7 +642,7 @@ sht_rm_name_re("ha=>.*");
 sht_rm_value_re("ha=>.*");
 sht_rm_value_re("ha=>.*");
 ...
 ...
 
 
-1.4.4.  sht_lock(htable=>key)
+4.4.  sht_lock(htable=>key)
 
 
    Lock the slot in htable corespoding to the key item.
    Lock the slot in htable corespoding to the key item.
 
 
@@ -572,7 +653,7 @@ sht_rm_value_re("ha=>.*");
 sht_lock("ha=>test");
 sht_lock("ha=>test");
 ...
 ...
 
 
-1.4.5.  sht_unlock(htable=>key)
+4.5.  sht_unlock(htable=>key)
 
 
    Unlock the slot in htable corespoding to the key item.
    Unlock the slot in htable corespoding to the key item.
 
 
@@ -585,7 +666,7 @@ $sht(ha=>test) = $sht(ha=>test) + 10;
 sht_unlock("ha=>test");
 sht_unlock("ha=>test");
 ...
 ...
 
 
-1.5. Exported pseudo-variables
+5. Exported pseudo-variables
 
 
      * $sht(htable=>key)
      * $sht(htable=>key)
      * $shtex(htable=>key)
      * $shtex(htable=>key)
@@ -593,13 +674,18 @@ sht_unlock("ha=>test");
      * $shtcv(htable=>key)
      * $shtcv(htable=>key)
      * $shtinc(htable=>key)
      * $shtinc(htable=>key)
      * $shtval(htable=>key)
      * $shtval(htable=>key)
+     * $shtrecord(attribute)
 
 
    Exported pseudo-variables are documented at
    Exported pseudo-variables are documented at
    http://www.kamailio.org/wiki/.
    http://www.kamailio.org/wiki/.
 
 
-1.6. MI Commands
+6. MI Commands
 
 
-1.6.1.  sht_reload
+   6.1. sht_reload
+   6.2. sht_dump
+   6.3. sht_delete
+
+6.1.  sht_reload
 
 
    Reload a hash table from database.
    Reload a hash table from database.
 
 
@@ -612,7 +698,7 @@ sht_unlock("ha=>test");
                 _hash_table_name_
                 _hash_table_name_
                 _empty_line_
                 _empty_line_
 
 
-1.6.2.  sht_dump
+6.2.  sht_dump
 
 
    Dump content of a hash table via MI.
    Dump content of a hash table via MI.
 
 
@@ -625,7 +711,7 @@ sht_unlock("ha=>test");
                 _hash_table_name_
                 _hash_table_name_
                 _empty_line_
                 _empty_line_
 
 
-1.6.3.  sht_delete
+6.3.  sht_delete
 
 
    Delete a key from a hash table via MI.
    Delete a key from a hash table via MI.
 
 
@@ -644,9 +730,18 @@ sht_unlock("ha=>test");
    Example (note the quoting when executing it via FIFO):
    Example (note the quoting when executing it via FIFO):
                 kamctl fifo sht_delete auth '"[email protected]::last_auth"'
                 kamctl fifo sht_delete auth '"[email protected]::last_auth"'
 
 
-1.7. Exported RPC Commands
+7. Exported RPC Commands
+
+   7.1. htable.get htable key
+   7.2. htable.delete htable key
+   7.3. htable.sets htable key value
+   7.4. htable.seti htable key value
+   7.5. htable.dump htable
+   7.6. htable.reload htable
+   7.7. htable.listTables
+   7.8. htable.stats
 
 
-1.7.1.  htable.get htable key
+7.1.  htable.get htable key
 
 
    Lists one value in a hash table
    Lists one value in a hash table
 
 
@@ -665,7 +760,7 @@ kamcmd htable.get students daniel
 kamcmd htable.get students course[0]
 kamcmd htable.get students course[0]
 ...
 ...
 
 
-1.7.2.  htable.delete htable key
+7.2.  htable.delete htable key
 
 
    Delete one value in a hash table
    Delete one value in a hash table
 
 
@@ -684,7 +779,7 @@ kamcmd htable.delete students anna
 kamcmd htable.delete students course[0]
 kamcmd htable.delete students course[0]
 ...
 ...
 
 
-1.7.3.  htable.sets htable key value
+7.3.  htable.sets htable key value
 
 
    Set an item in hash table to string value.
    Set an item in hash table to string value.
 
 
@@ -704,7 +799,7 @@ kamcmd htable.sets test x abc
 kamcmd htable.sets test x[0] abc
 kamcmd htable.sets test x[0] abc
 ...
 ...
 
 
-1.7.4.  htable.seti htable key value
+7.4.  htable.seti htable key value
 
 
    Set an item in hash table to integer value.
    Set an item in hash table to integer value.
 
 
@@ -724,7 +819,7 @@ kamcmd htable.seti test x 123
 kamcmd htable.sets test x[0] 123
 kamcmd htable.sets test x[0] 123
 ...
 ...
 
 
-1.7.5.  htable.dump htable
+7.5.  htable.dump htable
 
 
    Lists all the values in a hash table
    Lists all the values in a hash table
 
 
@@ -738,7 +833,7 @@ kamcmd htable.sets test x[0] 123
 kamcmd htable.dump ipban
 kamcmd htable.dump ipban
 ...
 ...
 
 
-1.7.6.  htable.reload htable
+7.6.  htable.reload htable
 
 
    Reload hash table from database.
    Reload hash table from database.
 
 
@@ -752,7 +847,7 @@ kamcmd htable.dump ipban
 kamcmd htable.reload ipban
 kamcmd htable.reload ipban
 ...
 ...
 
 
-1.7.7.  htable.listTables
+7.7.  htable.listTables
 
 
    Lists all defined tables
    Lists all defined tables
 
 
@@ -766,7 +861,7 @@ kamcmd htable.reload ipban
 kamcmd htable.listTables
 kamcmd htable.listTables
 ...
 ...
 
 
-1.7.8.  htable.stats
+7.8.  htable.stats
 
 
    Get statistics for hash tables - name, number of slots, number of
    Get statistics for hash tables - name, number of slots, number of
    items, max number of items per slot, min number of items per slot.
    items, max number of items per slot, min number of items per slot.
@@ -781,9 +876,12 @@ kamcmd htable.listTables
 kamcmd htable.stats
 kamcmd htable.stats
 ...
 ...
 
 
-1.8. Event routes
+8. Event routes
+
+   8.1. htable:mod-init
+   8.2. htable:expired:<table>
 
 
-1.8.1.  htable:mod-init
+8.1.  htable:mod-init
 
 
    When defined, the module calls event_route[htable:mod-init] after all
    When defined, the module calls event_route[htable:mod-init] after all
    modules have been initialized. A typical use case is to initialise
    modules have been initialized. A typical use case is to initialise
@@ -795,3 +893,16 @@ event_route[htable:mod-init] {
     $sht(a=>x) = 1;
     $sht(a=>x) = 1;
 }
 }
 ...
 ...
+
+8.2.  htable:expired:<table>
+
+   When defined, the module calls event_route[htable:expired:<table>] when
+   an entry in the given table expires. In this event route, the key and
+   value of the expired record are available with the $shtrecord(key) and
+   $shtrecord(value) pseudo-variables.
+...
+
+event_route[htable:expired:mytable] {
+    xlog("mytable record expired $shtrecord(key) => $shtrecord(value)\n");
+}
+...

+ 28 - 6
modules/htable/doc/htable_admin.xml

@@ -622,7 +622,7 @@ modparam("htable", "db_expires", 1)
 		<para>
 		<para>
 			If set to 1, will enable DMQ replication of actions performed upon 
 			If set to 1, will enable DMQ replication of actions performed upon 
 			entries in all tables having "dmqreplicate" parameter set. Any update 
 			entries in all tables having "dmqreplicate" parameter set. Any update 
-			action performed via psuedo-variables, MI and RPC commands will be 
+			action performed via pseudo-variables, MI and RPC commands will be 
 			repeated on all other nodes. Therefore, it is important to ensure the
 			repeated on all other nodes. Therefore, it is important to ensure the
 			table definition (size, autoexpire etc.) is identical across all instances.
 			table definition (size, autoexpire etc.) is identical across all instances.
 		</para>
 		</para>
@@ -772,6 +772,9 @@ sht_unlock("ha=>test");
 			<listitem><para>
 			<listitem><para>
 				<emphasis>$shtval(htable=>key)</emphasis>
 				<emphasis>$shtval(htable=>key)</emphasis>
 			</para></listitem>
 			</para></listitem>
+			<listitem><para>
+				<emphasis>$shtrecord(attribute)</emphasis>
+			</para></listitem>
 		</itemizedlist>
 		</itemizedlist>
 		<para>
 		<para>
 		Exported pseudo-variables are documented at &kamwikilink;.
 		Exported pseudo-variables are documented at &kamwikilink;.
@@ -1103,15 +1106,34 @@ kamcmd htable.stats
 			once, after core and module initialization, but before &kamailio; forks any
 			once, after core and module initialization, but before &kamailio; forks any
 			child processes.
 			child processes.
 		</para>
 		</para>
-        <programlisting  format="linespecific">
-...			
+<programlisting  format="linespecific">
+...
 event_route[htable:mod-init] {
 event_route[htable:mod-init] {
     $sht(a=>x) = 1;
     $sht(a=>x) = 1;
 }
 }
 ...
 ...
-		</programlisting>
-    </section>
-    </section>
+</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">htable:expired:&lt;table&gt;</function>
+		</title>
+		<para>
+			When defined, the module calls event_route[htable:expired:&lt;table&gt;]
+			when an entry in the given table expires. In this event route, the key and value
+			of the expired record are available with the $shtrecord(key) and $shtrecord(value)
+			pseudo-variables.
+		</para>
+<programlisting  format="linespecific">
+...
+
+event_route[htable:expired:mytable] {
+    xlog("mytable record expired $shtrecord(key) => $shtrecord(value)\n");
+}
+...
+</programlisting>
+	</section>
+	</section>
 
 
 </chapter>
 </chapter>
 
 

+ 63 - 0
modules/htable/ht_api.c

@@ -31,12 +31,16 @@
 #include "../../hashes.h"
 #include "../../hashes.h"
 #include "../../ut.h"
 #include "../../ut.h"
 #include "../../re.h"
 #include "../../re.h"
+#include "../../lib/kcore/faked_msg.h"
+#include "../../action.h"
+#include "../../route.h"
 
 
 #include "ht_api.h"
 #include "ht_api.h"
 #include "ht_db.h"
 #include "ht_db.h"
 
 
 
 
 ht_t *_ht_root = NULL;
 ht_t *_ht_root = NULL;
+ht_cell_t *ht_expired_cell;
 
 
 typedef struct _keyvalue {
 typedef struct _keyvalue {
 	str key;
 	str key;
@@ -565,6 +569,8 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 			/* found */
 			/* found */
 			if(now>0 && it->expire!=0 && it->expire<now) {
 			if(now>0 && it->expire!=0 && it->expire<now) {
 				/* entry has expired */
 				/* entry has expired */
+				ht_handle_expired_record(ht, it);
+
 				if(ht->flags==PV_VAL_INT) {
 				if(ht->flags==PV_VAL_INT) {
 					/* initval is integer, use it to create a fresh entry */
 					/* initval is integer, use it to create a fresh entry */
 					it->flags &= ~AVP_VAL_STR;
 					it->flags &= ~AVP_VAL_STR;
@@ -688,6 +694,8 @@ ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
 			/* found */
 			/* found */
 			if(ht->htexpire>0 && it->expire!=0 && it->expire<time(NULL)) {
 			if(ht->htexpire>0 && it->expire!=0 && it->expire<time(NULL)) {
 				/* entry has expired, delete it and return NULL */
 				/* entry has expired, delete it and return NULL */
+				ht_handle_expired_record(ht, it);
+
 				if(it->prev==NULL)
 				if(it->prev==NULL)
 					ht->entries[idx].first = it->next;
 					ht->entries[idx].first = it->next;
 				else
 				else
@@ -924,6 +932,7 @@ void ht_timer(unsigned int ticks, void *param)
 					if(it->expire!=0 && it->expire<now)
 					if(it->expire!=0 && it->expire<now)
 					{
 					{
 						/* expired */
 						/* expired */
+						ht_handle_expired_record(ht, it);
 						if(it->prev==NULL)
 						if(it->prev==NULL)
 							ht->entries[i].first = it->next;
 							ht->entries[i].first = it->next;
 						else
 						else
@@ -943,6 +952,60 @@ void ht_timer(unsigned int ticks, void *param)
 	return;
 	return;
 }
 }
 
 
+void ht_handle_expired_record(ht_t *ht, ht_cell_t *cell)
+{
+	ht_expired_cell = cell;
+
+	char route_name[64] = "htable:expired:";
+
+	if (ht->name.len + strlen(route_name) > 64)
+	{
+		LM_ERR("ht_expired_record route name too long");
+		return;
+	}
+
+	strncat(route_name, ht->name.s, ht->name.len);
+	ht_expired_run_event_route(route_name);
+
+	ht_expired_cell = NULL;
+}
+
+void ht_expired_run_event_route(char *route)
+{
+	int rt, backup_rt;
+	sip_msg_t *fmsg;
+
+	if (route == NULL)
+	{
+		LM_ERR("bad route\n");
+	}
+
+	LM_DBG("ht_expired_run_event_route event_route[%s]\n", route);
+
+	rt = route_get(&event_rt, route);
+
+	if (rt < 0 || event_rt.rlist[rt] == NULL)
+	{
+		LM_DBG("route does not exist");
+		return;
+	}
+
+	if (faked_msg_init() < 0)
+	{
+		LM_ERR("faked_msg_init() failed\n");
+		return;
+	}
+	fmsg = faked_msg_next();
+	fmsg->parsed_orig_ruri_ok = 0;
+
+	backup_rt = get_route_type();
+
+	set_route_type(EVENT_ROUTE);
+	run_top_route(event_rt.rlist[rt], fmsg, 0);
+
+	set_route_type(backup_rt);
+}
+
 int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
 int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
 {
 {
 	unsigned int idx;
 	unsigned int idx;

+ 2 - 0
modules/htable/ht_api.h

@@ -94,6 +94,8 @@ int ht_db_sync_tables(void);
 
 
 int ht_has_autoexpire(void);
 int ht_has_autoexpire(void);
 void ht_timer(unsigned int ticks, void *param);
 void ht_timer(unsigned int ticks, void *param);
+void ht_handle_expired_record(ht_t *ht, ht_cell_t *cell);
+void ht_expired_run_event_route(char *route);
 int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val);
 int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val);
 int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val);
 int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val);
 
 

+ 51 - 0
modules/htable/ht_var.c

@@ -26,6 +26,7 @@
 
 
 /* pkg copy */
 /* pkg copy */
 ht_cell_t *_htc_local=NULL;
 ht_cell_t *_htc_local=NULL;
+ht_cell_t *ht_expired_cell;
 
 
 int pv_get_ht_cell(struct sip_msg *msg,  pv_param_t *param,
 int pv_get_ht_cell(struct sip_msg *msg,  pv_param_t *param,
 		pv_value_t *res)
 		pv_value_t *res)
@@ -359,3 +360,53 @@ int pv_get_ht_dec(struct sip_msg *msg,  pv_param_t *param,
 {
 {
 	return pv_get_ht_add(msg, param, res, -1);
 	return pv_get_ht_add(msg, param, res, -1);
 }
 }
+
+int pv_parse_ht_expired_cell(pv_spec_t *sp, str *in)
+{
+	if ((in->len != 3 || strncmp(in->s, "key", in->len) != 0) &&
+	    (in->len != 5 || strncmp(in->s, "value", in->len) != 0))
+	{
+		return -1;
+	}
+
+	sp->pvp.pvn.u.isname.name.s.s = in->s;
+	sp->pvp.pvn.u.isname.name.s.len = in->len;
+	sp->pvp.pvn.u.isname.type = 0;
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
+
+	return 0;
+}
+
+int pv_get_ht_expired_cell(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res)
+{
+	if (res == NULL || ht_expired_cell == NULL)
+	{
+		return -1;
+	}
+
+	if (param->pvn.u.isname.name.s.len == 3 &&
+		strncmp(param->pvn.u.isname.name.s.s, "key", 3) == 0)
+	{
+		res->rs = ht_expired_cell->name;
+	}
+	else if (param->pvn.u.isname.name.s.len == 5 &&
+		strncmp(param->pvn.u.isname.name.s.s, "value", 5) == 0)
+	{
+		if(ht_expired_cell->flags&AVP_VAL_STR) {
+			res->rs = ht_expired_cell->value.s;
+			res->flags = PV_VAL_STR;
+		} else {
+			res->ri = ht_expired_cell->value.n;
+			res->flags = PV_VAL_INT|PV_TYPE_INT;
+		}
+		return 0;
+	}
+
+	if (res->rs.s == NULL)
+		res->flags = PV_VAL_NULL;
+	else
+		res->flags = PV_VAL_STR;
+
+	return 0;
+}

+ 3 - 0
modules/htable/ht_var.h

@@ -43,4 +43,7 @@ int pv_get_ht_inc(struct sip_msg *msg,  pv_param_t *param,
 int pv_get_ht_dec(struct sip_msg *msg,  pv_param_t *param,
 int pv_get_ht_dec(struct sip_msg *msg,  pv_param_t *param,
 		pv_value_t *res);
 		pv_value_t *res);
 
 
+int pv_parse_ht_expired_cell(pv_spec_t *sp, str *in);
+int pv_get_ht_expired_cell(struct sip_msg *msg, pv_param_t *param,
+		pv_value_t *res);
 #endif
 #endif

+ 3 - 0
modules/htable/htable.c

@@ -52,6 +52,7 @@ MODULE_VERSION
 int  ht_timer_interval = 20;
 int  ht_timer_interval = 20;
 int  ht_db_expires_flag = 0;
 int  ht_db_expires_flag = 0;
 int  ht_enable_dmq = 0;
 int  ht_enable_dmq = 0;
+extern ht_cell_t *ht_expired_cell;
 
 
 static int htable_init_rpc(void);
 static int htable_init_rpc(void);
 
 
@@ -87,6 +88,8 @@ static pv_export_t mod_pvs[] = {
 		pv_parse_ht_name, 0, 0, 0 },
 		pv_parse_ht_name, 0, 0, 0 },
 	{ {"shtdec", sizeof("shtdec")-1}, PVT_OTHER, pv_get_ht_dec, 0,
 	{ {"shtdec", sizeof("shtdec")-1}, PVT_OTHER, pv_get_ht_dec, 0,
 		pv_parse_ht_name, 0, 0, 0 },
 		pv_parse_ht_name, 0, 0, 0 },
+	{ {"shtrecord", sizeof("shtrecord")-1}, PVT_OTHER, pv_get_ht_expired_cell, 0,
+		pv_parse_ht_expired_cell, 0, 0, 0 },
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
 };
 };