134 if (iso == SQL_TXN_READ_COMMITTED) {
135 return "read_committed";
136 }
else if (iso == SQL_TXN_READ_UNCOMMITTED) {
137 return "read_uncommitted";
138 }
else if (iso == SQL_TXN_SERIALIZABLE) {
139 return "serializable";
140 }
else if (iso == SQL_TXN_REPEATABLE_READ) {
141 return "repeatable_read";
149 if (strncasecmp(txt,
"read_", 5) == 0) {
150 if (strncasecmp(txt + 5,
"c", 1) == 0) {
151 return SQL_TXN_READ_COMMITTED;
152 }
else if (strncasecmp(txt + 5,
"u", 1) == 0) {
153 return SQL_TXN_READ_UNCOMMITTED;
157 }
else if (strncasecmp(txt,
"ser", 3) == 0) {
158 return SQL_TXN_SERIALIZABLE;
159 }
else if (strncasecmp(txt,
"rep", 3) == 0) {
160 return SQL_TXN_REPEATABLE_READ;
174 if (class->username) {
177 if (class->password) {
180 if (class->sanitysql) {
188 SQLFreeHandle(SQL_HANDLE_ENV, class->env);
238 SQLHSTMT stmt =
NULL;
239 int res = 0,
error = 0;
244 if (strcmp(tableptr->
connection, database) == 0 && strcmp(tableptr->
table, tablename) == 0) {
255 ast_log(
LOG_WARNING,
"Unable to retrieve database handle for table description '%s@%s'\n", tablename, database);
262 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
263 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
268 res = SQLColumns(stmt,
NULL, 0,
NULL, 0, (
unsigned char *)tablename, SQL_NTS, (
unsigned char *)
"%", SQL_NTS);
269 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
270 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
271 ast_log(
LOG_ERROR,
"Unable to query database columns on connection '%s'.\n", database);
275 if (!(tableptr =
ast_calloc(
sizeof(
char),
sizeof(*tableptr) + strlen(database) + 1 + strlen(tablename) + 1))) {
276 ast_log(
LOG_ERROR,
"Out of memory creating entry for table '%s' on connection '%s'\n", tablename, database);
280 tableptr->
connection = (
char *)tableptr +
sizeof(*tableptr);
281 tableptr->
table = (
char *)tableptr +
sizeof(*tableptr) + strlen(database) + 1;
283 strcpy(tableptr->
table, tablename);
286 while ((res = SQLFetch(stmt)) != SQL_NO_DATA && res != SQL_ERROR) {
287 SQLGetData(stmt, 4, SQL_C_CHAR, columnname,
sizeof(columnname), &sqlptr);
290 ast_log(
LOG_ERROR,
"Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, tablename, database);
295 strcpy(
entry->name, columnname);
297 SQLGetData(stmt, 5, SQL_C_SHORT, &
entry->type,
sizeof(
entry->type),
NULL);
298 SQLGetData(stmt, 7, SQL_C_LONG, &
entry->size,
sizeof(
entry->size),
NULL);
299 SQLGetData(stmt, 9, SQL_C_SHORT, &
entry->decimals,
sizeof(
entry->decimals),
NULL);
300 SQLGetData(stmt, 10, SQL_C_SHORT, &
entry->radix,
sizeof(
entry->radix),
NULL);
301 SQLGetData(stmt, 11, SQL_C_SHORT, &
entry->nullable,
sizeof(
entry->nullable),
NULL);
302 SQLGetData(stmt, 16, SQL_C_LONG, &
entry->octetlen,
sizeof(
entry->octetlen),
NULL);
307 if (
entry->octetlen == 0) {
311 ast_debug(3,
"Found %s column with type %hd with len %ld, octetlen %ld, and numlen (%hd,%hd)\n",
entry->name,
entry->type, (
long)
entry->size, (
long)
entry->octetlen,
entry->decimals,
entry->radix);
315 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
336 if (strcasecmp(col->
name, colname) == 0) {
349 if (strcmp(tableptr->
connection, database) == 0 && strcmp(tableptr->
table, tablename) == 0) {
357 return tableptr ? 0 : -1;
362 struct timeval start;
369 stmt = exec_cb(obj, data);
375 ast_log(
LOG_WARNING,
"SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
400 struct timeval start;
413 stmt = prepare_cb(obj, data);
418 res = SQLExecute(stmt);
419 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
420 if (res == SQL_ERROR) {
425 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
431 ast_log(
LOG_WARNING,
"SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
466 return SQLPrepare(stmt, (
unsigned char *)sql, SQL_NTS);
477 return SQLExecDirect(stmt, (
unsigned char *)sql, SQL_NTS);
484 res = SQLExecute(stmt);
485 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
486 if (res == SQL_ERROR) {
503 if (SQLGetData(StatementHandle, ColumnNumber, TargetType,
ast_str_buffer(*
buf), 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
506 }
else if (pmaxlen > 0) {
518 SQLINTEGER nativeerror = 0;
519 SQLSMALLINT diagbytes = 0;
521 unsigned char state[10];
522 unsigned char diagnostic[256];
526 while (SQLGetDiagRec(handle_type, handle, ++i,
state, &nativeerror,
527 diagnostic,
sizeof(diagnostic), &diagbytes) == SQL_SUCCESS) {
532 ast_log(
LOG_WARNING,
"There are more than 10 diagnostic records! Ignore the rest.\n");
542 return class->isolation;
547 return class->forcecommit;
557 static char *cfg =
"res_odbc.conf";
561 const char *
dsn, *username, *password, *sanitysql;
562 int enabled, bse, conntimeout, forcecommit, isolation, maxconnections, logging, slowquerylimit;
563 struct timeval ncache = { 0, 0 };
564 int preconnect = 0, res = 0;
575 if (!strcasecmp(cat,
"ENV")) {
593 if (!strcasecmp(v->
name,
"pooling") ||
594 !strncasecmp(v->
name,
"share", 5) ||
595 !strcasecmp(v->
name,
"limit") ||
596 !strcasecmp(v->
name,
"idlecheck")) {
597 ast_log(
LOG_WARNING,
"The 'pooling', 'shared_connections', 'limit', and 'idlecheck' options were replaced by 'max_connections'. See res_odbc.conf.sample.\n");
598 }
else if (!strcasecmp(v->
name,
"enabled")) {
600 }
else if (!strcasecmp(v->
name,
"pre-connect")) {
602 }
else if (!strcasecmp(v->
name,
"dsn")) {
604 }
else if (!strcasecmp(v->
name,
"username")) {
606 }
else if (!strcasecmp(v->
name,
"password")) {
608 }
else if (!strcasecmp(v->
name,
"sanitysql")) {
610 }
else if (!strcasecmp(v->
name,
"backslash_is_escape")) {
612 }
else if (!strcasecmp(v->
name,
"connect_timeout")) {
617 }
else if (!strcasecmp(v->
name,
"negative_connection_cache")) {
619 if (sscanf(v->
value,
"%lf", &dncache) != 1 || dncache < 0) {
625 ncache.tv_sec = (int)dncache;
626 ncache.tv_usec = (dncache - ncache.tv_sec) * 1000000;
628 }
else if (!strcasecmp(v->
name,
"forcecommit")) {
630 }
else if (!strcasecmp(v->
name,
"isolation")) {
635 }
else if (!strcasecmp(v->
name,
"max_connections")) {
640 }
else if (!strcasecmp(v->
name,
"logging")) {
642 }
else if (!strcasecmp(v->
name,
"slow_query_limit")) {
658 SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env);
659 res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (
void *) SQL_OV_ODBC3, 0);
661 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
667 new->backslash_is_escape = bse ? 1 : 0;
671 new->negative_connection_cache = ncache;
719 "Usage: odbc show [class]\n"
720 " List settings of a particular ODBC class or,\n"
721 " if not specified, all classes.\n";
726 length = strlen(
a->word);
729 if (!strncasecmp(
a->word, class->
name, length) && ++which >
a->n) {
738 if (!ret && !strncasecmp(
a->word,
"all", length) && ++which >
a->n) {
744 ast_cli(
a->fd,
"\nODBC DSN Settings\n");
745 ast_cli(
a->fd,
"-----------------\n\n");
748 if ((
a->argc == 2) || (
a->argc == 3 && !strcmp(
a->argv[2],
"all")) || (!strcmp(
a->argv[2], class->
name))) {
752 ast_cli(
a->fd,
" Name: %s\n DSN: %s\n", class->
name, class->dsn);
754 if (class->last_negative_connect.tv_sec > 0) {
756 ast_strftime(timestr,
sizeof(timestr),
"%Y-%m-%d %T", &tm);
757 ast_cli(
a->fd,
" Last fail connection attempt: %s\n", timestr);
760 ast_cli(
a->fd,
" Number of active connections: %zd (out of %d)\n", class->connection_cnt, class->maxconnections);
761 ast_cli(
a->fd,
" Logging: %s\n", class->logging ?
"Enabled" :
"Disabled");
762 if (class->logging) {
763 ast_cli(
a->fd,
" Number of prepares executed: %d\n", class->prepares_executed);
764 ast_cli(
a->fd,
" Number of queries executed: %d\n", class->queries_executed);
766 if (class->sql_text) {
767 ast_cli(
a->fd,
" Longest running SQL query: %s (%ld milliseconds)\n", class->sql_text, class->longest_query_execution_time);
808 ast_debug(2,
"Releasing ODBC handle %p into pool\n", obj);
842 if (!strcmp(class->name,
name) && !class->delme) {
851 unsigned int max_connections;
858 max_connections =
class->maxconnections;
861 return max_connections;
874 char *test_sql =
"select 1";
879 res = SQLGetConnectAttr(connection->
con, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
880 if (SQL_SUCCEEDED(res)) {
881 return dead == SQL_CD_TRUE ? 1 : 0;
887 res = SQLAllocHandle(SQL_HANDLE_STMT, connection->
con, &stmt);
888 if (!SQL_SUCCEEDED(res)) {
893 test_sql =
class->sanitysql;
896 res = SQLPrepare(stmt, (
unsigned char *)test_sql, SQL_NTS);
897 if (!SQL_SUCCEEDED(res)) {
898 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
902 res = SQLExecute(stmt);
903 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
905 return SQL_SUCCEEDED(res) ? 0 : 1;
928 if (class->connection_cnt < class->maxconnections) {
941 class->connection_cnt++;
947 class->connection_cnt--;
957 ast_debug(2,
"Created ODBC handle %p on class '%s', new count is %zd\n", obj,
958 name, class->connection_cnt);
979 class->connection_cnt--;
980 ast_debug(2,
"ODBC handle %p dead - removing from class '%s', new count is %zd\n",
981 obj,
name, class->connection_cnt);
989 ast_debug(2,
"Reusing ODBC handle %p from class '%s'\n", obj,
name);
1014 unsigned char msg[200],
state[10];
1024 res = SQLDisconnect(con);
1026 if ((res = SQLFreeHandle(SQL_HANDLE_DBC, con)) == SQL_SUCCESS) {
1027 ast_debug(3,
"Database handle %p (connection %p) deallocated\n", obj, con);
1029 SQLGetDiagRec(SQL_HANDLE_DBC, con, 1,
state, &err, msg, 100, &mlen);
1030 ast_log(
LOG_WARNING,
"Unable to deallocate database handle %p? %d errno=%d %s\n", con, res, (
int)err, msg);
1041 unsigned char msg[200],
state[10];
1043 SQLINTEGER enable = 1;
1044 char *tracefile =
"/tmp/odbc.trace";
1047 long int negative_cache_expiration;
1054 if (time(
NULL) < negative_cache_expiration) {
1061 res = SQLAllocHandle(SQL_HANDLE_DBC, obj->
parent->
env, &con);
1063 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1068 SQLSetConnectAttr(con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)(
long) obj->
parent->
conntimeout, 0);
1069 SQLSetConnectAttr(con, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER *)(
long) obj->
parent->
conntimeout, 0);
1071 SQLSetConnectAttr(con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
1072 SQLSetConnectAttr(con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
1075 res = SQLConnect(con,
1080 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1081 SQLGetDiagRec(SQL_HANDLE_DBC, con, 1,
state, &err, msg, 100, &mlen);
1083 ast_log(
LOG_WARNING,
"res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (
int)err, msg);
1084 if ((res = SQLFreeHandle(SQL_HANDLE_DBC, con)) != SQL_SUCCESS) {
1085 SQLGetDiagRec(SQL_HANDLE_DBC, con, 1,
state, &err, msg, 100, &mlen);
1086 ast_log(
LOG_WARNING,
"Unable to deallocate database handle %p? %d errno=%d %s\n", con, res, (
int)err, msg);
1162 .
requires =
"res_odbc_transaction",
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_iterator_next(iter)
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_MUTEX
int ao2_match_by_addr(void *obj, void *arg, int flags)
A common ao2_callback is one that matches by address.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
#define ao2_unlink(container, obj)
Remove an object from a container.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
#define ao2_alloc(data_size, destructor_fn)
static const char config[]
General Asterisk PBX channel definitions.
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Generic File Format Support. Should be included by clients of the file handling routines....
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
int setenv(const char *name, const char *value, int overwrite)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_HEAD_INIT(head)
Initializes an rwlist head structure.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_REMOVE_HEAD
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_TRAVERSE
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_RWLIST_INSERT_TAIL
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_RWLIST_HEAD_DESTROY(head)
Destroys an rwlist head structure.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Asterisk locking-related definitions:
#define ast_cond_destroy(cond)
#define ast_cond_wait(cond, mutex)
#define ast_cond_init(cond, attr)
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
pthread_cond_t ast_cond_t
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
#define ast_cond_signal(cond)
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_REALTIME_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Core PBX routines and definitions.
static char * handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_threadstorage errors_buf
static struct ast_cli_entry cli_odbc[]
static void odbc_register_class(struct odbc_class *class, int connect)
static int load_odbc_config(void)
static int aoro2_class_cb(void *obj, void *arg, int flags)
static void odbc_obj_destructor(void *data)
static odbc_status odbc_obj_connect(struct odbc_obj *obj)
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
unsigned int ast_odbc_class_get_isolation(struct odbc_class *class)
Get the transaction isolation setting for an ODBC class.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
unsigned int ast_odbc_get_max_connections(const char *name)
Return the current configured maximum number of connections for a class.
int ast_odbc_clear_cache(const char *database, const char *tablename)
Remove a cache entry from memory This function may be called to clear entries created and cached by t...
struct odbc_cache_columns * ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
Find a column entry within a cached table structure.
static void odbc_class_destructor(void *data)
struct odbc_obj * _ast_odbc_request_obj(const char *name, int check, const char *file, const char *function, int lineno)
static struct ao2_container * class_container
struct ast_str * ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
Shortcut for printing errors to logs after a failed SQL operation.
static void destroy_table_cache(struct odbc_cache_tables *table)
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
const char * ast_odbc_isolation2text(int iso)
Convert from numeric transaction isolation values to their textual counterparts.
const char * ast_odbc_class_get_name(struct odbc_class *class)
Get the name of an ODBC class.
SQLRETURN ast_odbc_ast_str_SQLGetData(struct ast_str **buf, int pmaxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind)
Wrapper for SQLGetData to use with dynamic strings.
SQLHSTMT ast_odbc_direct_execute(struct odbc_obj *obj, SQLHSTMT(*exec_cb)(struct odbc_obj *obj, void *data), void *data)
Executes an non prepared statement and returns the resulting statement handle.
unsigned int ast_odbc_class_get_forcecommit(struct odbc_class *class)
Get the transaction forcecommit setting for an ODBC class.
static int load_module(void)
SQLRETURN ast_odbc_execute_sql(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Execute a unprepared SQL query.
static odbc_status odbc_obj_disconnect(struct odbc_obj *obj)
static int unload_module(void)
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
int ast_odbc_text2isolation(const char *txt)
Convert from textual transaction isolation values to their numeric constants.
static int connection_dead(struct odbc_obj *connection, struct odbc_class *class)
Determine if the connection has died.
struct odbc_obj * _ast_odbc_request_obj2(const char *name, struct ast_flags flags, const char *file, const char *function, int lineno)
int ast_odbc_smart_execute(struct odbc_obj *obj, SQLHSTMT stmt)
Executes a prepared statement handle.
#define ast_odbc_request_obj(name, check)
Get a ODBC connection object.
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define ast_str_make_space(buf, new_len)
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Main Channel structure associated with a channel.
descriptor for a cli entry.
Structure used to handle boolean flags.
Structure for mutex and tracking information.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
These structures are used for adaptive capabilities.
struct odbc_cache_tables::_columns columns
unsigned int slowquerylimit
unsigned int maxconnections
struct timeval negative_connection_cache
unsigned int backslash_is_escape
long longest_query_execution_time
struct odbc_class::@442 connections
struct odbc_class::@441 list
struct timeval last_negative_connect
struct odbc_class * parent
struct odbc_obj::@255 list
struct ast_channel * owner
unsigned int active
Is this record the current active transaction within the channel? Note that the active flag is really...
struct odbc_txn_frame::@443 list
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Time-related functions and macros.
int ast_time_t_to_string(time_t time, char *buf, size_t length)
Converts to a string representation of a time_t as decimal seconds since the epoch....
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int error(const char *format,...)