/******************************************************************************** * Copyright: (C) 2020 LingYun IoT System Studio * All rights reserved. * * Filename: sqlite_cli.c * Description: This head file is for client to save TLV packet in sqlite. * * Version: 1.0.0(2020年05月13日) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "2020年05月13日 12时14分23秒" * ********************************************************************************/ #include "sqlite_cli.h" #include "logger.h" static sqlite3 *s_clidb = NULL; /* description: open or create sqlite database if not exist * input args: * $db_file: sqlite database file name * return value: <0: failure 0:ok * */ int clidb_init(const char *db_file) { char sql[256]; char *errmsg = NULL; if( !db_file ) { log_err("Invalid input arguments\n"); return -1; } /*+-------------------------------------------------+ *| TLV packet database already exist, just open it | *+-------------------------------------------------+*/ if( 0==access(db_file, F_OK) ) { if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) ) { log_err("open TLV packet database file '%s' failure\n", db_file); return -2; } log_nrml("open TLV packet database file '%s' ok\n", db_file); return 0; } /*+---------------------------------------------------+ *| TLV packet database not exist, create and init it | *+---------------------------------------------------+*/ if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) ) { log_err("create TLV packet database file '%s' failure\n", db_file); return -2; } /* SQLite continues without syncing as soon as it has handed data off to the operating system */ sqlite3_exec(s_clidb, "pragma synchronous = OFF; ", NULL, NULL, NULL); /* enable full auto vacuum, Auto increase/decrease */ sqlite3_exec(s_clidb, "pragma auto_vacuum = 2 ; ", NULL, NULL, NULL); /* Create firehost table in the database */ strncpy(sql, "create table tlvpack(packet blob);", sizeof(sql)); if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, NULL, &errmsg) ) { log_err("create table in tlv packet database file '%s' failure: %s\n", db_file, errmsg); sqlite3_free(errmsg); /* free errmsg */ sqlite3_close(s_clidb); /* close databse */ unlink(db_file); /* remove database file */ } log_nrml("create and init TLV packet database file '%s' ok\n", db_file); return 0; } /* description: close sqlite database handler * return value: none */ void clidb_term(void) { log_warn("close tlv client sqlite database now\n"); sqlite3_close(s_clidb); return ; } /* description: push TLV packet into database * input args: * $pack: tlv packet pointer * return value: <0: failure 0:ok */ int clidb_push_tlvpack(tlv_buf_t *pack) { int rv = 0; char *errmsg = NULL; sqlite3_stmt *stat = NULL; if( !pack ) { log_err("Invalid input arguments\n"); return -1; } if( ! s_clidb ) { log_err("client tlv packet database not opened\n"); return -2; } rv = sqlite3_prepare_v2(s_clidb, "insert into tlvpack(packet) values(?)", -1, &stat, NULL); if(SQLITE_OK!=rv || !stat) { log_err("blob add sqlite3_prepare_v2 failure\n"); rv = -2; goto OUT; } if( SQLITE_OK != sqlite3_bind_blob(stat, 1, pack, sizeof(*pack), NULL) ) { log_err("blob add sqlite3_bind_blob failure\n"); rv = -3; goto OUT; } rv = sqlite3_step(stat); if( SQLITE_DONE!=rv && SQLITE_ROW!=rv ) { log_err("blob add sqlite3_step failure\n"); rv = -4; goto OUT; } OUT: sqlite3_finalize(stat); if( rv < 0 ) log_nrml("add new TLV packet report data into database failure, rv=%d\n", rv); else log_nrml("add new TLV packet report data into database ok\n"); return rv; } /* description: push TLV packet into database * input args: * $pack: tlv packet pointer * $id: item ID pointer, which can be used as key when remove * return value: <0: failure 0:ok */ int clidb_pop_tlvpack(tlv_buf_t *pack, int *id) { int rv = 0; sqlite3_stmt *stat = NULL; const tlv_buf_t *blob_ptr; if( !id || ! pack ) { log_err("invalid input arguments\n"); return -1; } if( ! s_clidb ) { log_err("client tlv packet database not opened\n"); return -2; } /* Only query the first packet record */ rv = sqlite3_prepare_v2(s_clidb, "select rowid,packet from tlvpack limit 0,1;", -1, &stat, NULL); if(SQLITE_OK!=rv || !stat) { log_err("firehost sqlite3_prepare_v2 failure\n"); rv = -3; goto out; } rv = sqlite3_step(stat); if( SQLITE_DONE!=rv && SQLITE_ROW!=rv ) { log_err("firehost sqlite3_step failure\n"); rv = -5; goto out; } /* 2rd argument<0> means first segement is rowid */ *id = sqlite3_column_int(stat, 0); if(*id <= 0) { rv = 0; goto out; } /* 2rd argument<1> means first segement is packet */ blob_ptr = sqlite3_column_blob(stat, 1); if( !blob_ptr ) { rv = 0; goto out; } memcpy(pack, blob_ptr, sizeof(*pack)); log_trace("Read TLV packet from database:\n"); logger_dump(LOG_LEVEL_TRACE, (char *)pack->buf, pack->len); rv = 1; out: sqlite3_finalize(stat); if( rv < 0) log_err("query TLV packet from database failure, rv=%d\n", rv); else if( rv > 0 ) log_nrml("query TLV packet from database ok\n"); return rv; } /* description: remove sepcified TLV packet from database * input args: * $id: remove item ID * return value: <0: failure 0:ok */ int clidb_del_tlvpack(int id) { char sql[SQL_COMMAND_LEN]; char *errmsg = NULL; if( !id ) { log_err("invalid input arguments\n"); return -1; } if( ! s_clidb ) { log_err("client tlv packet database not opened\n"); return -2; } /* remove packet from db */ memset(sql, 0, sizeof(sql)); snprintf(sql, sizeof(sql), "delete from tlvpack where rowid=%d;", id); if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, 0, &errmsg) ) { log_err("delete TLV packet ID[%d] from database failure: %s\n", id, errmsg); sqlite3_free(errmsg); return -2; } log_warn("delete TLV packet ID[%d] from database ok\n", id); /* Vacuum the database */ sqlite3_exec(s_clidb, "VACUUM;", NULL, 0, NULL); return 0; }