2020-05-05 23:05:36 +00:00
# include <stdlib.h>
# include <string.h>
# include <sqlite3.h>
# 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 )
{
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
{
LOG_ERROR ( " error selecting controllers from database: %s \n " , sqlite3_errstr ( s ) ) ;
break ;
}
}
}
sqlite3_finalize ( stmt ) ;
all_controllers [ row ] = NULL ;
return all_controllers ;
}
int
controller_save ( controller_t * controller )
{
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 )
{
LOG_ERROR ( " error inserting data: %s \n " , sqlite3_errmsg ( global_database ) ) ;
}
else
{
LOG_ERROR ( " error updating data: %s \n " , sqlite3_errmsg ( global_database ) ) ;
}
}
else
{
controller - > id = sqlite3_last_insert_rowid ( global_database ) ;
}
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 ) ;
}
cJSON *
controller_to_json ( controller_t * controller )
{
cJSON * json = cJSON_CreateObject ( ) ;
cJSON * json_name = cJSON_CreateString ( controller - > name ) ;
if ( json_name = = NULL )
{
cJSON_Delete ( json ) ;
return NULL ;
}
cJSON_AddItemToObject ( json , " name " , json_name ) ;
char uuid_str [ UUID_STR_LEN ] ;
uuid_unparse ( controller - > uid , uuid_str ) ;
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 )
{
cJSON_AddItemToArray ( json_relays , relay_to_json ( relays [ i ] ) ) ;
}
cJSON_AddItemToObject ( json , " relays " , json_relays ) ;
relay_free_list ( relays ) ;
2020-05-05 23:05:36 +00:00
return json ;
}
controller_t *
controller_get_by_id ( int id )
{
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 )
{
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 ( )
{
sqlite3_stmt * stmt ;
sqlite3_prepare_v2 ( global_database , " SELECT * FROM controllers; " , - 1 , & stmt , NULL ) ;
return controller_db_select ( stmt ) ;
}