Summary:ASTERISK-12339: CDR does not get written
Reporter:Private Name (falves11)Labels:
Date Opened:2008-07-08 08:59:26Date Closed:2008-08-11 14:59:14
Versions:Frequency of
Description:I upgraded to the current version, 128951, last night, and realized that the CDR does not get written to the database unless I use "resetCDR(w)" in the "h" extension, which constitutes a profound change from the past behavior. For example, I have this dialplan:

exten =>_X.,n,NoCDR()
exten =>_X.,n,GotoIf($[${Z} = 0]?default,rejected,1)
exten =>_X.,n,Set(CALLERID(all)=${NANI})
exten =>_X.,n,Set(TIMEOUT(absolute)=3600)
exten =>_X.,n,Set(i=1)
exten =>_X.,n,ForkCDR()
exten =>_X.,n,While($[${i} <= ${Z}])
exten =>_X.,n,Set(CDR(userfield)=${CLIST}${CUT(PLIST,-,${i})})
exten =>_X.,n,Set(CDR(accountcode)=${SIPIP:1})
exten =>_X.,n,Dial(${CUT(CARRIERLIST,-,${i})},45,L(3600000)) ;dial once
;exten =>_X.,n,Verbose(0,"${DIALSTATUS} Result: ${SIPIP:1}")
exten =>_X.,n,ResetCDR(w)
exten =>_X.,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?default,dropcall,1)
exten =>_X.,n,GotoIf($["${DIALSTATUS}" = "NOANSWER"]?default,dropcall,1)
exten =>_X.,n,Set(i=$[${i} + 1])
exten =>_X.,n,EndWhile
exten =>_X.,n,Hangup(34)
exten => h,1,ResetCDR(w) ;THIS IS REQUIRED TO GET CDR IN TRUNK 128951
exten => dropcall,1,Hangup()
exten => rejected,1,Verbose(0,"Rejected:" ${destino}-From: ${SIPIP:1})
exten => rejected,2,Hangup(34)


Please notice that the line
exten => h,1,ResetCDR(w) ;THIS IS REQUIRED TO GET CDR IN TRUNK 128951

is the only way to get cdr when the call drops normally. This is a radical departure from past versions, and I think it is a bug. The changes to the CDR technology are flawed. The CDR should be written automatocally without need for resetCDR(w)

My machine is open for inspection. I don't know how to submit traces.
Comments:By: Private Name (falves11) 2008-07-08 09:09:11

In past version, the NoCDR() command gets cancelled by the ForkCDR(), and that is good, but in the current version, the CDR gets forked, but when the call finishes it does not get written.
I do this
NoCDR() (once)
..if the call fails -> ResetCDR(w) and Dial another carrier
but now when the call drops, I have to do another ResetCDR(w)
otherwise I lose the CDR for a valid call with billsec > 0

By: Steve Murphy (murf) 2008-08-01 10:11:31

Trunk inherited many things from 1.4, and 1.4 from 1.2, etc.

Since the beginning, NoCDR() was written to strip the CDR from a channel.
When it finished, you had a null CDR ptr on the channel.

ForkCDR, in the first few lines of its code, gets the CDR ptr from the channel, and then traverses the next pointers on the cdr structs. So, if the CDR ptr is null, it's guaranteed to crash.

Why it doesn't crash, is because at several points in the PBX engine, if
the CDR pointer on the channel is null, it allocates a new one.

So, NoCDR() was really a misnomer. It didn't say "Don't give me a CDR at all", it would say "Do a weird reset of the CDR".

The description for the command in (core show application NoCDR) says:
"NoCDR(): This application will tell Asterisk not to maintain a CDR for the current call."
was blatantly false, as the usual result of calling NoCDR(), was that you'd get a CDR output for the call anyway!

What I did in trunk, was to make NoCDR work as advertised. I don't destroy the cdr struct, I just mark it with "AST_CDR_FLAG_DISABLED"-- when it comes time to post, the cdr is skipped and freed instead.

ForkCDR never explicitly reversed the action of a NoCDR. It was never documented to, nor is there any code to do such. What you are seeing is the fact that NoCDR() never really worked before, and now it does, which is messing you up.

So, if ResetCDR(w) is doing the trick for you now, you might want to stick with it! The 'w' will post the existing cdr to the backends, and leave you with a freshly initialized cdr to work with (ideal for forkcdr, I guess).

By: Private Name (falves11) 2008-08-11 05:43:51

CDR ODBC is broken in both Trunk and 1.4. It stops recording CDR after about 1.5 hours. I tried to use cdr_tds, but it needs to record userfield, where I store vital billing info. I wonder if you could patch cdr_tds and of course make it permanent. We need two methods of recording cdr that can be used for business. I cannot submit any traces becuause it just stops working. I think the whole ODBC engine collapses, befcause func_odbc also stops working. It is like the connection-reuse mechanism gets frozen. I can use cdr_tds which does notr suffer from such woes, but I need userfield. My machine is open for inspection, if I don't go out of business first.

By: Steve Murphy (murf) 2008-08-11 14:58:37

It would not be surprising that cdr_odbc would stop functioning after 1.5 hours because of the earlier reported memory leak... If it cannot allocate memory to make the request...

but, this is a different bug, and it would be best to create a new bug and open it against the odbc part of the cdr category...

So, I'll close this one, and hopefully, you will open a new one.