APUE Learning Example Source Code
guowenxue
2020-06-06 cd10eef059e9d9c34c927f3ac53ac43f4a9716c1
add TLV client database save and send support
2 files added
2 files modified
411 ■■■■■ changed files
prj1_tlv/lylib/sqlite_cli.c 268 ●●●●● patch | view | raw | blame | history
prj1_tlv/lylib/sqlite_cli.h 60 ●●●●● patch | view | raw | blame | history
prj1_tlv/makefile 2 ●●● patch | view | raw | blame | history
prj1_tlv/tlv_client.c 81 ●●●● patch | view | raw | blame | history
prj1_tlv/lylib/sqlite_cli.c
New file
@@ -0,0 +1,268 @@
/********************************************************************************
 *      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 <guowenxue@gmail.com>
 *      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;
}
prj1_tlv/lylib/sqlite_cli.h
New file
@@ -0,0 +1,60 @@
/********************************************************************************
 *      Copyright:  (C) 2020 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  sqlite_cli.h
 *    Description:  This head file is for client to save TLV packet in sqlite.
 *
 *        Version:  1.0.0(2020年05月13日)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2020年05月13日 12时14分23秒"
 *
 ********************************************************************************/
#ifndef  _SQLITE_CLI_H_
#define  _SQLITE_CLI_H_
#include "sqlite3.h"
#include "tlv_pack.h"
#define SQL_COMMAND_LEN        256
/*  description: open or create sqlite database if not exist
 *   input args:
 *              $db_file: sqlite database file name
 * return value: <0: failure   0:ok
 * */
extern int clidb_init(const char *db_file);
/*  description: close sqlite database handler
 * return value: none
 */
extern void clidb_term(void);
/*  description: push TLV packet into database
 *   input args:
 *               $pack:  tlv packet pointer
 * return value: <0: failure   0:ok
 */
extern int clidb_push_tlvpack(tlv_buf_t *pack);
/*  description: pop one TLV packet from 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
 */
extern int clidb_pop_tlvpack(tlv_buf_t *pack, int *id);
/*  description: remove sepcified TLV packet from database
 *   input args:
 *               $id:    remove item ID
 * return value: <0: failure   0:ok
 */
extern int clidb_del_tlvpack(int id);
#endif   /* ----- #ifndef _SQLITE_CLI_H_  ----- */
prj1_tlv/makefile
@@ -17,7 +17,7 @@
# Linker flags
LDFLAGS=-L${SUBDIR1} -l${SUBDIR1} 
LDFLAGS+=-lpthread
LDFLAGS+=-lpthread -lsqlite3
all: banner lib${SUBDIR1}
prj1_tlv/tlv_client.c
@@ -22,6 +22,7 @@
#include "ds18b20.h"
#include "socket.h"
#include "tlv_pack.h"
#include "sqlite_cli.h"
#define PROG_VERSION     "1.0.0"
#define RPI_SN           "RPI00001"
@@ -130,15 +131,11 @@
        } 
    }
#if 1
    if( !host )
    {
        printf("ERROR: No argument specify host server address and port, please refer to usage\n");
    //    return 1;
        return 1;
    }
#endif
    /* check program already running or not, if already running then exit, or set running as daemon */
    snprintf(pid_file, sizeof(pid_file), "/tmp/%s.pid", progname);
@@ -162,18 +159,16 @@
        return 2;
    }
    log_nrml("Program start running\n");
    /* install signal proc handler */
    install_proc_signal();
    log_nrml("Program start running\n");
#if 0
    if( initial_db(&sqldb, db_file) < 0)
    if( clidb_init("./tlv_client.db")< 0)
    {
        log_err("initialise sqlite database failure\n");
        log_err("initial sqlite database failure\n");
        return 3;
    }
#endif
    last_time = 0;
@@ -181,7 +176,7 @@
    while( !g_signal.stop )
    {
        time(&cur_time);
        if( cur_time-last_time > 3)
        if( cur_time-last_time > 10)
        {
            log_nrml("start sample temperature now.\n");
            rv = 0;
@@ -213,44 +208,49 @@
            }
        }
        if( (tlv.flag&TLV_FLAG_TX) && SOCK_STAT_CONNECTED==sock.status )
        if( SOCK_STAT_CONNECTED == sock.status )
        {
            if(0 == socket_send_tlv_pack(&sock, &tlv, DEF_ACK_TIMEOUT, DEF_RETRYTIMES) )
            {
                tlv.flag = 0;
            /* send current new sample TLV packet  */
            if( tlv.flag&TLV_FLAG_TX )
            {
                if(0 == socket_send_tlv_pack(&sock, &tlv, DEF_ACK_TIMEOUT, DEF_RETRYTIMES) )
                {
                    tlv.flag = 0;
                }
            }
        }
#if 0
        /* need to send TLV packet in database now  */
        for(i=0; i<5; i++)
        {
            /* get a TLV record from DB and send it by socket  */
            /* rv<0: Erorr  rv=0: No record  >0: record count  */
            rv = get_db_tlv_pack(sqldb, tlv, size) ;
            if( rv <= 0)
                break;
            if( 0 == socket_send_tlv_pack() )
            /* get TLV apcket from database and send it by socket, maxim 5 records  */
            for(i=0; i<5; i++)
            {
                /* delete the record from DB */
                del_db_tlv_pack();
                int            id;
                tlv_buf_t      tmp;
                if( clidb_pop_tlvpack(&tmp, &id) <= 0 )
                {
                    break;
                }
                /* send the TLV packet from database */
                if(0 == socket_send_tlv_pack(&sock, &tmp, DEF_ACK_TIMEOUT, DEF_RETRYTIMES) )
                {
                    /* delete the record from DB */
                    clidb_del_tlvpack(id);
                }
            }
        }
SAVE_DB:
        if( tlv_buf.flag & TLV_FLAG_DB)
        if( tlv.flag & TLV_FLAG_DB )
        {
            record_db_tlv(sqldb, tlv_buf, tlv_len);
            clidb_push_tlvpack(&tlv);
            tlv.flag = 0;
        }
#endif
        sleep(1);
    }
    logger_term();
    //db_term();
    clidb_term();
    return 0;
@@ -309,6 +309,9 @@
    int            rv = 0; 
    char           buf[128];
    if( sock->status != SOCK_STAT_CONNECTED )
        return -1;
    log_info("start to send tlv packet from socket now\n");
    for(i=0; i<retry_times; i++)
@@ -322,8 +325,12 @@
        if( (rv=socket_recv(sock, buf, sizeof(buf), timeout)) < 0 )
        {
            log_err("read ACK from server failure, rv=%d\n", rv);
            return -2;
            return 0;
        }
        /* todo: parser ACK from buf  */
        if( ACK )
            break;
    }
    return 0;