Asterisk - The Open Source Telephony Project GIT-master-80b953f
Loading...
Searching...
No Matches
writers.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2026, Sangoma Technologies Corporation
5 *
6 * George Joseph <gjoseph@sangoma.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \author George Joseph <gjoseph@sangoma.com>
22 *
23 * \brief Backend output functions.
24 *
25 * The writers all take a vector of cdrel_value objects and write them to the output
26 * file or database.
27 *
28 */
29
30#include "cdrel.h"
31
32/*
33 * We can save some time and ast_str memory allocation work by allocating a single
34 * thread-local buffer and re-using it.
35 */
37
38/*!
39 * \internal
40 * \brief Write a record to a text file
41 *
42 * Besides being used here, this function is also used by the legacy loggers
43 * that shortcut the advanced stuff.
44 *
45 * \param config The configuration object.
46 * \param record The data to write.
47 * \retval 0 on success
48 * \retval -1 on failure
49 */
50int write_record_to_file(struct cdrel_config *config, struct ast_str *record)
51{
52 FILE *out;
53 int res = 0;
54
55 ast_mutex_lock(&config->lock);
56 if ((out = fopen(config->output_filename, "a"))) {
57 res = fputs(ast_str_buffer(record), out);
58 fputs("\n", out);
59 fclose(out);
60 }
62
63 if (!out || res < 0) {
64 ast_log(LOG_ERROR, "Unable to write %s to file %s : %s\n",
65 RECORD_TYPE_STR(config->record_type), config->output_filename, strerror(errno));
66 return -1;
67 }
68 return 0;
69}
70
71/*!
72 * \internal
73 * \brief Concatenate and append a list of values to an ast_str
74 *
75 * \param config Config object
76 * \param values A vector of values
77 * \param str The ast_str to append to
78 * \retval 0 on success
79 * \retval -1 on failure
80 */
81static int dsv_appender(struct cdrel_config *config, struct cdrel_values *values, struct ast_str **str)
82{
83 int ix = 0;
84 int res = 0;
85
86 for (ix = 0; ix < AST_VECTOR_SIZE(values); ix++) {
88 ast_assert(value->data_type == cdrel_type_string);
89
90 res = ast_str_append(str, -1, "%s%s", ix == 0 ? "" : config->separator, value->values.string);
91 if (res < 0) {
92 return -1;
93 }
94 }
95
96 return res;
97}
98
99/*!
100 * \internal
101 * \brief Write a DSV list of values to a text file
102 *
103 * \param config Config object
104 * \param values A vector of values
105 * \retval 0 on success
106 * \retval -1 on failure
107 */
109{
110 int res = 0;
111 struct ast_str *str = ast_str_thread_get(&custom_buf, 1024);
112
114
115 res = dsv_appender(config, values, &str);
116 if (res < 0) {
117 return -1;
118 }
119
121}
122
123/*!
124 * \internal
125 * \brief Write a list of values as a JSON object to a text file
126 *
127 * \param config Config object
128 * \param values A vector of values
129 * \retval 0 on success
130 * \retval -1 on failure
131 *
132 * \note We are intentionally NOT using the ast_json APIs here because
133 * they're expensive and these are simple objects.
134 */
135static int json_writer(struct cdrel_config *config, struct cdrel_values *values)
136{
137 int ix = 0;
138 int res = 0;
139 struct ast_str *str = ast_str_thread_get(&custom_buf, 1024);
140
141 ast_str_set(&str, -1, "%s", "{");
142
143 for (ix = 0; ix < AST_VECTOR_SIZE(values); ix++) {
144 struct cdrel_value *value = AST_VECTOR_GET(values, ix);
145 ast_assert(value->data_type == cdrel_type_string);
146
147 res = ast_str_append(&str, -1, "%s\"%s\":%s", ix == 0 ? "" : config->separator, value->field_name, value->values.string);
148 if (res < 0) {
149 return -1;
150 }
151 }
152 ast_str_append(&str, -1, "%s", "}");
153
155}
156
157/*!
158 * \internal
159 * \brief Write a record to a database
160 *
161 * Besides being used here, this function is also used by the legacy loggers
162 * that shortcut the advanced stuff.
163 *
164 * \param config The configuration object.
165 * \param record The data to write.
166 * \retval 0 on success
167 * \retval -1 on failure
168 */
170{
171 int res = 0;
172 int ix;
173
174 ast_mutex_lock(&config->lock);
175 for (ix = 0; ix < AST_VECTOR_SIZE(values); ix++) {
176 struct cdrel_value *value = AST_VECTOR_GET(values, ix);
177 ast_assert(value->data_type == cdrel_type_string);
178 ast_debug(6, "%s '%s'\n", value->field_name, value->values.string);
179 res = sqlite3_bind_text(config->insert, ix + 1, value->values.string, -1, SQLITE_STATIC);
180 if (res != SQLITE_OK) {
181 ast_log(LOG_ERROR, "Unable to write %s to database %s. SQL bind for field %s:'%s'. Error: %s\n",
182 RECORD_TYPE_STR(config->record_type), config->output_filename,
183 value->field_name, value->values.string,
184 sqlite3_errmsg(config->db));
185 sqlite3_reset(config->insert);
186 ast_mutex_unlock(&config->lock);
187 return -1;
188 }
189 }
190
191 res = sqlite3_step(config->insert);
192 if (res != SQLITE_DONE) {
193 ast_log(LOG_ERROR, "Unable to write %s to database %s. Error: %s\n",
194 RECORD_TYPE_STR(config->record_type), config->output_filename,
195 sqlite3_errmsg(config->db));
196 sqlite3_reset(config->insert);
197 ast_mutex_unlock(&config->lock);
198 return -1;
199 }
200
201 sqlite3_reset(config->insert);
202 ast_mutex_unlock(&config->lock);
203
204 return res;
205}
206
207/*!
208 * \internal
209 * \brief Write a list of values to a database
210 *
211 * \param config Config object
212 * \param values A vector of values
213 * \retval 0 on success
214 * \retval -1 on failure
215 */
217{
219}
220
230
const char * str
Definition app_jack.c:150
#define ast_log
Definition astobj2.c:42
Private header for res_cdrel_custom.
@ cdrel_type_string
Definition cdrel.h:73
#define RECORD_TYPE_STR(_rt)
Definition cdrel.h:42
@ cdrel_format_json
Definition cdrel.h:49
@ cdrel_format_dsv
Definition cdrel.h:48
@ cdrel_format_sql
Definition cdrel.h:50
cdrel_backend_writer cdrel_backend_writers[cdrel_format_type_end]
static const char config[]
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_mutex_unlock(a)
Definition lock.h:197
#define ast_mutex_lock(a)
Definition lock.h:196
int errno
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition strings.h:693
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition strings.h:909
Support for dynamic strings.
Definition strings.h:623
union cdrel_value::@454 values
int value
Definition syslog.c:37
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
FILE * out
Definition utils/frame.c:33
#define ast_assert(a)
Definition utils.h:779
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:620
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691
static int dsv_writer(struct cdrel_config *config, struct cdrel_values *values)
Definition writers.c:108
int write_record_to_database(struct cdrel_config *config, struct cdrel_values *values)
Definition writers.c:169
int write_record_to_file(struct cdrel_config *config, struct ast_str *record)
Definition writers.c:50
static int json_writer(struct cdrel_config *config, struct cdrel_values *values)
Definition writers.c:135
static int database_writer(struct cdrel_config *config, struct cdrel_values *values)
Definition writers.c:216
static int dsv_appender(struct cdrel_config *config, struct cdrel_values *values, struct ast_str **str)
Definition writers.c:81
int load_writers(void)
Definition writers.c:221