1 //******************************************************************
3 // Copyright 2016 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
26 #include "ocpayload.h"
28 #include "oic_malloc.h"
29 #include "oic_string.h"
30 #include "ocstackinternal.h"
34 #define TAG "OIC_RD_DATABASE"
36 static sqlite3 *gRDDB = NULL;
38 static const uint8_t device_index = 2;
39 static const uint8_t ttl_index = 3;
40 static const uint8_t address_index = 4;
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;
47 static const uint8_t rt_value_index = 1;
48 static const uint8_t rt_link_id_index = 2;
50 static const uint8_t if_value_index = 1;
51 static const uint8_t if_link_id_index = 2;
53 #define VERIFY_SQLITE(arg) \
54 if (SQLITE_OK != (arg)) \
56 OIC_LOG_V(ERROR, TAG, "Error in " #arg ", Error Message: %s", sqlite3_errmsg(gRDDB)); \
57 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL); \
58 return OC_STACK_ERROR; \
61 #define CHECK_DATABASE_INIT \
64 OIC_LOG(ERROR, TAG, "Database is not initialized."); \
65 return OC_STACK_ERROR; \
69 #define XSTR(a) STR(a)
72 "create table RD_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT, " \
73 XSTR(OC_RSRVD_DEVICE_ID) " UNIQUE NOT NULL, " \
74 XSTR(OC_RSRVD_TTL) " NOT NULL, " \
78 "create table RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)" INTEGER PRIMARY KEY AUTOINCREMENT, " \
79 XSTR(OC_RSRVD_HREF) "," \
80 XSTR(OC_RSRVD_REL) "," \
81 XSTR(OC_RSRVD_TITLE) "," \
82 XSTR(OC_RSRVD_BITMAP)"," \
83 XSTR(OC_RSRVD_TTL) "," \
84 XSTR(OC_RSRVD_MEDIA_TYPE) "," \
85 "DEVICE_ID INT NOT NULL, " \
86 "FOREIGN KEY(DEVICE_ID) REFERENCES RD_DEVICE_LIST(ID) ON DELETE CASCADE );"
89 "create table RD_LINK_RT(" XSTR(OC_RSRVD_RESOURCE_TYPE) " NOT NULL, " \
90 "LINK_ID INT NOT NULL, "\
91 "FOREIGN KEY("XSTR(LINK_ID)") REFERENCES RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)") " \
95 "create table RD_LINK_IF(" XSTR(OC_RSRVD_INTERFACE) " NOT NULL, " \
96 "LINK_ID INT NOT NULL, "\
97 "FOREIGN KEY("XSTR(LINK_ID)") REFERENCES RD_DEVICE_LINK_LIST("XSTR(OC_RSRVD_INS)") " \
100 static void errorCallback(void *arg, int errCode, const char *errMsg)
105 OIC_LOG_V(ERROR, TAG, "SQLLite Error: %s : %d", errMsg, errCode);
108 OCStackResult OCRDDatabaseInit()
110 if (SQLITE_OK == sqlite3_config(SQLITE_CONFIG_LOG, errorCallback))
112 OIC_LOG_V(INFO, TAG, "SQLite debugging log initialized.");
116 sqlRet = sqlite3_open_v2(OCRDDatabaseGetStorageFilename(), &gRDDB,
117 SQLITE_OPEN_READWRITE, NULL);
118 if (SQLITE_OK != sqlRet)
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(OCRDDatabaseGetStorageFilename(), &gRDDB,
123 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
124 if (SQLITE_OK == sqlRet)
126 VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_TABLE, NULL, NULL, NULL));
127 OIC_LOG(DEBUG, TAG, "RD created RD_DEVICE_LIST table.");
129 VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_LL_TABLE, NULL, NULL, NULL));
130 OIC_LOG(DEBUG, TAG, "RD created RD_DEVICE_LINK_LIST table.");
132 VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_RT_TABLE, NULL, NULL, NULL));
133 OIC_LOG(DEBUG, TAG, "RD created RD_LINK_RT table.");
135 VERIFY_SQLITE(sqlite3_exec(gRDDB, RD_IF_TABLE, NULL, NULL, NULL));
136 OIC_LOG(DEBUG, TAG, "RD created RD_LINK_IF table.");
141 if (sqlRet == SQLITE_OK)
143 sqlite3_stmt *stmt = 0;
144 VERIFY_SQLITE(sqlite3_prepare_v2 (gRDDB, "PRAGMA foreign_keys = ON;", -1, &stmt, NULL));
146 if (SQLITE_DONE != sqlite3_step(stmt))
148 sqlite3_finalize(stmt);
149 return OC_STACK_ERROR;
152 VERIFY_SQLITE(sqlite3_finalize(stmt));
158 OCStackResult OCRDDatabaseClose()
161 VERIFY_SQLITE(sqlite3_close_v2(gRDDB));
165 static int storeResourceType(char **link, size_t size, uint8_t rowid)
168 VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
170 const char *insertRT = "INSERT INTO RD_LINK_RT VALUES(?, ?)";
171 sqlite3_stmt *stmtRT = 0;
173 for (size_t i = 0; i < size; i++)
175 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertRT, strlen(insertRT) + 1, &stmtRT, NULL));
178 VERIFY_SQLITE(sqlite3_bind_text(stmtRT, rt_value_index, link[i],
179 strlen(link[i]), SQLITE_STATIC));
181 VERIFY_SQLITE(sqlite3_bind_int(stmtRT, rt_link_id_index, rowid));
183 if (sqlite3_step(stmtRT) != SQLITE_DONE)
185 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
186 sqlite3_finalize(stmtRT);
191 VERIFY_SQLITE(sqlite3_finalize(stmtRT));
193 VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
200 static int storeInterfaceType(char **link, size_t size, uint8_t rowid)
204 VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
206 const char *insertIF = "INSERT INTO RD_LINK_IF VALUES(?, ?)";
207 sqlite3_stmt *stmtIF = 0;
209 for (size_t i = 0; i < size; i++)
211 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertIF, strlen(insertIF) + 1, &stmtIF, NULL));
215 VERIFY_SQLITE(sqlite3_bind_text(stmtIF, if_value_index, link[i], strlen(link[i]), SQLITE_STATIC));
216 VERIFY_SQLITE(sqlite3_bind_int(stmtIF, if_link_id_index, rowid));
218 if (sqlite3_step(stmtIF) != SQLITE_DONE)
220 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
221 res = sqlite3_finalize(stmtIF);
225 VERIFY_SQLITE(sqlite3_finalize(stmtIF));
227 VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
233 static int storeLinkPayload(OCRepPayload *rdPayload, int64_t rowid)
239 * Iterate over the properties manually rather than OCRepPayloadGetPropObjectArray to avoid
240 * the clone since we want to insert the 'ins' values into the payload.
242 OCRepPayloadValue *links;
243 for (links = rdPayload->values; links; links = links->next)
245 if (0 == strcmp(links->name, OC_RSRVD_LINKS))
247 if (links->type != OCREP_PROP_ARRAY || links->arr.type != OCREP_PROP_OBJECT)
256 const char *insertDeviceLLList = "INSERT INTO RD_DEVICE_LINK_LIST VALUES(?,?,?,?,?,?,?,?)";
257 sqlite3_stmt *stmt = 0;
259 for (size_t i = 0; i < links->arr.dimensions[0]; i++)
261 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceLLList, strlen(insertDeviceLLList) + 1, &stmt, NULL));
262 VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
264 OCRepPayload *link = links->arr.objArray[i];
266 if (OCRepPayloadGetPropString(link, OC_RSRVD_HREF, &uri))
268 VERIFY_SQLITE(sqlite3_bind_text(stmt, uri_index, uri, strlen(uri), SQLITE_STATIC));
271 OCRepPayload *p = NULL;
272 if (OCRepPayloadGetPropObject(link, OC_RSRVD_POLICY, &p))
275 if (OCRepPayloadGetPropInt(p, OC_RSRVD_BITMAP, &bm))
277 VERIFY_SQLITE(sqlite3_bind_int(stmt, p_index, bm));
281 size_t mtDim[MAX_REP_ARRAY_DEPTH] = {0};
282 char **mediaType = NULL;
283 if (OCRepPayloadGetStringArray(link, OC_RSRVD_MEDIA_TYPE, &mediaType, mtDim))
285 VERIFY_SQLITE(sqlite3_bind_text(stmt, mt_index, mediaType[0], strlen(mediaType[0]), SQLITE_STATIC));
288 VERIFY_SQLITE(sqlite3_bind_int(stmt, d_index, rowid));
290 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
292 OCRepPayloadGetStringArray(link, OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
294 size_t itfDim[MAX_REP_ARRAY_DEPTH] = {0};
296 OCRepPayloadGetStringArray(link, OC_RSRVD_INTERFACE, &itf, itfDim);
298 if (sqlite3_step(stmt) != SQLITE_DONE)
300 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
301 sqlite3_finalize(stmt);
304 VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
306 int64_t ins = sqlite3_last_insert_rowid(gRDDB);
307 if (!OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins))
309 OIC_LOG_V(ERROR, TAG, "Error setting 'ins' value");
310 return OC_STACK_ERROR;
312 VERIFY_SQLITE(storeResourceType(rt, rtDim[0], ins));
313 VERIFY_SQLITE(storeInterfaceType(itf, itfDim[0], ins));
315 OCPayloadDestroy((OCPayload *)p);
316 for (j = 0; j < mtDim[0]; j++)
318 OICFree(mediaType[j]);
322 for (j = 0; j < rtDim[0]; j++)
328 for (j = 0; j < itfDim[0]; j++)
336 VERIFY_SQLITE(sqlite3_finalize(stmt));
342 OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr *address)
346 VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
347 const char *insertDeviceList = "INSERT INTO RD_DEVICE_LIST VALUES(?,?,?,?)";
348 sqlite3_stmt *stmt = 0;
349 VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceList, strlen(insertDeviceList) + 1, &stmt, NULL));
351 char *deviceid = NULL;
352 if (OCRepPayloadGetPropString(payload, OC_RSRVD_DEVICE_ID, &deviceid))
354 VERIFY_SQLITE(sqlite3_bind_text(stmt, device_index, deviceid, strlen(deviceid), SQLITE_STATIC));
358 if (OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, &ttl))
360 VERIFY_SQLITE(sqlite3_bind_int(stmt, ttl_index, ttl));
363 char rdAddress[MAX_URI_LENGTH];
364 snprintf(rdAddress, MAX_URI_LENGTH, "%s:%d", address->addr, address->port);
365 OIC_LOG_V(DEBUG, TAG, "Address: %s", rdAddress);
366 VERIFY_SQLITE(sqlite3_bind_text(stmt, address_index, rdAddress, strlen(rdAddress), SQLITE_STATIC));
368 if (sqlite3_step(stmt) != SQLITE_DONE)
370 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
371 sqlite3_finalize(stmt);
372 return OC_STACK_ERROR;
374 VERIFY_SQLITE(sqlite3_finalize(stmt));
376 VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
378 int64_t rowid = sqlite3_last_insert_rowid(gRDDB);
381 VERIFY_SQLITE(storeLinkPayload(payload, rowid));
387 OCStackResult OCRDDatabaseDeleteResources(const char *deviceId, const uint8_t *instanceIds, uint8_t nInstanceIds)
391 VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
392 sqlite3_stmt *stmt = 0;
393 if (!instanceIds || !nInstanceIds)
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));
398 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId), SQLITE_STATIC));
402 const char pre[] = "DELETE FROM RD_DEVICE_LINK_LIST "
404 "SELECT RD_DEVICE_LINK_LIST.ins FROM RD_DEVICE_LINK_LIST "
405 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
406 "WHERE RD_DEVICE_LIST.di = ? AND RD_DEVICE_LINK_LIST.ins IN (";
407 size_t inLen = nInstanceIds + (nInstanceIds - 1);
408 const char post[] = "))";
409 size_t len = sizeof(pre) + inLen + sizeof(post);
410 char *delResource = OICCalloc(len, 1);
413 OIC_LOG(ERROR, TAG, "SQL query is NULL");
414 return OC_STACK_ERROR;
416 OICStrcat(delResource, len, pre);
417 OICStrcat(delResource, len, "?");
418 for (uint8_t i = 1; i < nInstanceIds; ++i)
420 OICStrcat(delResource, len, ",?");
422 OICStrcat(delResource, len, post);
423 int prepareResult = sqlite3_prepare_v2(gRDDB, delResource, strlen(delResource) + 1, &stmt, NULL);
424 OICFree(delResource);
425 VERIFY_SQLITE(prepareResult);
427 VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId), SQLITE_STATIC));
428 for (uint8_t i = 0; i < nInstanceIds; ++i)
430 VERIFY_SQLITE(sqlite3_bind_int(stmt, 2 + i, instanceIds[i]));
433 if (sqlite3_step(stmt) != SQLITE_DONE)
435 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
436 sqlite3_finalize(stmt);
437 return OC_STACK_ERROR;
439 VERIFY_SQLITE(sqlite3_finalize(stmt));
440 VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));