2020-05-05 23:05:36 +00:00
# include <stdlib.h>
# include <string.h>
# include <sqlite3.h>
2020-08-13 14:29:26 +00:00
# include <cache.h>
2020-05-05 23:05:36 +00:00
# include <cJSON.h>
# include <logger.h>
# include <database.h>
# include <models/controller.h>
# include <models/junction_tag.h>
# include <models/tag.h>
static int
db_update_insert ( controller_t * controller , sqlite3_stmt * stmt )
{
2020-08-14 21:48:57 +00:00
LOGGER_DEBUG ( " saving controller '%s' into database (id: %d) \n " , controller - > name , controller - > id ) ;
2020-05-05 23:05:36 +00:00
int rc ;
sqlite3_bind_int ( stmt , 1 , controller - > id ) ;
sqlite3_bind_blob ( stmt , 2 , controller - > uid , sizeof ( uuid_t ) , SQLITE_STATIC ) ;
sqlite3_bind_text ( stmt , 3 , controller - > name , - 1 , SQLITE_STATIC ) ;
sqlite3_bind_text ( stmt , 4 , controller - > ip , - 1 , SQLITE_STATIC ) ;
sqlite3_bind_int ( stmt , 5 , controller - > active ) ;
sqlite3_bind_int ( stmt , 6 , controller - > port ) ;
sqlite3_bind_int ( stmt , 7 , controller - > relay_count ) ;
rc = sqlite3_step ( stmt ) ;
sqlite3_finalize ( stmt ) ;
return rc ! = SQLITE_DONE ;
}
static controller_t *
controller_db_select_mapper ( sqlite3_stmt * stmt )
{
controller_t * new_controller = malloc ( sizeof ( controller_t ) ) ;
for ( int i = 0 ; i < sqlite3_column_count ( stmt ) ; i + + )
{
const char * name = sqlite3_column_name ( stmt , i ) ;
switch ( name [ 0 ] )
{
case ' a ' : // active
new_controller - > active = ( bool ) sqlite3_column_int ( stmt , i ) ;
break ;
case ' i ' :
switch ( name [ 1 ] )
{
case ' d ' : // id
new_controller - > id = sqlite3_column_int ( stmt , i ) ;
break ;
case ' p ' : // ip
strncpy ( new_controller - > ip , ( const char * ) sqlite3_column_text ( stmt , i ) , 16 ) ;
break ;
default : // ignore columns not implemented
break ;
}
break ;
case ' n ' : // name
strncpy ( new_controller - > name , ( const char * ) sqlite3_column_text ( stmt , i ) , 127 ) ;
break ;
case ' p ' : // port
new_controller - > port = sqlite3_column_int ( stmt , i ) ;
break ;
case ' r ' : // relay_count
new_controller - > relay_count = sqlite3_column_int ( stmt , i ) ;
break ;
case ' u ' : // uid
uuid_copy ( new_controller - > uid , ( const unsigned char * ) sqlite3_column_blob ( stmt , i ) ) ;
break ;
default : // ignore columns not implemented
break ;
}
}
new_controller - > relays = relay_get_by_controller_id ( new_controller - > id ) ;
return new_controller ;
}
static controller_t * *
controller_db_select ( sqlite3_stmt * stmt )
{
controller_t * * all_controllers = malloc ( sizeof ( controller_t * ) ) ;
int row = 0 ;
while ( true )
{
int s ;
s = sqlite3_step ( stmt ) ;
if ( s = = SQLITE_ROW )
{
controller_t * new_controller = controller_db_select_mapper ( stmt ) ;
row + + ;
all_controllers = ( controller_t * * ) realloc ( all_controllers , sizeof ( controller_t * ) * ( row + 1 ) ) ;
all_controllers [ row - 1 ] = new_controller ;
}
else
{
if ( s = = SQLITE_DONE )
{
break ;
}
else
{
2020-07-26 19:00:05 +00:00
LOGGER_ERR ( " error selecting controllers from database: %s \n " , sqlite3_errstr ( s ) ) ;
2020-05-05 23:05:36 +00:00
break ;
}
}
}
sqlite3_finalize ( stmt ) ;
all_controllers [ row ] = NULL ;
return all_controllers ;
}
int
controller_save ( controller_t * controller )
{
2020-08-15 10:13:03 +00:00
int opened_transaction = database_transaction_begin ( ) ;
2020-05-05 23:05:36 +00:00
sqlite3_stmt * stmt ;
if ( controller - > id )
{
sqlite3_prepare_v2 ( global_database , " UPDATE controllers set uid = ?2, name = ?3, ip = ?4, active = ?5, port = ?6, relay_count = ?7 WHERE id = ?1; " , - 1 , & stmt , NULL ) ;
}
else
{
sqlite3_prepare_v2 ( global_database , " INSERT INTO controllers(uid, name, ip, active, port, relay_count) values (?2, ?3, ?4, ?5, ?6, ?7); " , - 1 , & stmt , NULL ) ;
}
int result = db_update_insert ( controller , stmt ) ;
if ( result )
{
if ( controller - > id )
{
2020-07-26 19:00:05 +00:00
LOGGER_ERR ( " error inserting data: %s \n " , sqlite3_errmsg ( global_database ) ) ;
2020-05-05 23:05:36 +00:00
}
else
{
2020-07-26 19:00:05 +00:00
LOGGER_ERR ( " error updating data: %s \n " , sqlite3_errmsg ( global_database ) ) ;
2020-05-05 23:05:36 +00:00
}
2020-08-15 10:13:03 +00:00
if ( opened_transaction )
{
database_transaction_rollback ( ) ;
}
2020-05-05 23:05:36 +00:00
}
else
{
2020-05-11 20:36:47 +00:00
if ( ! controller - > id )
{
controller - > id = sqlite3_last_insert_rowid ( global_database ) ;
}
2020-08-15 10:13:03 +00:00
if ( opened_transaction )
{
database_transaction_commit ( ) ;
}
2020-05-05 23:05:36 +00:00
}
2020-08-13 14:29:26 +00:00
cache_invalidate_controller ( controller - > id ) ;
2020-05-05 23:05:36 +00:00
return result ;
}
int
controller_remove ( controller_t * controller )
{
sqlite3_stmt * stmt ;
if ( ! controller - > id )
{
return 0 ;
}
sqlite3_prepare_v2 ( global_database , " DELETE FROM controllers WHERE id=?1; " , - 1 , & stmt , NULL ) ;
sqlite3_bind_int ( stmt , 1 , controller - > id ) ;
int rc = sqlite3_step ( stmt ) ;
sqlite3_finalize ( stmt ) ;
return rc ! = SQLITE_DONE ;
}
void
controller_free ( controller_t * controller )
{
relay_free_list ( controller - > relays ) ;
free ( controller ) ;
}
void
controller_free_list ( controller_t * * controllers )
{
for ( int i = 0 ; controllers [ i ] ! = NULL ; + + i )
{
controller_free ( controllers [ i ] ) ;
}
free ( controllers ) ;
}
2020-08-14 21:18:22 +00:00
cJSON *
2020-05-05 23:05:36 +00:00
controller_to_json ( controller_t * controller )
{
2020-08-14 21:18:22 +00:00
cJSON * json ;
2020-08-13 14:29:26 +00:00
char * cached = cache_get_json_controller ( controller - > id ) ;
if ( cached )
{
2020-08-14 21:18:22 +00:00
json = cJSON_CreateRaw ( cached ) ;
free ( cached ) ;
return json ;
2020-08-13 14:29:26 +00:00
}
2020-08-10 22:10:59 +00:00
char uuid_str [ UUID_STR_LEN ] ;
uuid_unparse ( controller - > uid , uuid_str ) ;
LOGGER_DEBUG ( " JSONifying controller %s \n " , uuid_str ) ;
2020-08-14 21:18:22 +00:00
json = cJSON_CreateObject ( ) ;
2020-05-05 23:05:36 +00:00
cJSON * json_name = cJSON_CreateString ( controller - > name ) ;
if ( json_name = = NULL )
{
cJSON_Delete ( json ) ;
return NULL ;
}
cJSON_AddItemToObject ( json , " name " , json_name ) ;
cJSON * json_id = cJSON_CreateString ( uuid_str ) ;
if ( json_name = = NULL )
{
cJSON_Delete ( json ) ;
return NULL ;
}
cJSON_AddItemToObject ( json , " id " , json_id ) ;
cJSON * json_ip = cJSON_CreateString ( controller - > ip ) ;
if ( json_ip = = NULL )
{
cJSON_Delete ( json ) ;
return NULL ;
}
cJSON_AddItemToObject ( json , " ip " , json_ip ) ;
cJSON * json_port = cJSON_CreateNumber ( controller - > port ) ;
if ( json_port = = NULL )
{
cJSON_Delete ( json ) ;
return NULL ;
}
cJSON_AddItemToObject ( json , " port " , json_port ) ;
cJSON * json_relay_count = cJSON_CreateNumber ( controller - > relay_count ) ;
if ( json_relay_count = = NULL )
{
cJSON_Delete ( json ) ;
return NULL ;
}
cJSON_AddItemToObject ( json , " relay_count " , json_relay_count ) ;
cJSON * json_active = cJSON_CreateBool ( controller - > active ) ;
if ( json_active = = NULL )
{
cJSON_Delete ( json ) ;
return NULL ;
}
cJSON_AddItemToObject ( json , " active " , json_active ) ;
2020-05-06 23:38:13 +00:00
relay_t * * relays = relay_get_by_controller_id ( controller - > id ) ;
cJSON * json_relays = cJSON_CreateArray ( ) ;
for ( int i = 0 ; relays [ i ] ! = NULL ; + + i )
{
2020-08-14 21:18:22 +00:00
cJSON * json_relay = relay_to_json ( relays [ i ] ) ;
2020-08-13 14:29:26 +00:00
cJSON_AddItemToArray ( json_relays , json_relay ) ;
2020-05-06 23:38:13 +00:00
}
cJSON_AddItemToObject ( json , " relays " , json_relays ) ;
relay_free_list ( relays ) ;
2020-05-05 23:05:36 +00:00
2020-08-14 21:18:22 +00:00
char * json_str = cJSON_Print ( json ) ;
cache_put_json_controller ( controller - > id , json_str ) ;
2020-08-13 14:29:26 +00:00
cJSON_Delete ( json ) ;
2020-08-14 21:18:22 +00:00
json = cJSON_CreateRaw ( json_str ) ;
free ( json_str ) ;
return json ;
2020-05-05 23:05:36 +00:00
}
controller_t *
controller_get_by_id ( int id )
{
2020-08-10 22:10:59 +00:00
LOGGER_DEBUG ( " getting controller [id=%d] from database \n " , id ) ;
2020-05-05 23:05:36 +00:00
sqlite3_stmt * stmt ;
sqlite3_prepare_v2 ( global_database , " SELECT * FROM controllers WHERE id = ?1; " , - 1 , & stmt , NULL ) ;
sqlite3_bind_int ( stmt , 1 , id ) ;
controller_t * * sql_result = controller_db_select ( stmt ) ;
controller_t * result = sql_result [ 0 ] ;
free ( sql_result ) ;
return result ;
}
controller_t *
controller_get_by_uid ( uuid_t uid )
{
2020-08-10 22:10:59 +00:00
char uuid_str [ UUID_STR_LEN ] ;
uuid_unparse ( uid , uuid_str ) ;
LOGGER_DEBUG ( " getting controller [uid=%s] from database \n " , uuid_str ) ;
2020-05-05 23:05:36 +00:00
sqlite3_stmt * stmt ;
sqlite3_prepare_v2 ( global_database , " SELECT * FROM controllers WHERE uid = ?1; " , - 1 , & stmt , NULL ) ;
sqlite3_bind_blob ( stmt , 1 , uid , sizeof ( uuid_t ) , SQLITE_STATIC ) ;
controller_t * * sql_result = controller_db_select ( stmt ) ;
controller_t * result = sql_result [ 0 ] ;
free ( sql_result ) ;
return result ;
}
controller_t * *
controller_get_all ( )
{
2020-08-10 22:10:59 +00:00
LOGGER_DEBUG ( " getting all controllers from database \n " ) ;
2020-05-05 23:05:36 +00:00
sqlite3_stmt * stmt ;
sqlite3_prepare_v2 ( global_database , " SELECT * FROM controllers; " , - 1 , & stmt , NULL ) ;
return controller_db_select ( stmt ) ;
}