Merge remote-tracking branch 'origin/notification-service'
[iotivity.git] / resource / csdk / security / provisioning / src / provisioningdatabasemanager.c
1 /* *****************************************************************
2  *
3  * Copyright 2015 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 at
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 <stdio.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include <stdlib.h>
25
26 #include "sqlite3.h"
27 #include "logger.h"
28 #include "oic_malloc.h"
29 #include "provisioningdatabasemanager.h"
30 #include "pmutility.h"
31 #include "oic_string.h"
32 #include "utlist.h"
33
34
35 #define DB_FILE "PDM.db"
36
37 #define TAG "PDM"
38
39 #define PDM_STALE_STATE 1
40 #define PDM_ACTIVE_STATE 0
41
42 #define PDM_FIRST_INDEX 0
43 #define PDM_SECOND_INDEX 1
44
45 #define PDM_BIND_INDEX_FIRST 1
46 #define PDM_BIND_INDEX_SECOND 2
47 #define PDM_BIND_INDEX_THIRD 3
48
49 #define PDM_CREATE_T_DEVICE_LIST "create table T_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT,\
50                                   UUID BLOB NOT NULL UNIQUE, STATE INT NOT NULL);"
51
52 #define PDM_CREATE_T_DEVICE_LINK  "create table T_DEVICE_LINK_STATE(ID INT NOT NULL, ID2 INT NOT \
53                                    NULL,STATE INT NOT NULL, PRIMARY KEY (ID, ID2));"
54 /**
55  * Macro to verify sqlite success.
56  * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
57  */
58 #define PDM_VERIFY_SQLITE_OK(tag, arg, logLevel, retValue) do{ if (SQLITE_OK != (arg)) \
59             { OIC_LOG_V((logLevel), tag, "Error in " #arg ", Error Message: %s", \
60                sqlite3_errmsg(g_db)); return retValue; }}while(0)
61
62 #define PDM_SQLITE_TRANSACTION_BEGIN "BEGIN TRANSACTION;"
63 #define PDM_SQLITE_TRANSACTION_COMMIT "COMMIT;"
64 #define PDM_SQLITE_TRANSACTION_ROLLBACK "ROLLBACK;"
65 #define PDM_SQLITE_GET_STALE_INFO "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE STATE = ?"
66 #define PDM_SQLITE_INSERT_T_DEVICE_LIST "INSERT INTO T_DEVICE_LIST VALUES(?,?,?)"
67 #define PDM_SQLITE_GET_ID "SELECT ID FROM T_DEVICE_LIST WHERE UUID like ?"
68 #define PDM_SQLITE_INSERT_LINK_DATA "INSERT INTO T_DEVICE_LINK_STATE VALUES(?,?,?)"
69 #define PDM_SQLITE_DELETE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? and ID2 = ?"
70 #define PDM_SQLITE_DELETE_DEVICE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
71 #define PDM_SQLITE_DELETE_DEVICE "DELETE FROM T_DEVICE_LIST  WHERE ID = ?"
72 #define PDM_SQLITE_UPDATE_LINK "UPDATE T_DEVICE_LINK_STATE SET STATE = ?  WHERE ID = ? and ID2 = ?"
73 #define PDM_SQLITE_LIST_ALL_UUID "SELECT UUID FROM T_DEVICE_LIST WHERE STATE = 0"
74 #define PDM_SQLITE_GET_UUID "SELECT UUID,STATE FROM T_DEVICE_LIST WHERE ID = ?"
75 #define PDM_SQLITE_GET_LINKED_DEVICES "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE \
76                                            (ID = ? or ID2 = ?) and state = 0"
77 #define PDM_SQLITE_GET_DEVICE_LINKS "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE \
78                                           ID = ? and ID2 = ? and state = 0"
79 #define PDM_SQLITE_UPDATE_DEVICE "UPDATE T_DEVICE_LIST SET STATE = ?  WHERE UUID like ?"
80 #define PDM_SQLITE_GET_DEVICE_STATUS "SELECT STATE FROM T_DEVICE_LIST WHERE UUID like ?"
81 #define PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE "UPDATE T_DEVICE_LINK_STATE SET STATE = 1\
82                                                           WHERE ID = ? or ID2 = ?"
83
84 #define ASCENDING_ORDER(id1, id2) do{if( (id1) > (id2) )\
85   { int temp; temp = id1; id1 = id2; id2 = temp; }}while(0)
86
87 #define CHECK_PDM_INIT(tag) do{if(true != gInit)\
88   { OIC_LOG(ERROR, (tag), "PDB is not initialized"); \
89     return OC_STACK_PDM_IS_NOT_INITIALIZED; }}while(0)
90
91 static sqlite3 *g_db = NULL;
92 static bool gInit = false;  /* Only if we can open sqlite db successfully, gInit is true. */
93
94 /**
95  * function to create DB in case DB doesn't exists
96  */
97 static OCStackResult createDB(const char* path)
98 {
99
100     int result = 0;
101     result = sqlite3_open_v2(path, &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
102     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
103
104     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LIST, NULL, NULL, NULL);
105     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
106
107     OIC_LOG(INFO, TAG, "Created T_DEVICE_LIST");
108     result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LINK, NULL, NULL, NULL);
109     PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
110
111     OIC_LOG(INFO, TAG, "Created T_DEVICE_LINK_STATE");
112     gInit = true;
113     return OC_STACK_OK;
114 }
115
116
117 /**
118  * Function to begin any transaction
119  */
120 static OCStackResult begin()
121 {
122     int res = 0;
123     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_BEGIN, NULL, NULL, NULL);
124     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
125     return OC_STACK_OK;
126 }
127
128 /**
129  * Function to commit any transaction
130  */
131 static OCStackResult commit()
132 {
133     int res = 0;
134     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_COMMIT, NULL, NULL, NULL);
135     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
136     return OC_STACK_OK;
137 }
138
139 /**
140  * Function to rollback any transaction
141  */
142 static OCStackResult rollback()
143 {
144     int res = 0;
145     res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_ROLLBACK, NULL, NULL, NULL);
146     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
147     return OC_STACK_OK;
148 }
149
150 /**
151  * Error log callback called by SQLite stack in case of error
152  */
153 void errLogCallback(void *pArg, int iErrCode, const char *zMsg)
154 {
155     (void) pArg;
156     (void) iErrCode;
157     (void) zMsg;
158     OIC_LOG_V(DEBUG,TAG, "(%d) %s", iErrCode, zMsg);
159 }
160
161 OCStackResult PDMInit(const char *path)
162 {
163     int rc;
164     const char *dbPath = NULL;
165     if (SQLITE_OK !=  sqlite3_config(SQLITE_CONFIG_LOG, errLogCallback, NULL))
166     {
167         OIC_LOG(INFO, TAG, "Unable to enable debug log of sqlite");
168     }
169
170     if (NULL == path || !*path)
171     {
172         dbPath = DB_FILE;
173     }
174     else
175     {
176         dbPath = path;
177     }
178     rc = sqlite3_open_v2(dbPath, &g_db, SQLITE_OPEN_READWRITE, NULL);
179     if (SQLITE_OK != rc)
180     {
181         OIC_LOG_V(INFO, TAG, "ERROR: Can't open database: %s", sqlite3_errmsg(g_db));
182         return createDB(dbPath);
183     }
184     gInit = true;
185     return OC_STACK_OK;
186 }
187
188
189 OCStackResult PDMAddDevice(const OicUuid_t *UUID)
190 {
191     CHECK_PDM_INIT(TAG);
192     if (NULL == UUID)
193     {
194         return OC_STACK_INVALID_PARAM;
195     }
196
197     sqlite3_stmt *stmt = 0;
198     int res =0;
199     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_T_DEVICE_LIST,
200                               strlen(PDM_SQLITE_INSERT_T_DEVICE_LIST) + 1, &stmt, NULL);
201     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
202
203     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
204     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
205
206     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
207     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
208
209     res = sqlite3_step(stmt);
210     if (SQLITE_DONE != res)
211     {
212         if (SQLITE_CONSTRAINT == res)
213         {
214             //new OCStack result code
215             OIC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
216             sqlite3_finalize(stmt);
217             return OC_STACK_DUPLICATE_UUID;
218         }
219         OIC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
220         sqlite3_finalize(stmt);
221         return OC_STACK_ERROR;
222     }
223     sqlite3_finalize(stmt);
224     return OC_STACK_OK;
225 }
226
227 /**
228  * Function to check whether device is stale or not
229  */
230 OCStackResult PDMIsDeviceStale(const OicUuid_t *uuid, bool *result)
231 {
232     if (NULL == uuid || NULL == result)
233     {
234         OIC_LOG(ERROR, TAG, "UUID or result is NULL");
235         return OC_STACK_INVALID_PARAM;
236     }
237
238     sqlite3_stmt *stmt = 0;
239     int res = 0;
240     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_DEVICE_STATUS, strlen(PDM_SQLITE_GET_DEVICE_STATUS) + 1,
241                               &stmt, NULL);
242     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
243
244     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, uuid, UUID_LENGTH, SQLITE_STATIC);
245     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
246
247     bool retValue = false;
248     while(SQLITE_ROW == sqlite3_step(stmt))
249     {
250         int tempStaleStateFromDb = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
251         OIC_LOG_V(DEBUG, TAG, "Stale state is %d", tempStaleStateFromDb);
252         if (PDM_STALE_STATE == tempStaleStateFromDb)
253         {
254             OIC_LOG(INFO, TAG, "Device is stale");
255             retValue = true;
256         }
257     }
258     *result = retValue;
259     sqlite3_finalize(stmt);
260     return OC_STACK_OK;
261 }
262
263 /**
264  *function to get Id for given UUID
265  */
266 static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
267 {
268     sqlite3_stmt *stmt = 0;
269     int res = 0;
270     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
271     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
272
273     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
274     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
275
276     OIC_LOG(DEBUG, TAG, "Binding Done");
277     while (SQLITE_ROW == sqlite3_step(stmt))
278     {
279         int tempId = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
280         OIC_LOG_V(DEBUG, TAG, "ID is %d", tempId);
281         *id = tempId;
282         sqlite3_finalize(stmt);
283         return OC_STACK_OK;
284     }
285     sqlite3_finalize(stmt);
286     return OC_STACK_INVALID_PARAM;
287 }
288
289 /**
290  * Function to check duplication of device's Device ID.
291  */
292 OCStackResult PDMIsDuplicateDevice(const OicUuid_t* UUID, bool *result)
293 {
294
295     CHECK_PDM_INIT(TAG);
296     if (NULL == UUID || NULL == result)
297     {
298         OIC_LOG(ERROR, TAG, "UUID or result is NULL");
299         return OC_STACK_INVALID_PARAM;
300     }
301     sqlite3_stmt *stmt = 0;
302     int res = 0;
303     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
304     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
305
306     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
307     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
308
309     OIC_LOG(DEBUG, TAG, "Binding Done");
310     bool retValue = false;
311     while(SQLITE_ROW == sqlite3_step(stmt))
312     {
313         OIC_LOG(INFO, TAG, "Duplicated UUID");
314         retValue = true;
315     }
316
317     sqlite3_finalize(stmt);
318     *result = retValue;
319     return OC_STACK_OK;
320 }
321
322 /**
323  * Function to add link in sqlite
324  */
325 static OCStackResult addlink(int id1, int id2)
326 {
327     sqlite3_stmt *stmt = 0;
328     int res = 0;
329     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_LINK_DATA,
330                               strlen(PDM_SQLITE_INSERT_LINK_DATA) + 1, &stmt, NULL);
331     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
332
333     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
334     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
335
336     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
337     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
338
339     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
340     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
341
342     if (sqlite3_step(stmt) != SQLITE_DONE)
343     {
344         OIC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
345         sqlite3_finalize(stmt);
346         return OC_STACK_ERROR;
347     }
348     sqlite3_finalize(stmt);
349     return OC_STACK_OK;
350 }
351
352 OCStackResult PDMLinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
353 {
354     CHECK_PDM_INIT(TAG);
355     if (NULL == UUID1 || NULL == UUID2)
356     {
357         OIC_LOG(ERROR, TAG, "Invalid PARAM");
358         return  OC_STACK_INVALID_PARAM;
359     }
360
361     bool result = false;
362     if (OC_STACK_OK != PDMIsDeviceStale(UUID1, &result))
363     {
364         OIC_LOG(ERROR, TAG, "Internal error occured");
365         return OC_STACK_ERROR;
366     }
367     if (result)
368     {
369         OIC_LOG(ERROR, TAG, "UUID1:Stale device");
370         return OC_STACK_INVALID_PARAM;
371     }
372     result = false;
373     if (OC_STACK_OK != PDMIsDeviceStale(UUID2, &result))
374     {
375         OIC_LOG(ERROR, TAG, "Internal error occured");
376         return OC_STACK_ERROR;
377     }
378     if (result)
379     {
380         OIC_LOG(ERROR, TAG, "UUID2:Stale device");
381         return OC_STACK_INVALID_PARAM;
382     }
383
384     int id1 = 0;
385     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
386     {
387         OIC_LOG(ERROR, TAG, "Requested value not found");
388         return OC_STACK_INVALID_PARAM;
389     }
390     int id2 = 0;
391     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
392     {
393         OIC_LOG(ERROR, TAG, "Requested value not found");
394         return OC_STACK_INVALID_PARAM;
395     }
396
397     ASCENDING_ORDER(id1, id2);
398     return addlink(id1, id2);
399 }
400
401 /**
402  * Function to remove created link
403  */
404 static OCStackResult removeLink(int id1, int id2)
405 {
406     int res = 0;
407     sqlite3_stmt *stmt = 0;
408     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_LINK, strlen(PDM_SQLITE_DELETE_LINK) + 1, &stmt, NULL);
409     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
410
411     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
412     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
413
414     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
415     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
416
417     if (SQLITE_DONE != sqlite3_step(stmt))
418     {
419         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
420         sqlite3_finalize(stmt);
421         return OC_STACK_ERROR;
422     }
423     sqlite3_finalize(stmt);
424     return OC_STACK_OK;
425 }
426
427 OCStackResult PDMUnlinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
428 {
429     CHECK_PDM_INIT(TAG);
430     if (NULL == UUID1 || NULL == UUID2)
431     {
432         OIC_LOG(ERROR, TAG, "Invalid PARAM");
433         return  OC_STACK_INVALID_PARAM;
434     }
435
436     int id1 = 0;
437     if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
438     {
439         OIC_LOG(ERROR, TAG, "Requested value not found");
440         return OC_STACK_INVALID_PARAM;
441     }
442
443     int id2 = 0;
444     if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
445     {
446         OIC_LOG(ERROR, TAG, "Requested value not found");
447         return OC_STACK_INVALID_PARAM;
448     }
449     ASCENDING_ORDER(id1, id2);
450     return removeLink(id1, id2);
451 }
452
453 static OCStackResult removeFromDeviceList(int id)
454 {
455     sqlite3_stmt *stmt = 0;
456     int res = 0;
457     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_DEVICE,
458                               strlen(PDM_SQLITE_DELETE_DEVICE) + 1, &stmt, NULL);
459     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
460
461     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
462     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
463
464     if (sqlite3_step(stmt) != SQLITE_DONE)
465     {
466         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
467         sqlite3_finalize(stmt);
468         return OC_STACK_ERROR;
469     }
470     sqlite3_finalize(stmt);
471     return OC_STACK_OK;
472 }
473
474 OCStackResult PDMDeleteDevice(const OicUuid_t *UUID)
475 {
476     CHECK_PDM_INIT(TAG);
477     if (NULL == UUID)
478     {
479         return OC_STACK_INVALID_PARAM;
480     }
481     int id = 0;
482     if (OC_STACK_OK != getIdForUUID(UUID, &id))
483     {
484         OIC_LOG(ERROR, TAG, "Requested value not found");
485         return OC_STACK_INVALID_PARAM;
486     }
487     begin();
488     if(OC_STACK_OK != removeFromDeviceList(id))
489     {
490         rollback();
491         OIC_LOG(ERROR, TAG, "Requested value not found");
492         return OC_STACK_ERROR;
493     }
494     commit();
495     return OC_STACK_OK;
496 }
497
498
499 static OCStackResult updateLinkState(int id1, int id2, int state)
500 {
501     sqlite3_stmt *stmt = 0;
502     int res = 0 ;
503     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK,
504                               strlen(PDM_SQLITE_UPDATE_LINK) + 1, &stmt, NULL);
505     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
506
507     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
508     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
509
510     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id1);
511     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
512
513     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, id2);
514     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
515
516     if (SQLITE_DONE != sqlite3_step(stmt))
517     {
518         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
519         sqlite3_finalize(stmt);
520         return OC_STACK_ERROR;
521     }
522     sqlite3_finalize(stmt);
523     return OC_STACK_OK;
524 }
525
526 OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2)
527 {
528     CHECK_PDM_INIT(TAG);
529     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2)
530     {
531         OIC_LOG(ERROR, TAG, "Invalid PARAM");
532         return  OC_STACK_INVALID_PARAM;
533     }
534
535     int id1 = 0;
536     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
537     {
538         OIC_LOG(ERROR, TAG, "Requested value not found");
539         return OC_STACK_INVALID_PARAM;
540     }
541
542     int id2 = 0;
543     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
544     {
545         OIC_LOG(ERROR, TAG, "Requested value not found");
546         return OC_STACK_INVALID_PARAM;
547     }
548     ASCENDING_ORDER(id1, id2);
549     return updateLinkState(id1, id2, PDM_STALE_STATE);
550
551 }
552
553 OCStackResult PDMGetOwnedDevices(OCUuidList_t **uuidList, size_t *numOfDevices)
554 {
555     CHECK_PDM_INIT(TAG);
556     if (NULL != *uuidList)
557     {
558         OIC_LOG(ERROR, TAG, "Not null list will cause memory leak");
559         return OC_STACK_INVALID_PARAM;
560     }
561     sqlite3_stmt *stmt = 0;
562     int res = 0;
563     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_LIST_ALL_UUID,
564                               strlen(PDM_SQLITE_LIST_ALL_UUID) + 1, &stmt, NULL);
565     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
566
567     size_t counter  = 0;
568     while (SQLITE_ROW == sqlite3_step(stmt))
569     {
570         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
571         OicUuid_t *uid = (OicUuid_t *)ptr;
572         OCUuidList_t *temp = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
573         if (NULL == temp)
574         {
575             OIC_LOG_V(ERROR, TAG, "Memory allocation problem");
576             sqlite3_finalize(stmt);
577             return OC_STACK_NO_MEMORY;
578         }
579         memcpy(&temp->dev.id, uid->id, UUID_LENGTH);
580         LL_PREPEND(*uuidList,temp);
581         ++counter;
582     }
583     *numOfDevices = counter;
584     sqlite3_finalize(stmt);
585     return OC_STACK_OK;
586 }
587
588 static OCStackResult getUUIDforId(int id, OicUuid_t *uid, bool *result)
589 {
590     sqlite3_stmt *stmt = 0;
591     int res = 0;
592     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_UUID,
593                               strlen(PDM_SQLITE_GET_UUID) + 1, &stmt, NULL);
594     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
595
596     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
597     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
598
599     while (SQLITE_ROW == sqlite3_step(stmt))
600     {
601         const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
602         memcpy(uid, ptr, sizeof(OicUuid_t));
603
604         int temp = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
605         if(PDM_STALE_STATE == temp)
606         {
607             if(result)
608             {
609                 *result = true;
610             }
611         }
612         else
613         {
614             if(result)
615             {
616                 *result = false;
617             }
618         }
619         sqlite3_finalize(stmt);
620         return OC_STACK_OK;
621     }
622     sqlite3_finalize(stmt);
623     return OC_STACK_INVALID_PARAM;
624 }
625
626 OCStackResult PDMGetLinkedDevices(const OicUuid_t *UUID, OCUuidList_t **UUIDLIST, size_t *numOfDevices)
627 {
628     CHECK_PDM_INIT(TAG);
629     if (NULL == UUID || NULL == numOfDevices || !UUIDLIST)
630     {
631         return OC_STACK_INVALID_PARAM;
632     }
633     if (NULL != *UUIDLIST )
634     {
635         OIC_LOG(ERROR, TAG, "Not null list will cause memory leak");
636         return OC_STACK_INVALID_PARAM;
637     }
638     bool result = false;
639     OCStackResult ret = PDMIsDeviceStale(UUID, &result);
640     if (OC_STACK_OK != ret)
641     {
642         OIC_LOG(ERROR, TAG, "Internal error occured");
643         return OC_STACK_ERROR;
644     }
645     if (result)
646     {
647         OIC_LOG(ERROR, TAG, "Device is stale");
648         return OC_STACK_INVALID_PARAM;
649     }
650     int id = 0;
651     if (OC_STACK_OK != getIdForUUID(UUID, &id))
652     {
653         OIC_LOG(ERROR, TAG, "Requested value not found");
654         return OC_STACK_INVALID_PARAM;
655     }
656
657
658     sqlite3_stmt *stmt = 0;
659     int res = 0;
660     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_LINKED_DEVICES,
661                               strlen(PDM_SQLITE_GET_LINKED_DEVICES) + 1, &stmt, NULL);
662     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
663
664     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
665     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
666
667     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
668     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
669
670     size_t counter  = 0;
671     while (SQLITE_ROW == sqlite3_step(stmt))
672     {
673         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
674         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
675
676         OicUuid_t temp = {{0,}};
677         if (i1 != id)
678         {
679             getUUIDforId(i1, &temp, NULL);
680         }
681         if (i2 != id)
682         {
683             getUUIDforId(i2, &temp, NULL);
684         }
685
686         OCUuidList_t *tempNode = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
687         if (NULL == tempNode)
688         {
689             OIC_LOG(ERROR, TAG, "No Memory");
690             sqlite3_finalize(stmt);
691             return OC_STACK_NO_MEMORY;
692         }
693         memcpy(&tempNode->dev.id, &temp.id, UUID_LENGTH);
694         LL_PREPEND(*UUIDLIST,tempNode);
695         ++counter;
696     }
697     *numOfDevices = counter;
698      sqlite3_finalize(stmt);
699      return OC_STACK_OK;
700 }
701
702 OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t **staleDevList, size_t *numOfDevices)
703 {
704     CHECK_PDM_INIT(TAG);
705     if (NULL != *staleDevList)
706     {
707         OIC_LOG(ERROR, TAG, "Not null list will cause memory leak");
708         return OC_STACK_INVALID_PARAM;
709     }
710
711     sqlite3_stmt *stmt = 0;
712     int res = 0;
713     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_STALE_INFO,
714                               strlen(PDM_SQLITE_GET_STALE_INFO) + 1, &stmt, NULL);
715     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
716
717     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_STALE_STATE);
718     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
719
720     size_t counter  = 0;
721     while (SQLITE_ROW == sqlite3_step(stmt))
722     {
723         int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
724         int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
725         OicUuid_t temp1 = {{0,}};
726         OicUuid_t temp2 = {{0,}};;
727         getUUIDforId(i1, &temp1, NULL);
728         getUUIDforId(i2, &temp2, NULL);
729
730         OCPairList_t *tempNode = (OCPairList_t *) OICCalloc(1, sizeof(OCPairList_t));
731         if (NULL == tempNode)
732         {
733             OIC_LOG(ERROR, TAG, "No Memory");
734             sqlite3_finalize(stmt);
735             return OC_STACK_NO_MEMORY;
736         }
737         memcpy(&tempNode->dev.id, &temp1.id, UUID_LENGTH);
738         memcpy(&tempNode->dev2.id, &temp2.id, UUID_LENGTH);
739         LL_PREPEND(*staleDevList, tempNode);
740         ++counter;
741     }
742     *numOfDevices = counter;
743     sqlite3_finalize(stmt);
744     return OC_STACK_OK;
745 }
746
747 OCStackResult PDMClose()
748 {
749     CHECK_PDM_INIT(TAG);
750     int res = 0;
751     res = sqlite3_close(g_db);
752     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
753     return OC_STACK_OK;
754 }
755
756 void PDMDestoryOicUuidLinkList(OCUuidList_t* ptr)
757 {
758     if(ptr)
759     {
760         OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
761         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
762         {
763             LL_DELETE(ptr, tmp1);
764             OICFree(tmp1);
765         }
766     }
767 }
768
769 void PDMDestoryStaleLinkList(OCPairList_t* ptr)
770 {
771     if(ptr)
772     {
773         OCPairList_t *tmp1 = NULL,*tmp2=NULL;
774         LL_FOREACH_SAFE(ptr, tmp1, tmp2)
775         {
776             LL_DELETE(ptr, tmp1);
777             OICFree(tmp1);
778         }
779     }
780 }
781
782 OCStackResult PDMIsLinkExists(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2,
783                                bool* result)
784 {
785     CHECK_PDM_INIT(TAG);
786     if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2 || NULL == result)
787     {
788         return OC_STACK_INVALID_PARAM;
789     }
790     int id1 = 0;
791     int id2 = 0;
792     if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
793     {
794         OIC_LOG(ERROR, TAG, "Requested value not found");
795         return OC_STACK_INVALID_PARAM;
796     }
797
798     if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
799     {
800         OIC_LOG(ERROR, TAG, "Requested value not found");
801         return OC_STACK_INVALID_PARAM;
802     }
803
804     bool isStale = false;
805     if (OC_STACK_OK != PDMIsDeviceStale(uuidOfDevice1, &isStale))
806     {
807         OIC_LOG(ERROR, TAG, "uuidOfDevice1:Internal error occured");
808         return OC_STACK_ERROR;
809     }
810     if (isStale)
811     {
812         OIC_LOG(ERROR, TAG, "uuidOfDevice1:Device is stale");
813         return OC_STACK_INVALID_PARAM;
814     }
815
816     isStale = false;
817     if (OC_STACK_OK != PDMIsDeviceStale(uuidOfDevice2, &isStale))
818     {
819         OIC_LOG(ERROR, TAG, "uuidOfDevice2:Internal error occured");
820         return OC_STACK_ERROR;
821     }
822     if (isStale)
823     {
824         OIC_LOG(ERROR, TAG, "uuidOfDevice2:Device is stale");
825         return OC_STACK_INVALID_PARAM;
826     }
827
828     ASCENDING_ORDER(id1, id2);
829
830     sqlite3_stmt *stmt = 0;
831     int res = 0;
832     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_DEVICE_LINKS,
833                               strlen(PDM_SQLITE_GET_DEVICE_LINKS) + 1, &stmt, NULL);
834     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
835
836     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
837     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
838
839     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
840     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
841
842     bool ret = false;
843     while(SQLITE_ROW == sqlite3_step(stmt))
844     {
845         OIC_LOG(INFO, TAG, "Link already exists between devices");
846         ret = true;
847     }
848     sqlite3_finalize(stmt);
849     *result = ret;
850     return OC_STACK_OK;
851 }
852
853 static OCStackResult updateDeviceState(const OicUuid_t *uuid, int state)
854 {
855     sqlite3_stmt *stmt = 0;
856     int res = 0 ;
857     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_DEVICE,
858                               strlen(PDM_SQLITE_UPDATE_DEVICE) + 1, &stmt, NULL);
859     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
860
861     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
862     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
863
864     res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, uuid, UUID_LENGTH, SQLITE_STATIC);
865     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
866
867     if (SQLITE_DONE != sqlite3_step(stmt))
868     {
869         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
870         sqlite3_finalize(stmt);
871         return OC_STACK_ERROR;
872     }
873     sqlite3_finalize(stmt);
874     return OC_STACK_OK;
875 }
876
877 static OCStackResult updateLinkForStaleDevice(const OicUuid_t *devUuid)
878 {
879     sqlite3_stmt *stmt = 0;
880     int res = 0 ;
881
882     int id = 0;
883     if (OC_STACK_OK != getIdForUUID(devUuid, &id))
884     {
885         OIC_LOG(ERROR, TAG, "Requested value not found");
886         return OC_STACK_INVALID_PARAM;
887     }
888
889     res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE,
890                               strlen(PDM_SQLITE_UPDATE_LINK_STALE_FOR_STALE_DEVICE) + 1,
891                                &stmt, NULL);
892     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
893
894     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
895     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
896
897     res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
898     PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
899
900     if (SQLITE_DONE != sqlite3_step(stmt))
901     {
902         OIC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
903         sqlite3_finalize(stmt);
904         return OC_STACK_ERROR;
905     }
906     sqlite3_finalize(stmt);
907     return OC_STACK_OK;
908 }
909
910 OCStackResult PDMSetDeviceStale(const OicUuid_t* uuidOfDevice)
911 {
912     CHECK_PDM_INIT(TAG);
913     if (NULL == uuidOfDevice)
914     {
915         OIC_LOG(ERROR, TAG, "Invalid PARAM");
916         return  OC_STACK_INVALID_PARAM;
917     }
918     begin();
919     OCStackResult res = updateLinkForStaleDevice(uuidOfDevice);
920     if (OC_STACK_OK != res)
921     {
922         rollback();
923         OIC_LOG(ERROR, TAG, "unable to update links");
924         return res;
925     }
926     res = updateDeviceState(uuidOfDevice, PDM_STALE_STATE);
927     if (OC_STACK_OK != res)
928     {
929         rollback();
930         OIC_LOG(ERROR, TAG, "unable to update device state");
931         return res;
932     }
933     commit();
934     return OC_STACK_OK;
935 }