RaspberrPi project source code
Guo Wenxue
2023-09-08 bffa2be267ab1fdafbc6c9348df053e477e63f49
commit | author | age
29b331 1 /********************************************************************************
GW 2  *      Copyright:  (C) 2020 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  database.c
6  *    Description:  This library used to operate blob packet in sqlite database.
7  *
8  *        Version:  1.0.0(2020年05月13日)
9  *         Author:  Guo Wenxue <guowenxue@gmail.com>
10  *      ChangeLog:  1, Release initial version on "2020年05月13日 12时14分23秒"
11  *
12  ********************************************************************************/
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include "database.h"
19 #include "logger.h"
20
21 /* Blob packet table name */
22 #define TABLE_NAME     "PackTable"
23
24 /* Use static global handler here in order to simplify the API,
25  * But it will make this library not thread safe
26  */
27 static sqlite3         *s_clidb = NULL;
28
29
30 /* description: open or create sqlite database if not exist
31  * input args:
32  * $db_file: sqlite database file name
33  * return value: <0: failure   0:ok
34  * */
35 int database_init(const char *db_file)
36 {
37     char               sql[SQL_COMMAND_LEN]={0};
38     char              *errmsg = NULL;
39
40     if( !db_file )
41     {
42         log_error("%s() Invalid input arguments\n", __func__);
43         return -1;
44     }
45
46     /*+------------------------------------------+
47      *|   database already exist, just open it   |
48      *+------------------------------------------+*/
49     if( 0==access(db_file, F_OK) )
50     {
51         if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) )
52         {
53             log_error("open database file '%s' failure\n", db_file);
54             return -2;
55         }
56         log_info("open database file '%s' ok\n", db_file);
57         return 0;
58     }
59
60     /*+-----------------------------------------+
61      *|  database not exist, create and init it |
62      *+-----------------------------------------+*/
63
64     if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) )
65     {
66         log_error("create database file '%s' failure\n", db_file);
67         return -2;
68     }
69
70     /* SQLite continues without syncing as soon as it has handed data off to the operating system */
71     sqlite3_exec(s_clidb, "pragma synchronous = OFF; ", NULL, NULL, NULL);
72
73     /* enable full auto vacuum, Auto increase/decrease  */
74     sqlite3_exec(s_clidb, "pragma auto_vacuum = 2 ; ", NULL, NULL, NULL);
75
76     /* Create firehost table in the database */
77     snprintf(sql, sizeof(sql), "CREATE TABLE %s(packet BLOB);", TABLE_NAME);
78     if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, NULL, &errmsg) )
79     {
80         log_error("create data_table in database file '%s' failure: %s\n", db_file, errmsg);
81         sqlite3_free(errmsg); /* free errmsg  */
82         sqlite3_close(s_clidb);   /* close databse */
83         unlink(db_file);      /* remove database file */
84         return -3;
85     }
86
87     log_info("create and init database file '%s' ok\n", db_file);
88     return 0;
89 }
90
91
92 /* description: close sqlite database handler
93  * return value: none
94  */
95 void database_term(void)
96 {
97     log_warn("close sqlite database now\n");
98     sqlite3_close(s_clidb);
99
100     return ;
101 }
102
103
104 /* description: push a blob packet into database
105  * input args:
106  *      $pack:  blob packet data address
107  *      $size:  blob packet data bytes
108  * return value: <0: failure   0:ok
109  */
110 int database_push_packet(void *pack, int size)
111 {
112     char               sql[SQL_COMMAND_LEN]={0};
113     int                rv = 0;
114     sqlite3_stmt      *stat = NULL;
115
116     if( !pack || size<=0 )
117     {
118         log_error("%s() Invalid input arguments\n", __func__);
119         return -1;
120     }
121
122     if( ! s_clidb )
123     {
124         log_error("sqlite database not opened\n");
125         return -2;
126     }
127
bffa2b 128     snprintf(sql, sizeof(sql), "INSERT INTO %s(packet) VALUES(?)", TABLE_NAME);
29b331 129     rv = sqlite3_prepare_v2(s_clidb, sql, -1, &stat, NULL);
GW 130     if(SQLITE_OK!=rv || !stat)
131     {
132         log_error("blob add sqlite3_prepare_v2 failure\n");
133         rv = -2;
134         goto OUT;
135     }
136
137     if( SQLITE_OK != sqlite3_bind_blob(stat, 1, pack, size, NULL) )
138     {
139         log_error("blob add sqlite3_bind_blob failure\n");
140         rv = -3;
141         goto OUT;
142     }
143
144     rv = sqlite3_step(stat);
145     if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
146     {
147         log_error("blob add sqlite3_step failure\n");
148         rv = -4;
149         goto OUT;
150     }
151
152 OUT:
153     sqlite3_finalize(stat);
154
155     if( rv < 0 )
156         log_error("add new blob packet into database failure, rv=%d\n", rv);
157     else
158         log_info("add new blob packet into database ok\n");
159
160     return rv;
161 }
162
163
164 /* description: pop the first blob packet from database
165  * input args:
166  *      $pack:  blob packet output buffer address
167  *      $size:  blob packet output buffer size
168  *      $byte:  blob packet bytes
169  * return value: <0: failure   0:ok
170  */
171 int database_pop_packet(void *pack, int size, int *bytes)
172 {
173     char               sql[SQL_COMMAND_LEN]={0};
174     int                rv = 0;
175     sqlite3_stmt      *stat = NULL;
176     const void        *blob_ptr;
177
178     if( !pack || size<=0 )
179     {
180         log_error("%s() Invalid input arguments\n", __func__);
181         return -1;
182     }
183
184     if( ! s_clidb )
185     {
186         log_error("sqlite database not opened\n");
187         return -2;
188     }
189
190     /* Only query the first packet record */
bffa2b 191     snprintf(sql, sizeof(sql), "SELECT packet FROM %s WHERE rowid = (SELECT rowid FROM %s LIMIT 1);", TABLE_NAME, TABLE_NAME);
29b331 192     rv = sqlite3_prepare_v2(s_clidb, sql, -1, &stat, NULL);
GW 193     if(SQLITE_OK!=rv || !stat)
194     {
195         log_error("firehost sqlite3_prepare_v2 failure\n");
196         rv = -3;
197         goto out;
198     }
199
200     rv = sqlite3_step(stat);
201     if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
202     {
203         log_error("firehost sqlite3_step failure\n");
204         rv = -5;
205         goto out;
206     }
207
208     /* 1rd argument<0> means first segement is packet  */
209     blob_ptr = sqlite3_column_blob(stat, 0);
210     if( !blob_ptr )
211     {
212         rv = -6;
213         goto out;
214     }
215
216     *bytes = sqlite3_column_bytes(stat, 0);
217
218     if( *bytes > size )
219     {
220         log_error("blob packet bytes[%d] larger than bufsize[%d]\n", *bytes, size);
221         *bytes = 0;
222         rv = -1;
223     }
224
225     memcpy(pack, blob_ptr, *bytes);
226     rv = 0;
227
228 out:
229     sqlite3_finalize(stat);
230     return rv;
231 }
232
233
234 /* description: remove the first blob packet from database
235  * input args: none
236  * return value: <0: failure   0:ok
237  */
238 int database_del_packet(void)
239 {
240     char               sql[SQL_COMMAND_LEN]={0};
241     char              *errmsg = NULL;
242
243     if( ! s_clidb )
244     {
245         log_error("sqlite database not opened\n");
246         return -2;
247     }
248
249     /*  remove packet from db */
250     memset(sql, 0, sizeof(sql));
bffa2b 251     snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE rowid = (SELECT rowid FROM %s LIMIT 1);", TABLE_NAME, TABLE_NAME);
29b331 252     if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, 0, &errmsg) )
GW 253     {
254         log_error("delete first blob packet from database failure: %s\n", errmsg);
255         sqlite3_free(errmsg);
256         return -2;
257     }
258     log_warn("delete first blob packet from database ok\n");
259
260     /*  Vacuum the database */
261     sqlite3_exec(s_clidb, "VACUUM;", NULL, 0, NULL);
262
263     return 0;
264 }
265