139 if (iso == SQL_TXN_READ_COMMITTED) {
140 return "read_committed";
141 }
else if (iso == SQL_TXN_READ_UNCOMMITTED) {
142 return "read_uncommitted";
143 }
else if (iso == SQL_TXN_SERIALIZABLE) {
144 return "serializable";
145 }
else if (iso == SQL_TXN_REPEATABLE_READ) {
146 return "repeatable_read";
154 if (strncasecmp(txt,
"read_", 5) == 0) {
155 if (strncasecmp(txt + 5,
"c", 1) == 0) {
156 return SQL_TXN_READ_COMMITTED;
157 }
else if (strncasecmp(txt + 5,
"u", 1) == 0) {
158 return SQL_TXN_READ_UNCOMMITTED;
162 }
else if (strncasecmp(txt,
"ser", 3) == 0) {
163 return SQL_TXN_SERIALIZABLE;
164 }
else if (strncasecmp(txt,
"rep", 3) == 0) {
165 return SQL_TXN_REPEATABLE_READ;
179 if (class->username) {
182 if (class->password) {
185 if (class->sanitysql) {
193 SQLFreeHandle(SQL_HANDLE_ENV, class->env);
243 SQLHSTMT stmt =
NULL;
244 int res = 0,
error = 0;
249 if (strcmp(tableptr->
connection, database) == 0 && strcmp(tableptr->
table, tablename) == 0) {
260 ast_log(
LOG_WARNING,
"Unable to retrieve database handle for table description '%s@%s'\n", tablename, database);
267 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
268 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
273 res = SQLColumns(stmt,
NULL, 0,
NULL, 0, (
unsigned char *)tablename, SQL_NTS, (
unsigned char *)
"%", SQL_NTS);
274 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
275 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
276 ast_log(
LOG_ERROR,
"Unable to query database columns on connection '%s'.\n", database);
280 if (!(tableptr =
ast_calloc(
sizeof(
char),
sizeof(*tableptr) + strlen(database) + 1 + strlen(tablename) + 1))) {
281 ast_log(
LOG_ERROR,
"Out of memory creating entry for table '%s' on connection '%s'\n", tablename, database);
285 tableptr->
connection = (
char *)tableptr +
sizeof(*tableptr);
286 tableptr->
table = (
char *)tableptr +
sizeof(*tableptr) + strlen(database) + 1;
288 strcpy(tableptr->
table, tablename);
291 while ((res = SQLFetch(stmt)) != SQL_NO_DATA && res != SQL_ERROR) {
292 SQLGetData(stmt, 4, SQL_C_CHAR, columnname,
sizeof(columnname), &sqlptr);
294 if (!(entry =
ast_calloc(
sizeof(
char),
sizeof(*entry) + strlen(columnname) + 1))) {
295 ast_log(
LOG_ERROR,
"Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, tablename, database);
299 entry->
name = (
char *)entry +
sizeof(*entry);
300 strcpy(entry->
name, columnname);
302 SQLGetData(stmt, 5, SQL_C_SHORT, &entry->
type,
sizeof(entry->
type),
NULL);
303 SQLGetData(stmt, 7, SQL_C_LONG, &entry->
size,
sizeof(entry->
size),
NULL);
305 SQLGetData(stmt, 10, SQL_C_SHORT, &entry->
radix,
sizeof(entry->
radix),
NULL);
316 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);
320 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
341 if (strcasecmp(col->
name, colname) == 0) {
354 if (strcmp(tableptr->
connection, database) == 0 && strcmp(tableptr->
table, tablename) == 0) {
362 return tableptr ? 0 : -1;
367 struct timeval start;
374 stmt = exec_cb(obj, data);
380 ast_log(
LOG_WARNING,
"SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
405 struct timeval start;
418 stmt = prepare_cb(obj, data);
423 res = SQLExecute(stmt);
424 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
425 if (res == SQL_ERROR) {
430 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
436 ast_log(
LOG_WARNING,
"SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
471 return SQLPrepare(stmt, (
unsigned char *)sql, SQL_NTS);
482 return SQLExecDirect(stmt, (
unsigned char *)sql, SQL_NTS);
489 res = SQLExecute(stmt);
490 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
491 if (res == SQL_ERROR) {
508 if (SQLGetData(StatementHandle, ColumnNumber, TargetType,
ast_str_buffer(*
buf), 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
511 }
else if (pmaxlen > 0) {
523 SQLINTEGER nativeerror = 0;
524 SQLSMALLINT diagbytes = 0;
526 unsigned char state[10];
527 unsigned char diagnostic[256];
531 while (SQLGetDiagRec(handle_type, handle, ++i,
state, &nativeerror,
532 diagnostic,
sizeof(diagnostic), &diagbytes) == SQL_SUCCESS) {
537 ast_log(
LOG_WARNING,
"There are more than 10 diagnostic records! Ignore the rest.\n");
547 return class->isolation;
552 return class->forcecommit;
562 static char *cfg =
"res_odbc.conf";
566 const char *
dsn, *username, *password, *sanitysql;
567 int enabled, bse, conntimeout, forcecommit, isolation, maxconnections, logging, slowquerylimit;
568 struct timeval ncache = { 0, 0 };
569 int preconnect = 0, res = 0, cache_is_queue = 0;
571 unsigned int max_cache_size;
581 if (!strcasecmp(cat,
"ENV")) {
601 if (!strcasecmp(v->
name,
"pooling") ||
602 !strncasecmp(v->
name,
"share", 5) ||
603 !strcasecmp(v->
name,
"limit") ||
604 !strcasecmp(v->
name,
"idlecheck")) {
605 ast_log(
LOG_WARNING,
"The 'pooling', 'shared_connections', 'limit', and 'idlecheck' options were replaced by 'max_connections'. See res_odbc.conf.sample.\n");
606 }
else if (!strcasecmp(v->
name,
"enabled")) {
608 }
else if (!strcasecmp(v->
name,
"pre-connect")) {
610 }
else if (!strcasecmp(v->
name,
"dsn")) {
612 }
else if (!strcasecmp(v->
name,
"username")) {
614 }
else if (!strcasecmp(v->
name,
"password")) {
616 }
else if (!strcasecmp(v->
name,
"sanitysql")) {
618 }
else if (!strcasecmp(v->
name,
"backslash_is_escape")) {
620 }
else if (!strcasecmp(v->
name,
"connect_timeout")) {
625 }
else if (!strcasecmp(v->
name,
"negative_connection_cache")) {
627 if (sscanf(v->
value,
"%lf", &dncache) != 1 || dncache < 0) {
633 ncache.tv_sec = (int)dncache;
634 ncache.tv_usec = (dncache - ncache.tv_sec) * 1000000;
636 }
else if (!strcasecmp(v->
name,
"forcecommit")) {
638 }
else if (!strcasecmp(v->
name,
"isolation")) {
643 }
else if (!strcasecmp(v->
name,
"max_connections")) {
648 }
else if (!strcasecmp(v->
name,
"logging")) {
650 }
else if (!strcasecmp(v->
name,
"slow_query_limit")) {
655 }
else if (!strcasecmp(v->
name,
"cache_type")) {
657 !strcasecmp(v->
value,
"roundrobin") ||
658 !strcasecmp(v->
value,
"queue");
659 }
else if (!strcasecmp(v->
name,
"cache_size")) {
660 if (!strcasecmp(v->
value,
"-1")) {
676 SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env);
677 res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (
void *) SQL_OV_ODBC3, 0);
679 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
685 new->backslash_is_escape = bse ? 1 : 0;
689 new->negative_connection_cache = ncache;
740 "Usage: odbc show [class]\n"
741 " List settings of a particular ODBC class or,\n"
742 " if not specified, all classes.\n";
747 length = strlen(
a->word);
750 if (!strncasecmp(
a->word, class->
name, length) && ++which >
a->n) {
759 if (!ret && !strncasecmp(
a->word,
"all", length) && ++which >
a->n) {
765 ast_cli(
a->fd,
"\nODBC DSN Settings\n");
766 ast_cli(
a->fd,
"-----------------\n\n");
769 if ((
a->argc == 2) || (
a->argc == 3 && !strcmp(
a->argv[2],
"all")) || (!strcmp(
a->argv[2], class->
name))) {
773 ast_cli(
a->fd,
" Name: %s\n DSN: %s\n", class->
name, class->dsn);
775 if (class->last_negative_connect.tv_sec > 0) {
777 ast_strftime(timestr,
sizeof(timestr),
"%Y-%m-%d %T", &tm);
778 ast_cli(
a->fd,
" Last fail connection attempt: %s\n", timestr);
781 ast_cli(
a->fd,
" Number of active connections: %zd (out of %d)\n", class->connection_cnt, class->maxconnections);
782 ast_cli(
a->fd,
" Cache Type: %s\n", class->cache_is_queue ?
"round-robin queue" :
"stack (last release, first re-use)");
783 ast_cli(
a->fd,
" Cache Usage: %u cached out of %u\n", class->cur_cache,
784 class->max_cache_size < class->maxconnections ? class->max_cache_size : class->maxconnections);
785 ast_cli(
a->fd,
" Logging: %s\n", class->logging ?
"Enabled" :
"Disabled");
786 if (class->logging) {
787 ast_cli(
a->fd,
" Number of prepares executed: %d\n", class->prepares_executed);
788 ast_cli(
a->fd,
" Number of queries executed: %d\n", class->queries_executed);
790 if (class->sql_text) {
791 ast_cli(
a->fd,
" Longest running SQL query: %s (%ld milliseconds)\n", class->sql_text, class->longest_query_execution_time);
832 ast_debug(2,
"Releasing ODBC handle %p into pool\n", obj);
850 if (class->cache_is_queue) {
856 if (class->cur_cache >= class->max_cache_size) {
858 if (class->cache_is_queue) {
866 --
class->connection_cnt;
869 ast_debug(2,
"ODBC Pool '%s' exceeded cache size, dropping '%p', connection count is %zd (%u cached)\n",
870 class->name, obj, class->connection_cnt, class->cur_cache);
893 if (!strcmp(class->name,
name) && !class->delme) {
902 unsigned int max_connections;
909 max_connections =
class->maxconnections;
912 return max_connections;
925 char *test_sql =
"select 1";
930 res = SQLGetConnectAttr(connection->
con, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
931 if (SQL_SUCCEEDED(res)) {
932 return dead == SQL_CD_TRUE ? 1 : 0;
938 res = SQLAllocHandle(SQL_HANDLE_STMT, connection->
con, &stmt);
939 if (!SQL_SUCCEEDED(res)) {
944 test_sql =
class->sanitysql;
947 res = SQLPrepare(stmt, (
unsigned char *)test_sql, SQL_NTS);
948 if (!SQL_SUCCEEDED(res)) {
949 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
953 res = SQLExecute(stmt);
954 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
956 return SQL_SUCCEEDED(res) ? 0 : 1;
982 if (class->connection_cnt < class->maxconnections) {
995 class->connection_cnt++;
1001 class->connection_cnt--;
1012 ast_debug(2,
"Created ODBC handle %p on class '%s', new count is %zd\n", obj,
1013 name, class->connection_cnt);
1031 class->connection_cnt--;
1034 ast_debug(2,
"ODBC handle %p dead - removing from class '%s', new count is %zd\n",
1035 obj,
name, class->connection_cnt);
1045 ast_debug(2,
"Reusing ODBC handle %p from class '%s'\n", obj,
name);
1070 unsigned char msg[200],
state[10];
1080 res = SQLDisconnect(con);
1082 if ((res = SQLFreeHandle(SQL_HANDLE_DBC, con)) == SQL_SUCCESS) {
1083 ast_debug(3,
"Database handle %p (connection %p) deallocated\n", obj, con);
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);
1097 unsigned char msg[200],
state[10];
1099 SQLINTEGER enable = 1;
1100 char *tracefile =
"/tmp/odbc.trace";
1103 long int negative_cache_expiration;
1110 if (time(
NULL) < negative_cache_expiration) {
1117 res = SQLAllocHandle(SQL_HANDLE_DBC, obj->
parent->
env, &con);
1119 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1124 SQLSetConnectAttr(con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)(
long) obj->
parent->
conntimeout, 0);
1125 SQLSetConnectAttr(con, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER *)(
long) obj->
parent->
conntimeout, 0);
1127 SQLSetConnectAttr(con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
1128 SQLSetConnectAttr(con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
1131 res = SQLConnect(con,
1136 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1137 SQLGetDiagRec(SQL_HANDLE_DBC, con, 1,
state, &err, msg, 100, &mlen);
1139 ast_log(
LOG_WARNING,
"res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (
int)err, msg);
1140 if ((res = SQLFreeHandle(SQL_HANDLE_DBC, con)) != SQL_SUCCESS) {
1141 SQLGetDiagRec(SQL_HANDLE_DBC, con, 1,
state, &err, msg, 100, &mlen);
1142 ast_log(
LOG_WARNING,
"Unable to deallocate database handle %p? %d errno=%d %s\n", con, res, (
int)err, msg);
1218 .
requires =
"res_odbc_transaction",
int setenv(const char *name, const char *value, int overwrite)
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.
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_LIST_LAST(head)
Returns the last entry contained in a list.
#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(head, elm, field)
Removes a specific entry from 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 max_cache_size
unsigned int maxconnections
struct timeval negative_connection_cache
unsigned int backslash_is_escape
unsigned int cache_is_queue
long longest_query_execution_time
struct odbc_class::@447 list
struct odbc_class::@448 connections
struct timeval last_negative_connect
struct odbc_obj::@260 list
struct odbc_class * parent
struct odbc_txn_frame::@449 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...
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,...)