From e00d9e8daa1129a9430304b43689781fd86949eb Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 18 Nov 2011 00:09:52 +0000 Subject: [PATCH] reduce memory usage of voip_tiered, RT#14903 --- FS/FS/cdr.pm | 47 ++++++++++----- FS/FS/cdr_termination.pm | 4 +- FS/FS/part_pkg/voip_tiered.pm | 130 +++++++++++++++++++++++++----------------- FS/FS/svc_phone.pm | 31 +++++----- 4 files changed, 129 insertions(+), 83 deletions(-) diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm index 850f797bc..1507dde95 100644 --- a/FS/FS/cdr.pm +++ b/FS/FS/cdr.pm @@ -130,9 +130,9 @@ following fields are currently supported: =item svcnum - Link to customer service (see L) -=item freesidestatus - NULL, done (or something) +=item freesidestatus - NULL, processing-tiered, done -=item freesiderewritestatus - NULL, done (or something) +=item freesiderewritestatus - NULL, done, skipped =item cdrbatch @@ -404,10 +404,7 @@ sub set_status_and_rated_price { if ($opt{'inbound'}) { - my $term = qsearchs('cdr_termination', { - acctid => $self->acctid, - termpart => 1 # inbound - }); + my $term = $self->cdr_termination( 1 ); #1: inbound my $error; if ( $term ) { warn "replacing existing cdr status (".$self->acctid.")\n" if $term; @@ -419,10 +416,10 @@ sub set_status_and_rated_price { termpart => 1, rated_price => $rated_price, status => $status, - svcnum => $svcnum, }); $term->rated_seconds($opt{rated_seconds}) if exists($opt{rated_seconds}); $term->rated_minutes($opt{rated_minutes}) if exists($opt{rated_minutes}); + $term->svcnum($svcnum) if $svcnum; return $term->insert; } else { @@ -437,6 +434,29 @@ sub set_status_and_rated_price { } } +=item cdr_termination [ TERMPART ] + +=cut + +sub cdr_termination { + my $self = shift; + + if ( scalar(@_) && $_[0] ) { + my $termpart = shift; + + qsearchs('cdr_termination', { acctid => $self->acctid, + termpart => $termpart, + } + ); + + } else { + + qsearch('cdr_termination', { acctid => $self->acctid, } ); + + } + +} + =item calldate_unix Parses the calldate in SQL string format and returns a UNIX timestamp. @@ -753,14 +773,13 @@ sub clear_status { return $error; } - my @cdr_termination = qsearch('cdr_termination', - { 'acctid' => $self->acctid } ); - foreach my $cdr_termination ( @cdr_termination ) { - $cdr_termination->status(''); - $error = $cdr_termination->replace; + foreach my $cdr_termination ( $self->cdr_termination ) { + #$cdr_termination->status(''); + #$error = $cdr_termination->replace; + $error = $cdr_termination->delete; if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; + $dbh->rollback if $oldAutoCommit; + return $error; } } diff --git a/FS/FS/cdr_termination.pm b/FS/FS/cdr_termination.pm index 5e3080511..0209f0d0c 100644 --- a/FS/FS/cdr_termination.pm +++ b/FS/FS/cdr_termination.pm @@ -119,8 +119,8 @@ sub check { || $self->ut_foreign_key('acctid', 'cdr', 'acctid') #|| $self->ut_foreign_key('termpart', 'part_termination', 'termpart') || $self->ut_number('termpart') - || $self->ut_float('rated_price') - || $self->ut_enum('status', [ '', 'done' ] ) # , 'skipped' ] ) + || $self->ut_floatn('rated_price') + || $self->ut_enum('status', [ '', 'processing-tiered', 'done' ] ) # , 'skipped' ] ) ; return $error if $error; diff --git a/FS/FS/part_pkg/voip_tiered.pm b/FS/FS/part_pkg/voip_tiered.pm index 29e60d499..1ed2450c2 100644 --- a/FS/FS/part_pkg/voip_tiered.pm +++ b/FS/FS/part_pkg/voip_tiered.pm @@ -107,7 +107,6 @@ sub calc_usage { # pass one: find the total minutes/calls and store the CDRs ### my $total = 0; - my @cdrs = (); my @cust_svc; if( $self->option('bill_inactive_svcs',1) ) { @@ -161,11 +160,16 @@ sub calc_usage { $included_min = 0; } - $cdr->tmp_inout( $pass ); - $cdr->tmp_rated_seconds( $seconds ); - $cdr->tmp_rated_minutes( $charge_min ); - $cdr->tmp_svcnum( $cust_svc->svcnum ); - push @cdrs, $cdr; + my $error = $cdr->set_status_and_rated_price( + 'processing-tiered', + '', #charge, + $cust_svc->svcnum, + 'inbound' => ($pass eq 'inbound'), + 'rated_minutes' => $charge_min, + 'rated_seconds' => $seconds, + ); + die $error if $error; + $total += $charge_min; } # $cdr @@ -191,55 +195,79 @@ sub calc_usage { my $charges = 0; my @invoice_details_sort; - foreach my $cdr (@cdrs) { - - my $charge_min = $cdr->tmp_rated_minutes; - - my $charge = sprintf('%.4f', ( $min_charge * $charge_min ) - + 0.0000000001 ); #so 1.00005 rounds to 1.0001 - - - if ( $charge > 0 ) { - $charges += $charge; - - my $detail = - $cdr->downstream_csv( 'format' => $output_format, - 'charge' => $charge, - 'seconds' => ($use_duration ? - $cdr->duration : - $cdr->billsec), - 'granularity' => $granularity, - ); - - my $call_details = - { format => 'C', - detail => $detail, - amount => $charge, - #classnum => $cdr->calltypenum, #classnum - #phonenum => $phonenum, #XXX need this to sort on them - accountcode => $cdr->accountcode, - startdate => $cdr->startdate, - duration => $cdr->tmp_rated_seconds, - }; - - #warn " adding details on charge to invoice: [ ". - # join(', ', @{$call_details} ). " ]" - # if ( $DEBUG && ref($call_details) ); - push @invoice_details_sort, [ $call_details, $cdr->calldate_unix ]; + $options{'status'} = 'processing-tiered'; + + foreach my $cust_svc (@cust_svc) { + + my $svc_x; + if( $self->option('bill_inactive_svcs',1) ) { + $svc_x = $cust_svc->h_svc_x($$sdate, $last_bill); + } + else { + $svc_x = $cust_svc->svc_x; } - my $error = $cdr->set_status_and_rated_price( - 'done', - $charge, - $cdr->tmp_svcnum, - 'inbound' => ($cdr->tmp_inout eq 'inbound'), - 'rated_minutes' => $charge_min, - 'rated_seconds' => $cdr->tmp_rated_seconds, - ); - die $error if $error; + foreach my $pass (split('_', $cdr_inout)) { + $options{'inbound'} = ( $pass eq 'inbound' ); - } + foreach my $cdr ( + $svc_x->get_cdrs( %options ) + ) { + + my $object = $options{'inbound'} + ? $cdr->cdr_termination( 1 ) #1: inbound + : $cdr; + + my $charge_min = $object->rated_minutes; + + my $charge = sprintf('%.4f', ( $min_charge * $charge_min ) + + 0.0000000001 ); #so 1.00005 rounds to 1.0001 + + if ( $charge > 0 ) { + $charges += $charge; + + my $detail = + $cdr->downstream_csv( 'format' => $output_format, + 'charge' => $charge, + 'seconds' => ($use_duration ? + $cdr->duration : + $cdr->billsec), + 'granularity' => $granularity, + ); + + my $call_details = + { format => 'C', + detail => $detail, + amount => $charge, + #classnum => $cdr->calltypenum, #classnum + #phonenum => $phonenum, #XXX need this to sort on them + accountcode => $cdr->accountcode, + startdate => $cdr->startdate, + duration => $object->rated_seconds, + }; + + #warn " adding details on charge to invoice: [ ". + # join(', ', @{$call_details} ). " ]" + # if ( $DEBUG && ref($call_details) ); + push @invoice_details_sort, [ $call_details, $cdr->calldate_unix ]; + } + + my $error = $cdr->set_status_and_rated_price( + 'done', + $charge, + $cust_svc->svcnum, + 'inbound' => $options{'inbound'}, + 'rated_minutes' => $charge_min, + 'rated_seconds' => $object->rated_seconds, + ); + die $error if $error; + + } # $cdr + + } # $pass + + } # $cust_svc my @sorted_invoice_details = sort { ${$a}[1] <=> ${$b}[1] } @invoice_details_sort; foreach my $sorted_call_detail ( @sorted_invoice_details ) { diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm index 494539150..e3d18e092 100644 --- a/FS/FS/svc_phone.pm +++ b/FS/FS/svc_phone.pm @@ -650,7 +650,7 @@ Accepts the following options: =item for_update => 1: SELECT the CDRs "FOR UPDATE". -=item status => "" (or "done"): Return only CDRs with that processing status. +=item status => "" (or "processing-tiered", "done"): Return only CDRs with that processing status. =item inbound => 1: Return CDRs for inbound calls. With "status", will filter on inbound processing status. @@ -673,25 +673,24 @@ sub get_cdrs { my @where; if ( $options{'inbound'} ) { + @fields = ( 'dst' ); if ( exists($options{'status'}) ) { - # must be 'done' or '' - my $sq = 'EXISTS ( SELECT 1 FROM cdr_termination '. - 'WHERE cdr.acctid = cdr_termination.acctid '. - 'AND cdr_termination.status = \'done\' '. - 'AND cdr_termination.termpart = 1 )'; - if ( $options{'status'} eq 'done' ) { - push @where, $sq; - } - elsif ($options{'status'} eq '' ) { - push @where, "NOT $sq"; - } - else { - warn "invalid status: $options{'status'} (ignored)\n"; + my $status = $options{'status'}; + if ( $status ) { + push @where, 'EXISTS ( SELECT 1 FROM cdr_termination '. + 'WHERE cdr.acctid = cdr_termination.acctid '. + "AND cdr_termination.status = '$status' ". #quoting kludge + 'AND cdr_termination.termpart = 1 )'; + } else { + push @where, 'NOT EXISTS ( SELECT 1 FROM cdr_termination '. + 'WHERE cdr.acctid = cdr_termination.acctid '. + 'AND cdr_termination.termpart = 1 )'; } } - } - else { + + } else { + @fields = ( 'charged_party' ); push @fields, 'src' if !$options{'disable_src'}; $hash{'freesidestatus'} = $options{'status'} -- 2.11.0