Update snapshot(2017-12-06)
[platform/upstream/iotivity.git] / resource / csdk / resource-directory / src / internal / rd_database.c
1 //******************************************************************
2 //
3 // Copyright 2016 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License a
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "sqlite3.h"
25 #include "logger.h"
26 #include "ocpayload.h"
27 #include "octypes.h"
28 #include "oic_malloc.h"
29 #include "oic_string.h"
30
31 #ifdef RD_SERVER
32
33 #define TAG "RD_DATABASE"
34 #define RD_PATH "RD.db"
35
36 static sqlite3 *gRDDB = NULL;
37
38 static const uint8_t device_index = 2;
39 static const uint8_t ttl_index = 3;
40 static const uint8_t address_index = 4;
41
42 static const uint8_t uri_index = 2;
43 static const uint8_t p_index = 5;
44 static const uint8_t mt_index = 7;
45 static const uint8_t d_index = 8;
46
47 static const uint8_t rt_value_index = 1;
48 static const uint8_t rt_link_id_index = 2;
49
50 static const uint8_t if_value_index = 1;
51 static const uint8_t if_link_id_index = 2;
52
53 static const uint8_t bind_index_value = 1;
54
55 #define VERIFY_SQLITE(arg) \
56     if (SQLITE_OK != (arg)) \
57     { \
58         OIC_LOG_V(ERROR, TAG, "Error in " #arg ", Error Message: %s",  sqlite3_errmsg(gRDDB)); \
59         sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL); \
60         return OC_STACK_ERROR; \
61     }
62
63 #define CHECK_DATABASE_INIT \
64     if (!gRDDB) \
65     { \
66         OIC_LOG(ERROR, TAG, "Database is not initialized."); \
67         return OC_STACK_ERROR; \
68     }
69
70 #define STR(a) #a
71 #define XSTR(a) STR(a)
72
73 #define RD_TABLE \
74     "create table RD_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT, " \
75     XSTR(OC_RSRVD_DEVICE_ID) " UNIQUE NOT NULL, " \
76     XSTR(OC_RSRVD_TTL) " NOT NULL, " \
77     "ADDRESS NOT NULL);"
78
79 #define RD_LL_TABLE  \
80     "create table RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)" INTEGER PRIMARY KEY AUTOINCREMENT, " \
81     XSTR(OC_RSRVD_HREF)  "," \
82     XSTR(OC_RSRVD_REL)   ","  \
83     XSTR(OC_RSRVD_TITLE) "," \
84     XSTR(OC_RSRVD_BITMAP)"," \
85     XSTR(OC_RSRVD_TTL)   "," \
86     XSTR(OC_RSRVD_MEDIA_TYPE) "," \
87     "DEVICE_ID INT NOT NULL, " \
88     "FOREIGN KEY(DEVICE_ID) REFERENCES RD_DEVICE_LIST(ID) ON DELETE CASCADE );"
89
90 #define RD_RT_TABLE \
91     "create table RD_LINK_RT(" XSTR(OC_RSRVD_RESOURCE_TYPE) " NOT NULL, " \
92     "LINK_ID INT NOT NULL, "\
93     "FOREIGN KEY("XSTR(LINK_ID)") REFERENCES RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)") " \
94     "ON DELETE CASCADE);"
95
96 #define RD_IF_TABLE \
97     "create table RD_LINK_IF(" XSTR(OC_RSRVD_INTERFACE) " NOT NULL, " \
98     "LINK_ID INT NOT NULL, "\
99     "FOREIGN KEY("XSTR(LINK_ID)") REFERENCES RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)") " \
100     "ON DELETE CASCADE);"
101
102 static void errorCallback(void *arg, int errCode, const char *errMsg)
103 {
104     OC_UNUSED(arg);
105     OC_UNUSED(errCode);
106     OC_UNUSED(errMsg);
107     OIC_LOG_V(ERROR, TAG, "SQLLite Error: %s : %d", errMsg, errCode);
108 }
109
110 OCStackResult OCRDDatabaseInit(const char *path)
111 {
112     if (SQLITE_OK == sqlite3_config(SQLITE_CONFIG_LOG, errorCallback))
113     {
114         OIC_LOG_V(INFO, TAG, "SQLite debugging log initialized.");
115     }
116
117     int sqlRet = sqlite3_open_v2(!path ? RD_PATH : path, &gRDDB, SQLITE_OPEN_READWRITE, NULL);
118     if (SQLITE_OK != sqlRet)
119     {
120         OIC_LOG(DEBUG, TAG, "RD database file did not open, as no table exists.");
121         OIC_LOG(DEBUG, TAG, "RD creating new table.");
122         sqlRet = sqlite3_open_v2(!path ? RD_PATH : path, &gRDDB,
123                                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
124         if (SQLITE_OK == sqlRet)
125         {
126             VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_TABLE, NULL, NULL, NULL));
127             OIC_LOG(DEBUG, TAG, "RD created RD_DEVICE_LIST table.");
128
129             VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_LL_TABLE, NULL, NULL, NULL));
130             OIC_LOG(DEBUG, TAG, "RD created RD_DEVICE_LINK_LIST table.");
131
132             VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_RT_TABLE, NULL, NULL, NULL));
133             OIC_LOG(DEBUG, TAG, "RD created RD_LINK_RT table.");
134
135             VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_IF_TABLE, NULL, NULL, NULL));
136             OIC_LOG(DEBUG, TAG, "RD created RD_LINK_IF table.");
137             sqlRet = SQLITE_OK;
138         }
139     }
140
141     if (sqlRet == SQLITE_OK)
142     {
143         sqlite3_stmt *stmt = 0;
144         VERIFY_SQLITE(sqlite3_prepare_v2 (gRDDB, "PRAGMA foreign_keys = ON;", -1, &stmt, NULL));
145
146         if (SQLITE_DONE != sqlite3_step(stmt))
147         {
148             sqlite3_finalize(stmt);
149             return OC_STACK_ERROR;
150         }
151
152         VERIFY_SQLITE(sqlite3_finalize(stmt));
153     }
154
155     return OC_STACK_OK;
156 }
157
158 OCStackResult OCRDDatabaseClose()
159 {
160     CHECK_DATABASE_INIT;
161     VERIFY_SQLITE(sqlite3_close_v2(gRDDB));
162     return OC_STACK_OK;
163 }
164
165 static int storeResourceType(char **link, size_t size, uint8_t rowid)
166 {
167     int res = 1;
168     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
169
170     const char *insertRT = "INSERT INTO RD_LINK_RT VALUES(?, ?)";
171     sqlite3_stmt *stmtRT = 0;
172
173     for (size_t i = 0; i < size; i++)
174     {
175         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertRT, strlen(insertRT) + 1, &stmtRT, NULL));
176         if (link[i])
177         {
178             VERIFY_SQLITE(sqlite3_bind_text(stmtRT, rt_value_index, link[i],
179                     strlen(link[i])+1, SQLITE_STATIC));
180
181             VERIFY_SQLITE(sqlite3_bind_int(stmtRT, rt_link_id_index, rowid));
182         }
183         if (SQLITE_DONE != sqlite3_step(stmtRT))
184         {
185             sqlite3_finalize(stmtRT);
186             return res;
187         }
188     }
189
190     VERIFY_SQLITE(sqlite3_finalize(stmtRT));
191
192     VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
193     res = SQLITE_OK;
194
195     return res;
196 }
197
198
199 static int storeInterfaceType(char **link, size_t size, uint8_t rowid)
200 {
201     int res = 1;
202
203     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
204
205     const char *insertIF = "INSERT INTO RD_LINK_IF VALUES(?, ?)";
206     sqlite3_stmt *stmtIF = 0;
207
208     for (size_t i = 0; i < size; i++)
209     {
210         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertIF, strlen(insertIF) + 1, &stmtIF, NULL));
211
212         if (link[i])
213         {
214             VERIFY_SQLITE(sqlite3_bind_text(stmtIF, if_value_index, link[i], strlen(link[i])+1, SQLITE_STATIC));
215             VERIFY_SQLITE(sqlite3_bind_int(stmtIF, if_link_id_index, rowid));
216         }
217         if (SQLITE_DONE != sqlite3_step(stmtIF))
218         {
219             res = sqlite3_finalize(stmtIF);
220             return res;
221         }
222     }
223     VERIFY_SQLITE(sqlite3_finalize(stmtIF));
224
225     VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
226     res = SQLITE_OK;
227
228     return res;
229 }
230
231 static int storeLinkPayload(OCRepPayload *rdPayload, int64_t rowid)
232 {
233     OCRepPayload **links = NULL;
234     size_t dimensions[MAX_REP_ARRAY_DEPTH];
235     int res = 1 ;
236     size_t j = 0;
237
238     if (OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, &links, dimensions))
239     {
240         const char *insertDeviceLLList = "INSERT INTO RD_DEVICE_LINK_LIST VALUES(?,?,?,?,?,?,?,?)";
241         sqlite3_stmt *stmt = 0;
242
243         for (size_t i = 0; i < dimensions[0]; i++)
244         {
245             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceLLList, strlen(insertDeviceLLList) + 1, &stmt, NULL));
246             VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
247
248             OCRepPayload *link = links[i];
249             char *uri = NULL;
250             if (OCRepPayloadGetPropString(link, OC_RSRVD_HREF, &uri))
251             {
252                 VERIFY_SQLITE(sqlite3_bind_text(stmt, uri_index, uri, strlen(uri), SQLITE_STATIC));
253             }
254
255             OCRepPayload *p = NULL;
256             if (OCRepPayloadGetPropObject(link, OC_RSRVD_POLICY, &p))
257             {
258                 int64_t bm = 0;
259                 if (OCRepPayloadGetPropInt(p, OC_RSRVD_BITMAP, &bm))
260                 {
261                     VERIFY_SQLITE(sqlite3_bind_int(stmt, p_index, bm));
262                 }
263             }
264
265             size_t mtDim[MAX_REP_ARRAY_DEPTH] = {0};
266             char **mediaType = NULL;
267             if (OCRepPayloadGetStringArray(link, OC_RSRVD_MEDIA_TYPE, &mediaType, mtDim))
268             {
269                 VERIFY_SQLITE(sqlite3_bind_text(stmt, mt_index, mediaType[0], mtDim[0], SQLITE_STATIC));
270             }
271
272             VERIFY_SQLITE(sqlite3_bind_int(stmt, d_index, rowid));
273
274             size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
275             char **rt = NULL;
276             OCRepPayloadGetStringArray(link, OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
277
278             size_t itfDim[MAX_REP_ARRAY_DEPTH] = {0};
279             char **itf = NULL;
280             OCRepPayloadGetStringArray(link, OC_RSRVD_INTERFACE, &itf, itfDim);
281
282             int sqlRet = sqlite3_step(stmt);
283             if (SQLITE_DONE != sqlRet)
284             {
285                 sqlite3_finalize(stmt);
286             }
287             else
288             {
289                 VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
290
291                 int64_t ins = sqlite3_last_insert_rowid(gRDDB);
292                 VERIFY_SQLITE(storeResourceType(rt, rtDim[0], ins));
293                 VERIFY_SQLITE(storeInterfaceType(itf, itfDim[0], ins));
294             }
295
296             OICFree(uri);
297             OCPayloadDestroy((OCPayload *)p);
298             for (j = 0; j < mtDim[0]; j++)
299             {
300                 OICFree(mediaType[j]);
301             }
302             OICFree(mediaType);
303
304             for (j = 0; j < rtDim[0]; j++)
305             {
306                 OICFree(rt[j]);
307             }
308             OICFree(rt);
309
310             for (j = 0; j < itfDim[0]; j++)
311             {
312                 OICFree(itf[j]);
313             }
314             OICFree(itf);
315
316             if (SQLITE_DONE != sqlRet)
317             {
318                 // Free links
319                 size_t count = calcDimTotal(dimensions);
320                 for (size_t k = 0; k < count; k++)
321                 {
322                     OCRepPayloadDestroy(links[k]);
323                 }
324                 OICFree(links);
325
326                 return res;
327             }
328         }
329
330         VERIFY_SQLITE(sqlite3_finalize(stmt));
331         res = SQLITE_OK;
332
333         // Free links
334         size_t count = calcDimTotal(dimensions);
335         for (size_t k = 0; k < count; k++)
336         {
337             OCRepPayloadDestroy(links[k]);
338         }
339         OICFree(links);
340     }
341     return res;
342 }
343
344 OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr *address)
345 {
346     CHECK_DATABASE_INIT;
347
348     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
349     const char *insertDeviceList = "INSERT INTO RD_DEVICE_LIST VALUES(?,?,?,?)";
350     sqlite3_stmt *stmt = 0;
351     VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceList, strlen(insertDeviceList) + 1, &stmt, NULL));
352
353     char *deviceid = NULL;
354     if (OCRepPayloadGetPropString(payload, OC_RSRVD_DEVICE_ID, &deviceid))
355     {
356         VERIFY_SQLITE(sqlite3_bind_text(stmt, device_index, deviceid, strlen(deviceid) + 1, SQLITE_STATIC));
357     }
358
359     int64_t ttl = 0;
360     if (OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, &ttl))
361     {
362         VERIFY_SQLITE(sqlite3_bind_int(stmt, ttl_index, ttl));
363     }
364
365     char rdAddress[MAX_URI_LENGTH];
366     snprintf(rdAddress, MAX_URI_LENGTH, "%s:%d", address->addr, address->port);
367     OIC_LOG_V(DEBUG, TAG, "Address: %s", rdAddress);
368     VERIFY_SQLITE(sqlite3_bind_text(stmt, address_index, rdAddress, strlen(rdAddress) + 1, SQLITE_STATIC));
369
370     if (SQLITE_DONE != sqlite3_step(stmt))
371     {
372         sqlite3_finalize(stmt);
373         OICFree(deviceid);
374         return OC_STACK_ERROR;
375     }
376     VERIFY_SQLITE(sqlite3_finalize(stmt));
377
378     VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
379
380     int64_t rowid = sqlite3_last_insert_rowid(gRDDB);
381     if (rowid)
382     {
383         VERIFY_SQLITE(storeLinkPayload(payload, rowid));
384     }
385     OICFree(deviceid);
386     return OC_STACK_OK;
387 }
388
389 OCStackResult OCRDDatabaseDeleteDevice(const char *deviceId)
390 {
391     CHECK_DATABASE_INIT;
392     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
393
394     sqlite3_stmt *stmt = 0;
395     char *delDevice = "DELETE FROM RD_DEVICE_LIST WHERE "XSTR(OC_RSRVD_DEVICE_ID)" = ?";
396     VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, delDevice, strlen(delDevice) + 1, &stmt, NULL));
397
398     VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId) + 1, SQLITE_STATIC));
399
400     if (SQLITE_DONE != sqlite3_step(stmt))
401     {
402         sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
403         sqlite3_finalize(stmt);
404         return OC_STACK_ERROR;
405     }
406     VERIFY_SQLITE(sqlite3_finalize(stmt));
407     VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
408
409     return OC_STACK_OK;
410 }
411
412 #endif