mirror of https://github.com/sipwise/rtpengine.git
Change-Id: If50b0528520fe816ed63494dc6c6e707fe9eca2cchanges/94/11294/26
parent
77f9e4c310
commit
f5cc21f92b
@ -0,0 +1,231 @@
|
||||
#include "db.h"
|
||||
#include <mysql.h>
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "main.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
static MYSQL __thread *mysql_conn;
|
||||
static MYSQL_STMT __thread
|
||||
*stm_insert_call,
|
||||
*stm_close_call,
|
||||
*stm_insert_stream,
|
||||
*stm_close_stream,
|
||||
*stm_config_stream;
|
||||
|
||||
|
||||
static void my_stmt_close(MYSQL_STMT **st) {
|
||||
if (!*st)
|
||||
return;
|
||||
mysql_stmt_close(*st);
|
||||
*st = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void reset_conn() {
|
||||
my_stmt_close(&stm_insert_call);
|
||||
my_stmt_close(&stm_close_call);
|
||||
my_stmt_close(&stm_insert_stream);
|
||||
my_stmt_close(&stm_close_stream);
|
||||
my_stmt_close(&stm_config_stream);
|
||||
mysql_close(mysql_conn);
|
||||
mysql_conn = NULL;
|
||||
}
|
||||
|
||||
|
||||
INLINE int prep(MYSQL_STMT **st, const char *str) {
|
||||
*st = mysql_stmt_init(mysql_conn);
|
||||
if (!*st)
|
||||
return -1;
|
||||
if (mysql_stmt_prepare(*st, str, strlen(str))) {
|
||||
ilog(LOG_ERR, "Failed to prepare statement '%s': %s", str, mysql_stmt_error(*st));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int check_conn() {
|
||||
if (mysql_conn)
|
||||
return 0;
|
||||
if (!c_mysql_host || !c_mysql_db)
|
||||
return -1;
|
||||
|
||||
ilog(LOG_DEBUG, "connecting to MySQL");
|
||||
|
||||
mysql_conn = mysql_init(NULL);
|
||||
if (!mysql_conn)
|
||||
goto err;
|
||||
if (!mysql_real_connect(mysql_conn, c_mysql_host, c_mysql_user, c_mysql_pass, c_mysql_db, c_mysql_port,
|
||||
NULL, CLIENT_IGNORE_SIGPIPE))
|
||||
goto err;
|
||||
if (mysql_select_db(mysql_conn, c_mysql_db))
|
||||
goto err;
|
||||
if (mysql_autocommit(mysql_conn, 0))
|
||||
goto err;
|
||||
|
||||
if (prep(&stm_insert_call, "insert into recording_calls (call_id) values (?)"))
|
||||
goto err;
|
||||
if (prep(&stm_insert_stream, "insert into recording_streams (`call`, local_filename, full_filename, " \
|
||||
"file_format, " \
|
||||
"output_type, " \
|
||||
"stream_id, ssrc) values (?,?,?,?,?,?,?)"))
|
||||
goto err;
|
||||
if (prep(&stm_close_call, "update recording_calls set end_time = now() where id = ?"))
|
||||
goto err;
|
||||
if (prep(&stm_close_stream, "update recording_streams set end_time = now() where id = ?"))
|
||||
goto err;
|
||||
if (prep(&stm_config_stream, "update recording_streams set channels = ?, sample_rate = ? where id = ?"))
|
||||
goto err;
|
||||
|
||||
ilog(LOG_INFO, "Connection to MySQL established");
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (mysql_conn) {
|
||||
ilog(LOG_ERR, "Failed to connect to MySQL: %s", mysql_error(mysql_conn));
|
||||
reset_conn();
|
||||
}
|
||||
else
|
||||
ilog(LOG_ERR, "Failed to connect to MySQL: out of memory");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
INLINE void my_str(MYSQL_BIND *b, const char *s) {
|
||||
*b = (MYSQL_BIND) {
|
||||
.buffer_type = MYSQL_TYPE_STRING,
|
||||
.buffer = (void *) s,
|
||||
.buffer_length = strlen(s),
|
||||
.length = &b->buffer_length,
|
||||
};
|
||||
}
|
||||
INLINE void my_ull(MYSQL_BIND *b, const unsigned long long *ull) {
|
||||
*b = (MYSQL_BIND) {
|
||||
.buffer_type = MYSQL_TYPE_LONGLONG,
|
||||
.buffer = (void *) ull,
|
||||
.buffer_length = sizeof(*ull),
|
||||
.is_unsigned = 1,
|
||||
};
|
||||
}
|
||||
INLINE void my_i(MYSQL_BIND *b, const int *i) {
|
||||
*b = (MYSQL_BIND) {
|
||||
.buffer_type = MYSQL_TYPE_LONG,
|
||||
.buffer = (void *) i,
|
||||
.buffer_length = sizeof(*i),
|
||||
.is_unsigned = 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
static void execute_wrap(MYSQL_STMT **stmt, MYSQL_BIND *binds, unsigned long long *auto_id) {
|
||||
for (int retr = 0; retr < 5; retr++) {
|
||||
if (mysql_stmt_bind_param(*stmt, binds))
|
||||
goto err;
|
||||
if (mysql_stmt_execute(*stmt))
|
||||
goto err;
|
||||
if (auto_id) {
|
||||
*auto_id = mysql_insert_id(mysql_conn);
|
||||
if (*auto_id <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (mysql_commit(mysql_conn))
|
||||
goto err;
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
ilog(LOG_ERR, "Failed to bind or execute prepared statement: %s",
|
||||
mysql_stmt_error(*stmt));
|
||||
if (retr > 2) {
|
||||
reset_conn();
|
||||
if (check_conn())
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void db_do_call(metafile_t *mf) {
|
||||
if (check_conn())
|
||||
return;
|
||||
if (mf->db_id > 0)
|
||||
return;
|
||||
|
||||
MYSQL_BIND b[1];
|
||||
my_str(&b[0], mf->call_id);
|
||||
|
||||
execute_wrap(&stm_insert_call, b, &mf->db_id);
|
||||
}
|
||||
|
||||
|
||||
void db_do_stream(metafile_t *mf, output_t *op, const char *type, unsigned int id, unsigned long ssrc) {
|
||||
if (check_conn())
|
||||
return;
|
||||
if (mf->db_id <= 0)
|
||||
return;
|
||||
if (op->db_id > 0)
|
||||
return;
|
||||
|
||||
MYSQL_BIND b[7];
|
||||
my_ull(&b[0], &mf->db_id);
|
||||
my_str(&b[1], op->file_name);
|
||||
my_str(&b[2], op->full_filename);
|
||||
my_str(&b[3], op->file_format);
|
||||
my_str(&b[4], type);
|
||||
b[5] = (MYSQL_BIND) {
|
||||
.buffer_type = MYSQL_TYPE_LONG,
|
||||
.buffer = &id,
|
||||
.buffer_length = sizeof(id),
|
||||
.is_unsigned = 1,
|
||||
};
|
||||
b[6] = (MYSQL_BIND) {
|
||||
.buffer_type = MYSQL_TYPE_LONG,
|
||||
.buffer = &ssrc,
|
||||
.buffer_length = sizeof(ssrc),
|
||||
.is_unsigned = 1,
|
||||
};
|
||||
|
||||
execute_wrap(&stm_insert_stream, b, &op->db_id);
|
||||
}
|
||||
|
||||
void db_close_call(metafile_t *mf) {
|
||||
if (check_conn())
|
||||
return;
|
||||
if (mf->db_id <= 0)
|
||||
return;
|
||||
|
||||
MYSQL_BIND b[1];
|
||||
my_ull(&b[0], &mf->db_id);
|
||||
|
||||
execute_wrap(&stm_close_call, b, NULL);
|
||||
}
|
||||
void db_close_stream(output_t *op) {
|
||||
if (check_conn())
|
||||
return;
|
||||
if (op->db_id <= 0)
|
||||
return;
|
||||
|
||||
MYSQL_BIND b[1];
|
||||
my_ull(&b[0], &op->db_id);
|
||||
|
||||
execute_wrap(&stm_close_stream, b, NULL);
|
||||
}
|
||||
|
||||
void db_config_stream(output_t *op) {
|
||||
if (check_conn())
|
||||
return;
|
||||
if (op->db_id <= 0)
|
||||
return;
|
||||
|
||||
MYSQL_BIND b[3];
|
||||
my_i(&b[0], &op->actual_format.channels);
|
||||
my_i(&b[1], &op->actual_format.clockrate);
|
||||
my_ull(&b[2], &op->db_id);
|
||||
|
||||
execute_wrap(&stm_config_stream, b, NULL);
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
#ifndef _DB_H_
|
||||
#define _DB_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
void db_do_call(metafile_t *);
|
||||
void db_close_call(metafile_t *);
|
||||
void db_do_stream(metafile_t *mf, output_t *op, const char *type, unsigned int id, unsigned long ssrc);
|
||||
void db_close_stream(output_t *op);
|
||||
void db_config_stream(output_t *op);
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
Reference in new issue