Hi.
I searched the source code for you. There is something wrong with your odbc connection. Turn on debugging for odbc and you will see the point, where in source file the function listed below has exited with NULL because obj==NULL. Function ast_debug() will output debugging info and you should be able to determine which condition triggered it based on the text.
if (!(class = ao2_callback(class_container, 0, aoro2_class_cb, (char *) name))) {
ast_debug(1, "Class '%s' not found!\n", name);
return NULL;
}
ast_mutex_lock(&class->lock);
while (!obj) {
obj = AST_LIST_REMOVE_HEAD(&class->connections, list);
if (!obj) {
if (class->connection_cnt < class->maxconnections) {
/* If no connection is immediately available establish a new
* one if allowed. If we try and fail we give up completely as
* we could go into an infinite loop otherwise.
*/
obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
if (!obj) {
break;
}
obj->parent = ao2_bump(class);
if (odbc_obj_connect(obj) == ODBC_FAIL) {
ao2_ref(obj->parent, -1);
ao2_ref(obj, -1);
obj = NULL;
break;
}
class->connection_cnt++;
ast_debug(2, "Created ODBC handle %p on class '%s', new count is %zd\n", obj,
name, class->connection_cnt);
} else {
/* Otherwise if we're not allowed to create a new one we
* wait for another thread to give up the connection they
* own.
*/
ast_cond_wait(&class->cond, &class->lock);
}
} else if (connection_dead(obj, class)) {
/* If the connection is dead try to grab another functional one from the
* pool instead of trying to resurrect this one.
*/
ao2_ref(obj, -1);
obj = NULL;
class->connection_cnt--;
ast_debug(2, "ODBC handle %p dead - removing from class '%s', new count is %zd\n",
obj, name, class->connection_cnt);
} else {
/* We successfully grabbed a connection from the pool and all is well!
*/
obj->parent = ao2_bump(class);
ast_debug(2, "Reusing ODBC handle %p from class '%s'\n", obj, name);
}
}
ast_mutex_unlock(&class->lock);
ao2_ref(class, -1);
return obj;
I don’t find this file where I can found this syntax ?
struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags, const char *file, const char *function, int lineno)
{
struct odbc_obj *obj = NULL;
struct odbc_class *class;
if (!(class = ao2_callback(class_container, 0, aoro2_class_cb, (char *) name))) {
ast_debug(1, "Class '%s' not found!\n", name);
return NULL;
}
ast_mutex_lock(&class->lock);
while (!obj) {
obj = AST_LIST_REMOVE_HEAD(&class->connections, list);
if (!obj) {
if (class->connection_cnt < class->maxconnections) {
/* If no connection is immediately available establish a new
* one if allowed. If we try and fail we give up completely as
* we could go into an infinite loop otherwise.
*/
obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
if (!obj) {
break;
}
obj->parent = ao2_bump(class);
if (odbc_obj_connect(obj) == ODBC_FAIL) {
ao2_ref(obj->parent, -1);
ao2_ref(obj, -1);
obj = NULL;
break;
}
class->connection_cnt++;
ast_debug(2, "Created ODBC handle %p on class '%s', new count is %zd\n", obj,
name, class->connection_cnt);
} else {
/* Otherwise if we're not allowed to create a new one we
* wait for another thread to give up the connection they
* own.
*/
ast_cond_wait(&class->cond, &class->lock);
}
} else if (connection_dead(obj, class)) {
/* If the connection is dead try to grab another functional one from the
* pool instead of trying to resurrect this one.
*/
ao2_ref(obj, -1);
obj = NULL;
class->connection_cnt--;
ast_debug(2, "ODBC handle %p dead - removing from class '%s', new count is %zd\n",
obj, name, class->connection_cnt);
} else {
/* We successfully grabbed a connection from the pool and all is well!
*/
obj->parent = ao2_bump(class);
ast_debug(2, "Reusing ODBC handle %p from class '%s'\n", obj, name);
}
}
localhost*CLI>
== Setting global variable 'SIPDOMAIN' to '192.168.40.55'
-- Executing [101@from-internal:1] NoOp("PJSIP/103-0000000a", "## Internal Call to the 101 ##") in new stack
-- Executing [101@from-internal:2] Verbose("PJSIP/103-0000000a", "Call start time: 2018-07-16 17:41:31") in new stack
Call start time: 2018-07-16 17:41:31
-- Executing [101@from-internal:3] Set("PJSIP/103-0000000a", "CDR(calldate)=2018-07-16 17:41:31") in new stack
-- Executing [101@from-internal:4] Set("PJSIP/103-0000000a", "CDR(useragent)=Arnold") in new stack
-- Executing [101@from-internal:5] Set("PJSIP/103-0000000a", "NOW=20180716_154131") in new stack
-- Executing [101@from-internal:6] Set("PJSIP/103-0000000a", "REC_FILE_NAME=OUT_20180716_154131_101_.wav") in new stack
-- Executing [101@from-internal:7] MixMonitor("PJSIP/103-0000000a", "OUT_20180716_154131_101_.wav,b V(1)") in new stack
-- Executing [101@from-internal:8] Dial("PJSIP/103-0000000a", "PJSIP/101,20,r") in new stack
-- Called PJSIP/101
== Begin MixMonitor Recording PJSIP/103-0000000a
-- PJSIP/101-0000000b is ringing
== Spawn extension (from-internal, 101, 8) exited non-zero on 'PJSIP/103-0000000a'
== MixMonitor close filestream (mixed)
== End MixMonitor Recording PJSIP/103-0000000a
localhost*CLI>
Now how can I send the calldate, clid, src, dst, disposition from the cdr table in a custom table like
-> Callsusers
iKey (auto_increment)
Date (Datetime)
Source (Varchar [80])
Destination (Varchar [80])
Clid (Varchar [80])
Type (Varchar [80])
Well in your position i think u can use alias.It is written in manual how to use them.Fox example you can use
alias start => callStart
alias end => callEnd
what this basically means. it means chan_start with time stamp will send the insert string information about the call which started in to database where column is callStart and also t will send chan_end in to column callEnd -IF this columns exist in your table.same u can do with dst src calldate and etc.I think there was an example aslias where it was written (i have seen it ons asterisk 15). Check it out please.