2006-07-24 15:19:05 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application Call Detail Recorder module
* Copyright 2006 , Author : Yossi Neiman of Cartis Solutions , Inc . < freeswitch AT cartissolutions . com >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application Call Detail Recorder module
*
* The Initial Developer of the Original Code is
* Yossi Neiman < freeswitch AT cartissolutions . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Yossi Neiman < freeswitch AT cartissolutions . com >
*
* Description : This C + + source file describes the CDRContainer singleton object used by mod_cdr to control
* the creation , processing , and destruction of various CDR logger objects .
*
* cdrcontainer . cpp
*
*/
# include "cdrcontainer.h"
# include "baseregistry.h"
CDRContainer : : CDRContainer ( )
{
}
CDRContainer : : CDRContainer ( switch_memory_pool_t * module_pool )
{
// Create the APR threadsafe queue, though I don't know if this is the current memory pool.
switch_queue_create ( & cdrqueue , 5224288 , module_pool ) ;
2006-12-07 04:15:38 +00:00
queue_paused = 0 ;
strcpy ( configfile , " mod_cdr.conf " ) ;
2006-07-24 15:19:05 +00:00
switch_mod_cdr_newchannel_t * newchannel ; // = new switch_mod_cdr_newchannel_t;
newchannel = 0 ;
if ( ! ( xml = switch_xml_open_cfg ( configfile , & cfg , NULL ) ) )
switch_console_printf ( SWITCH_CHANNEL_LOG , " open of %s failed \n " , configfile ) ;
else
{
BaseRegistry & registry ( BaseRegistry : : get ( ) ) ;
for ( BaseRegistry : : iterator it = registry . begin ( ) ; it ! = registry . end ( ) ; + + it )
{
basecdr_creator func = * it ;
BaseCDR * _ptr = func ( newchannel ) ;
std : : auto_ptr < BaseCDR > ptr ( _ptr ) ;
ptr - > connect ( cfg , xml , settings , param ) ;
if ( ptr - > is_activated ( ) )
registry . add_active ( it ) ;
}
}
switch_xml_free ( xml ) ;
}
CDRContainer : : ~ CDRContainer ( )
{
if ( switch_queue_size ( cdrqueue ) > 0 )
process_records ( ) ;
switch_mod_cdr_newchannel_t * newchannel ; //= new switch_mod_cdr_newchannel_t;
newchannel = 0 ;
BaseRegistry & registry ( BaseRegistry : : get ( ) ) ;
for ( BaseRegistry : : iterator it = registry . active_begin ( ) ; it ! = registry . active_end ( ) ; + + it )
{
basecdr_creator func = * it ;
BaseCDR * _ptr = func ( newchannel ) ;
std : : auto_ptr < BaseCDR > ptr ( _ptr ) ;
ptr - > disconnect ( ) ;
}
switch_console_printf ( SWITCH_CHANNEL_LOG , " mod_cdr shutdown gracefully. " ) ;
}
2006-12-07 04:15:38 +00:00
# ifdef SWITCH_QUEUE_ENHANCED
void CDRContainer : : reload ( switch_stream_handle_t * stream )
{
// The queue can't be paused otherwise it will never be able to reload safely.
if ( queue_paused )
{
stream - > write_function ( stream , " The queue is currently paused, resuming it. \n " ) ;
queue_resume ( stream ) ;
}
// Something tells me I still need to figure out what to do if there are items still in queue after reload that are no longer active in the configuration.
switch_queue_isempty ( cdrqueue ) ; // Waits for the queue to be empty
switch_mod_cdr_newchannel_t * newchannel ; // = new switch_mod_cdr_newchannel_t;
newchannel = 0 ;
const char * err ;
switch_xml_t xml_root ;
if ( ( xml_root = switch_xml_open_root ( 1 , & err ) ) ) {
switch_console_printf ( SWITCH_CHANNEL_LOG , " Reloading the XML file... \n " ) ;
switch_xml_free ( xml_root ) ;
}
if ( ! ( xml = switch_xml_open_cfg ( configfile , & cfg , NULL ) ) )
switch_console_printf ( SWITCH_CHANNEL_LOG , " open of %s failed \n " , configfile ) ;
else
{
BaseRegistry & registry ( BaseRegistry : : get ( ) ) ;
for ( BaseRegistry : : iterator it = registry . active_begin ( ) ; it ! = registry . active_end ( ) ; + + it )
{
basecdr_creator func = * it ;
BaseCDR * _ptr = func ( newchannel ) ;
std : : auto_ptr < BaseCDR > ptr ( _ptr ) ;
ptr - > disconnect ( ) ;
}
registry . reset_active ( ) ;
for ( BaseRegistry : : iterator it = registry . begin ( ) ; it ! = registry . end ( ) ; + + it )
{
basecdr_creator func = * it ;
BaseCDR * _ptr = func ( newchannel ) ;
std : : auto_ptr < BaseCDR > ptr ( _ptr ) ;
ptr - > connect ( cfg , xml , settings , param ) ;
if ( ptr - > is_activated ( ) )
registry . add_active ( it ) ;
}
}
switch_xml_free ( xml ) ;
switch_queue_unblockpop ( cdrqueue ) ;
switch_console_printf ( SWITCH_CHANNEL_LOG , " mod_cdr configuration reloaded. " ) ;
}
void CDRContainer : : queue_pause ( switch_stream_handle_t * stream )
{
if ( queue_paused )
stream - > write_function ( stream , " Queue is already paused. \n " ) ;
else
{
queue_paused = 1 ;
switch_queue_blockpop ( cdrqueue ) ;
stream - > write_function ( stream , " CDR queue is now paused. Beware that this can waste resources the longer you keep it paused. \n " ) ;
}
}
void CDRContainer : : queue_resume ( switch_stream_handle_t * stream )
{
if ( ! queue_paused )
stream - > write_function ( stream , " Queue is currently running, no need to resume it. \n " ) ;
else
{
queue_paused = 0 ;
switch_queue_unblockpop ( cdrqueue ) ;
stream - > write_function ( stream , " CDR queue has now resumed processing CDR records. \n " ) ;
}
}
# endif
void CDRContainer : : active ( switch_stream_handle_t * stream )
{
switch_mod_cdr_newchannel_t * newchannel ; // = new switch_mod_cdr_newchannel_t;
newchannel = 0 ;
stream - > write_function ( stream , " The following mod_cdr logging backends are currently marked as active: \n " ) ;
BaseRegistry & registry ( BaseRegistry : : get ( ) ) ;
for ( BaseRegistry : : iterator it = registry . active_begin ( ) ; it ! = registry . active_end ( ) ; + + it )
{
basecdr_creator func = * it ;
BaseCDR * _ptr = func ( newchannel ) ;
std : : auto_ptr < BaseCDR > ptr ( _ptr ) ;
stream - > write_function ( stream , " %s \n " , ptr - > get_display_name ( ) . c_str ( ) ) ;
}
}
void CDRContainer : : available ( switch_stream_handle_t * stream )
{
switch_mod_cdr_newchannel_t * newchannel ; // = new switch_mod_cdr_newchannel_t;
newchannel = 0 ;
stream - > write_function ( stream , " The following mod_cdr logging backends are currently avaible for use (providing you configure them): \n " ) ;
BaseRegistry & registry ( BaseRegistry : : get ( ) ) ;
for ( BaseRegistry : : iterator it = registry . begin ( ) ; it ! = registry . end ( ) ; + + it )
{
basecdr_creator func = * it ;
BaseCDR * _ptr = func ( newchannel ) ;
std : : auto_ptr < BaseCDR > ptr ( _ptr ) ;
stream - > write_function ( stream , " %s \n " , ptr - > get_display_name ( ) . c_str ( ) ) ;
}
}
2006-07-24 15:19:05 +00:00
void CDRContainer : : add_cdr ( switch_core_session_t * session )
{
switch_mod_cdr_newchannel_t * newchannel = new switch_mod_cdr_newchannel_t ;
memset ( newchannel , 0 , sizeof ( * newchannel ) ) ;
newchannel - > channel = switch_core_session_get_channel ( session ) ;
assert ( newchannel - > channel ! = 0 ) ;
newchannel - > session = session ;
newchannel - > callerextension = switch_channel_get_caller_extension ( newchannel - > channel ) ;
newchannel - > callerprofile = switch_channel_get_caller_profile ( newchannel - > channel ) ;
2006-12-07 04:15:38 +00:00
while ( newchannel - > callerprofile )
2006-07-24 15:19:05 +00:00
{
2006-12-07 04:15:38 +00:00
BaseRegistry & registry ( BaseRegistry : : get ( ) ) ;
for ( BaseRegistry : : iterator it = registry . active_begin ( ) ; it ! = registry . active_end ( ) ; + + it )
2006-07-24 15:19:05 +00:00
{
2006-12-07 04:15:38 +00:00
basecdr_creator func = * it ;
2006-07-24 15:19:05 +00:00
BaseCDR * newloggerobject = func ( newchannel ) ;
switch_console_printf ( SWITCH_CHANNEL_LOG , " Adding a new logger object to the queue. \n " ) ;
switch_queue_push ( cdrqueue , newloggerobject ) ;
}
2006-12-07 04:15:38 +00:00
newchannel - > callerprofile = newchannel - > callerprofile - > next ;
if ( newchannel - > callerextension )
2006-07-24 15:19:05 +00:00
newchannel - > callerextension = newchannel - > callerextension - > next ;
}
2006-12-07 04:15:38 +00:00
2006-07-24 15:19:05 +00:00
delete newchannel ;
}
void CDRContainer : : process_records ( )
{
BaseCDR * tempnewloggerobject = 0 , * newloggerobject = 0 ;
while ( switch_queue_pop ( cdrqueue , reinterpret_cast < void * * > ( & tempnewloggerobject ) ) = = SWITCH_STATUS_SUCCESS )
{
newloggerobject = tempnewloggerobject ;
newloggerobject - > process_record ( ) ;
delete newloggerobject ;
}
}
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
2006-12-07 04:15:38 +00:00
* mode : c + +
2007-02-09 02:36:03 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 expandtab :
*/